What is wrong with foreach in Qt? - qt

Well, I tried it all. This should be very simple, yet I am stock at finding out what in the world is going on with my foreach. It just don't help.
#include <QCoreApplication>
//coreapplication or Qapplication the error is there
#include <QList>
#include <QDebug>
int main()
{
QList<int> list;
list << 1 << 2 << 3 << 4 << 5;
foreach (int i, list) //expected token ';' got 'int'.
{
qDebug() << i;
}
}
/*
QT += core gui
TARGET = QtTest
CONFIG += console
CONFIG -= app_bundle
CONFIG += no_keywords
TEMPLATE = app
SOURCES += main.cpp
*/

You specified no_keywords in your config. You have to use Q_FOREACH instead of foreach. See the documentation for foreach.
That being said, I would switch to the C++11 range-based for, since it doesn't have issues with commas in types. For example,
Q_FOREACH (QPair<int, int> p, pairList)
won't compile since the preprocessor thinks you're trying to invoke the macro with 3 arguments instead of 2.

Instead you can use the C++11 for(:):
for(int i:list)
{
qDebug() << i;
}
Note that you will have to compile with the C++-11 flag, therefore add this line to your project file:
QMAKE_CXXFLAGS += -std=c++11
Note that the C++11 for is more efficient than the Qt foreach as indicated by: Qt foreach loop ordering vs. for loop for QList
Edit:
Like commented by Frank Osterfeld you can also use:
CONFIG+=c++11
in your .pro file since Qt 5.4 as commented here: How to use C++11 in your Qt Projects.

Related

How to load a dynamic library on demand from a C++ function/Qt method

