Using Signals/Slots to avoid circular dependencies? - c++

I've got an unelegant chunk of C++ Qt code where main creates a graphics item (the parent) which creates a bunch of child graphics items. The child and parent have to call each others methods, i.e. the parent needs to tell its children to do some things (move, change color, etc), and the children will signal the parent to do things to its other children. Having both call each others' methods is leading to some ugly circular code, and it's getting frustrating dodging C2027 errors. Would it make any sense to use a custom signal/slot system as a method of communication between the child and parent? Or should I stay the course with my current design and just try and solve these kinds of bugs?
For example, this code (my current design) generates C2027:
Mainwindow:
#include "mainwindow.h"
#include "ui_mainwindow.h"
vector<Foo*> FooArray;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
int viewwidth = ui->graphicsView->width();
...
FooArray.push_back(new Foo(5, viewwidth, scene));
FooArray[0]->loadBars();
}
Foo:
#include "Foo.h" //includes bar.h
vector<int> ActiveList;
vector<Bar*> BarArray;
Foo::Foo(int id, int w, QGraphicsScene* scene)
{
this->id = id;
this->width = w;
this->scene = scene;
}
...
void Foo::loadBars()
{
...
BarArray.resize(nitems);
BarArray[k] = new Bar(id, k, this);
BarArray[k]->setPos(...);
scene->addItem(BarArray[k]);
...
}
void Foo::doSomething()
{
...
}
Bar:
#include "Bar.h" //forward declares Foo; isn't executed until Foo exists.
Bar::Bar(int setid, int num, Foo* foo)
{
this->s = setid;
this->n = num;
this->owner = foo;
}
...
void Bar::someFunction()
{
...
owner->doSomething();
...
}

Yes, that's precisely what signals and slots are for.
Right now you have Bar::someFunction() which calls Foo::doSomething()
What you can do instead is:
Declare doSomething() as a slot
Have Bar emit a signal somethingHappened()
When creating the children, connect their somethingHappened() signal to the parent's doSomething() slot
This is an example of dependency injection, and it allows you to swap the parent class for something else in the future without having to change Bar at all.

Related

Linking a QWidget to another QWidget new created

