Compare commits

...

2 Commits

Author SHA1 Message Date
Alf Gaida
4ca5973d60 Adding upstream version 0.9.0+20151025. 2015-10-31 01:09:15 +01:00
Alf Gaida
88b1696810 Adding upstream version 0.9.0+20150924. 2015-09-25 19:21:58 +02:00
15 changed files with 1253 additions and 13 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
build
*.kdev4

View File

@ -5,7 +5,6 @@ Upstream Authors:
Copyright: Copyright:
Copyright (c) 2013-2014 LXQt team Copyright (c) 2013-2014 LXQt team
License: GPL-2 and LGPL-2.1+ License: LGPL-2.1+
The full text of the licenses can be found in the 'COPYING' file. The full text of the licenses can be found in the 'COPYING' file.
src/qiconloader_p.h is under LGPL-2.1 or 3 with Digia Qt LGPL Exception version 1.1
Based on source code from the Qt 4.8 Project by Digia Plc

View File

@ -7,6 +7,8 @@ set(CMAKE_AUTOMOC ON)
find_package(Qt5Widgets REQUIRED QUIET) find_package(Qt5Widgets REQUIRED QUIET)
find_package(Qt5LinguistTools REQUIRED QUIET) find_package(Qt5LinguistTools REQUIRED QUIET)
find_package(Qt5DBus REQUIRED QUIET)
find_package(dbusmenu-qt5 REQUIRED QUIET)
find_package(lxqt REQUIRED QUIET) find_package(lxqt REQUIRED QUIET)

View File

@ -0,0 +1,25 @@
Digia Qt LGPL Exception version 1.1
===================================
As an additional permission to the GNU Lesser General Public License version
2.1, the object code form of a "work that uses the Library" may incorporate
material from a header file that is part of the Library. You may distribute
such object code under terms of your choice, provided that:
(i) the header files of the Library have not been modified; and
(ii) the incorporated material is limited to numerical parameters, data
structure layouts, accessors, macros, inline functions and
templates; and
(iii) you comply with the terms of Section 6 of the GNU Lesser General
Public License version 2.1.
Moreover, you may apply this exception to a modified version of the Library,
provided that such modification does not involve copying material from the
Library into the modified Library's header files unless such material is
limited to (i) numerical parameters; (ii) data structure layouts;
(iii) accessors; and (iv) small macros, templates and inline functions of
five lines or less in length.
Furthermore, you are not required to apply this additional permission to a
modified version of the Library.

View File

@ -3,15 +3,34 @@ include_directories(
"${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"
) )
set(qtlxqt_HDRS
lxqtplatformtheme.h
lxqtsystemtrayicon.h
statusnotifieritem/statusnotifieritem.h
statusnotifieritem/dbustypes.h
)
set(qtlxqt_SRCS set(qtlxqt_SRCS
main.cpp main.cpp
lxqtplatformtheme.cpp lxqtplatformtheme.cpp
lxqtsystemtrayicon.cpp
statusnotifieritem/statusnotifieritem.cpp
statusnotifieritem/dbustypes.cpp
) )
add_library(qtlxqt SHARED ${qtlxqt_SRCS}) qt5_add_dbus_adaptor(qtlxqt_SRCS
statusnotifieritem/org.kde.StatusNotifierItem.xml
statusnotifieritem/statusnotifieritem.h
StatusNotifierItem
)
add_library(qtlxqt SHARED ${qtlxqt_HDRS} ${qtlxqt_SRCS})
target_link_libraries(qtlxqt target_link_libraries(qtlxqt
Qt5::Widgets Qt5::Widgets
Qt5::DBus
dbusmenu-qt5
lxqt
) )
# there is no standard way to get the plugin dir of Qt5 with cmake # there is no standard way to get the plugin dir of Qt5 with cmake

View File

@ -291,13 +291,10 @@ QVariant LXQtPlatformTheme::themeHint(ThemeHint hint) const {
break; break;
case ContextMenuOnMouseRelease: case ContextMenuOnMouseRelease:
break; break;
#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
// this was introduced in Qt 5.3.
case MousePressAndHoldInterval: case MousePressAndHoldInterval:
break; break;
case MouseDoubleClickDistance: case MouseDoubleClickDistance:
break; break;
#endif
default: default:
break; break;
} }

