How do I keep my own animated KDE wallpapers from running together? - c++

I recently tried writing animated wallpaper plugins for KDE4. When I switch among them, the animations get jumbled. That is, the previous animation doesn't stop, and the previous frames and the current frames get mixed together. I embed the frames into each program as image resources. Then I write code like the following for each wallpaper. Can anyone tell me what I'm missing (or if it's just a KDE bug)?
dancingcoffee.h
#ifndef DANCINGCOFFEE_H
#define DANCINGCOFFEE_H
#include <Plasma/Wallpaper>
#include <QPainter>
#include <QTimer>
class DancingCoffee : public Plasma::Wallpaper
{
Q_OBJECT
public:
DancingCoffee(QObject *parent, const QVariantList& args);
void paint(QPainter *painter, const QRectF &exposedRect);
private slots:
void updateBackground();
private:
const int m_frames;
const int m_interval;
int m_frame_number;
QTimer m_timer;
};
#endif // DANCINGCOFFEE_H
dancingcoffee.cpp
#include "dancingcoffee.h"
#include <QImage>
K_EXPORT_PLASMA_WALLPAPER(coffee, DancingCoffee)
DancingCoffee::DancingCoffee(QObject *parent, const QVariantList &args) :
Plasma::Wallpaper(parent, args),
m_frames(2),
m_interval(1000 / m_frames)
{
m_frame_number = 0;
m_timer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateBackground()));
m_timer.start(m_interval);
}
void DancingCoffee::paint(QPainter *painter, const QRectF &exposedRect)
{
QString name = QString(":/images/frame-%1.png").arg(m_frame_number);
QImage image(name);
painter->drawImage(exposedRect, image);
}
void DancingCoffee::updateBackground()
{
++m_frame_number;
m_frame_number %= m_frames;
m_timer.start(m_interval);
emit update(boundingRect());
}
CMakeLists.txt
set(CMAKE_INSTALL_PREFIX /usr)
project(plasma-wallpaper-coffee)
cmake_minimum_required(VERSION 2.8)
find_package(KDE4 REQUIRED)
find_package(KDE4Workspace REQUIRED)
include(KDE4Defaults)
add_definitions(${KDE4_DEFINITIONS})
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
set(TARGET plasma_wallpaper_coffee)
set(SRC_LIST dancingcoffee.cpp)
qt4_add_resources(RCC_LIST dancingcoffee.qrc)
kde4_add_plugin(${TARGET} ${SRC_LIST} ${RCC_LIST})
target_link_libraries(${TARGET} ${KDE4_PLASMA_LIBS})
install(TARGETS ${TARGET} DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES plasma-wallpaper-coffee.desktop DESTINATION ${SERVICES_INSTALL_DIR})
plasma-wallpaper-coffee.desktop
[Desktop Entry]
Name=Coffee
Type=Service
Icon=image-jpeg
ServiceTypes=Plasma/Wallpaper
X-KDE-Library=plasma_wallpaper_coffee
X-KDE-PluginInfo-Author=Chris French
X-KDE-PluginInfo-Email=unclechromedome#gmail.com
X-KDE-PluginInfo-Name=coffee
X-KDE-PluginInfo-Version=0.1
X-KDE-PluginInfo-Website=
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
And voila! Animated wallpaper on my desktop. But the wallpapers don't play well together. I have to kill the desktop and restart it when I switch wallpapers, and sometimes that doesn't even work. Sometimes I have to do a hard reboot. It's a pain for me, and unacceptable if I ever distribute the wallpapers.

Related

How to register QObject class in CMake with qt_add_qml_module?