I have dynamic library created as follows
cat myfile.cc
struct Tcl_Interp;
extern "C" int My_Init(Tcl_Interp *) { return 0; }
1) complile the cc file
g++ -fPIC -c myfile.cc
2) Creating a shared library
g++ -static-libstdc++ -static-libgcc -shared -o libmy.so myfile.o -L/tools/linux64/qt-4.6.0/lib -lQtCore -lQtGui
3) load the library from a TCL proc
then I give command
tclsh
and given command
% load libmy.so
is there any C++ function/ Qt equivalent to load that can load the shared library on demand from another C++ function.
My requirement is to load the dynamic library on run time inside the function and then use the qt functions directly
1) load the qt shared libraries (for lib1.so)
2) call directly the functions without any call for resolve
For example we have dopen, but for that for each function call we have to call dsym. My requirement is only call for shared library then directly call those functions.
You want boilerplate-less delay loading. On Windows, MSVC implements delay loading by emitting a stub that resolves the function through a function pointer. You can do the same. First, let's observe that function pointers and functions are interchangeable if all you do is call them. The syntax for invoking a function or a function pointer is the same:
void foo_impl() {}
void (*foo)() = foo_impl;
int main() {
foo_impl();
foo();
}
The idea is to set the function pointer initially to a thunk that will resolve the real function at runtime:
extern void (*foo)();
void foo_thunk() {
foo = QLibrary::resolve("libmylib", "foo");
if (!foo) abort();
return foo();
}
void (*foo)() = foo_thunk;
int main() {
foo(); // calls foo_thunk to resolve foo and calls foo from libmylib
foo(); // calls foo from libmylib
}
When you first call foo, it will really call foo_thunk, resolve the function address, and call real foo implementation.
To do this, you can split the library into two libraries:
The library implementation. It is unaware of demand-loading.
A demand-load stub.
The executable will link to the demand-load stub library; that is either static or dynamic. The demand-load stub will automatically resolve the symbols at runtime and call into the implementation.
If you're clever, you can design the header for the implementation such that the header itself can be used to generate all the stubs without having to enter their details twice.
Complete Example
Everything follows, it's also available from https://github.com/KubaO/stackoverflown/tree/master/questions/demand-load-39291032
The top-level project consists of:
lib1 - the dynamic library
lib1_demand - the static demand-load thunk for lib1
main - the application that uses lib1_demand
demand-load-39291032.pro
TEMPLATE = subdirs
SUBDIRS = lib1 lib1_demand main
main.depends = lib1_demand
lib1_demand.depends = lib1
We can factor out the cleverness into a separate header. This header allows us to define the library interface so that the thunks can be automatically generated.
The heavy use of preprocessor and a somewhat redundant syntax is needed due to limitations of C. If you wanted to implement this for C++ only, there'd be no need to repeat the argument list.
demand_load.h
// Configuration macros:
// DEMAND_NAME - must be set to a unique identifier of the library
// DEMAND_LOAD - if defined, the functions are declared as function pointers, **or**
// DEMAND_BUILD - if defined, the thunks and function pointers are defined
#if defined(DEMAND_FUN)
#error Multiple inclusion of demand_load.h without undefining DEMAND_FUN first.
#endif
#if !defined(DEMAND_NAME)
#error DEMAND_NAME must be defined
#endif
#if defined(DEMAND_LOAD)
// Interface via a function pointer
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args;
#elif defined(DEMAND_BUILD)
// Implementation of the demand loader stub
#ifndef DEMAND_CAT
#define DEMAND_CAT_(x,y) x##y
#define DEMAND_CAT(x,y) DEMAND_CAT_(x,y)
#endif
void (* DEMAND_CAT(resolve_,DEMAND_NAME)(const char *))();
#if defined(__cplusplus)
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args; \
ret name##_thunk args { \
name = reinterpret_cast<decltype(name)>(DEMAND_CAT(resolve_,DEMAND_NAME)(#name)); \
return name arg_call; \
}\
ret (*name)args = name##_thunk;
#else
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args; \
ret name##_impl args { \
name = (void*)DEMAND_CAT(resolve_,DEMAND_NAME)(#name); \
name arg_call; \
}\
ret (*name)args = name##_impl;
#endif // __cplusplus
#else
// Interface via a function
#define DEMAND_FUN(ret,name,args,arg_call) \
ret name args;
#endif
Then, the dynamic library itself:
lib1/lib1.pro
TEMPLATE = lib
SOURCES = lib1.c
HEADERS = lib1.h
INCLUDEPATH += ..
DEPENDPATH += ..
Instead of declaring the functions directly, we'll use DEMAND_FUN from demand_load.h. If DEMAND_LOAD_LIB1 is defined when the header is included, it will offer a demand-load interface to the library. If DEMAND_BUILD is defined, it'll define the demand-load thunks. If neither is defined, it will offer a normal interface.
We take care to undefine the implementation-specific macros so that the global namespace is not polluted. We can then include multiple libraries the project, each one individually selectable between demand- and non-demand loading.
lib1/lib1.h
#ifndef LIB_H
#define LIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define DEMAND_NAME LIB1
#ifdef DEMAND_LOAD_LIB1
#define DEMAND_LOAD
#endif
#include "demand_load.h"
#undef DEMAND_LOAD
DEMAND_FUN(int, My_Add, (int i, int j), (i,j))
DEMAND_FUN(int, My_Subtract, (int i, int j), (i,j))
#undef DEMAND_FUN
#undef DEMAND_NAME
#ifdef __cplusplus
}
#endif
#endif
The implementation is uncontroversial:
lib1/lib1.c
#include "lib1.h"
int My_Add(int i, int j) {
return i+j;
}
int My_Subtract(int i, int j) {
return i-j;
}
For the user of such a library, demand loading is reduced to defining one macro and using the thunk library lib1_demand instead of the dynamic library lib1.
main/main.pro
if (true) {
# Use demand-loaded lib1
DEFINES += DEMAND_LOAD_LIB1
LIBS += -L../lib1_demand -llib1_demand
} else {
# Use direct-loaded lib1
LIBS += -L../lib1 -llib1
}
QT = core
CONFIG += console c++11
CONFIG -= app_bundle
TARGET = demand-load-39291032
TEMPLATE = app
INCLUDEPATH += ..
DEPENDPATH += ..
SOURCES = main.cpp
main/main.cpp
#include "lib1/lib1.h"
#include <QtCore>
int main() {
auto a = My_Add(1, 2);
Q_ASSERT(a == 3);
auto b = My_Add(3, 4);
Q_ASSERT(b == 7);
auto c = My_Subtract(5, 7);
Q_ASSERT(c == -2);
}
Finally, the implementation of the thunk. Here we have a choice between using dlopen+dlsym or QLibrary. For simplicity, I opted for the latter:
lib1_demand/lib1_demand.pro
QT = core
TEMPLATE = lib
CONFIG += staticlib
INCLUDEPATH += ..
DEPENDPATH += ..
SOURCES = lib1_demand.cpp
HEADERS = ../demand_load.h
lib1_demand/lib1_demand.cpp
#define DEMAND_BUILD
#include "lib1/lib1.h"
#include <QLibrary>
void (* resolve_LIB1(const char * name))() {
auto f = QLibrary::resolve("../lib1/liblib1", name);
return f;
}
Quite apart from the process of loading a library into your C++ code (which Kuber Ober's answer covers just fine) the code that you are loading is wrong; even if you manage to load it, your code will crash! This is because you have a variable of type Tcl_Interp at file scope; that's wrong use of the Tcl library. Instead, the library provides only one way to obtain a handle to an interpreter context, Tcl_CreateInterp() (and a few other functions that are wrappers round it), and that returns a Tcl_Interp* that has already been initialised correctly. (Strictly, it actually returns a handle to what is effectively an internal subclass of Tcl_Interp, so you really can't usefully allocate one yourself.)
The correct usage of the library is this:
Tcl_FindExecutable(NULL); // Or argv[0] if you have it
Tcl_Interp *interp = Tcl_CreateInterp();
// And now, you can use the rest of the API as you see fit
That's for putting a Tcl interpreter inside your code. To do it the other way round, you create an int My_Init(Tcl_Interp*) function as you describe and it is used to tell you where the interpreter is, but then you wouldn't be asking how to load the code, as Tcl has reasonable support for that already.

Boost in Qt: Installation and Symbol(s) not found for architectures x86_64

I am back to Qt and C++ programming after a year break. I am trying to install boost library into Qt on Mac (10.9.4) and I am completely confused. This is what I did:
I installed boost using homebrew.
I see that hpp files are installed here:
/usr/local/Cellar/boost/1.55.0_2/include/boost
and libraries here:
/usr/local/Cellar/boost/1.55.0_2/lib
Now I start a new Qt console project.
the project file:
QT += core
QT -= gui
TARGET = testQt
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += /usr/local/Cellar/boost/1.55.0_2
And the main file:
#include <QCoreApplication>
#include <QtCore>
#include <iostream>
#include <QDebug>
#include <boost/regex.hpp>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::string line;
boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );
while (std::cin)
{
std::getline(std::cin, line);
boost::smatch matches;
if (boost::regex_match(line, matches, pat))
std::cout << matches[2] << std::endl;
}
return a.exec();
}
Not compiling. Issues:
Symbol(s) not found for architectures x86_64
linker command failed with exist code 1
Since I am absolutely noob with boost, did I do it right? If yes, why is it not compiling?
Thanks a lot!
You need to link with boost too!
LIBS += -L/usr/local/Cellar/boost/1.55.0_2/lib -lboost