View File

@ -28,6 +28,8 @@
#ifndef LXQTPLATFORMTHEME_H #ifndef LXQTPLATFORMTHEME_H
#define LXQTPLATFORMTHEME_H #define LXQTPLATFORMTHEME_H
#include "lxqtsystemtrayicon.h"
#include <qpa/qplatformtheme.h> // this private header is subject to changes #include <qpa/qplatformtheme.h> // this private header is subject to changes
#include <QtGlobal> #include <QtGlobal>
#include <QVariant> #include <QVariant>
@ -54,6 +56,18 @@ public:
virtual QVariant themeHint(ThemeHint hint) const; virtual QVariant themeHint(ThemeHint hint) const;
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const
{
auto trayIcon = new LXQtSystemTrayIcon;
if (trayIcon->isSystemTrayAvailable())
return trayIcon;
else
{
delete trayIcon;
return nullptr;
}
}
// virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const; // virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
// virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, // virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
// QPlatformTheme::IconOptions iconOptions = 0) const; // QPlatformTheme::IconOptions iconOptions = 0) const;

382
src/lxqtsystemtrayicon.cpp Normal file
View File

@ -0,0 +1,382 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org/
*
* Copyright: 2015 LXQt team
* Authors:
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include "lxqtsystemtrayicon.h"
#include <QAction>
#include <QIcon>
#include <QMenu>
#include <QRect>
#include <QApplication>
#include <QDBusMetaType>
#include <QDBusInterface>
SystemTrayMenu::SystemTrayMenu()
: QPlatformMenu(),
m_tag(0),
m_menu(new QMenu())
{
connect(m_menu.data(), &QMenu::aboutToShow, this, &QPlatformMenu::aboutToShow);
connect(m_menu.data(), &QMenu::aboutToHide, this, &QPlatformMenu::aboutToHide);
}
SystemTrayMenu::~SystemTrayMenu()
{
if (m_menu)
m_menu->deleteLater();
}
QPlatformMenuItem *SystemTrayMenu::createMenuItem() const
{
return new SystemTrayMenuItem();
}
void SystemTrayMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
{
if (SystemTrayMenuItem *ours = qobject_cast<SystemTrayMenuItem*>(menuItem))
{
bool inserted = false;
if (SystemTrayMenuItem *oursBefore = qobject_cast<SystemTrayMenuItem*>(before))
{
for (auto it = m_items.begin(); it != m_items.end(); ++it)
{
if (*it == oursBefore)
{
m_items.insert(it, ours);
if (m_menu)
m_menu->insertAction(oursBefore->action(), ours->action());
inserted = true;
break;
}
}
}
if (!inserted)
{
m_items.append(ours);
if (m_menu)
m_menu->addAction(ours->action());
}
}
}
QPlatformMenuItem *SystemTrayMenu::menuItemAt(int position) const
{
if (position < m_items.size())
return m_items.at(position);
return nullptr;
}
QPlatformMenuItem *SystemTrayMenu::menuItemForTag(quintptr tag) const
{
auto it = std::find_if(m_items.constBegin(), m_items.constEnd(), [tag] (SystemTrayMenuItem *item)
{
return item->tag() == tag;
});
if (it != m_items.constEnd())
return *it;
return nullptr;
}
void SystemTrayMenu::removeMenuItem(QPlatformMenuItem *menuItem)
{
if (SystemTrayMenuItem *ours = qobject_cast<SystemTrayMenuItem*>(menuItem))
{
m_items.removeOne(ours);
if (ours->action() && m_menu)
m_menu->removeAction(ours->action());
}
}
void SystemTrayMenu::setEnabled(bool enabled)
{
if (!m_menu)
return;
m_menu->setEnabled(enabled);
}
void SystemTrayMenu::setIcon(const QIcon &icon)
{
if (!m_menu)
return;
m_menu->setIcon(icon);
}
void SystemTrayMenu::setTag(quintptr tag)
{
m_tag = tag;
}
void SystemTrayMenu::setText(const QString &text)
{
if (!m_menu)
return;
m_menu->setTitle(text);
}
void SystemTrayMenu::setVisible(bool visible)
{
if (!m_menu)
return;
m_menu->setVisible(visible);
}
void SystemTrayMenu::syncMenuItem(QPlatformMenuItem *)
{
// Nothing to do
}
void SystemTrayMenu::syncSeparatorsCollapsible(bool enable)
{
if (!m_menu)
return;
m_menu->setSeparatorsCollapsible(enable);
}
quintptr SystemTrayMenu::tag() const
{
return m_tag;
}
QMenu *SystemTrayMenu::menu() const
{
return m_menu.data();
}
SystemTrayMenuItem::SystemTrayMenuItem()
: QPlatformMenuItem(),
m_tag(0),
m_action(new QAction(this))
{
connect(m_action, &QAction::triggered, this, &QPlatformMenuItem::activated);
connect(m_action, &QAction::hovered, this, &QPlatformMenuItem::hovered);
}
SystemTrayMenuItem::~SystemTrayMenuItem()
{
}
void SystemTrayMenuItem::setCheckable(bool checkable)
{
m_action->setCheckable(checkable);
}
void SystemTrayMenuItem::setChecked(bool isChecked)
{
m_action->setChecked(isChecked);
}
void SystemTrayMenuItem::setEnabled(bool enabled)
{
m_action->setEnabled(enabled);
}
void SystemTrayMenuItem::setFont(const QFont &font)
{
m_action->setFont(font);
}
void SystemTrayMenuItem::setIcon(const QIcon &icon)
{
m_action->setIcon(icon);
}
void SystemTrayMenuItem::setIsSeparator(bool isSeparator)
{
m_action->setSeparator(isSeparator);
}
void SystemTrayMenuItem::setMenu(QPlatformMenu *menu)
{
if (SystemTrayMenu *ourMenu = qobject_cast<SystemTrayMenu *>(menu))
m_action->setMenu(ourMenu->menu());
}
void SystemTrayMenuItem::setRole(QPlatformMenuItem::MenuRole)
{
}
void SystemTrayMenuItem::setShortcut(const QKeySequence &shortcut)
{
m_action->setShortcut(shortcut);
}
void SystemTrayMenuItem::setTag(quintptr tag)
{
m_tag = tag;
}
void SystemTrayMenuItem::setText(const QString &text)
{
m_action->setText(text);
}
void SystemTrayMenuItem::setVisible(bool isVisible)
{
m_action->setVisible(isVisible);
}
void SystemTrayMenuItem::setIconSize(int)
{
}
quintptr SystemTrayMenuItem::tag() const
{
return m_tag;
}
QAction *SystemTrayMenuItem::action() const
{
return m_action;
}
LXQtSystemTrayIcon::LXQtSystemTrayIcon()
: QPlatformSystemTrayIcon(),
mSni(nullptr)
{
// register types
qDBusRegisterMetaType<ToolTip>();
qDBusRegisterMetaType<IconPixmap>();
qDBusRegisterMetaType<IconPixmapList>();
}
LXQtSystemTrayIcon::~LXQtSystemTrayIcon()
{
}
void LXQtSystemTrayIcon::init()
{
if (!mSni)
{
mSni = new StatusNotifierItem(QString::number(QCoreApplication::applicationPid()), this);
mSni->setTitle(QApplication::applicationDisplayName());
// default menu
QPlatformMenu *menu = createMenu();
menu->setParent(this);
QPlatformMenuItem *menuItem = menu->createMenuItem();
menuItem->setParent(menu);
menuItem->setText(tr("Quit"));
menuItem->setIcon(QIcon::fromTheme("application-exit"));
connect(menuItem, &QPlatformMenuItem::activated, qApp, &QApplication::quit);
menu->insertMenuItem(menuItem, nullptr);
updateMenu(menu);
connect(mSni, &StatusNotifierItem::activateRequested, [this](const QPoint &)
{
emit activated(QPlatformSystemTrayIcon::Trigger);
});
connect(mSni, &StatusNotifierItem::secondaryActivateRequested, [this](const QPoint &)
{
emit activated(QPlatformSystemTrayIcon::MiddleClick);
});
}
}
void LXQtSystemTrayIcon::cleanup()
{
delete mSni;
mSni = nullptr;
}
void LXQtSystemTrayIcon::updateIcon(const QIcon &icon)
{
if (!mSni)
return;
if (icon.name().isEmpty())
{
mSni->setIconByPixmap(icon);
mSni->setToolTipIconByPixmap(icon);
}
else
{
mSni->setIconByName(icon.name());
mSni->setToolTipIconByName(icon.name());
}
}
void LXQtSystemTrayIcon::updateToolTip(const QString &tooltip)
{
if (!mSni)
return;
mSni->setToolTipTitle(tooltip);
}
void LXQtSystemTrayIcon::updateMenu(QPlatformMenu *menu)
{
if (!mSni)
return;
if (SystemTrayMenu *ourMenu = qobject_cast<SystemTrayMenu*>(menu))
mSni->setContextMenu(ourMenu->menu());
}
QPlatformMenu *LXQtSystemTrayIcon::createMenu() const
{
return new SystemTrayMenu();
}
QRect LXQtSystemTrayIcon::geometry() const
{
// StatusNotifierItem doesn't provide the geometry
return QRect();
}
void LXQtSystemTrayIcon::showMessage(const QString &title, const QString &msg,
const QIcon &icon, MessageIcon, int secs)
{
if (!mSni)
return;
mSni->showMessage(title, msg, icon.name(), secs);
}
bool LXQtSystemTrayIcon::isSystemTrayAvailable() const
{
QDBusInterface systrayHost("org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher",
"org.kde.StatusNotifierWatcher");
return systrayHost.isValid() && systrayHost.property("IsStatusNotifierHostRegistered").toBool();
}
bool LXQtSystemTrayIcon::supportsMessages() const
{
return true;
}