I have a QObject derived class Expense that I use in QML like this.
// main.qml
Expense {
id: expenseManager
onExpenseCreated: {
// Do something
}
}
The expense class has no UI components, it has some basic Signal and Slots for API communications.
// expense.h
#ifndef EXPENSE_H
#define EXPENSE_H
#include <QObject>
#include <QString>
#include "service.h"
class Expense : public QObject
{
Q_OBJECT
private:
Service service;
void networkError();
bool buttonLock = false;
public:
explicit Expense(QObject *parent = nullptr);
public slots:
void createInvoice(QString item, float amount);
signals:
void expenseCreated();
};
#endif // EXPENSE_H
I have used qmlRegisterType() for registering Expense type in QML. Below is how my main() looks like.
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
......
qmlRegisterType<Expense>("com.kadbyte.expense", 1, 0, "Expense");
........
return app.exec();
}
Everything working perfectly as it used to. But recently I have upgraded my project to QT6 with CMake as the build tool instead of QMake. In the docs I saw that we can use qt_add_qml_module command in CMakeList.txt to register C++ Classes instead of qmlRegisterType(), by adding QML_ELEMENT macro to the QObject class.
But I can't understand how to do this, the documentation doesn't make sense as it uses qmake example (Link to docs) instead of CMake. Below is my CMakeLists.txt file
cmake_minimum_required(VERSION 3.16)
project(Udyan VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
qt_add_executable(appUdyan
main.cpp
expense.h expense.cpp
)
qt_add_qml_module(appUdyan
URI Udyan
VERSION 1.0
QML_FILES qml/main.qml
)
set_target_properties(appUdyan PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_compile_definitions(appUdyan
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(appUdyan
PRIVATE Qt6::Quick)
So how to use qt_add_qml_module to registering QObject class to use in QML?
Note: All the example I have given above is just an MRE and not my complete code.
You just need to add QML_ELEMENT to your QObject-derived Expense class's header and make sure you have moc enabled in your CMakeLists.txt. In application case it doesn't matter if the expense.h/cpp sources are included via qt_add_executable or qt_add_qml_module. I think it's clearer to add them to qt_add_qml_module SOURCES. Then you just import module URI in you QML file. In the example below I'm printing out property value from Expense object in QML.
CMakeLists.txt
set(CMAKE_AUTOMOC ON)
qt_add_qml_module(appUdyan
URI udyan
VERSION 1.0
QML_FILES
main.qml
SOURCES
expense.h
expense.cpp
)
C++
#include <QObject>
#include <QtQml/qqmlregistration.h>
class Expense : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int value READ value NOTIFY valueChanged)
public:
explicit Expense(QObject *parent = nullptr);
int value() const;
signals:
void valueChanged();
private:
int m_value {5};
};
QML:
import QtQuick
import udyan
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Expense {
id: expense
Component.onCompleted: console.log(expense.value)
}
}

no such file or directory [duplicate]

This question already has an answer here:
no such file or directory
(1 answer)
Closed 2 years ago.
i'm trying to get the image from my webcam using qt, opencv
here's my codes:
.pro file:
#-------------------------------------------------
#
# Project created by QtCreator 2013-12-20T07:42:20
#
#-------------------------------------------------
QT += core gui
TARGET = QtCvCapture
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
imagecapture.cpp \
moc_imagecapture.cpp \
moc_mainwindow.cpp
HEADERS += mainwindow.h \
imagecapture.h \
ui_mainwindow.h
FORMS += mainwindow.ui
#include opencv for PC x86
#INCLUDEPATH += /usr/local/include/opencv
#LIBS +=/usr/local/lib/*.so
INCLUDEPATH += C:\opencv\build\include
LIBS += C:\opencv\release\bin\libopencv_core451.dll
LIBS += C:\opencv\release\bin\libopencv_highgui451.dll
LIBS += C:\opencv\release\bin\libopencv_imgcodecs451.dll
LIBS += C:\opencv\release\bin\libopencv_imgproc451.dll
LIBS += C:\opencv\release\bin\libopencv_features2d451.dll
LIBS += C:\opencv\release\bin\libopencv_calib3d451.dll
#include opencv for ARM
#INCLUDEPATH += /opt/opencv.arm/include/opencv
#LIBS += /opt/opencv.arm/lib/*.so
imagecapture.h:
#ifndef IMAGECAPTURE_H
#define IMAGECAPTURE_H
#include <QObject>
#include <QImage>
#include <QTimer>
#include <cv.h>
#include <highgui.h>
class ImageCapture : public QObject
{
Q_OBJECT
public:
explicit ImageCapture(QObject *parent = 0);
~ImageCapture();
signals:
public slots:
//!< attempts to start camera, camera number is given in cameraIndex (see cvCaptureFromCAM docs)
void captureFromCamera( int cameraIndex = -1 ); //index = -1 to capture form any camera
void stopCapture(); //!< stops timer and release OpenCV capture structure
protected:
QImage convert(IplImage * image); //!< create QImage from OpenCV image data
QImage IplImage2QImage(const IplImage *iplImage);
protected slots:
void timer_stick(); //!< grab and send frame on each timer tick
signals:
void imageCaptured( const QImage& image );
void error( const QString& text );
protected:
QTimer * _timer; //!< timeout signal is used to capture frames at regular intervals (or whenever possible in case of camera)
CvCapture * _cvCap; //!< used to grab image data from video or camera
IplImage* imagerd;
};
#endif // IMAGECAPTURE_H
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <imagecapture.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
public slots:
void on_actionOpen_Camera_triggered();
void displayImage(const QImage &image);
protected slots:
void captureError(const QString &text);
public:
ImageCapture *_capture;
};
#endif // MAINWINDOW_H
(i don't know if this kind of presentation is acceptable, i haven't seen anyone doing it yet)
the problems are:
C:\Users\FPT Shop\Downloads\QtCvCapture\QtCvCapture\mainwindow.h:4: error: QMainWindow: No such file
or directory
In file included from ..\QtCvCapture\mainwindow.cpp:1:
..\QtCvCapture\mainwindow.h:4:10: fatal error: QMainWindow: No such file or directory
same issues for cv.h and QtGUI/QApplicaiton, this happended when i try to #include them
what I have done: I have installed OpenCV and CMake following the instruction in https://wiki.qt.io/How_to_setup_Qt_and_openCV_on_Windows#OpenCV
the installation was successful, after which I compiled the program, then I'm met with the errors above. I have recheck and the files that the compiler claimed to be missing are there, in the folder (which I have linked in the .pro file). I found some answer said that it could be because my code is outdated? which I found reasonable because the code that's I'm using was published wayy back in 2013... sooo
what do you guys think?