How to compose multiple unit test result in a single txt file

I am using QTestLib Library and QTest for running my unit tests. I am working on windows 7 and using Qt 4.8 When I run my test using:
int main(int argc, char *argv[])
{
// Test gui widgets - 2 Spinboxes and 1 Combobox
QApplication a(argc, argv);
TestSpinBox testSpinBoxObj;
TestComboBox testComboBoxObj;
QTest::qExec(&testComboBoxObj, argc,argv);
QTest::qExec(&testSpinBoxObj, argc,argv);
return 0;
}
I get the output in the console:
Starting D:\Projects\Qt Learning\TestGui (1)\TestGui\debug\TestGui.exe...
********* Start testing of TestComboBox *********
Config: Using QTest library 4.8.1, Qt 4.8.1
PASS : TestComboBox::initTestCase()
PASS : TestComboBox::testComboBoxStepUp()
PASS : TestComboBox::testComboBoxStepDown()
PASS : TestComboBox::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped
********* Finished testing of TestComboBox *********
********* Start testing of TestSpinBox *********
Config: Using QTest library 4.8.1, Qt 4.8.1
PASS : TestSpinBox::initTestCase()
PASS : TestSpinBox::testSpinBoxStepUp()
PASS : TestSpinBox::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped
********* Finished testing of TestSpinBox *********
D:\Projects\Qt Learning\TestGui (1)\TestGui\debug\TestGui.exe exited with code 0
How to get the same in a single text file
There is -o filename option to specify output file. For each test object you can redirect output to own file and later concatenate them together.
QList<QObject *> objects;
objects << new TestSpinBox << new TestComboBox;
QString result;
foreach (QObject *o, objects) {
QTemporaryFile f;
f.open();
QStringList args = app.arguments();
args << "-o" << f.fileName();
QTest::qExec(o, args);
result += "\r\n" + f.readAll();
}
qDeleteAll(objects);