124
src/lxqtsystemtrayicon.h Normal file
View File

@ -0,0 +1,124 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org/
*
* Copyright: 2015 LXQt team
* Authors:
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#ifndef LXQTSYSTEMTRAYICON_H
#define LXQTSYSTEMTRAYICON_H
#include <qpa/qplatformmenu.h>
#include <qpa/qplatformsystemtrayicon.h>
#include "statusnotifieritem/statusnotifieritem.h"
class SystemTrayMenuItem;
class QAction;
class QMenu;
class SystemTrayMenu : public QPlatformMenu
{
Q_OBJECT
public:
SystemTrayMenu();
~SystemTrayMenu() Q_DECL_OVERRIDE;
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void setTag(quintptr tag) Q_DECL_OVERRIDE;
void setText(const QString &text) Q_DECL_OVERRIDE;
void setVisible(bool visible) Q_DECL_OVERRIDE;
void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE;
quintptr tag() const Q_DECL_OVERRIDE;
QPlatformMenuItem *createMenuItem() const Q_DECL_OVERRIDE;
QMenu *menu() const;
private:
quintptr m_tag;
QPointer<QMenu> m_menu;
QList<SystemTrayMenuItem*> m_items;
};
class SystemTrayMenuItem : public QPlatformMenuItem
{
Q_OBJECT
public:
SystemTrayMenuItem();
~SystemTrayMenuItem() Q_DECL_OVERRIDE;
void setCheckable(bool checkable) Q_DECL_OVERRIDE;
void setChecked(bool isChecked) Q_DECL_OVERRIDE;
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
void setFont(const QFont &font) Q_DECL_OVERRIDE;
void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void setIsSeparator(bool isSeparator) Q_DECL_OVERRIDE;
void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
void setRole(MenuRole role) Q_DECL_OVERRIDE;
void setShortcut(const QKeySequence &shortcut) Q_DECL_OVERRIDE;
void setTag(quintptr tag) Q_DECL_OVERRIDE;
void setText(const QString &text) Q_DECL_OVERRIDE;
void setVisible(bool isVisible) Q_DECL_OVERRIDE;
quintptr tag() const Q_DECL_OVERRIDE;
void setIconSize(int size)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
Q_DECL_OVERRIDE
#endif
;
QAction *action() const;
private:
quintptr m_tag;
QAction *m_action;
};
class LXQtSystemTrayIcon : public QPlatformSystemTrayIcon
{
public:
LXQtSystemTrayIcon();
~LXQtSystemTrayIcon() Q_DECL_OVERRIDE;
void init() Q_DECL_OVERRIDE;
void cleanup() Q_DECL_OVERRIDE;
void updateIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void updateToolTip(const QString &tooltip) Q_DECL_OVERRIDE;
void updateMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
QRect geometry() const Q_DECL_OVERRIDE;
void showMessage(const QString &title, const QString &msg,
const QIcon &icon, MessageIcon iconType, int secs) Q_DECL_OVERRIDE;
bool isSystemTrayAvailable() const Q_DECL_OVERRIDE;
bool supportsMessages() const Q_DECL_OVERRIDE;
QPlatformMenu *createMenu() const Q_DECL_OVERRIDE;
private:
StatusNotifierItem *mSni;
};
#endif

