Add an option to display a tray icon.

Also implement "Minimize to tray" functionality.
This commit is contained in:
Felix Geyer 2014-11-02 10:15:44 +01:00
parent 870d7355ca
commit 4cdb9a645d
6 changed files with 111 additions and 1 deletions

View File

@ -104,6 +104,8 @@ void Config::init(const QString& fileName)
m_defaults.insert("security/passwordscleartext", false); m_defaults.insert("security/passwordscleartext", false);
m_defaults.insert("security/autotypeask", true); m_defaults.insert("security/autotypeask", true);
m_defaults.insert("GUI/Language", "system"); m_defaults.insert("GUI/Language", "system");
m_defaults.insert("GUI/ShowTrayIcon", false);
m_defaults.insert("GUI/MinimizeToTray", false);
} }
Config* Config::instance() Config* Config::instance()

View File

@ -33,6 +33,7 @@ const QString MainWindow::BaseWindowTitle = "KeePassX";
MainWindow::MainWindow() MainWindow::MainWindow()
: m_ui(new Ui::MainWindow()) : m_ui(new Ui::MainWindow())
, m_trayIcon(Q_NULLPTR)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -201,6 +202,8 @@ MainWindow::MainWindow()
m_actionMultiplexer.connect(m_ui->actionSearch, SIGNAL(triggered()), m_actionMultiplexer.connect(m_ui->actionSearch, SIGNAL(triggered()),
SLOT(toggleSearch())); SLOT(toggleSearch()));
updateTrayIcon();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -429,12 +432,26 @@ void MainWindow::closeEvent(QCloseEvent* event)
saveWindowInformation(); saveWindowInformation();
event->accept(); event->accept();
QApplication::quit();
} }
else { else {
event->ignore(); event->ignore();
} }
} }
void MainWindow::changeEvent(QEvent *event)
{
if ((event->type() == QEvent::WindowStateChange) && isMinimized()
&& isTrayIconEnabled() && config()->get("GUI/MinimizeToTray").toBool())
{
event->ignore();
hide();
}
else {
QMainWindow::changeEvent(event);
}
}
void MainWindow::saveWindowInformation() void MainWindow::saveWindowInformation()
{ {
config()->set("GUI/MainWindowGeometry", saveGeometry()); config()->set("GUI/MainWindowGeometry", saveGeometry());
@ -467,6 +484,35 @@ bool MainWindow::saveLastDatabases()
return accept; return accept;
} }
void MainWindow::updateTrayIcon()
{
if (isTrayIconEnabled()) {
if (!m_trayIcon) {
m_trayIcon = new QSystemTrayIcon(filePath()->applicationIcon(), this);
QMenu* menu = new QMenu(this);
QAction* actionToggle = new QAction(tr("Toggle window"), menu);
menu->addAction(actionToggle);
menu->addAction(m_ui->actionQuit);
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(trayIconTriggered(QSystemTrayIcon::ActivationReason)));
connect(actionToggle, SIGNAL(triggered()), SLOT(toggleWindow()));
m_trayIcon->setContextMenu(menu);
m_trayIcon->show();
}
}
else {
if (m_trayIcon) {
delete m_trayIcon;
m_trayIcon = Q_NULLPTR;
}
}
}
void MainWindow::showEntryContextMenu(const QPoint& globalPos) void MainWindow::showEntryContextMenu(const QPoint& globalPos)
{ {
m_ui->menuEntries->popup(globalPos); m_ui->menuEntries->popup(globalPos);
@ -511,4 +557,31 @@ void MainWindow::applySettingsChanges()
else { else {
m_inactivityTimer->deactivate(); m_inactivityTimer->deactivate();
} }
updateTrayIcon();
}
void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason)
{
if (reason == QSystemTrayIcon::Trigger) {
toggleWindow();
}
}
void MainWindow::toggleWindow()
{
if (QApplication::activeWindow() == this) {
hide();
}
else {
show();
raise();
activateWindow();
}
}
bool MainWindow::isTrayIconEnabled() const
{
return config()->get("GUI/ShowTrayIcon").toBool()
&& QSystemTrayIcon::isSystemTrayAvailable();
} }

View File

