How i can use Poppler-QML-plugin in my application? - qt

Hello guys i have found into this repository
https://github.com/dept2/Poppler-QML-plugin
a qml plugin for show a pdf file into a qml file, but i don't know how i can use it someone can help me?
In ubuntu 18.04 version i have found this plugin with command line sudo apt-cache search poppler and i have installed the package but i have the same problem , how i can use it ?
Thanks in advance

There are 2 possible methods:
1. Compile and install the plugin:
To install this package I must install the plugin for it first download the project, open a terminal in the project directory and execute the following:
qmake
make
sudo make install
Then in the .qml import the module, the Poppler item provides an imageProvider so you should use an Image as I show below:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.11
import org.docviewer.poppler 1.0 // <--- import
import QtQuick.Dialogs 1.3
Window {
id: win
visible: true
width: 640
height: 480
title: qsTr("Poppler Example")
function urlToPath(urlString) {
var s
if (urlString.startsWith("file:///")) {
var k = urlString.charAt(9) === ':' ? 8 : 7
s = urlString.substring(k)
} else {
s = urlString
}
return decodeURIComponent(s);
}
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.home
nameFilters: ["PDF files (*.pdf)", "All files (*)"]
onAccepted: timer.running = true
Component.onCompleted: visible = true
}
Timer {
id: timer
interval: 100; repeat: false
onTriggered: {
poppler.path = urlToPath(""+fileDialog.fileUrl)
view.focus = true
}
}
Poppler{
id: poppler
}
ListView{
id: view
height: parent.height
width: 100
model: poppler.numPages
delegate: Image{
id: image
width: parent.width
source: poppler.loaded? "image://poppler/page/" + (modelData+1): ""
sourceSize.width: width
MouseArea{
anchors.fill: parent
onClicked: {
image.ListView.view.currentIndex = index
image.ListView.view.focus = true
}
}
}
}
Flickable {
height: parent.height
anchors.left: view.right
anchors.right: parent.right
contentWidth: bigImage.width;
contentHeight: bigImage.height
boundsBehavior: Flickable.StopAtBounds
Image{
id: bigImage
sourceSize.width: win.width - view.width
source: (poppler.loaded && view.currentIndex >= 0)? "image://poppler/page/"+(view.currentIndex+1): ""
}
}
}
Output:
2. Create .pri
I have created a .pri that is a simple way to attach the files to the project:
poppler-qml.pri:
INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/pdfModel.cpp \
$$PWD/pageImageProvider.cpp
HEADERS += \
$$PWD/pdfModel.h \
$$PWD/pageImageProvider.h
unix|win32: LIBS += -lpoppler-qt5
The files must have the following structure:
poppler-qml
   ├── pageImageProvider.cpp
   ├── pageImageProvider.h
   ├── pdfModel.cpp
   ├── pdfModel.h
   └── poppler-qml.pri
