From 9176cdd1474e31625f047257d974240e11176310 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Mon, 26 Jan 2015 16:13:18 +0100 Subject: [PATCH] System tray icon basics --- src/qtgui/guiutils.cpp | 2 ++ src/qtgui/guiutils.h | 9 +++++++-- src/qtgui/rclmain_w.cpp | 39 +++++++++++++++++++++++++++++--------- src/qtgui/rclmain_w.h | 11 ++++++++--- src/qtgui/recoll.pro.in | 2 ++ src/qtgui/systray.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ src/qtgui/systray.h | 42 +++++++++++++++++++++++++++++++++++++++++ src/qtgui/uiprefs.ui | 20 ++++++++++++++++++++ src/qtgui/uiprefs_w.cpp | 10 +++++++++- src/qtgui/uiprefs_w.h | 1 + 10 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 src/qtgui/systray.cpp create mode 100644 src/qtgui/systray.h diff --git a/src/qtgui/guiutils.cpp b/src/qtgui/guiutils.cpp index 30d94b77..7f3720e9 100644 --- a/src/qtgui/guiutils.cpp +++ b/src/qtgui/guiutils.cpp @@ -252,6 +252,8 @@ void rwSettings(bool writing) SETTING_RW(prefs.fileTypesByCats, "/Recoll/prefs/query/asearchFilTypByCat", Bool, false); + SETTING_RW(prefs.showTrayIcon, "/Recoll/prefs/showTrayIcon", Bool, false); + SETTING_RW(prefs.closeToTray, "/Recoll/prefs/closeToTray", Bool, false); if (g_dynconf == 0) { // Happens diff --git a/src/qtgui/guiutils.h b/src/qtgui/guiutils.h index be40c48a..114258c1 100644 --- a/src/qtgui/guiutils.h +++ b/src/qtgui/guiutils.h @@ -124,6 +124,9 @@ class PrefsPack { // of the case where we might need an incompatible change int rclVersion; + bool showTrayIcon; + bool closeToTray; + // Advanced search window clause list state vector advSearchClauses; @@ -140,8 +143,10 @@ class PrefsPack { queryReplaceAbstract(false), startWithAdvSearchOpen(false), termMatchType(0), - rclVersion(1505) - { } + rclVersion(1505), + showTrayIcon(false), + closeToTray(false) + {} }; /** Global preferences record */ diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 599e7184..e0dfcdfe 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -84,6 +84,7 @@ using std::pair; #include "fileudi.h" #include "snippets_w.h" #include "fragbuts.h" +#include "systray.h" using namespace confgui; @@ -440,6 +441,14 @@ void RclMain::init() emit sortDataChanged(m_sortspec); } + if (prefs.showTrayIcon && QSystemTrayIcon::isSystemTrayAvailable()) { + m_trayicon = new RclTrayIcon(this, + QIcon(QString(":/images/recoll.png"))); + m_trayicon->show(); + } else { + m_trayicon = 0; + } + fileRebuildIndexAction->setEnabled(FALSE); fileToggleIndexingAction->setEnabled(FALSE); // Start timer on a slow period (used for checking ^C). Will be @@ -659,19 +668,22 @@ void RclMain::adjustPrefsMenu() setStemLang(prefs.queryStemLang); } -void RclMain::closeEvent( QCloseEvent * ) +void RclMain::showTrayMessage(const QString& text) { - fileExit(); + if (m_trayicon) + m_trayicon->showMessage("Recoll", text, + QSystemTrayIcon::Information, 1000); } -// We also want to get rid of the advanced search form and previews -// when we exit (not our children so that it's not systematically -// created over the main form). -bool RclMain::close() +void RclMain::closeEvent(QCloseEvent *ev) { - LOGDEB(("RclMain::close\n")); - fileExit(); - return false; + LOGDEB(("RclMain::closeEvent\n")); + if (prefs.closeToTray && m_trayicon && m_trayicon->isVisible()) { + hide(); + ev->ignore(); + } else { + fileExit(); + } } void RclMain::fileExit() @@ -776,6 +788,7 @@ void RclMain::periodic100() } // Update the "start/stop indexing" menu entry, can't be done from // the "start/stop indexing" slot itself + IndexerState prevstate = m_indexerState; if (m_idxproc) { m_indexerState = IXST_RUNNINGMINE; fileToggleIndexingAction->setText(tr("Stop &Indexing")); @@ -800,6 +813,11 @@ void RclMain::periodic100() } } + if ((prevstate == IXST_RUNNINGMINE || prevstate == IXST_RUNNINGNOTMINE) + && m_indexerState == IXST_NOTRUNNING) { + showTrayMessage("Indexing done"); + } + // Possibly cleanup the dead viewers for (vector::iterator it = m_viewers.begin(); it != m_viewers.end(); it++) { @@ -871,12 +889,15 @@ void RclMain::toggleIndexing() m_idxproc->startExec("recollindex", args, false, false); } break; + case IXST_UNKNOWN: + return; } } void RclMain::rebuildIndex() { switch (m_indexerState) { + case IXST_UNKNOWN: case IXST_RUNNINGMINE: case IXST_RUNNINGNOTMINE: return; //?? Should not have been called diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 4798c5da..6921d904 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -49,12 +49,15 @@ namespace confgui { using confgui::ConfIndexW; +class RclTrayIcon; + class RclMain : public QMainWindow, public Ui::RclMainBase { Q_OBJECT public: - enum IndexerState {IXST_NOTRUNNING, IXST_RUNNINGMINE, IXST_RUNNINGNOTMINE}; + enum IndexerState {IXST_UNKNOWN, IXST_NOTRUNNING, + IXST_RUNNINGMINE, IXST_RUNNINGNOTMINE}; RclMain(QWidget * parent = 0) : QMainWindow(parent), curPreview(0), @@ -77,7 +80,7 @@ public: m_idxkilled(false), m_catgbutvecidx(0), m_sortspecnochange(false), - m_indexerState(IXST_RUNNINGNOTMINE), + m_indexerState(IXST_UNKNOWN), m_queryActive(false), m_firstIndexing(false), m_searchIsSimple(false) @@ -104,7 +107,6 @@ public: void newDupsW(const Rcl::Doc doc, const std::vector dups); public slots: - virtual bool close(); virtual void fileExit(); virtual void idxStatus(); virtual void periodic100(); @@ -163,6 +165,7 @@ public slots: virtual void resultCount(int); virtual void applyStyleSheet(); virtual void setFilterCtlStyle(int stl); + virtual void showTrayMessage(const QString& text); signals: void docSourceChanged(RefCntr); @@ -215,6 +218,8 @@ private: // preview (if no ext app set) QString m_urltoview; + RclTrayIcon *m_trayicon; + virtual void init(); virtual void setupResTB(bool combo); virtual void previewPrevOrNextInTab(Preview *, int sid, int docnum, diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index 204c420f..36f03b8f 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -33,6 +33,7 @@ HEADERS += \ snippets_w.h \ spell_w.h \ ssearch_w.h \ + systray.h \ uiprefs_w.h \ viewaction_w.h \ @@ -59,6 +60,7 @@ SOURCES += \ snippets_w.cpp \ spell_w.cpp \ ssearch_w.cpp \ + systray.cpp \ uiprefs_w.cpp \ viewaction_w.cpp \ diff --git a/src/qtgui/systray.cpp b/src/qtgui/systray.cpp new file mode 100644 index 00000000..3d08b321 --- /dev/null +++ b/src/qtgui/systray.cpp @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#include "systray.h" +#include "rclmain_w.h" + +void RclTrayIcon::init() +{ + QAction *restoreAction = new QAction(tr("Restore"), this); + QAction *quitAction = new QAction(tr("Quit"), this); + + connect(restoreAction, SIGNAL(triggered()), this, SLOT(onRestore())); + connect(quitAction, SIGNAL(triggered()), m_mainw, SLOT(fileExit())); + + QMenu *trayIconMenu = new QMenu(0); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addAction(quitAction); + setContextMenu(trayIconMenu); +} + +void RclTrayIcon::onRestore() +{ + // Hide and show to restore on current desktop + m_mainw->hide(); + m_mainw->show(); +} diff --git a/src/qtgui/systray.h b/src/qtgui/systray.h new file mode 100644 index 00000000..f4ec946c --- /dev/null +++ b/src/qtgui/systray.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _SYSTRAY_H_INCLUDED_ +#define _SYSTRAY_H_INCLUDED_ + +#include +#include + +class RclMain; + +class RclTrayIcon : public QSystemTrayIcon { + Q_OBJECT + + public: + + RclTrayIcon(RclMain *mainw, const QIcon& icon, QObject* parent = 0) + : QSystemTrayIcon(icon, parent), m_mainw(mainw) { + init(); + } +public slots: + void onRestore(); + +private: + void init(); + RclMain *m_mainw; +}; + +#endif /* _SYSTRAY_H_INCLUDED_ */ diff --git a/src/qtgui/uiprefs.ui b/src/qtgui/uiprefs.ui index 7f6dec92..cb580bff 100644 --- a/src/qtgui/uiprefs.ui +++ b/src/qtgui/uiprefs.ui @@ -277,6 +277,26 @@ + + + + Show system tray icon. + + + false + + + + + + + Close to tray instead of exiting. + + + false + + + diff --git a/src/qtgui/uiprefs_w.cpp b/src/qtgui/uiprefs_w.cpp index 56a4e87a..ab7d43bd 100644 --- a/src/qtgui/uiprefs_w.cpp +++ b/src/qtgui/uiprefs_w.cpp @@ -92,7 +92,6 @@ void UIPrefsDialog::init() ssAutoSpaceCB, SLOT(setDisabled(bool))); connect(ssAutoAllCB, SIGNAL(toggled(bool)), ssAutoSpaceCB, SLOT(setChecked(bool))); - setFromPrefs(); } @@ -126,6 +125,8 @@ void UIPrefsDialog::setFromPrefs() initStartAdvCB->setChecked(prefs.startWithAdvSearchOpen); keepSortCB->setChecked(prefs.keepSort); + showTrayIconCB->setChecked(prefs.showTrayIcon); + closeToTrayCB->setChecked(prefs.closeToTray); previewHtmlCB->setChecked(prefs.previewHtml); switch (prefs.previewPlainPre) { case PrefsPack::PP_BR: @@ -289,6 +290,8 @@ void UIPrefsDialog::accept() prefs.startWithAdvSearchOpen = initStartAdvCB->isChecked(); prefs.keepSort = keepSortCB->isChecked(); + prefs.showTrayIcon = showTrayIconCB->isChecked(); + prefs.closeToTray = closeToTrayCB->isChecked(); prefs.previewHtml = previewHtmlCB->isChecked(); if (plainBRRB->isChecked()) { @@ -520,6 +523,11 @@ static bool samedir(const string& dir1, const string& dir2) return false; } +void UIPrefsDialog::on_showTrayIconCB_clicked() +{ + closeToTrayCB->setEnabled(showTrayIconCB->checkState()); +} + /** * Browse to add another index. * We do a textual comparison to check for duplicates, except for diff --git a/src/qtgui/uiprefs_w.h b/src/qtgui/uiprefs_w.h index bbce0d2b..a422c0d5 100644 --- a/src/qtgui/uiprefs_w.h +++ b/src/qtgui/uiprefs_w.h @@ -57,6 +57,7 @@ public slots: virtual void addExtraDbPB_clicked(); virtual void delExtraDbPB_clicked(); virtual void togExtraDbPB_clicked(); + virtual void on_showTrayIconCB_clicked(); virtual void actAllExtraDbPB_clicked(); virtual void unacAllExtraDbPB_clicked(); virtual void setStemLang(const QString& lang);