@ -20,6 +20,7 @@
#include <QActionGroup> #include <QActionGroup>
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon>
#include "core/SignalMultiplexer.h" #include "core/SignalMultiplexer.h"
#include "gui/DatabaseWidget.h" #include "gui/DatabaseWidget.h"
@ -44,6 +45,7 @@ public Q_SLOTS:
protected: protected:
void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE;
void changeEvent(QEvent* event) Q_DECL_OVERRIDE;
private Q_SLOTS: private Q_SLOTS:
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None); void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None);
@ -61,6 +63,8 @@ private Q_SLOTS:
void saveToolbarState(bool value); void saveToolbarState(bool value);
void rememberOpenDatabases(const QString& filePath); void rememberOpenDatabases(const QString& filePath);
void applySettingsChanges(); void applySettingsChanges();
void trayIconTriggered(QSystemTrayIcon::ActivationReason reason);
void toggleWindow();
private: private:
static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0); static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0);
@ -69,6 +73,8 @@ private:
void saveWindowInformation(); void saveWindowInformation();
bool saveLastDatabases(); bool saveLastDatabases();
void updateTrayIcon();
bool isTrayIconEnabled() const;
const QScopedPointer<Ui::MainWindow> m_ui; const QScopedPointer<Ui::MainWindow> m_ui;
SignalMultiplexer m_actionMultiplexer; SignalMultiplexer m_actionMultiplexer;
@ -78,6 +84,7 @@ private:
QStringList m_openDatabases; QStringList m_openDatabases;
InactivityTimer* m_inactivityTimer; InactivityTimer* m_inactivityTimer;
int m_countDefaultAttributes; int m_countDefaultAttributes;
QSystemTrayIcon* m_trayIcon;
Q_DISABLE_COPY(MainWindow) Q_DISABLE_COPY(MainWindow)
}; };

View File

@ -47,6 +47,8 @@ SettingsWidget::SettingsWidget(QWidget* parent)
connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)),
this, SLOT(enableAutoSaveOnExit(bool))); this, SLOT(enableAutoSaveOnExit(bool)));
connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)),
m_generalUi->systrayMinimizeToTrayCheckBox, SLOT(setEnabled(bool)));
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)), connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)),
m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool))); m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
@ -80,6 +82,9 @@ void SettingsWidget::loadSettings()
m_generalUi->languageComboBox->setCurrentIndex(defaultIndex); m_generalUi->languageComboBox->setCurrentIndex(defaultIndex);
} }
m_generalUi->systrayShowCheckBox->setChecked(config()->get("GUI/ShowTrayIcon").toBool());
m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool());
if (autoType()->isAvailable()) { if (autoType()->isAvailable()) {
m_globalAutoTypeKey = static_cast<Qt::Key>(config()->get("GlobalAutoTypeKey").toInt()); m_globalAutoTypeKey = static_cast<Qt::Key>(config()->get("GlobalAutoTypeKey").toInt());
m_globalAutoTypeModifiers = static_cast<Qt::KeyboardModifiers>(config()->get("GlobalAutoTypeModifiers").toInt()); m_globalAutoTypeModifiers = static_cast<Qt::KeyboardModifiers>(config()->get("GlobalAutoTypeModifiers").toInt());
@ -118,6 +123,10 @@ void SettingsWidget::saveSettings()
m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked()); m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked());
int currentLangIndex = m_generalUi->languageComboBox->currentIndex(); int currentLangIndex = m_generalUi->languageComboBox->currentIndex();
config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString()); config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString());
config()->set("GUI/ShowTrayIcon", m_generalUi->systrayShowCheckBox->isChecked());
config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked());
if (autoType()->isAvailable()) { if (autoType()->isAvailable()) {
config()->set("GlobalAutoTypeKey", m_generalUi->autoTypeShortcutWidget->key()); config()->set("GlobalAutoTypeKey", m_generalUi->autoTypeShortcutWidget->key());
config()->set("GlobalAutoTypeModifiers", config()->set("GlobalAutoTypeModifiers",

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>456</width> <width>456</width>
<height>288</height> <height>340</height>
</rect> </rect>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
@ -96,6 +96,23 @@
<item row="9" column="1"> <item row="9" column="1">
<widget class="QComboBox" name="languageComboBox"/> <widget class="QComboBox" name="languageComboBox"/>
</item> </item>
<item row="10" column="0">
<widget class="QCheckBox" name="systrayShowCheckBox">
<property name="text">
<string>Show a system tray icon</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="systrayMinimizeToTrayCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Hide window to system tray when minimized</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>

View File

@ -39,6 +39,8 @@ int main(int argc, char** argv)
// don't set organizationName as that changes the return value of // don't set organizationName as that changes the return value of
// QDesktopServices::storageLocation(QDesktopServices::DataLocation) // QDesktopServices::storageLocation(QDesktopServices::DataLocation)
QApplication::setQuitOnLastWindowClosed(false);
if (!Crypto::init()) { if (!Crypto::init()) {
QString error = QCoreApplication::translate("Main", QString error = QCoreApplication::translate("Main",
"Fatal error while testing the cryptographic functions."); "Fatal error while testing the cryptographic functions.");