I am try to, by pressing a button in the main QWidget, to create a new QWidget. In that new created QWidget I want to have a button connected to a slot of the main QWidget.
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI* s=new SmallGUI{};
s->show();
});
}
void something(){
//something
}
and the second class
class SmallGUI1 :
public QWidget
{
public:
SmallGUI(){connection();};
private:
QPushButton* N =new QPushButton;
void connection(){
//to connect N to something()
}
I want to connect N to something() .
Before we start, there are some other problems with you code.
Note that in your second class, the constructor is not named the same as the class, which will cause some... Problems.
You also forgot to put a parent for your buttons (which may thus cause some unexpected results) AND for your Widgets (which is again not a good idea).
So, that being said, let us get to the main topic.
I tend to only put prototypes and declare the attributes in the .h file to make the code clearer, but you may of course adapt it to your needs or to your own programming convention.
There are several ways to do something like this, but the simplest one should look like this :
SmallGUI1.h :
#include "UI.h" //The file in which the class UI is declared
//OR :
//class UI; //If you need to include this file in UI.h
class SmallGUI1 : public QWidget{
Q_OBJECT //Q_OBJECT macro, check the doc for more explainations about it
public:
explicit SmallGUI1(UI *parent = nullptr); //Explicit means that this constructor cannot be used for implicit casts
~SmallGUI1();//Destructor needed because I only put the constructor above
private:
QPushButton* N; //Not very good looking to initialize attributes in the .h in my opinion, but works fine.
}
SmallGUI1.cpp :
SmallGUI1::SmallGUI1(UI *parent) : QWidget(parent){
N = new QPushButton(tr("Some text on the button") , this); //tr to enable translation on this string
//************* If I understood your question correctly, this is what you are looking for *************
connect(N , &QPushButton::clicked , parent , &UI::doSomething); //Select the signal you want
/*
Some code here
*/
show();
}
SmallGUI1::~SmallGUI1(){qDeleteAll(children());}
UI.h :
class UI : public QWidget{
Q_OBJECT
public:
explicit UI(QWidget *parent = nullptr);
~UI();
private:
QPushButton* all;
private slots :
void createSmallGUI1();
void doSomething();
}
UI.cpp :
#include "SmallGUI1.h"
UI::UI(QWidget *parent) : QWidget(parent){
all = new QPushButton(tr("ALL") , this);
connect(all , &QPushButton::clicked , this , &UI::createSmallGUI1);
/*
Some code here
*/
}
UI::~UI(){qDeleteAll(children());}
void UI::createSmallGUI1(){SmallGUI1 *gui = new SmallGUI1(this);}
void UI::doSomething(){
/*
Clever code here
*/
}
You can define the second widget as a child of the main widget to make things easier:
class UI : public QWidget {
...
private:
SmallGUI* s;
...
and then initialize it in the UI constructor, along with your all button. You can initially hide the child widget or disable it:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
and 'show' it with button clicked signal
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
Doing so gives you the option to connect the clicked signal of your N button to the something function in the parent class
connect(s->N, &QPushButton::clicked, this, &UI::something);
The complete program would be as follows,
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QWidget>
class SmallGUI : public QWidget {
public:
SmallGUI(QWidget* parent) : QWidget(parent) {
N = new QPushButton{"btn2", this};
connection();
};
QPushButton* N;
private:
void connection(){};
};
class UI : public QWidget {
public:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
private:
SmallGUI* s;
QPushButton* all;
void connection() {
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
connect(s->N, &QPushButton::clicked, this, &UI::something);
}
void something() { QMessageBox::information(this, "Hello", "Hello"); }
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
UI w;
w.show();
return a.exec();
}
It is not good idea to connect to parent's slots from "nested" class, since SmallGUI1 will be tied to class UI.
Here is better solution, I think:
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI1* s=new SmallGUI1;
connect(s,&USmallGUI1::button_clicked,this,&UI::something);
s->show();
});
}
void something(){
//something
}
And SmallGUI1 class:
class SmallGUI1 :
public QWidget
{
public:
SmallGUI1(){connection();};
signals:
void button_clicked();
private:
QPushButton* N;
void connection(){
//to connect N to something()
N = new QPushButton;
connect(N,&QPushButton::clicked,this,&SmallGUI1::button_clicked)
}
This way, you are connecting QPusButton::clicked signal from SmallGUI1 to the signal SmallGUI1::button_clicked(). Dont need to implement additional slot, just connect signal to signal.
And in UI you are connecting button_clicked() signal to the slot dosomething()
DONT FORGET THE CONSTRUCTOR OF SmallGUI1! In your code, SmallGUI() will be just a method, which will not be called when SmallGUI1 is instantiated, and you have to call it by yourself.

QT how to pass Qlist to class Constructor

am trying to pass Qlist to class constructor but no success with it. I can pass basic variables but with Qlist am getting error in editor
error: no matching constructor for initialization of 'Worker'
compiler error
error: no matching function for call to 'Worker::Worker(QList<MainWindow::MainWindow(QWidget*)::pnp_com_info>&)'
Worker* worker = new Worker(pnp_data);
here is what am doing.
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// my sample structure
struct pnp_com_info{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
QList<pnp_com_info> pnp_data; // Qlist container
pnp_com_info pnp_component_data; // struct
// fill with data
pnp_component_data.com_name = "e18";
pnp_component_data.angle = 600;
// add it to Qlist container
pnp_data.append(pnp_component_data);
// Worker worker(5); // sample int passed OK.
// try to pass Qlist to worker constructor
Worker* worker = new Worker(pnp_data); // no success get error : no matching constructor for initialization of 'Worker'
}
worker.h source code
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject {
Q_OBJECT
public:
struct pnp_com_info{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
// Worker(int sampleVar);
Worker(QList<pnp_com_info> pnpData);
~Worker();
public slots:
void doWork();
signals:
private:
QList<pnp_com_info> pnp_components_data;
};
#endif // WORKER_H
worker.cpp
#include "worker.h"
// --- CONSTRUCTOR ---
Worker::Worker(QList<pnp_com_info> pnp_data) {
// Worker::Worker(int sampleVar) {
this->pnp_components_data = pnp_data;
}
// --- DECONSTRUCTOR ---
Worker::~Worker() {
// free resources
}
// --- PROCESS ---
// Start processing data.
void Worker::doWork() {
// do some work
}
so any idea what am doing wrong. thanks
In the worker.cpp, you are not "inside" the class scope. So there you need to fully qualify the type:
Worker::Worker(QList<Worker::pnp_com_info> pnp_data) {
And then in MainWindow you of course need to use the same struct, Worker::pnp_com_info and not define a new struct type.
You might want to put the struct definition somewhere else than under Worker too. But where, that's impossible to advice on based on just the code you are showing; perhaps having it as nested struct inside Worker is a fine place for it.
I personally like to use Qt Creator (or whatever IDE I might be using, for any programming language) refactoring functionality to generate the method definition to .cpp file. Write the declaration inside th class in .h file as usual, then right click it to get context menu, select refactoring and select the generate option you want. Avoids mistakes like this and can save quite a lot if head banging especially when coding while a bit tired.

Qt: passing objects to every window

Im a beginner at C++ since I'm a Java-Dev. I'm learning Qt right now.
Now I want in my widget application on central object for holding special functionality (for example a bunch of methods for sending different network-command or something like that). In my mainwindow.cpp I've got this
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//...
BusinessLogic* bl = new BusinessLogic;
bl->setMyValue(44);
this->setBusinessLogic(bl);
this->getBusinessLogic();
//...
}
BusinessLogic* MainWindow::getBusinessLogic()
{
return this->bl;
}
void MainWindow::setBusinessLogic(BusinessLogic* newbl)
{
this->bl = newbl;
}
Where BusinessLogic.cpp is the class which I want to access from all windows in my application. So in my Dialog which get opend when the pushButton is clicked, I try to use the businesslogic instance like this in the constructor
Dialog::Dialog(QDialog *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
//...
((MainWindow*)parent)->getBusinessLogic();
}
Unfortunately the program crashes everytime the dialog get instanciated (the line with ((MainWindow*)parent)->getBusinessLogic(); get called.
What can I do?
There are several methods for achieving your goal(all depends on your requirements) but one approach is you can create Singleton class of your BusinessLogic and then access it anywhere. have a look here. OR you can also pass object of class one class to another. OR you can use signal slot mechanism.
For you best Solution can be
Class BLogic{
public:
static BLogic* instance(){
static BLogic ins;
return &ins;
}
void setVal(int v){
val = v;
}
private:
BLogic(){}
int val;
};
Now you can call functions of BLogic from any class like
BLogic::instance()->setVal(10);
OR Example of passing objects can be
class ClassA
{
public:
void setClassB(ClassB *ob){
m_classB = ob;
}
ClassB* getClassB(){
return m_classB;
}
private:
ClassB* m_classB;
};
class ClassB
{
public:
void setClassA(ClassA *ob){
m_classA = ob;
}
ClassA* getClassA(){
return m_classA;
}
private:
ClassA* m_classA;
};
Now from main.cpp
ClassA* obA = new ClassA;
ClassB* obB = new ClassB;
obA->setClassB(obB);
obB->setClassA(obA);
Don't pass a zero parent or a dangling pointer to the dialog.
But more seriously, verify your assumptions:
qDebug() << "the parent object is" << parent;
auto p = qobject_cast<MainWindow*>(parent);
if (p)
p->getBusinessLogic();
Debug output will give you some idea of whether a parent is set, and of what type it is at the moment. Remember that during the construction of a MainWindow instance, it goes through being different types (quite literally). So depending on when you construct the child, you might get a parent of type QWidget* or QMainWindow* or MainWindow*. During the destruction you could even get a QObject* parent!

Why does my attempt at connecting a pushbutton to a lambda fail?

I have some issues while trying to use lambda expression to make connections between a pushbutton and a function I want to call when I click the button.
I am using Qt 5.6, with the compiler MinGW 4.9.2 (the default one). My code is the following :
In mainwindow.cpp :
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initBuildings();
initPage();
for (int i(0); i<buildings.size(); ++i) {
connect(static_cast<QAbstractButton*>(widgetlist.at(i).at(2)), &QAbstractButton::clicked, [this, i]() {
buildings.at(i).buy(amountMultiplier);});
}
}
void MainWindow::initBuildings()
{
Building b1 = Building("Building 1",100,1,200);
Building b2 = Building("Building 2",1000,10,2000);
buildings.append(b1);
buildings.append(b2);
}
void MainWindow::initPage()
{
for (int i(0); i<buildings.size(); i++) {
QList<QWidget *> buttons;
QLabel *namelabel = new QLabel(buildings.at(i).getName());
QLabel *amountlabel = new QLabel;
QPushButton *buybutton = new QPushButton(this);
QPushButton *upgradebutton = new QPushButton(this);
amountlabel->setFixedSize(50,40);
buybutton->setFixedSize(100,40);
upgradebutton->setFixedSize(100,40);
buttons.append(namelabel);
buttons.append(amountlabel);
buttons.append(buybutton);
buttons.append(upgradebutton);
widgetlist.append(buttons);
}
}
In mainwindow.h :
#include <QMainWindow>
#include <QScrollArea>
#include <QList>
#include <building.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void initBuildings();
void initPage();
Ui::MainWindow *ui;
int amountMultiplier;
QList<Building> buildings;
QList<QList<QWidget*>> widgetlist;
};
And "Building" is a class I have created which does not inherit from another class. The function I want to use is a public funtion of this class:
void buy(int amount) const;
It doesn't compile and I get several errors :
no matching function for call to 'MainWindow::connect(QAbstractButton*, void (QAbstractButton::*)(bool), MainWindow::MainWindow(QWidget*)::<lambda()>)
invalid use of incomplete type 'struct QtPrivate::QEnableIf< false, QMetaObject::Connection>
cannot convert '<lambda closure object>MainWindow::MainWindow(QWidget*)::< lambda()>{((MainWindow*)this), i}' (type 'MainWindow::MainWindow(QWidget*)::< lambda()>') to type 'const QObject*
I tried to change the lambda capture list, or to change the way I get the value in the lists but it doesn't change anything and I don't figure what is the problem. Maybe I am wrong in the use of the lambda ?
Two problems:
buildings.at() returns a const Building &, and the buy method is not const. You must index the buildings using [] instead.
The type returned from widgetlist.at(i).at(2) is definitely not QPushButton* - if it was, the code would compile. Even the error message indicates what the issue is:
no matching function for call to 'MainWindow::connect(QWidget* const&, void (QAbstractButton::*)(bool), [...])
This compiles:
// https://github.com/KubaO/stackoverflown/tree/master/questions/lambda-list-37615204
#include <QtWidgets>
struct Building {
void buy() {}
};
class Class : public QObject {
QList<Building> m_buildings;
QList<QList<QWidget*>> m_widgets;
public:
Class() {
for (int i = 0; i<m_buildings.size(); ++i)
connect(static_cast<QAbstractButton*>(m_widgets.at(i).at(2)), &QAbstractButton::clicked, [=] {
m_buildings[i].buy();
});
}
};
int main() {}
If you wish an extra measure of safety in face of programming errors on your part, replace the static_cast with a qobject_cast, it'll then abort if you cast a non-button instead of doing something possibly misleading.
According to the documentation, your lambda should accept a bool argument.

Pass instance of class to a another constructor that adds its object to a list owned by passed instance

As the title says I want to create an object of class Note and add its pointer to a list of the object of class Traymenu. I am missing the whole thing I guess, please take a look on how I call the Note's constructor in traymenus's newNote and what I am doing in note.h.
traymenu.h:
#ifndef TRAYMENU_H
#define TRAYMENU_H
#include <QSystemTrayIcon>
#include <QIcon>
#include <QPixmap>
#include <QMenu> //in use for context menu
#include <QList>
#include "note.h"
class Traymenu : public QSystemTrayIcon
{
public:
Traymenu();
~Traymenu();
void createMainContextMenu();
void newNote(QWidget, Traymenu);
void exitProgram();
private:
QSystemTrayIcon mainIcon;
QMenu mainContextMenu;
QList<Note> notelist; //List that holds references to Note objects
//template argument 1 is invalid
};
#endif // TRAYMENU_H
traymenu.cpp:
#include "traymenu.h"
#include <QDebug>
Traymenu::Traymenu(){
mainIcon.setIcon(QIcon(QPixmap("C:\\program.png")));
mainIcon.setVisible(true);
mainIcon.show();
createMainContextMenu();
}
Traymenu::~Traymenu(){
}
void Traymenu::newNote(){
Note(Traymenu *this); //HOW TO PASS THE TRAYMENU INSTANC TO NOTE???
}
void Traymenu::exitProgram(){
delete this; //deletes traymenu object (icon disappears)
}
void Traymenu::createMainContextMenu(){
QAction *actionNewNote = mainContextMenu.addAction("Neue Notiz");
mainContextMenu.addSeparator();
QAction *actionExitProgram = mainContextMenu.addAction("Programm beenden");
actionNewNote->setIcon(QIcon("C:\\new.ico"));
actionNewNote->setIconVisibleInMenu(true);
//Qt5 new signal connection: http://qt-project.org/wiki/New_Signal_Slot_Syntax
QObject::connect(actionNewNote,&QAction::triggered,this,&Traymenu::newNote);
QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);
mainIcon.setContextMenu(&mainContextMenu);
}
note.h:
#ifndef NOTE_H
#define NOTE_H
#include <QWidget>
#include "traymenu.h"
namespace Ui{
class Note;
}
class Note : public QWidget
{
public:
Note(QWidget *parent = 0, Traymenu *trayMenuIn);
~Note();
void appendNoteToNotelist();
private:
Q_OBJECT
Ui::Note *ui;
Traymenu *pTraymenu = &trayMenuIn; //trayMenuIn was not declared in this scope
//Why declare a formal parameter?
};
#endif // NOTE_H
note.cpp:
#include "note.h"
#include "ui_note.h"
Note::Note(QWidget *parent, Traymenu *trayMenuIn) :
QWidget(parent),
ui(new Ui::Note)
{
ui->setupUi(this);
Note::appendNoteToNotelist();
}
Note::~Note()
{
delete ui;
}
void Note::appendNoteToNotelist(){
pTraymenu.append(&ui);
}
I list each problem followed by an illustrative snippet of your mistake.
QObjects are not copyable. You can't pass their instances anywhere. You can't store their instances in most containers. std::list is a notable example. QWidgets are QObjects, too. You can only pass QObjects by pointer, or by reference. To store QObjects in containers, you must store a smart pointer, e.g. std::unique_ptr or std::shared_ptr or QSharedPointer to an instance created on the heap.
void newNote(QWidget, Traymenu);
Calling delete this inside a method should be done with utmost care; except for special circumstances it's just wrong. If you're new to C++, the rule of thumb is: it's always wrong. If you want to delete an object instance that you're sure is on the heap, you can call deleteLater. It will perform the deletion once the control returns to the event loop.
The typical way of exiting an application is by calling QCoreApplication::quit().
QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);
Parameters with default values must come after parameters without default values.
Note(QWidget *parent = 0, Traymenu *trayMenuIn);
When you pass a parameter in a function/method call, you don't need to provide the types again.
Note(Traymenu *this);
When holding references to QObjects whose lifetime is not well controlled, you should use QPointer to avoid dangling pointer references. A QPointer resets itself to zero when the object is deleted elsewhere, thus giving you a clean crash (as opposed to undefined and possibly very misleading behavior).
Traymenu *pTraymenu
Initialization of class members should be done in default member initializers, and/or an initialization list. Your code below has nothing to do with formal parameters:
Traymenu *pTraymenu = &trayMenuIn;
After all those fixes, and some others, the code looks like below. You could compile it as a self-contained, single file - it works, although you never show the notes, so they remain invisible.
// https://github.com/KubaO/stackoverflown/tree/master/questions/note-tray-21753641
#include <QtWidgets>
#include <list>
// Note.h
namespace Ui{
class Note {
public:
void setupUi(QWidget *) {} // dummy for sscce.org
};
}
class TrayMenu;
class Note : public QWidget
{
Q_OBJECT
public:
Note(TrayMenu *trayMenu, QWidget *parent = {});
private:
Ui::Note m_ui;
QPointer<TrayMenu> m_traymenu;
};
// TrayMenu.h
class Note;
class TrayMenu : public QObject {
Q_OBJECT
public:
TrayMenu();
void createMainContextMenu();
void newNote();
private:
QSystemTrayIcon m_mainIcon;
QMenu m_mainContextMenu;
std::list<Note> m_notes;
};
// TrayMenu.cpp
template <int N> auto decode64(const char (&arg)[N], int rows) {
auto const raw = QByteArray::fromBase64(QByteArray::fromRawData(arg, N-1));
QImage img((const quint8 *)raw.data(), rows, rows, raw.size()/rows, QImage::Format_MonoLSB);
img = std::move(img).convertToFormat(QImage::Format_Indexed8);
img.setColor(1, qRgba(0, 0, 0, 0)); // make transparent
return img;
}
// convert baseline_language_black_18dp.png -flatten -negate -monochrome mono:-|base64 -b80
static const char language_d64[] =
"/////w//////D/////8P/z/A/w//DwD+D/8BAPwP/wEA+A9/IEbgDz8cjuEPPxyPww8fHg+HDw+PHw8P"
"DwAAAA8PAAAADw8AAAAPx8c/Pg7Hzz8+DsfHHz4Ox4c/Pg7Hxz8/DsfHPz4ODwAAAA4PAAAADw8AAAAP"
"H48fjw8fHg+HDz8cj4MPPxiH4Q9/IMbgD/8AAPAP/wMA/A//DwD/D/8/4P8P/////w//////D/////8P";
static const auto language_icon = decode64(language_d64, 36);
// convert baseline_note_add_black_18dp.png -flatten -negate -monochrome mono:-|base64 -b80
static const char note_add_d64[] =
"/////w//////D/////8PfwDA/w8/AMD/Dz8AAP8PPwAY/w8/ADD8Dz8AePwPPwDw8A8/APjhDz8A8OMP"
"PwDwxw8/AJDCDz8AAMAPPwAAwA8/AATADz8AD8APPwAGwA8/AA/ADz8ABsAPP/D/wA8/8P/ADz/w/8AP"
"PwAOwA8/AAfADz8ADsAPPwAGwA8/AAbADz8AAMAPPwAAwA8/AADAD38AAOAP/////w//////D/////8P";
static const auto note_add_icon = decode64(note_add_d64, 36);
TrayMenu::TrayMenu() {
m_mainIcon.setIcon(QPixmap::fromImage(language_icon));
m_mainIcon.setVisible(true);
m_mainIcon.show();
createMainContextMenu();
}
void TrayMenu::newNote() {
m_notes.emplace_back(this);
m_notes.back().show();
}
void TrayMenu::createMainContextMenu() {
auto *actionNewNote = m_mainContextMenu.addAction("Neue Notiz");
m_mainContextMenu.addSeparator();
auto *actionExitProgram = m_mainContextMenu.addAction("Programm beenden");
actionNewNote->setIcon(QPixmap::fromImage(note_add_icon));
actionNewNote->setIconVisibleInMenu(true);
QObject::connect(actionNewNote, &QAction::triggered, this, &TrayMenu::newNote);
QObject::connect(actionExitProgram, &QAction::triggered, QCoreApplication::quit);
m_mainIcon.setContextMenu(&m_mainContextMenu);
}
// Note.cpp
Note::Note(TrayMenu *trayMenu, QWidget *parent) :
QWidget(parent),
m_traymenu(trayMenu)
{
m_ui.setupUi(this);
}
// main.cpp
int main(int argc, char ** argv) {
QApplication app(argc, argv);
TrayMenu menu;
return app.exec();
}
#include "main.moc"