View File

@ -0,0 +1,75 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXDE-Qt - a lightweight, Qt based, desktop toolset
* http://lxqt.org
*
* Copyright: 2015 LXQt team
* Authors:
* Balázs Béla <balazsbela[at]gmail.com>
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include "dbustypes.h"
// Marshall the IconPixmap data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const IconPixmap &icon)
{
argument.beginStructure();
argument << icon.width;
argument << icon.height;
argument << icon.bytes;
argument.endStructure();
return argument;
}
// Retrieve the ImageStruct data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, IconPixmap &icon)
{
argument.beginStructure();
argument >> icon.width;
argument >> icon.height;
argument >> icon.bytes;
argument.endStructure();
return argument;
}
// Marshall the ToolTip data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const ToolTip &toolTip)
{
argument.beginStructure();
argument << toolTip.iconName;
argument << toolTip.iconPixmap;
argument << toolTip.title;
argument << toolTip.description;
argument.endStructure();
return argument;
}
// Retrieve the ToolTip data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, ToolTip &toolTip)
{
argument.beginStructure();
argument >> toolTip.iconName;
argument >> toolTip.iconPixmap;
argument >> toolTip.title;
argument >> toolTip.description;
argument.endStructure();
return argument;
}

View File

@ -0,0 +1,60 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXDE-Qt - a lightweight, Qt based, desktop toolset
* http://lxqt.org
*
* Copyright: 2015 LXQt team
* Authors:
* Balázs Béla <balazsbela[at]gmail.com>
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include <QDBusArgument>
#ifndef DBUSTYPES_H
#define DBUSTYPES_H
struct IconPixmap {
int width;
int height;
QByteArray bytes;
};
typedef QList<IconPixmap> IconPixmapList;
Q_DECLARE_METATYPE(IconPixmap)
Q_DECLARE_METATYPE(IconPixmapList)
struct ToolTip {
QString iconName;
QList<IconPixmap> iconPixmap;
QString title;
QString description;
};
Q_DECLARE_METATYPE(ToolTip)
QDBusArgument &operator<<(QDBusArgument &argument, const IconPixmap &icon);
const QDBusArgument &operator>>(const QDBusArgument &argument, IconPixmap &icon);
QDBusArgument &operator<<(QDBusArgument &argument, const ToolTip &toolTip);
const QDBusArgument &operator>>(const QDBusArgument &argument, ToolTip &toolTip);
#endif // DBUSTYPES_H