ERROR that looks so main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'?

I have naturally trivial question as I mean: we press button --> counter increases, counter increases --> QLabel's value is renewed. I caught strange error and don't want to do. I'm not dummy in C++ but in QT I am. It's my first and most trivial application in it.
Some answers there (on Stack Overflow) advised to add virtual constructor. It has no effect.
I tried to rewrite signals and slots to new qt5 style but there were another problems, I was too lazy to fix them, was it (rewriting, not laziness :) ) a good way, maybe problem is really with versions?
I just haven't tried to reinstall QT or install Qt4, maybe problem is in it?
about versions:
$ qmake --version
responds:
QMake version 3.0
Using Qt version 5.5.1 in /usr/lib/x86_64-linux-gnu
conn.pro:
TEMPLATE = app
QT += core gui
TARGET = conn
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
SOURCES += main.cpp
main.cpp:
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QObject>
class Counter : public QObject {
Q_OBJECT
private:
double i_;
public:
virtual ~Counter()
{
}
Counter() : QObject(), i_(0)
{
}
public slots:
void slot_incCounter();
signals:
void goodbye(){}
void counterChanged(double){}
};
void Counter::slot_incCounter() {
emit counterChanged(++i_);
if (i_ == 5) {
emit goodbye();
}
}
int main(int argc, char* argv[]) {
QApplication my_app(argc, argv);
QLabel label1("label i created");
label1.show();
QPushButton button1("press me");
button1.show();
Counter counter1;
QObject::connect(&button1, SIGNAL(clicked()),
&counter1, SLOT(slot_incCounter()));
QObject::connect(&counter1, SIGNAL(counterChanged(double a)),
&label1, SLOT(setNum(double a)));
QObject::connect(&counter1, SIGNAL(goodbye()),
&my_app, SLOT(quit()));
return my_app.exec();
}
Try to run it:
qmake && make && ./conn
So I see in console:
g++ -m64 -Wl,-O1 -o conn main.o -L/usr/X11R6/lib64 -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
main.o: In function `main':
main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'
collect2: error: ld returned 1 exit status
Makefile:144: recipe for target 'conn' failed
make`:` *** [conn] Error 1
What should I do?
Qt uses the meta object compiler (moc) to enable e.g. signal and slots. By default it works perfectly if the Q_OBJECT macro is in a header file. So the easiest would be you put Counter into it's own header/implementation file, rerun qmake and make. (That's by the way good practice...)
If you want to stick with a single main.cpp file you need to tell the moc explicitly that this file contains macros moc needs to parse. You do this with the following line at the very end of main.cpp:
#include "main.moc"
Then also rerun qmake and make.
Please keep in mind that the manually including a moc-include directive is not the best choice. So better split your C++ classes into separate files right from the beginning...
Thank you very much! Your answer was full, useful and making all more obvious.
Solution was:
1. Move class Counter to Counter.h
Since this moment the message about vtable disappeared. Appeared messages that goodbye() and Counter::counterChanged(double) have multiple definition. The first definition was mine in Counter.cpp (WRONG WAY). The second was in moc_Counter.cpp, generated by MOC utility. So:
2. Remove definitions (my empty definitions) of signal functions, because moc makes its own in file moc_Counter.cpp:
// SIGNAL 0
void Counter::goodbye()
{
QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR);
}
// SIGNAL 1
void Counter::counterChanged(double _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}
and they cause a problem of multiple definition.
Summing it up, working code:
main.cpp:
#include <QApplication>
#include "Counter.h"
int main(int argc, char* argv[]) {
QApplication my_app(argc, argv);
QLabel label1("1");
label1.show();
QPushButton button1("press me");
button1.show();
Counter counter1;
QObject::connect(&button1, SIGNAL(clicked()),
&counter1, SLOT(slot_incCounter()));
QObject::connect(&counter1, SIGNAL(counterChanged(double)),
&label1, SLOT(setNum(double)));
QObject::connect(&counter1, SIGNAL(goodbye()),
&my_app, SLOT(quit()));
return my_app.exec();
}
void Counter::slot_incCounter() {
emit counterChanged(++i_);
if (i_ == 5) {
emit goodbye();
}
}
Counter.h:
#ifndef COUNTER_H
#define COUNTER_H
#include <QLabel>
#include <QPushButton>
#include <QObject>
class Counter : public QObject {
Q_OBJECT
private:
double i_;
public:
virtual ~Counter()
{
}
Counter() : QObject()
{
}
public slots:
void slot_incCounter();
signals:
void goodbye();
void counterChanged(double);
};
#endif // COUNTER_H
Counter.cpp:
#include "Counter.h"
Thank you, you're great!

Pass a QImage object between class methods

I have two functions. In one function, i have a QImage and then i want to pass that QImage to another function. Both the function have different Arguments. Please tell me how can i do it?
CMakeLists.txt
cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
# Qt #####################################################
find_package(Qt4 REQUIRED)
set( QT_USE_QTGUI TRUE )
include(${QT_USE_FILE})
add_definitions (-DQT_NO_KEYWORDS)
# All source files
set(SELECTION_INTERFACE_SOURCE_CPP
src/SelectionInterface.cpp)
# All header files that use Qt Keywords (e.g. OBJECT)
set(SELECTION_INTERFACE_MOC_H
src/SelectionInterface.h
)
# Wrap for MOC
qt4_wrap_ui (SELECTION_INTERFACE_UI_H ${SELECTION_INTERFACE_UI})
qt4_wrap_cpp(SELECTION_INTERFACE_MOC ${SELECTION_INTERFACE_MOC_H})
rosbuild_add_library (selection_interface_lib
${SELECTION_INTERFACE_SOURCE_CPP}
${SELECTION_INTERFACE_MOC})
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
rosbuild_add_executable(newtest_node src/SelectionInterface.cpp)
target_link_libraries (newtest_node selection_interface_lib ${QT_LIBRARIES})
Makefile
include $(shell rospack find mk)/cmake.mk
manifest
<package>
<description brief="newTestCode">
newTestCode
</description>
<author>admin</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/newTestCode</url>
<depend package="roscpp"/>
<depend package="sensor_msgs"/>
<depend package="std_msgs"/>
</package>
SelectionInterface.h
#ifndef SELECTION_INTERFACE_H
#define SELECTION_INTERFACE_H
#include <QApplication>
#include <QtGui/QWidget>
#include <QtGui/QMenu>
#include <QtGui/QAction>
#include <QMainWindow>
#include <QDebug>
#include <QLabel>
#include <QGraphicsPixmapItem>
class Image:public QMainWindow
{
Q_OBJECT
public:
void getImage();
void displayImage();
QImage tempImage;
};
#endif
SelectionInterface.cpp
#include "SelectionInterface.h"
void Image::getImage()
{
QImage myImage("/home/usr/Pictures/image.jpg");
qDebug() << myImage.height();
tempImage= myImage.copy();
}
void Image::displayImage()
{
QImage finalImage = tempImage;
qDebug()<<finalImage.height();
}
int main (int argc, char** argv)
{
QApplication app(argc, argv);
Image object;
object.getImage();
object.displayImage();
object.show();
return app.exec();
}
First of all, it is better that you use the term methods rather than functions, because these are class members and you will find most people calling these methods out there. Namely, these are members of your Image class.
You can use a member variable for it inside the Image class, which is accessible inside the first method as well as second.
class member
#include <QApplication>
#include <QMainWindow>
#include <QImage>
#include <QDebug>
class Image : public QMainWindow
{
Q_OBJECT
public:
void getImage() {
QImage myImage("/home/lpapp/Downloads/android.png");
qDebug() << myImage.height();
tempImage= myImage.copy();
}
void displayImage() {
QImage finalImage = tempImage;
qDebug() << finalImage.height();
}
private:
QImage tempImage;
};
#include "main.moc"
int main (int argc, char** argv)
{
QApplication app(argc, argv);
Image object;
object.getImage();
object.displayImage();
object.show();
return app.exec();
}
This should print out the same height, to make a very quick verification. You can find the command below, on my system, as to how to build and run this code. You need to generate the moc file, and then supply the include paths and libraries for the build and then, finally, run the application.
moc-qt5 -o main.moc main.cpp && g++ -I/usr/include/qt/QtWidgets -I/usr/include/qt/QtGui -I/usr/include/qt/QtCore -I/usr/include/qt -fPIC -lQt5Core -lQt5Widgets -lQt5Gui main.cpp && ./a.out
Output:
900
900
Although, depending on your use case, copy-on-write (COW) might not be sufficient enough, and you will want to use a pointer member to avoid the costly operation.
The documentation can be found here for the copy method; it will copy the whole, by default, if you do not specify the sub-area.
You can also use a static variable inside the same file that you set in method 1, and access in method 2. Note, you should define the static, in that case, outside the class to get a different approach. This is probably less frequently used than the class member, so I would prefer that.
You could probably also set the image on an external class, or variable, and then access. This all depends a lot on your particular case. This is broad question.
You could always use a QPainter as well, to draw the "source" into the "destination" with drawImage().

Undefined reference to vtable, Qt in Linux

I was trying to compile a Qt and OpenGL program under Code::Blocks in Ubuntu 10.04. I get the 'undefined reference to 'vtable for GLWidget'
#ifndef _GLWIDGET_H
#define _GLWIDGET_H
#include <QtOpenGL/QGLWidget>
#include "stdlib.h"
class GLWidget : public QGLWidget {
Q_OBJECT // must include this if you use Qt signals/slots
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void keyPressEvent(QKeyEvent *event);
};
#endif /* _GLWIDGET_H */
I borrowed the code from this guy to see if it works, because mine wasn't working because of the same reason. Code
And here is the GLWidget.cpp:
#include <QtGui/QMouseEvent>
#include "glwidget.h"
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) {
setMouseTracking(true);
}
GLWidget::~GLWidget()
{
}
void GLWidget::initializeGL() {
...
}
void GLWidget::resizeGL(int w, int h) {
...
}
void GLWidget::paintGL() {
...
}
void GLWidget::keyPressEvent(QKeyEvent* event) {
...
}
}
I removed the code from the GL part to keep it shorter. Should you need it, I can always post it up.
#include <QtGui/QApplication>
#include <QtOpenGL/QGLWidget>
#include "glwidget.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
GLWidget window;
window.resize(800,600);
window.show();
return app.exec();
}
In your project.pro file add
QT += opengl
So it knows that it has to link to GL libraries.
Clean your project and run qmake on it.
'undefined reference to 'vtable for GLWidget' most probably means that the definition of the first non inline virtual function of GLWidget isn't linked in the executable.
In the present case, my guess it is that it should be provided by the file generated by moc (but as I don't program for QT, I may be mistaken here).
This happens sometimes when adding Q_OBJECT to a header file and can mean a missing moc_ file.
I have found from personal experience doing the following has resolved the issue:
$ qmake filename.pro
$ make
I had this exact problem after adding Q_OBJECT to one of the header files in my project.
I was only getting this error message from within QT Creator, and not when I built my project from the Linux command line.
For me, the solution was to delete the YourProjectName-build-desktop folder which resides on the same level as your project directory. Then when I built the project from within QT Creator, it magically worked.