QT load resource files for debugging - qt

So I've created a qrc file and have a file at /stylesheets/main.qss.
I have stylesheet information in this main.qss file. My goal here is to have a qss file I can work out of and potentially hot reload over time. My issue is that when I debug there is no /stylesheets/main.qss in the debug build location. So it loads the file as an empty string, don't even get an exception. What am I missing?
main.qss
/*#MainBackgroundColor = rgb(40,40,40)*/
/*#MainBorderColor = rgb(0,102,255)*/
/*#MainTextColor = rgb(255,255,255)*/
*
{
color: rgb(255,255,255);
background-color: rgb(40,40,40);
}
QStatusBar
{
border-top: 3px solid rgb(0,102,255);
}
Loading the stylesheet
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//We want a frameless window.
setWindowFlags(Qt::FramelessWindowHint);
//Load the style sheet into the window
QFile File(":/stylesheets/main.qss");
File.open(QFile::ReadOnly);
QString stylesheet = QLatin1String(File.readAll());
//Setup the UI
ui->setupUi(this);
this->setStyleSheet(stylesheet);
}
MainWindow::~MainWindow()
{
delete ui;
}
resources.qrc
<RCC>
<qresource prefix="/">
<file>stylesheets/main.qss</file>
</qresource>
</RCC>
.pro file
#-------------------------------------------------
#
# Project created by QtCreator 2019-02-20T18:02:31
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = SmartDraw
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES += \
main.cpp \
mainwindow.cpp \
stylesheetloader.cpp
HEADERS += \
mainwindow.h \
stylesheetloader.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
resources.qrc
DISTFILES += \
stylesheets/main.qss
EDIT: Found the solution. Apparently Qt isn't very good about updating everything if you happen to have the pro file open. If something super obviously wrong happens like this you need to run Build->Clean All then Build->Run QMake to get everything stituated again.

What I do is keep the stylesheet file (*.qss) next to the app while debugging. Then load it in main.cpp and subscribe for changes using QFileSystemWatcher.
This way I can edit the *.qss file with a nice editor, like SublimeText, and every time I save it, I can see the changes inmediatly:
#include "mydialog.h"
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QSharedPointer>
#include <QFileSystemWatcher>
typedef QSharedPointer<QFileSystemWatcher> QWatcherPtr;
void setStyleSheet(QApplication &a, const QString &strPath, const bool &subscribe = false)
{
// set stylesheet
QFile f(strPath);
if (!f.exists())
{
qDebug() << "[ERROR] Unable to set stylesheet," << strPath << "file not found.";
}
else
{
// set stylesheet
f.open(QFile::ReadOnly | QFile::Text);
QTextStream ts(&f);
a.setStyleSheet(ts.readAll());
f.close();
// subscribe to changes (only once)
if (!subscribe)
{
return;
}
QWatcherPtr watcher = QWatcherPtr(new QFileSystemWatcher);
watcher->addPath(strPath);
QObject::connect(watcher.data(), &QFileSystemWatcher::fileChanged, &a,
[&a, watcher, strPath]()
{
setStyleSheet(a, strPath, false);
});
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// set stylesheet and subscribe to changes
setStyleSheet(a, "./style.qss", true);
MyDialog w;
w.show();
return a.exec();
}

Related

My custom C++ plugin is not being consumed by the qml test application

I am new to Qt and learning few of the modules in Qt-Qml from youtube and Qt documentation. I want to create cpp plugin which is to be consumed by the qml application.
For this, I have created two projects. One is for creating a plugin library and another application is for consuming the plugin.
I am able to create the plugin library successfully. But, not able to consume it by the test application.
The test application is compiled successfully but throwing below error during run time.
QQmlApplicationEngine failed to load component
qrc:/main.qml:3:1: module "MyPlugin" is not installed
I have read the Qt documentation and googled a lot, but could not able to resolve it.
Qt : 5.15.7
Qt Creator: 5.0.3
OS: Ubuntu 18.04
Project 1: Creating Plugin library
CreatePlugin.pro
TEMPLATE = lib
TARGET = CreatePlugin
QT += qml quick
CONFIG += plugin c++11
DESTDIR = ../pluginFiles
TARGET = $$qtLibraryTarget($$TARGET)
uri = MyPlugin
# Input
SOURCES += \
createplugin_plugin.cpp \
myplugin.cpp
HEADERS += \
createplugin_plugin.h \
myplugin.h
DISTFILES = qmldir
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
copy_qmldir.target = $$OUT_PWD/qmldir
copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
copy_qmldir.commands = $(COPY_FILE) "$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)"
"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)"
QMAKE_EXTRA_TARGETS += copy_qmldir
PRE_TARGETDEPS += $$copy_qmldir.target
}
qmldir.files = qmldir
unix {
installPath = $$[QT_INSTALL_QML]/$$replace(uri, \., /)
qmldir.path = $$installPath
target.path = $$installPath
INSTALLS += target qmldir
}
# Copy the qmldir file to the same folder as the plugin binary
cpqmldir.files = qmldir
cpqmldir.path = $$DESTDIR
COPIES += cpqmldir
createplugin_plugin.h
#ifndef CREATEPLUGIN_PLUGIN_H
#define CREATEPLUGIN_PLUGIN_H
#include <QQmlExtensionPlugin>
class CreatePluginPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri) override;
};
#endif // CREATEPLUGIN_PLUGIN_H
createplugin_plugin.cpp
#include "createplugin_plugin.h"
#include "myplugin.h"
#include <qqml.h>
void CreatePluginPlugin::registerTypes(const char *uri)
{
// #uri MyPlugin
qmlRegisterType<MyPlugin>(uri, 1, 0, "MyPlugin");
}
myplugin.h
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QObject>
#include <QString>
class MyPlugin : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(MyPlugin)
public:
explicit MyPlugin(QObject *parent = nullptr);
~MyPlugin() override;
public slots:
QString getString();
};
#endif // MYPLUGIN_H
myplugin.cpp
#include "myplugin.h"
MyPlugin::MyPlugin(QObject *parent)
: QObject(parent)
{
// By default, QQuickItem does not draw anything. If you subclass
// QQuickItem to create a visual item, you will need to uncomment the
// following line and re-implement updatePaintNode()
// setFlag(ItemHasContents, true);
}
MyPlugin::~MyPlugin()
{
}
QString MyPlugin::getString()
{
return "This is CPP String";
}
qmldir
module MyPlugin
plugin CreatePlugin
Project 2: TestPlugin
TestPlugin.pro
QT += quick
CONFIG += c++11
# 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.12
import QtQuick.Window 2.12
import MyPlugin 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MyPlugin {
id: mypluginId
}
Component.onCompleted: console.log(mypluginId.getString())
}