View File

@ -0,0 +1,69 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.StatusNotifierItem">
<property name="Category" type="s" access="read"/>
<property name="Id" type="s" access="read"/>
<property name="Title" type="s" access="read"/>
<property name="Status" type="s" access="read"/>
<property name="WindowId" type="i" access="read"/>
<property name="IconThemePath" type="s" access="read"/>
<property name="Menu" type="o" access="read"/>
<property name="ItemIsMenu" type="b" access="read"/>
<property name="IconName" type="s" access="read"/>
<property name="IconPixmap" type="a(iiay)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="IconPixmapList"/>
</property>
<property name="OverlayIconName" type="s" access="read"/>
<property name="OverlayIconPixmap" type="a(iiay)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="IconPixmapList"/>
</property>
<property name="AttentionIconName" type="s" access="read"/>
<property name="AttentionIconPixmap" type="a(iiay)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="IconPixmapList"/>
</property>
<property name="AttentionMovieName" type="s" access="read"/>
<property name="ToolTip" type="(sa(iiay)ss)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="ToolTip"/>
</property>
<method name="ContextMenu">
<arg name="x" type="i" direction="in"/>
<arg name="y" type="i" direction="in"/>
</method>
<method name="Activate">
<arg name="x" type="i" direction="in"/>
<arg name="y" type="i" direction="in"/>
</method>
<method name="SecondaryActivate">
<arg name="x" type="i" direction="in"/>
<arg name="y" type="i" direction="in"/>
</method>
<method name="Scroll">
<arg name="delta" type="i" direction="in"/>
<arg name="orientation" type="s" direction="in"/>
</method>
<signal name="NewTitle">
</signal>
<signal name="NewIcon">
</signal>
<signal name="NewAttentionIcon">
</signal>
<signal name="NewOverlayIcon">
</signal>
<signal name="NewToolTip">
</signal>
<signal name="NewStatus">
<arg name="status" type="s"/>
</signal>
</interface>
</node>

