From 439c155552f6508ae26a7a43f9361fc0ee23a307 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 1 Apr 2021 05:12:59 +0200 Subject: [PATCH] Show countdown for clipboard clearing (#6333) * Closes #1843 Co-authored-by: Jonathan White --- src/gui/Clipboard.cpp | 30 ++++++++++++++++++----------- src/gui/Clipboard.h | 8 +++++++- src/gui/MainWindow.cpp | 26 +++++++++++++++++++++++++ src/gui/MainWindow.h | 7 +++++++ src/gui/styles/base/basestyle.qss | 4 ++++ src/gui/styles/dark/DarkStyle.cpp | 3 ++- src/gui/styles/light/LightStyle.cpp | 3 ++- 7 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index ab4a84cf0..804a53143 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -39,8 +39,7 @@ Clipboard::Clipboard(QObject* parent) m_pasteboard = new MacPasteboard(); } #endif - m_timer->setSingleShot(true); - connect(m_timer, SIGNAL(timeout()), SLOT(clearClipboard())); + connect(m_timer, SIGNAL(timeout()), SLOT(countdownTick())); connect(qApp, SIGNAL(aboutToQuit()), SLOT(clearCopiedText())); } @@ -77,7 +76,9 @@ void Clipboard::setText(const QString& text, bool clear) if (config()->get(Config::Security_ClearClipboard).toBool()) { int timeout = config()->get(Config::Security_ClearClipboardTimeout).toInt(); if (timeout > 0) { - m_timer->start(timeout * 1000); + m_secondsElapsed = -1; + countdownTick(); + m_timer->start(1000); } } } @@ -85,15 +86,9 @@ void Clipboard::setText(const QString& text, bool clear) void Clipboard::clearCopiedText() { - if (m_timer->isActive()) { - m_timer->stop(); - } + m_timer->stop(); + emit updateCountdown(-1, ""); - clearClipboard(); -} - -void Clipboard::clearClipboard() -{ auto* clipboard = QApplication::clipboard(); if (!clipboard) { qWarning("Unable to access the clipboard."); @@ -108,6 +103,19 @@ void Clipboard::clearClipboard() m_lastCopied.clear(); } +void Clipboard::countdownTick() +{ + m_secondsElapsed++; + int timeout = config()->get(Config::Security_ClearClipboardTimeout).toInt(); + int timeLeft = timeout - m_secondsElapsed; + if (timeLeft <= 0) { + clearCopiedText(); + } else { + emit updateCountdown(100 * timeLeft / timeout, + QObject::tr("Clearing the clipboard in %1 second(s)…", "", timeLeft).arg(timeLeft)); + } +} + Clipboard* Clipboard::instance() { if (!m_instance) { diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index 7465f30a5..c97d91881 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -19,6 +19,7 @@ #ifndef KEEPASSX_CLIPBOARD_H #define KEEPASSX_CLIPBOARD_H +#include #include #ifdef Q_OS_MACOS #include "core/MacPasteboard.h" @@ -39,8 +40,11 @@ public: public slots: void clearCopiedText(); +signals: + void updateCountdown(int percentage, QString message); + private slots: - void clearClipboard(); + void countdownTick(); private: explicit Clipboard(QObject* parent = nullptr); @@ -48,6 +52,8 @@ private: static Clipboard* m_instance; QTimer* m_timer; + int m_secondsElapsed = 0; + #ifdef Q_OS_MACOS // This object lives for the whole program lifetime and we cannot delete it on exit, // so ignore leak warnings. See https://bugreports.qt.io/browse/QTBUG-54832 diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 8a6ea610a..830e34d3e 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -623,6 +623,19 @@ MainWindow::MainWindow() connect(qApp, SIGNAL(openFile(QString)), this, SLOT(openDatabase(QString))); connect(qApp, SIGNAL(quitSignalReceived()), this, SLOT(appExit()), Qt::DirectConnection); + statusBar()->setFixedHeight(24); + m_progressBarLabel = new QLabel(statusBar()); + m_progressBarLabel->setVisible(false); + statusBar()->addPermanentWidget(m_progressBarLabel); + m_progressBar = new QProgressBar(statusBar()); + m_progressBar->setVisible(false); + m_progressBar->setTextVisible(false); + m_progressBar->setMaximumWidth(100); + m_progressBar->setFixedHeight(15); + m_progressBar->setMaximum(100); + statusBar()->addPermanentWidget(m_progressBar); + connect(clipboard(), SIGNAL(updateCountdown(int, QString)), this, SLOT(updateProgressBar(int, QString))); + restoreConfigState(); } @@ -1388,6 +1401,19 @@ void MainWindow::updateTrayIcon() QApplication::setQuitOnLastWindowClosed(!isTrayIconEnabled()); } +void MainWindow::updateProgressBar(int percentage, QString message) +{ + if (percentage < 0) { + m_progressBar->setVisible(false); + m_progressBarLabel->setVisible(false); + } else { + m_progressBar->setValue(percentage); + m_progressBar->setVisible(true); + m_progressBarLabel->setText(message); + m_progressBarLabel->setVisible(true); + } +} + void MainWindow::obtainContextFocusLock() { m_contextMenuFocusLock = true; diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 4163ba71a..7faf72fdf 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -20,11 +20,15 @@ #define KEEPASSX_MAINWINDOW_H #include +#include #include +#include +#include #include #include "core/SignalMultiplexer.h" #include "gui/Application.h" +#include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" #include "gui/osutils/ScreenLockListener.h" @@ -143,6 +147,7 @@ private slots: void releaseContextFocusLock(); void agentEnabled(bool enabled); void updateTrayIcon(); + void updateProgressBar(int percentage, QString message); private: static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0); @@ -174,6 +179,8 @@ private: QPointer m_trayIcon; QPointer m_screenLockListener; QPointer m_searchWidget; + QPointer m_progressBar; + QPointer m_progressBarLabel; Q_DISABLE_COPY(MainWindow) diff --git a/src/gui/styles/base/basestyle.qss b/src/gui/styles/base/basestyle.qss index ff5d915bb..e015efc25 100644 --- a/src/gui/styles/base/basestyle.qss +++ b/src/gui/styles/base/basestyle.qss @@ -69,3 +69,7 @@ QPlainTextEdit, QTextEdit { background-color: palette(base); padding-left: 4px; } + +QStatusBar { + background-color: palette(window); +} diff --git a/src/gui/styles/dark/DarkStyle.cpp b/src/gui/styles/dark/DarkStyle.cpp index b42d319af..a43419667 100644 --- a/src/gui/styles/dark/DarkStyle.cpp +++ b/src/gui/styles/dark/DarkStyle.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include DarkStyle::DarkStyle() @@ -110,7 +111,7 @@ QString DarkStyle::getAppStyleSheet() const void DarkStyle::polish(QWidget* widget) { if (qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) - || qobject_cast(widget)) { + || qobject_cast(widget) || qobject_cast(widget)) { auto palette = widget->palette(); #if defined(Q_OS_MACOS) if (!osUtils->isDarkMode()) { diff --git a/src/gui/styles/light/LightStyle.cpp b/src/gui/styles/light/LightStyle.cpp index 483e1323b..537e483ba 100644 --- a/src/gui/styles/light/LightStyle.cpp +++ b/src/gui/styles/light/LightStyle.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include LightStyle::LightStyle() @@ -111,7 +112,7 @@ QString LightStyle::getAppStyleSheet() const void LightStyle::polish(QWidget* widget) { if (qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) - || qobject_cast(widget)) { + || qobject_cast(widget) || qobject_cast(widget)) { auto palette = widget->palette(); #if defined(Q_OS_MACOS) if (osUtils->isDarkMode()) {