And then add it to your .pro:
...
include(poppler-qml/poppler-qml.pri)
and main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <pdfModel.h>
int main(int argc, char *argv[])
{
qputenv("POPPLERPLUGIN_DEBUG", "1"); /// enable debug
qmlRegisterType<PdfModel>("org.docviewer.poppler", 1, 0, "Poppler");
...
For example in the following link you can find an example.
Note:
The initial code of the plugin has a bug because if it asks for a page that does not exist the application should return a null QImage but as it does not do the verification the application can be broken
page = document->page(numPage -1);
if(!page)
return result;

Related

Transport QML Image via Bridge

I have at the moment a simple PySide6 app which uses qml for image capturing. I want to transport the image to our app but cannot figure out how. I am not sure, if saving QML image is an attempt in the right direction.
My PySide App
import sys
from pathlib import Path
from PySide6.QtCore import QObject, Slot
from PySide6.QtGui import QGuiApplication, QImage
from PySide6.QtQml import QQmlApplicationEngine, QmlElement
QML_IMPORT_NAME = "io.qt.textproperties"
QML_IMPORT_MAJOR_VERSION = 1
#QmlElement
class Bridge(QObject):
#Slot(QImage)
def capture(self, preview):
# Do something with the preview
print(type(preview))
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
# Get the path of the current directory, and then add the name
# of the QML file, to load it.
qml_file = Path(__file__).parent / "simpleCam.qml"
engine.load(qml_file)
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
MY QML File
import QtQuick
import QtQuick.Controls
import QtMultimedia
import io.qt.textproperties
ApplicationWindow {
id: mainFrame
width: 640
height: 480
visible: true
title: qsTr("Cam Test")
Bridge {
id: bridge
}
Rectangle {
width: 640
height: 400
MediaDevices {
id: mediaDevices
}
CaptureSession {
imageCapture: ImageCapture {
id: capture
}
camera: Camera {
id: camera
}
videoOutput: output
}
VideoOutput {
id: output
anchors.fill: parent
}
Button {
id: startCamButton
text: "Start Cam"
anchors.top: output.bottom
anchors.left: output.left
onClicked: {
camera.start()
camImage.opacity = 0
}
}
Button {
id: takePicButton
text: "take pic"
anchors.top: output.bottom
anchors.left: startCamButton.right
onClicked: {
capture.capture()
camImage.opacity = 1
}
}
Image {
id: camImage
anchors.fill: parent
source: capture.preview
}
}
}
The Result
What is missing?
In the Button with id: takePicButton I want to transport the image to the PySide6 Bridge. If I add to theonClicked Signal bridge.capture(capture.preview) I got the Error:
TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed.`
How can I solve this problem?
You should use the imageCaptured signal.
Change:
imageCapture: ImageCapture {
id: capture
}
To:
imageCapture: ImageCapture {
id: capture
onImageCaptured: function(req_id, preview){bridge.capture(req_id, preview)}
}
And change in main.py:
#Slot(QImage)
def capture(self, preview):
# Do something with the preview
print(type(preview))
To:
#Slot(int, QImage)
def capture(self,req_id, preview):
print(req_id)
print(type(preview))
Working example here.
You might want to look at this answer for other use cases.

Create Transparent Window in QtQuick to show external application through

I am trying to create a QtQuick application running under Linux (Lubuntu 20.04) with a transparent window that shows the desktop or any other application running in the background.I also require a couple of other windows which aren't transparent.
I have tried the suggestions here:
QtQuick 2 Transparent Window Background I just end up with either a grey or black background which doesn't show the desktop.
I have tried all combinations of opacity: 0.0 or color: "transparent", but none give the correct effect.
Here is a minimal non working example:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
id: transparentWindowTest
//flags: Qt.FramelessWindowHint
visible: true
width: 500
height: 500
x: (Screen.width - width) / 2
y: (Screen.height - height) / 2
color: "transparent"
opacity: 0.0
Rectangle {
id: transparentWindow
anchors.left: parent.left
anchors.top: parent.top
width: 300
height: 300
color: "transparent"
opacity: 0.0
}
Rectangle {
id: rightWindow
anchors.left: transparentWindow.right
anchors.top: parent.top
width: 200
height: parent.height
color: "blue"
}
Rectangle {
id: bottomWindow
anchors.left: parent.left
anchors.top: transparentWindow.bottom
width: parent.width
height: 200
color: "red"
}
}
Any suggestions on the best way of achieving this?
I have also tried the suggestions in:
How to make a transparent window with Qt Quick?, but these just show a dark background that is not transparent at all. Note that I had to modify the second example so that it would compile under Qt5.15.2, as show below:
transparent2.pro:
QT += quick
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
opacity: 0.0
color: "transparent"
Rectangle {
id: root
width: 250
height: 250
// completely transparent background
color: "#00FFFFFF"
border.color: "#F00"
border.width: 2
Rectangle {
id: ball
height: 50; width: 50
x: 100
color: "#990000FF"
radius: height / 2
}
SequentialAnimation {
running: true; loops: Animation.Infinite
NumberAnimation { target: ball; property: "y"; to: root.height - ball.height; duration: 1000; easing.type: Easing.OutBounce }
PauseAnimation { duration: 1000 }
NumberAnimation { target: ball; property: "y"; to: 0; duration: 700 }
PauseAnimation { duration: 1000 }
}
}
}
Here is a screenshot showing the output:

Popup item loses opaquness

I have a weird problem with Popup QML component from QtQuick2 , when I do open() it, it shows with transparent background , and it should be opaque.
This is how I call the Popup component from the main.qml file :
NewUser {
id: new_user_form
}
This is the component's source:
// File: NewUser.qml
Popup {
id: new_user_popup
modal: true
focus: true
x: 10
y: 10
width: 300
height: 200
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: "red"
}
}
And this is the output:
Now, I can fix this error by moving the source of the NewUser.qml into main.qml and everything looks fine now:
This is the now 'fixed' main.qml:
Popup {
id: new_user_form
modal: true
focus: true
x: 10
y: 10
width: 300
height: 200
}
See, the popup is completely OPAQUE:
So, why if I move the source code of the component into a separate file from main.qml it loses the opaquness ? My main.qml has a lot of other stuff, but I believe it is not related to the popup, also the ID is unique. I hope this is not some issue with QT 5.8 RC (which I am using for development) , it is not yet official but soon it will be.
EDIT:
I believe I found a bug. The bug is reproducible with Qt 5.8 and Qt 5.7
To reproduce, create a project with the following files:
Main file:
//main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
NewUser {
id: new_user_form
}
Button {
text: "open popup"
onClicked: {
new_user_form.open()
}
}
}
The component file (NewUser.qml)
//File: NewUser.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
import QtQuick.Templates 2.0
Popup {
id: new_user_popup
modal: true
focus: true
x: 10; y:10;
height: 200; width: 300;
Button {
text: "Test button"
}
}
//File: qtquickcontrols2.conf
; This file can be edited to change the style of the application
; See Styling Qt Quick Controls 2 in the documentation for details:
; http://doc.qt.io/qt-5/qtquickcontrols2-styles.html
[Controls]
Style=Material
[Universal]
Theme=Light
;Accent=Steel
[Material]
Theme=Light
;Accent=BlueGrey
;Primary=BlueGray
//File: main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
That does the bug do? If you click on the button "open popup" you will see a dimmed screen but no popup at all.
This is not a bug. See, you are not using a namespace for the templates import.
import QtQuick.Templates 2.0 as T
For the sake of clarity, there is a one-to-one mapping between the types provided by the QtQuick.Templates and QtQuick.Controls imports. For every type available in the QtQuick.Controls import, a non-visual template type by the same name exists in the QtQuick.Templates import. It is recommended to use a namespace for the templates import to avoid overlap with the types provided by the QtQuick.Controls import.

QML animation - moving the application window

I want to create an animation to move (or resize) my application Window built using QML.
I have the following code (most of it created by default when we create a QT quick Controls application:
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
MainForm.ui.qml
import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.3
Item {
width: 640
height: 480
property alias button1: button1
property alias button2: button2
RowLayout {
anchors.centerIn: parent
Button {
id: button1
text: qsTr("Press Me 1")
}
Button {
id: button2
text: qsTr("Press Me 2")
}
}
}
main.qml
import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Dialogs 1.2
ApplicationWindow {
id: mainWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("&Open")
onTriggered: console.log("Open action triggered");
}
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
MainForm {
anchors.fill: parent
button1.onClicked: Qt.quit();
button2.onClicked: state = "other";
}
transitions: [
Transition {
from: "*"
to: "other"
NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad; duration: 2000 }
}
]
states: [
State {
name: "other"
PropertyChanges {
target: mainWindow
x: x + 200
}
}
]
MessageDialog {
id: messageDialog
function show(caption) {
messageDialog.text = caption;
messageDialog.open();
}
}
}
With this code, I was simply trying to move my window 200 pixels to the right. When I try to run it, I get qrc:/main.qml:42 Cannot assign to non-existent property "states". I believe that is weird, because when I start typing "states" and choose to auto-complete, it builds to me the whole structure, so I thought it should exist...
I'm new to QML, and I'm not fully familiar with the several options of animations that exists. This one I've tried based on the example that comes with QT creator (animation.pro - code from transitions).
I believe it should be quite simple, right? Could you help me with this?
Qt Creator has a feature where you can insert code snippets using certain keywords. You can see which snippets are available by going to Tools > Options > Text Editor > Snippets.
Snippets will show up as red in the auto completion popup, and regular properties (or types, as is the case below) will show up as green:
So, ApplicationWindow doesn't have a states property. If you're ever in doubt, go to the documentation for the type you're interested in (e.g. http://doc.qt.io/qt-5/qml-qtquick-controls-applicationwindow.html) and click on the link that says "List of all members, including inherited members". This will show you all properties, functions, etc. belonging
to that type.
If you want to animate the window's position, you can use a NumberAnimation without using states:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.5
ApplicationWindow {
id: window
width: 400
height: 400
visible: true
NumberAnimation {
id: xyAnimation
target: window
properties: "x,y"
easing.type: Easing.InOutQuad
duration: 2000
to: 500
}
Button {
text: "Start"
onClicked: xyAnimation.start()
}
}
state is a property in Item, however ApplicationWindow is not an Item. To add state/transition to an non-Item type, use StateGroup:
ApplicationWindow {
id: mainWindow
//your code...
MainForm {
button2.onClicked: { myWindowStates.state = "other";}
}
StateGroup {
id: myWindowStates
transitions: [
Transition {
from: "*"; to: "other"
NumberAnimation {
properties: "x,y"; easing.type: Easing.Linear;
duration: 2000
}
}
]
states: [
State {
name: "other"
PropertyChanges {
target: mainWindow
x: mainWindow.x + 200
explicit: true //Remember to set this
}
}
]
}
}
Remember to set PropertyChange.explict to true, otherwise the state behavior is wrong and your window will disappear after the transition finished.

How to handle too many QML and audio files

I finished a Qt Quick UI project, where I am using many QML and audio files. It is an application for children. In the main screen I have 10 sections. One is for letters (Pismena.qml), second for numbers(Cislice.qml) etc (Tvary.qml,Farby.qml). If you choose some section, then you can browse through the images, which are accompanied by sound. One section contains about 30 png and 30 mp3 files. Everything works fine.
But if I want to deploy this application and transform this project into a Qt Quick Application project, I have a problem. For three sections it is OK, but if I want to use four sections, I get errors like:
Error: "Internal data flow error."
Error: "GStreamer encountered a general stream error."
Error: "Failed to connect stream: Too large"
These error messages are displayed immediately when I start the application, not when I am browsing the images.
Also some audio elements are not played.
Here is my main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Here is my main.qml (it's not complete)
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtGraphicalEffects 1.0
import QtQuick.Window 2.0
import QtMultimedia 5.0
ApplicationWindow {
visible: true
width: 1024
height:300
Rectangle {
width: parent.width
height: parent.height
id: appWindow
property alias pismenaIconAlias: pismenaIcon
Pismena{
id: pismena
visible: false
}
Cislice{
id: cislice
visible: false
}
Farby{
id: farby
visible: false
}
Tvary{
id: tvary
visible: false
}
Image{
id: pismenaIcon
source: "file:" + applicationDirPath + "/obrazky/pismenaIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
pismena.visible = true
}
}
}
Image{
id: cisliceIcon
source: "file:" + applicationDirPath + "/obrazky/cisliceIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
cislice.visible = true
}
}
Image{
id: farbyIcon
source: "file:" + applicationDirPath + "/obrazky/farbyIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
farby.visible = true
}
}
Image{
id: tvaryIcon
source: "file:" + applicationDirPath + "/obrazky/tvaryIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
tvary.visible = true
}
}
}
}
In the main.qml file, if you choose Pismena(pismenaIcon Image element), you are redirected to that file - Pismena.qml, where you can browse through Images with sounds:
import QtQuick 2.3
import "myJava.js" as MyScript
import QtMultimedia 5.0
import QtQuick.Window 2.0
Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Audio {
id: hrajPismeno
}
Image {
id: pis
MouseArea{
anchors.fill: parent
onClicked: {
pis.source = "file:" + applicationDirPath + MyScript.cobr()
hrajPismeno.source = "file:" + applicationDirPath + MyScript.zobr()
hrajPismeno.play()
}
}
}
}
And here is my myJava.js
.pragma library
var pr = 0;
var c = 1;
var z = 1;
var numberOfItems = 33;
var itemFolder = "\/pismena\/";
function cobr(){
c = (c === numberOfItems) ? 0 : c;
c = c + 1;
var s = itemFolder + c + ".png";
return s;
}
function setLetters(){
numberOfItems = 33;
itemFolder = "\/pismena\/";
}
function zobr(){
z = (z === numberOfItems) ? 0 : z;
z = z + 1;
var r = itemFolder + z + ".mp3";
return r;
}
I am using Qt 5.3 On Linux Mint 13.
Why I can not use many Audio files?
In Pismena.qml you have not set the initial width and height for the Item and also for the Image. So in the window there is no place where user can actually click. Also there is no default path for the Image element.
EDIT
In each Audio element, set the autoLoad property to false.

Resources