Intellisense for QDialog object in Qt Console application

I'd like to show and then close a dialog after 5 seconds within my main() function in a Qt Console application. Here is my code that works:
Main.cpp:
#include <QApplication>
#include "splash.h"
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// some stuff to do
Splash splash;
QTimer::singleShot(5000, &splash, SLOT(close()));
splash.exec();
// some more stuff to do
exit(0);
// return a.exec();
}
text_console.pro:
QT += widgets \
gui
CONFIG += c++11 console
CONFIG -= app_bundle
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp \
splash.cpp
FORMS += \
splash.ui
HEADERS += \
splash.h
The above code complies and works, but I do not get complete intellisense for the splash object (e.g. setModal(), exec()). What am I doing wrong?
I am using Qt5 in linux.

How to invoke QML methods from C++?

I have my QML file which contains methods. These methods need to be called from C++ by using QMetaObject::invokeMethod().
QML :
// MyItem.qml
import QtQuick 2.0
Item {
function signalBroker(name, value) {
if (name == "volume_radio") {
updateVolume(value);
} else if (name == "mute_radio") {
updateMute();
}
}
}
Not sure why you wanna rely on Javascript but here is the complete code.
sample.pro
QT += qml quick
QT -= gui
SOURCES += main.cpp
RESOURCES += resources.qrc
main.cpp
#include <QCoreApplication>
#include <QQmlEngine>
#include <QQmlComponent>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QQmlEngine engine;
QQmlComponent component(&engine, "qrc:/main.qml");
QObject *object = component.create();
QVariant name = "volume_radio";
QVariant value = 24;
QMetaObject::invokeMethod(object, "signalBroker",
Q_ARG(QVariant, name),
Q_ARG(QVariant, value));
delete object;
return app.exec();
}
resources.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
main.qml
import QtQuick 2.0
Item {
function updateVolume(value) {
console.log('Volume from C++ = ' + value)
}
function updateMute() {
console.log('Radio is now mute.')
}
function signalBroker(name, value) {
if (name === 'volume_radio') {
updateVolume(value)
} else if (name === 'mute_radio') {
updateMute()
}
}
}
When I run it I get the following output
qml: Volume from C++ = 24
Please Note: On main.cpp when loading the main.qml file please make sure to provide a full path (or :/main.qml) or a qrc URL or the compiler will not find the QML file you are trying to load.
Your app can be a GUI app or a console app, it does not matter so long as you include the corresponding header files and update your .pro file.

QT 5.6 with OPenCV Run time 0xc0000139