View File

@ -0,0 +1,299 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org/
*
* Copyright: 2015 LXQt team
* Authors:
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include "statusnotifieritem.h"
#include "statusnotifieritemadaptor.h"
#include <QDBusInterface>
#include <QDBusServiceWatcher>
#include <dbusmenu-qt5/dbusmenuexporter.h>
int StatusNotifierItem::mServiceCounter = 0;
StatusNotifierItem::StatusNotifierItem(QString id, QObject *parent)
: QObject(parent),
mAdaptor(new StatusNotifierItemAdaptor(this)),
mService(QString("org.freedesktop.StatusNotifierItem-%1-%2")
.arg(QCoreApplication::applicationPid())
.arg(++mServiceCounter)),
mId(id),
mTitle("Test"),
mStatus("Active"),
mMenu(nullptr)
{
// register service
QDBusConnection::sessionBus().registerService(mService);
QDBusConnection::sessionBus().registerObject("/StatusNotifierItem", this);
registerToHost();
// monitor the watcher service in case the host restarts
QDBusServiceWatcher *watcher = new QDBusServiceWatcher("org.kde.StatusNotifierWatcher",
QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForOwnerChange,
this);
connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &StatusNotifierItem::onServiceOwnerChanged);
}
StatusNotifierItem::~StatusNotifierItem()
{
QDBusConnection::sessionBus().unregisterObject("/StatusNotifierItem");
QDBusConnection::sessionBus().unregisterService(mService);
QDBusConnection::sessionBus().disconnectFromBus(mService);
delete mMenu;
}
void StatusNotifierItem::registerToHost()
{
QDBusInterface interface("org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher",
"org.kde.StatusNotifierWatcher",
QDBusConnection::sessionBus());
interface.asyncCall("RegisterStatusNotifierItem", mService);
}
void StatusNotifierItem::onServiceOwnerChanged(const QString& service, const QString& oldOwner,
const QString& newOwner)
{
if (!newOwner.isEmpty())
registerToHost();
}
void StatusNotifierItem::setTitle(const QString &title)
{
if (mTitle == title)
return;
mTitle = title;
emit mAdaptor->NewTitle();
}
void StatusNotifierItem::setStatus(const QString &status)
{
if (mStatus == status)
return;
mStatus = status;
emit mAdaptor->NewStatus(mStatus);
}
void StatusNotifierItem::setMenuPath(const QString& path)
{
mMenuPath.setPath(path);
}
void StatusNotifierItem::setIconByName(const QString &name)
{
if (mIconName == name)
return;
mIconName = name;
emit mAdaptor->NewIcon();
}
void StatusNotifierItem::setIconByPixmap(const QIcon &icon)
{
if (mIconCacheKey == icon.cacheKey())
return;
mIconCacheKey = icon.cacheKey();
mIcon = iconToPixmapList(icon);
mIconName.clear();
emit mAdaptor->NewIcon();
}
void StatusNotifierItem::setOverlayIconByName(const QString &name)
{
if (mOverlayIconName == name)
return;
mOverlayIconName = name;
emit mAdaptor->NewOverlayIcon();
}
void StatusNotifierItem::setOverlayIconByPixmap(const QIcon &icon)
{
if (mOverlayIconCacheKey == icon.cacheKey())
return;
mOverlayIconCacheKey = icon.cacheKey();
mOverlayIcon = iconToPixmapList(icon);
mOverlayIconName.clear();
emit mAdaptor->NewOverlayIcon();
}
void StatusNotifierItem::setAttentionIconByName(const QString &name)
{
if (mAttentionIconName == name)
return;
mAttentionIconName = name;
emit mAdaptor->NewAttentionIcon();
}
void StatusNotifierItem::setAttentionIconByPixmap(const QIcon &icon)
{
if (mAttentionIconCacheKey == icon.cacheKey())
return;
mAttentionIconCacheKey = icon.cacheKey();
mAttentionIcon = iconToPixmapList(icon);
mAttentionIconName.clear();
emit mAdaptor->NewAttentionIcon();
}
void StatusNotifierItem::setToolTipTitle(const QString &title)
{
if (mTooltipTitle == title)
return;
mTooltipTitle = title;
emit mAdaptor->NewToolTip();
}
void StatusNotifierItem::setToolTipSubTitle(const QString &subTitle)
{
if (mTooltipSubtitle == subTitle)
return;
mTooltipSubtitle = subTitle;
emit mAdaptor->NewToolTip();
}
void StatusNotifierItem::setToolTipIconByName(const QString &name)
{
if (mTooltipIconName == name)
return;
mTooltipIconName = name;
emit mAdaptor->NewToolTip();
}
void StatusNotifierItem::setToolTipIconByPixmap(const QIcon &icon)
{
if (mTooltipIconCacheKey == icon.cacheKey())
return;
mTooltipIconCacheKey = icon.cacheKey();
mTooltipIcon = iconToPixmapList(icon);
mTooltipIconName.clear();
emit mAdaptor->NewToolTip();
}
void StatusNotifierItem::setContextMenu(QMenu* menu)
{
if (mMenu == menu)
return;
delete mMenu;
mMenu = menu;
mMenu->setParent(nullptr);
setMenuPath("/MenuBar");
new DBusMenuExporter(this->menu().path(), mMenu);
}
void StatusNotifierItem::Activate(int x, int y)
{
if (mStatus == "NeedsAttention")
mStatus = "Active";
emit activateRequested(QPoint(x, y));
}
void StatusNotifierItem::SecondaryActivate(int x, int y)
{
if (mStatus == "NeedsAttention")
mStatus = "Active";
emit secondaryActivateRequested(QPoint(x, y));
}
void StatusNotifierItem::ContextMenu(int x, int y)
{
if (mMenu)
{
if (mMenu->isVisible())
mMenu->popup(QPoint(x, y));
else
mMenu->hide();
}
}
void StatusNotifierItem::Scroll(int delta, const QString &orientation)
{
Qt::Orientation orient = Qt::Vertical;
if (orientation.toLower() == "horizontal")
orient = Qt::Horizontal;
emit scrollRequested(delta, orient);
}
void StatusNotifierItem::showMessage(const QString& title, const QString& msg,
const QString& iconName, int secs)
{
QDBusInterface interface("org.freedesktop.Notifications", "/org/freedesktop/Notifications",
"org.freedesktop.Notifications", QDBusConnection::sessionBus());
interface.call("Notify", mTitle, (uint) 0, iconName, title,
msg, QStringList(), QVariantMap(), secs);
}
IconPixmapList StatusNotifierItem::iconToPixmapList(const QIcon& icon)
{
IconPixmapList pixmapList;
// long live KDE!
for (const QSize &size : icon.availableSizes())
{
QImage image = icon.pixmap(size).toImage();
IconPixmap pix;
pix.height = image.height();
pix.width = image.width();
if (image.format() != QImage::Format_ARGB32)
image = image.convertToFormat(QImage::Format_ARGB32);
pix.bytes = QByteArray((char *) image.bits(), image.byteCount());
// swap to network byte order if we are little endian
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
{
quint32 *uintBuf = (quint32 *) pix.bytes.data();
for (uint i = 0; i < pix.bytes.size() / sizeof(quint32); ++i)
{
*uintBuf = qToBigEndian(*uintBuf);
++uintBuf;
}
}
pixmapList.append(pix);
}
return pixmapList;
}

