2015-01-29 21:56:53 +08:00
|
|
|
#include "systemtrayicon.h"
|
|
|
|
#include <QString>
|
|
|
|
#include <QSystemTrayIcon>
|
2015-01-30 00:33:17 +08:00
|
|
|
#include <QMenu>
|
|
|
|
#include <QFile>
|
2015-01-29 21:56:53 +08:00
|
|
|
#include <QDebug>
|
2015-01-30 00:33:17 +08:00
|
|
|
#include "src/misc/settings.h"
|
2015-01-29 21:56:53 +08:00
|
|
|
|
|
|
|
SystemTrayIcon::SystemTrayIcon()
|
|
|
|
{
|
|
|
|
QString desktop = getenv("XDG_CURRENT_DESKTOP");
|
|
|
|
if (false);
|
2015-02-22 05:55:54 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
|
|
|
|
else if (true)
|
|
|
|
{
|
2015-02-22 07:47:18 +08:00
|
|
|
backendType = SystrayBackendType::StatusNotifier;
|
|
|
|
gtk_init(nullptr, nullptr);
|
|
|
|
snMenu = gtk_menu_new();
|
|
|
|
QString settingsDir = Settings::getSettingsDirPath();
|
|
|
|
QFile iconFile(settingsDir+"/icon.png");
|
|
|
|
if (iconFile.open(QIODevice::Truncate | QIODevice::WriteOnly))
|
|
|
|
{
|
|
|
|
QFile resIconFile(":/img/icon.png");
|
|
|
|
if (resIconFile.open(QIODevice::ReadOnly))
|
|
|
|
iconFile.write(resIconFile.readAll());
|
|
|
|
resIconFile.close();
|
|
|
|
iconFile.close();
|
|
|
|
}
|
|
|
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file((settingsDir+"/icon.png").toStdString().c_str(), 0);
|
2015-02-22 05:55:54 +08:00
|
|
|
statusNotifier = status_notifier_new_from_pixbuf("qtox",
|
2015-02-22 07:47:18 +08:00
|
|
|
STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS, pixbuf);
|
2015-02-22 05:55:54 +08:00
|
|
|
status_notifier_register(statusNotifier);
|
2015-02-22 07:47:18 +08:00
|
|
|
GtkWidget* item = gtk_menu_item_new_with_label("Test");
|
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(snMenu), item);
|
|
|
|
gtk_widget_show(item);
|
2015-02-22 05:55:54 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-01-29 21:56:53 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
|
|
|
|
else if (desktop.toLower() == "unity")
|
|
|
|
{
|
2015-01-30 00:33:17 +08:00
|
|
|
QString settingsDir = Settings::getSettingsDirPath();
|
|
|
|
QFile iconFile(settingsDir+"/icon.png");
|
|
|
|
if (iconFile.open(QIODevice::Truncate | QIODevice::WriteOnly))
|
|
|
|
{
|
|
|
|
QFile resIconFile(":/img/icon.png");
|
|
|
|
if (resIconFile.open(QIODevice::ReadOnly))
|
|
|
|
iconFile.write(resIconFile.readAll());
|
|
|
|
resIconFile.close();
|
|
|
|
iconFile.close();
|
|
|
|
}
|
2015-01-29 21:56:53 +08:00
|
|
|
backendType = SystrayBackendType::Unity;
|
|
|
|
unityMenu = gtk_menu_new();
|
2015-01-30 00:33:17 +08:00
|
|
|
unityIndicator = app_indicator_new_with_path(
|
|
|
|
"qTox",
|
|
|
|
"icon",
|
|
|
|
APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
|
|
|
|
settingsDir.toStdString().c_str()
|
|
|
|
);
|
|
|
|
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
|
2015-01-29 21:56:53 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-02-08 02:40:49 +08:00
|
|
|
else if (desktop.toLower() == "kde"
|
|
|
|
&& getenv("KDE_SESSION_VERSION") == QString("5"))
|
|
|
|
{
|
|
|
|
backendType = SystrayBackendType::KDE5;
|
|
|
|
qWarning() << "SystemTrayIcon: Detected a KDE5 session, disabling the icon";
|
|
|
|
}
|
2015-01-29 21:56:53 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
qtIcon = new QSystemTrayIcon;
|
|
|
|
backendType = SystrayBackendType::Qt;
|
2015-01-30 00:44:23 +08:00
|
|
|
connect(qtIcon, &QSystemTrayIcon::activated, this, &SystemTrayIcon::activated);
|
2015-01-29 21:56:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:38:08 +08:00
|
|
|
SystemTrayIcon::~SystemTrayIcon()
|
|
|
|
{
|
|
|
|
qDebug() << "Deleting SystemTrayIcon";
|
|
|
|
}
|
|
|
|
|
2015-01-30 00:33:17 +08:00
|
|
|
QString SystemTrayIcon::extractIconToFile(QIcon icon, QString name)
|
|
|
|
{
|
|
|
|
QString iconPath;
|
2015-01-30 00:44:23 +08:00
|
|
|
(void) icon;
|
|
|
|
(void) name;
|
2015-01-30 00:33:17 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
|
|
|
|
iconPath = Settings::getSettingsDirPath()+"/"+name+".png";
|
|
|
|
QSize iconSize = icon.actualSize(QSize{64,64});
|
|
|
|
icon.pixmap(iconSize).save(iconPath);
|
|
|
|
#endif
|
|
|
|
return iconPath;
|
|
|
|
}
|
|
|
|
|
2015-01-29 21:56:53 +08:00
|
|
|
void SystemTrayIcon::setContextMenu(QMenu* menu)
|
|
|
|
{
|
|
|
|
if (false);
|
2015-02-22 05:55:54 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
|
2015-02-22 07:47:18 +08:00
|
|
|
else if (backendType == SystrayBackendType::StatusNotifier)
|
2015-02-22 05:55:54 +08:00
|
|
|
{
|
2015-02-22 07:47:18 +08:00
|
|
|
void (*callbackClick)(StatusNotifier*, gint, gint, gpointer) =
|
2015-02-22 05:55:54 +08:00
|
|
|
[](StatusNotifier*, gint, gint, gpointer data)
|
|
|
|
{
|
|
|
|
((SystemTrayIcon*)data)->activated(QSystemTrayIcon::Trigger);
|
|
|
|
};
|
2015-02-22 07:47:18 +08:00
|
|
|
g_signal_connect(statusNotifier, "activate", G_CALLBACK(callbackClick), this);
|
|
|
|
|
|
|
|
for (QAction* a : menu->actions())
|
|
|
|
{
|
|
|
|
QString aText = a->text().replace('&',"");
|
|
|
|
GtkWidget* item;
|
|
|
|
if (a->isSeparator())
|
|
|
|
item = gtk_menu_item_new();
|
|
|
|
else if (a->icon().isNull())
|
|
|
|
item = gtk_menu_item_new_with_label(aText.toStdString().c_str());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QString iconPath = extractIconToFile(a->icon(),"iconmenu"+a->icon().name());
|
|
|
|
GtkWidget* image = gtk_image_new_from_file(iconPath.toStdString().c_str());
|
|
|
|
item = gtk_image_menu_item_new_with_label(aText.toStdString().c_str());
|
|
|
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
|
|
|
|
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item),TRUE);
|
|
|
|
}
|
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(snMenu), item);
|
|
|
|
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a)
|
|
|
|
{
|
|
|
|
((QAction*)a)->activate(QAction::Trigger);
|
|
|
|
};
|
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
}
|
|
|
|
void (*callbackMenu)(StatusNotifier*, gint, gint, gpointer) =
|
|
|
|
[](StatusNotifier*, gint, gint, gpointer data)
|
|
|
|
{
|
|
|
|
gtk_widget_show_all(((SystemTrayIcon*)data)->snMenu);
|
|
|
|
gtk_menu_popup(GTK_MENU(((SystemTrayIcon*)data)->snMenu), 0, 0, 0, 0, 3, gtk_get_current_event_time());
|
|
|
|
};
|
|
|
|
g_signal_connect(statusNotifier, "context-menu", G_CALLBACK(callbackMenu), this);
|
2015-02-22 05:55:54 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-01-29 21:56:53 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
|
|
|
|
else if (backendType == SystrayBackendType::Unity)
|
|
|
|
{
|
2015-01-30 00:33:17 +08:00
|
|
|
for (QAction* a : menu->actions())
|
|
|
|
{
|
|
|
|
QString aText = a->text().replace('&',"");
|
|
|
|
GtkWidget* item;
|
|
|
|
if (a->isSeparator())
|
|
|
|
item = gtk_menu_item_new();
|
|
|
|
else if (a->icon().isNull())
|
|
|
|
item = gtk_menu_item_new_with_label(aText.toStdString().c_str());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QString iconPath = extractIconToFile(a->icon(),"iconmenu"+a->icon().name());
|
|
|
|
GtkWidget* image = gtk_image_new_from_file(iconPath.toStdString().c_str());
|
|
|
|
item = gtk_image_menu_item_new_with_label(aText.toStdString().c_str());
|
|
|
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
|
|
|
|
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item),TRUE);
|
|
|
|
}
|
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(unityMenu), item);
|
|
|
|
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a)
|
|
|
|
{
|
|
|
|
((QAction*)a)->activate(QAction::Trigger);
|
|
|
|
};
|
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
}
|
|
|
|
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
|
|
|
|
DbusmenuServer *menuServer;
|
|
|
|
DbusmenuMenuitem *rootMenuItem;
|
|
|
|
g_object_get(unityIndicator, "dbus-menu-server", &menuServer, NULL);
|
|
|
|
g_object_get(menuServer, "root-node", &rootMenuItem, NULL);
|
|
|
|
void (*callback)(DbusmenuMenuitem *, gpointer) =
|
|
|
|
[](DbusmenuMenuitem *, gpointer data)
|
|
|
|
{
|
|
|
|
((SystemTrayIcon*)data)->activated(QSystemTrayIcon::Unknown);
|
|
|
|
};
|
|
|
|
g_signal_connect(rootMenuItem, "about-to-show", G_CALLBACK(callback), this);
|
2015-01-29 21:56:53 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-02-08 02:40:49 +08:00
|
|
|
else if (backendType == SystrayBackendType::Qt)
|
2015-01-29 21:56:53 +08:00
|
|
|
{
|
|
|
|
qtIcon->setContextMenu(menu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemTrayIcon::show()
|
|
|
|
{
|
|
|
|
setVisible(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemTrayIcon::hide()
|
|
|
|
{
|
|
|
|
setVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemTrayIcon::setVisible(bool newState)
|
|
|
|
{
|
|
|
|
if (false);
|
2015-02-22 05:55:54 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
|
2015-02-22 07:47:18 +08:00
|
|
|
else if (backendType == SystrayBackendType::StatusNotifier)
|
2015-02-22 05:55:54 +08:00
|
|
|
{
|
|
|
|
if (newState)
|
|
|
|
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_ACTIVE);
|
|
|
|
else
|
|
|
|
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_PASSIVE);
|
|
|
|
}
|
|
|
|
#endif
|
2015-01-29 21:56:53 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
|
|
|
|
else if (backendType == SystrayBackendType::Unity)
|
|
|
|
{
|
2015-01-30 00:33:17 +08:00
|
|
|
if (newState)
|
|
|
|
app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_ACTIVE);
|
|
|
|
else
|
|
|
|
app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_PASSIVE);
|
2015-01-29 21:56:53 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-02-08 02:40:49 +08:00
|
|
|
else if (backendType == SystrayBackendType::Qt)
|
2015-01-29 21:56:53 +08:00
|
|
|
{
|
|
|
|
if (newState)
|
|
|
|
qtIcon->show();
|
|
|
|
else
|
|
|
|
qtIcon->hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemTrayIcon::setIcon(QIcon &&icon)
|
|
|
|
{
|
|
|
|
if (false);
|
2015-02-22 05:55:54 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
|
2015-02-22 07:47:18 +08:00
|
|
|
else if (backendType == SystrayBackendType::StatusNotifier)
|
2015-02-22 05:55:54 +08:00
|
|
|
{
|
2015-02-22 07:48:06 +08:00
|
|
|
void (*callbackFreeImage)(guchar*, gpointer) =
|
|
|
|
[](guchar*, gpointer image)
|
|
|
|
{
|
|
|
|
delete reinterpret_cast<QImage*>(image);
|
|
|
|
};
|
|
|
|
QImage* image = new QImage(icon.pixmap(64, 64).toImage());
|
|
|
|
if (image->format() != QImage::Format_ARGB32_Premultiplied)
|
|
|
|
*image = image->convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
|
|
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
|
|
|
|
8, image->width(), image->height(),
|
|
|
|
image->bytesPerLine(), callbackFreeImage, image);
|
2015-02-22 05:55:54 +08:00
|
|
|
status_notifier_set_from_pixbuf(statusNotifier, STATUS_NOTIFIER_ICON, pixbuf);
|
|
|
|
}
|
|
|
|
#endif
|
2015-01-29 21:56:53 +08:00
|
|
|
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
|
|
|
|
else if (backendType == SystrayBackendType::Unity)
|
|
|
|
{
|
2015-01-30 00:33:17 +08:00
|
|
|
// Alternate file names or appindicator will not reload the icon
|
|
|
|
if (app_indicator_get_icon(unityIndicator) == QString("icon2"))
|
|
|
|
{
|
|
|
|
extractIconToFile(icon,"icon");
|
|
|
|
app_indicator_set_icon_full(unityIndicator, "icon","qtox");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
extractIconToFile(icon,"icon2");
|
|
|
|
app_indicator_set_icon_full(unityIndicator, "icon2","qtox");
|
|
|
|
}
|
2015-01-29 21:56:53 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-02-08 02:40:49 +08:00
|
|
|
else if (backendType == SystrayBackendType::Qt)
|
2015-01-29 21:56:53 +08:00
|
|
|
{
|
|
|
|
qtIcon->setIcon(icon);
|
|
|
|
}
|
|
|
|
}
|