qDebug not showing __FILE__,__LINE__

According to qlogging.h
#define qDebug QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug
but when I use like this, file,line,function name not show.
qDebug()<< "abc"; // only show abc;
qDebug()<< ""; // show nothing;
I search for a while, it seems no one had my problem like above.
I use ubuntu14.04,g++ version 4.8.2, qt5.3 build from git.
You can reformat from default output format.
This function was introduced in Qt 5.0.
The line number does not output because the default message pattern is "%{if-category}%{category}: %{endif}%{message}". This format means that the default outputting format is not including metadata like a line number or file name.
% cat logtest.pro
TEMPLATE = app
TARGET = logtest
mac:CONFIG-=app_bundle
SOURCES += main.cpp
% cat main.cpp
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
qSetMessagePattern("%{file}(%{line}): %{message}");
QCoreApplication a(argc, argv);
qDebug() << "my output";
return 0;
}
% qmake && make
% ./logtest
main.cpp(8): my output
You can also use QT_MESSAGE_PATTERN environment variable for setting the message pattern without calling qSetMessagePattern().
See reference for other placeholder. http://qt-project.org/doc/qt-5/qtglobal.html#qSetMessagePattern
If you dig in Qt history you can find out that the __FILE__ and __FUNCTION__ are logged only in debug builds since 1 Oct 2014. The git commit hash is d78fb442d750b33afe2e41f31588ec94cf4023ad. The commit message states:
Logging: Disable tracking of debug source info for release builds
Tracking the file, line, function means the information has to be
stored in the binaries, enlarging the size. It also might be a
surprise to some commercial customers that their internal file &
function names are 'leaked'. Therefore we enable it for debug builds
only.
Here's a simple example of how you might use the captured QMessageLogContext data in a custom message handler installed using qInstallMessageHandler. I didn't output the category or version members because they didn't seem useful. If desired you could also log to a file this way.
#include <QDebug>
#include <QString>
#include <QDateTime>
#include <iostream>
void verboseMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
static const char* typeStr[] = {"[ Debug]", "[ Warning]", "[Critical]", "[ Fatal]" };
if(type <= QtFatalMsg)
{
QByteArray localMsg = msg.toLocal8Bit();
QString contextString(QStringLiteral("(%1, %2, %3)")
.arg(context.file)
.arg(context.function)
.arg(context.line));
QString timeStr(QDateTime::currentDateTime().toString("dd-MM-yy HH:mm:ss:zzz"));
std::cerr << timeStr.toLocal8Bit().constData() << " - "
<< typeStr[type] << " "
<< contextString.toLocal8Bit().constData() << " "
<< localMsg.constData() << std::endl;
if(type == QtFatalMsg)
{
abort();
}
}
}
int main()
{
//Use default handler
qDebug() << "default handler";
qWarning() << "default handler";
qCritical() << "default handler";
//Install verbose handler
qInstallMessageHandler(verboseMessageHandler);
qDebug() << "verbose handler";
qWarning() << "verbose handler";
qCritical() << "verbose handler";
//Restore default handler
qInstallMessageHandler(0);
qDebug() << "default handler";
qWarning() << "default handler";
qCritical() << "default handler";
return 0;
}
You can use standard C++'s __LINE__ and __FILE__. Also, take a look at What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__ SO question. If you use GCC, you can write __PRETTY_FUNCTION__ to get information about function from where the code executes. Just prepare debug-define you like.
For example, here is small compilable application:
#include <QApplication>
#include <QDebug>
#include <iostream>
// Qt-way
#define MyDBG (qDebug()<<__FILE__<<__LINE__<<__PRETTY_FUNCTION__)
// GCC
#define MyStdDBG (std::cout<< __FILE__<<":"<<__LINE__<<" in "<<__PRETTY_FUNCTION__<<std::endl)
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Qt-way
MyDBG;
MyDBG << "Something happened!";
// GCC
MyStdDBG;
return a.exec();
}
It gives next output:
../path/main.cpp 14 int main(int, char**)
../path/main.cpp 15 int main(int, char**) Something happened!
../path/main.cpp:18 in int main(int, char**)
UPD: Added pure C++-way to output.
I think you need to define:
#define qDebug() QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug()
and use it as
qDebug() << "abc";
or
#define qDebug QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug()
and use it as:
qDebug << "abc";
According to documentation qDebug() is already a macro to QMessageLogger(). Default Message handler prints only the message to stderr. I think you might want to use qInstallMessageHandler() to install your own message handler, that uses the context
Edit:
There is a relevant section in a manual, that describes this issue. In Qt4 context variable was not passed to installed message handler, so this solution is Qt5+ only. Default message handler does not make use of passed in context, but you can easily install your own, it's just a function pointer. There is even an example in the manual.
This depends on your Qt version number, whether you are using a debug build or a release build of Qt, and whether you have customized Qt message handling in your application.
According to Qt 5.4 documentation written in source code "qlogging.cpp":
QMessageLogger is used to generate messages for the Qt logging framework. Usually one uses
it through qDebug(), qWarning(), qCritical, or qFatal() functions,
which are actually macros: For example qDebug() expands to
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug()
for debug builds, and QMessageLogger(0, 0, 0).debug() for release builds.
So if you do not see file, line and function name information in your output, very likely you are using a release version of Qt.
If you still want to see the file, line and function name information in your output with a release version of Qt, there are several ways of achieving it, as very well explained in some of the previous answers.
If you wonder how to get the debug context in a non-debug build: Define QT_MESSAGELOGCONTEXT while compiling your code, and the information won't be stripped:
http://doc.qt.io/qt-5/qmessagelogcontext.html