Anyone got QT 5.6 working with OpenCV ?
Tried OpenCV latest 2.4.13 (at time of writing) and went back to OpenCV 2.4.9.
None worked - program will compile, link but crash on "During Startup program exited with code 0xc0000139". I never had any problems with QT 5.5.1 and OpenCV.
Here is stripped down code:
**mainwindow.cpp:**
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
cv::Mat image = cv::imread("C:/Users/foo/pics/cheetah.jpg");
cv::namedWindow("My Image");
cv::imshow("My Image", image);
cvWaitKey(0);
}
MainWindow::~MainWindow()
{
delete ui;
}
**main.cpp (used default):**
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
**mainwindow.h: (used default)**
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
**test_opencv.pro:**
INCLUDEPATH += "C:\Users\foo\Downloads\opencv\build\include"
LIBS += -LC:\Users\foo\Downloads\opencv\build\lib \
-lopencv_core249.dll \
-lopencv_highgui249.dll \
-lopencv_imgproc249.dll \
-lopencv_features2d249.dll \
-lopencv_video249.dll \
-lopencv_calib3d249.dll
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test_opencv
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
Path set:
C:\Qt\Tools\mingw492_32\bin
C:\Qt\5.6\mingw49_32\bin
C:\Users\foo\Downloads\opencv\build\bin
QT works fine with no OpenCV calls. With above code, running with QT Debug will see this:
"During Startup program exited with code 0xc0000139".
QT Error message
I have double checked my path. The OpenCV DLLs are defined in the Path. problem is not about not finding the runtime dynamically link dlls. I also checked my System32 and other directories for any old OpenCV dlls that might interfere as the path is traversed. No issues.
OpenCV was built with CMake and successfully build and installed. No issues there.
Thanks
Sean

Cannot import QML plugin

Let's consider an example QML plugin PluginExample (see C++ Plugins for QML) created in the directory $HOME/projects/org/example/PluginExample ($HOME/projects is in QML2_IMPORT_PATH).
pluginexample.pro:
TEMPLATE = lib
TARGET = PluginExample
QT += qml quick
CONFIG += qt plugin
TARGET = $$qtLibraryTarget($$TARGET)
uri = org.example.PluginExample
# Input
SOURCES += \
pluginexample_plugin.cc \
myitem.cc
HEADERS += \
pluginexample_plugin.hh \
myitem.hh
OTHER_FILES = qmldir
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
copy_qmldir.target = $$OUT_PWD/qmldir
copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
QMAKE_EXTRA_TARGETS += copy_qmldir
PRE_TARGETDEPS += $$copy_qmldir.target
}
qmldir.files = qmldir
unix {
installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
qmldir.path = $$installPath
target.path = $$installPath
INSTALLS += target qmldir
}
myitem.hh:
#ifndef MYITEM_H
#define MYITEM_H
#include <QQuickItem>
class MyItem : public QQuickItem
{
Q_OBJECT
Q_DISABLE_COPY(MyItem)
Q_PROPERTY(QString text READ text CONSTANT)
public:
MyItem(QQuickItem *parent = 0);
QString text() const;
~MyItem();
};
#endif // MYITEM_H
myitem.cc:
#include "myitem.hh"
MyItem::MyItem(QQuickItem *parent):
QQuickItem(parent)
{
}
MyItem::~MyItem()
{
}
QString MyItem::text() const
{
return "MyItem";
}
pluginexample_plugin.hh:
#ifndef PLUGINEXAMPLE_PLUGIN_H
#define PLUGINEXAMPLE_PLUGIN_H
#include <QQmlExtensionPlugin>
class PluginExamplePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char *uri);
};
#endif // PLUGINEXAMPLE_PLUGIN_H
pluginexample_plugin.cc:
#include "pluginexample_plugin.hh"
#include "myitem.hh"
#include <qqml.h>
void PluginExamplePlugin::registerTypes(const char *uri)
{
// #uri org.example.PluginExample
qmlRegisterType<MyItem>(uri, 1, 0, "MyItem");
}
qmldir:
module org.example.PluginExample
plugin PluginExample
The most part of the plugin's code was auto-generated by the project wizard.
It builds fine, but when I try to import org.example.PluginExample 1.0 from another project, I get this error:
module "org.example.PluginExample" plugin "PluginExample" not found
How can I fix that? Do I need to specify additional information to build/locate the plugin?
PS. Qt 5.3, Linux x86_64
EDIT 1:
I copied libPluginExample.so from the build directory (build-PluginExample-Desktop_Qt_5_3_0_GCC_64bit-Debug) to the source directory (PluginExample), and the error disappeared. Is this the best solution?
EDIT 2:
To avoid manual copying of the plugin library after each build, the following changes need to be applied to the *.pro file (unix-specific):
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
# ...
unix {
QMAKE_POST_LINK += $(COPY_FILE) $$quote($${OUT_PWD}/lib$${TARGET}.so) $$_PRO_FILE_PWD_
}
}

Resources