Should now work with and without QSystemTrayIcon support in Qt.
There's still some fugly workaround for QMenu's focus issues, which will
probably require some X11 hackery at some point to do it a bit less fugly,
but maybe the DBusMenu is specced earlier...
connect(_trayIcon, SIGNAL(messageClicked()),
SIGNAL(messageClicked()));
- setTrayMenu(_trayIcon->contextMenu());
- _trayIcon->setContextMenu(trayMenu());
-
_blinkTimer.setInterval(500);
_blinkTimer.setSingleShot(false);
connect(&_blinkTimer, SIGNAL(timeout()), SLOT(on_blinkTimeout()));
setMode(Legacy);
SystemTray::init();
+
+ _trayIcon->setContextMenu(trayMenu());
}
void LegacySystemTray::syncLegacyIcon() {
}
void StatusNotifierItem::init() {
-// workaround until we handle the tray menu more sanely
-#ifdef QT_NO_SYSTEMTRAYICON
- setTrayMenu(new QMenu(associatedWidget()));
-#endif
-
- trayMenu()->installEventFilter(this);
-
qDBusRegisterMetaType<DBusImageStruct>();
qDBusRegisterMetaType<DBusImageVector>();
qDBusRegisterMetaType<DBusToolTipStruct>();
setMode(StatusNotifier);
StatusNotifierItemParent::init();
+ trayMenu()->installEventFilter(this);
}
void StatusNotifierItem::registerToDaemon() {
bool StatusNotifierItem::eventFilter(QObject *watched, QEvent *event) {
if(mode() == StatusNotifier) {
//FIXME: ugly ugly workaround to weird QMenu's focus problems
+#ifdef HAVE_KDE
if(watched == trayMenu() &&
(event->type() == QEvent::WindowDeactivate || (event->type() == QEvent::MouseButtonRelease && static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton))) {
// put at the back of event queue to let the action activate anyways
QTimer::singleShot(0, trayMenu(), SLOT(hide()));
}
+#else
+ if(watched == trayMenu() && event->type() == QEvent::HoverLeave) {
+ trayMenu()->hide();
+ }
+#endif
}
return StatusNotifierItemParent::eventFilter(watched, event);
}
//TODO: nicer placement, possible?
if (!m_statusNotifierItem->trayMenu()->isVisible()) {
+#ifdef HAVE_KDE
m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
+#endif
m_statusNotifierItem->trayMenu()->popup(QPoint(x,y));
#ifdef HAVE_KDE
KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <QApplication>
#include <QMenu>
#include "systemtray.h"
+#include "action.h"
#include "actioncollection.h"
#include "client.h"
#include "iconloader.h"
#include "qtui.h"
#ifdef HAVE_KDE
+# include <KMenu>
# include <KWindowInfo>
# include <KWindowSystem>
#endif
return _associatedWidget;
}
-void SystemTray::setTrayMenu(QMenu *menu) {
- if(menu)
- _trayMenu = menu;
- else
- _trayMenu = new QMenu();
-
+void SystemTray::init() {
ActionCollection *coll = QtUi::actionCollection("General");
+ _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, SLOT(minimizeRestore()));
+
+#ifdef HAVE_KDE
+ KMenu *kmenu;
+ _trayMenu = kmenu = new KMenu();
+ kmenu->addTitle(qApp->windowIcon(), "Quassel IRC");
+#else
+ _trayMenu = new QMenu(associatedWidget());
+#endif
+
+ _trayMenu->setTitle("Quassel IRC");
+
+#ifndef HAVE_KDE
+ _trayMenu->setAttribute(Qt::WA_Hover);
+#endif
_trayMenu->addAction(coll->action("ConnectCore"));
_trayMenu->addAction(coll->action("DisconnectCore"));
_trayMenu->addAction(coll->action("CoreInfo"));
-#ifndef HAVE_KDE
_trayMenu->addSeparator();
+ _trayMenu->addAction(_minimizeRestoreAction);
_trayMenu->addAction(coll->action("Quit"));
-#endif /* HAVE_KDE */
+
+ connect(_trayMenu, SIGNAL(aboutToShow()), SLOT(trayMenuAboutToShow()));
+}
+
+void SystemTray::trayMenuAboutToShow() {
+ if(GraphicalUi::isMainWidgetVisible())
+ _minimizeRestoreAction->setText(tr("&Minimize"));
+ else
+ _minimizeRestoreAction->setText(tr("&Restore"));
}
void SystemTray::setMode(Mode mode_) {
if(mode_ != _mode) {
_mode = mode_;
- if(_mode == Legacy) {
- _trayMenu->setWindowFlags(Qt::Popup);
- } else {
- _trayMenu->setWindowFlags(Qt::Window);
+#ifdef HAVE_KDE
+ if(_trayMenu) {
+ if(_mode == Legacy) {
+ _trayMenu->setWindowFlags(Qt::Popup);
+ } else {
+ _trayMenu->setWindowFlags(Qt::Window);
+ }
}
+#endif
}
}
void SystemTray::activate(SystemTray::ActivationReason reason) {
emit activated(reason);
}
+
+void SystemTray::minimizeRestore() {
+ GraphicalUi::toggleMainWidget();
+}
#include "icon.h"
+class Action;
class QMenu;
class SystemTray : public QObject {
explicit SystemTray(QWidget *parent);
virtual ~SystemTray();
- virtual void init() {}
+ virtual void init();
inline State state() const;
inline bool isAlerted() const;
inline QString toolTipTitle() const;
inline QString toolTipSubTitle() const;
inline QMenu *trayMenu() const;
- void setTrayMenu(QMenu *);
private slots:
+ void minimizeRestore();
+ void trayMenuAboutToShow();
private:
Mode _mode;
QMenu *_trayMenu;
QWidget *_associatedWidget;
+ Action *_minimizeRestoreAction;
};
// inlines
// therefore we watch for activation event and use our stopwatch :)
if(GetTickCount() - _dwTickCount < 300) {
// we were active in the last 300ms -> hide it
- minimizeRestore(false);
+ if(perform)
+ minimizeRestore(false);
+ return false;
} else {
- minimizeRestore(true);
+ if(perform)
+ minimizeRestore(true);
+ return true;
}
#elif defined(HAVE_KDE) && defined(Q_WS_X11)
return true;
}
+bool GraphicalUi::isMainWidgetVisible() {
+ return !instance()->checkMainWidgetVisibility(false);
+}
+
void GraphicalUi::minimizeRestore(bool show) {
if(show)
activateMainWidget();
//! Toggle main widget
static void toggleMainWidget();
+ //! Check if the main widget if (fully, in KDE) visible
+ static bool isMainWidgetVisible();
+
protected:
//! This is the widget we associate global actions with, typically the main window
void setMainWidget(QWidget *);
* it should be activated or hidden. Without KDE, we need to resort to checking the current state
* as Qt knows it, ignoring windows covering it.
* @param performToggle If true, toggle the window's state in addition to checking visibility
- * @return True, if the window is currently visible
+ * @return True, if the window is currently *not* visible (needs activation)
*/
bool checkMainWidgetVisibility(bool performToggle);