QT Systray icon appears next to launcher on Ubuntu instead of on the panel

I am new to QT and need to build an app with an app-indicator. As QT seems easier than GTK+, I am making it in QT.
I would mention that I have sni-qt installed and app indicators of vlc and skype appear normal on the panel. I am using QT5 on Ubuntu 13.04 64-bit.
I followed this tutorial step by step: http://qt-project.org/doc/qt-4.8/desktop-systray.html
But when I run it, here's how it appears (The cross is the icon I am using):
How do I fix this?
I'm afraid that Qt5 is not supported by sni-qt at the moment, so you either have to wait for a new release that will support it, or code it using gtk+ and libappindicator using this guide. There are even examples for various of languages. Since Qt5 also distributes GLib events that makes the integration a lot more easier. First you need to find out whether you're running on Unity or not (to support more desktops than just unity), that you can do by retrieving XDG_CURRENT_DESKTOP environment variable and if it returns Unity you create appindicator, otherwise create QSystemTrayIcon.
First you need to include required headers:
#undefine signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
}
#define signals public
Since app-indicator directly uses "signals" name we need to undefine the default Qt "keyword" signals which normally translates to public. Then, since we're coding C++ and libappindicator is coded in C we need to use extern "C" not to use C++ name mangling.
Next create the AppIndicator/QSystemTrayIcon based on what desktop are we on:
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if (is_unity) {
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
} else {
QSystemTrayIcon *icon;
QMenu *m = new QMenu();
m->addAction(tr("Quit"), qApp, SLOT(quit()));
}
Finally we create the proxy function to call Qt signal from it, to declare the function we need to use extern "C" so there will not be any undefined behaviour.
extern "C" {
void quitIndicator(GtkMenu *, gpointer);
}
Now the proxy function:
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
Just wanted to add, for anyone that is using Qt and trying to show a app indicator in Ubuntu 13+ as others have mentioned sni-qt is not working, I was able to use the above reply to make a Qt app that works, still trying to get the icon to change and show popup messages, but this is a great start, once i get the icon and message to work i might post it out on my site Voidrealms.com:
Be sure to do sudo apt-get install libappindicator-dev
Make a new project with a QDialog in it and modify as seen below:
Pro file:
#-------------------------------------------------
#
# Project created by QtCreator 2014-03-28T20:34:54
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = PluginServiceGUI
TEMPLATE = app
# includes for the libappindicator
# /usr/lib/x86_64-linux-gnu libglib-2.0.a
INCLUDEPATH += "/usr/include/libappindicator-0.1"
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/atk-1.0"
LIBS += -L/usr/lib/x86_64-linux-gnu -lgobject-2.0
LIBS += -L/usr/lib/x86_64-linux-gnu -lappindicator
LIBS += -L/usr/lib/x86_64-linux-gnu -lgtk-x11-2.0
#These seem to not be needed
#LIBS += -L/usr/lib/x86_64-linux-gnu -lcairo
#LIBS += -L/usr/lib/x86_64-linux-gnu -lpango-1.0
#LIBS += -L/usr/lib/x86_64-linux-gnu -lglib-2.0
# end incudes for libappindicator
SOURCES += main.cpp\
dialog.cpp
HEADERS += dialog.h
FORMS += dialog.ui
RESOURCES += \
resources.qrc
In the main.cpp
#include "dialog.h"
#include <QApplication>
#include <QtGui>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QMenu>
// http://stackoverflow.com/questions/17193307/qt-systray-icon-appears-next-to-launcher-on-ubuntu-instead-of-on-the-panel
// requires libappindicator-dev
// sudo apt-get install libappindicator-dev
// installs the headers in: /usr/include/libappindicator-0.1/libappindicator
#undef signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
void quitIndicator(GtkMenu *, gpointer);
}
#define signals public
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
void ShowUnityAppIndicator()
{
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
}
void ShowQtSysTray(QApplication* app, QDialog* dialog)
{
Q_INIT_RESOURCE(resources);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(0, QObject::tr("Systray"),
QObject::tr("I couldn't detect any system tray "
"on this system."));
}
QApplication::setQuitOnLastWindowClosed(false);
QSystemTrayIcon* trayIcon = new QSystemTrayIcon(dialog);
QAction* Action = new QAction("hello", dialog);
QMenu* trayIconMenu = new QMenu(dialog);
trayIconMenu->addAction("Quit", app, SLOT(quit()));
trayIconMenu->addAction(Action);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon (":/icons/Icons/accept.png"));
trayIcon->show();
trayIcon->showMessage("Title","Message");
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
//Determine the desktop type
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if(is_unity)
{
ShowUnityAppIndicator();
}
else
{
//Show the SystemTrayIcon the Qt way
ShowQtSysTray(&a, &w);
}
// w.show();
return a.exec();
}

Resources