View File

@ -0,0 +1,177 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org/
*
* Copyright: 2015 LXQt team
* Authors:
* Paulo Lieuthier <paulolieuthier@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#ifndef STATUS_NOTIFIER_ITEM_H
#define STATUS_NOTIFIER_ITEM_H
#include <QObject>
#include <QIcon>
#include <QMenu>
#include "dbustypes.h"
class StatusNotifierItemAdaptor;
class StatusNotifierItem : public QObject
{
Q_OBJECT
Q_PROPERTY(QString Title READ title)
Q_PROPERTY(QString Id READ id)
Q_PROPERTY(QString Status READ status)
Q_PROPERTY(QDBusObjectPath Menu READ menu)
Q_PROPERTY(QString IconName READ iconName)
Q_PROPERTY(IconPixmapList IconPixmap READ iconPixmap)
Q_PROPERTY(QString OverlayIconName READ overlayIconName)
Q_PROPERTY(IconPixmapList OverlayIconPixmap READ overlayIconPixmap)
Q_PROPERTY(QString AttentionIconName READ attentionIconName)
Q_PROPERTY(IconPixmapList AttentionIconPixmap READ attentionIconPixmap)
Q_PROPERTY(ToolTip ToolTip READ toolTip)
public:
StatusNotifierItem(QString id, QObject *parent = nullptr);
~StatusNotifierItem();
QString id() const
{ return mId; }
QString title() const
{ return mTitle; }
void setTitle(const QString &title);
QString status() const
{ return mStatus; }
void setStatus(const QString &status);
QDBusObjectPath menu() const
{ return mMenuPath; }
void setMenuPath(const QString &path);
QString iconName() const
{ return mIconName; }
void setIconByName(const QString &name);
IconPixmapList iconPixmap() const
{ return mIcon; }
void setIconByPixmap(const QIcon &icon);
QString overlayIconName() const
{ return mOverlayIconName; }
void setOverlayIconByName(const QString &name);
IconPixmapList overlayIconPixmap() const
{ return mOverlayIcon; }
void setOverlayIconByPixmap(const QIcon &icon);
QString attentionIconName() const
{ return mAttentionIconName; }
void setAttentionIconByName(const QString &name);
IconPixmapList attentionIconPixmap() const
{ return mAttentionIcon; }
void setAttentionIconByPixmap(const QIcon &icon);
QString toolTipTitle() const
{ return mTooltipTitle; }
void setToolTipTitle(const QString &title);
QString toolTipSubTitle() const
{ return mTooltipSubtitle; }
void setToolTipSubTitle(const QString &subTitle);
QString toolTipIconName() const
{ return mTooltipIconName; }
void setToolTipIconByName(const QString &name);
IconPixmapList toolTipIconPixmap() const
{ return mTooltipIcon; }
void setToolTipIconByPixmap(const QIcon &icon);
ToolTip toolTip() const
{
ToolTip tt;
tt.title = mTooltipTitle;
tt.description = mTooltipSubtitle;
tt.iconName = mTooltipIconName;
tt.iconPixmap = mTooltipIcon;
return tt;
}
void setContextMenu(QMenu *menu);
public slots:
void Activate(int x, int y);
void SecondaryActivate(int x, int y);
void ContextMenu(int x, int y);
void Scroll(int delta, const QString &orientation);
void showMessage(const QString &title, const QString &msg, const QString &iconName, int secs);
private:
void registerToHost();
IconPixmapList iconToPixmapList(const QIcon &icon);
private slots:
void onServiceOwnerChanged(const QString &service, const QString &oldOwner,
const QString &newOwner);
signals:
void activateRequested(const QPoint &pos);
void secondaryActivateRequested(const QPoint &pos);
void scrollRequested(int delta, Qt::Orientation orientation);
private:
StatusNotifierItemAdaptor *mAdaptor;
QString mService;
QString mId;
QString mTitle;
QString mStatus;
// icons
QString mIconName, mOverlayIconName, mAttentionIconName;
IconPixmapList mIcon, mOverlayIcon, mAttentionIcon;
qint64 mIconCacheKey, mOverlayIconCacheKey, mAttentionIconCacheKey;
// tooltip
QString mTooltipTitle, mTooltipSubtitle, mTooltipIconName;
IconPixmapList mTooltipIcon;
qint64 mTooltipIconCacheKey;
// menu
QMenu *mMenu;
QDBusObjectPath mMenuPath;
static int mServiceCounter;
};
#endif