[plasma/plasma-workspace] klipper: Klipper: Split the system tray menu between items and context menu

Jonathan Marten null at kde.org
Sun Oct 16 18:05:41 BST 2022


Git commit b906f72d2a0d14a8081ba7bf9420441930412018 by Jonathan Marten.
Committed on 16/10/2022 at 17:05.
Pushed by marten into branch 'master'.

Klipper: Split the system tray menu between items and context menu

As suggested a long time ago in the referenced bug and duplicates,
but never implemented for the traditional Klipper.  Makes the
system tray popup smaller, especially if the user has configured
a large number of history entries, and makes the traditional Klipper
work in the same way as the Plasma applet:  left click = history items,
right click = context menu.

Add icons to some actions  
Change text for action "show-on-mouse-pos" to reflect what it now does  
Change "KDE" -> "Plasma" in about text  
Eliminate redundant member variable KlipperPopup::m_nHistoryItems  

BUG:93649  
I18N:  
GUI:

M  +27   -11   klipper/klipper.cpp
M  +6    -0    klipper/klipper.h
M  +13   -35   klipper/klipperpopup.cpp
M  +2    -24   klipper/klipperpopup.h
M  +1    -1    klipper/main.cpp
M  +1    -1    klipper/tray.cpp

https://invent.kde.org/plasma/plasma-workspace/commit/b906f72d2a0d14a8081ba7bf9420441930412018

diff --git a/klipper/klipper.cpp b/klipper/klipper.cpp
index e2ee6e2345..ee2fea2c16 100644
--- a/klipper/klipper.cpp
+++ b/klipper/klipper.cpp
@@ -25,8 +25,10 @@
 #include <QSaveFile>
 #include <QtConcurrent>
 
+#include <KAboutData>
 #include <KActionCollection>
 #include <KGlobalAccel>
+#include <KHelpMenu>
 #include <KLocalizedString>
 #include <KMessageBox>
 #include <KNotification>
@@ -140,7 +142,6 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo
     m_history = new History(this);
     m_popup = new KlipperPopup(m_history);
     m_popup->setWindowFlags(m_popup->windowFlags() | Qt::FramelessWindowHint);
-    m_popup->setShowHelp(m_mode == KlipperMode::Standalone);
     connect(m_history, &History::changed, this, &Klipper::slotHistoryChanged);
     connect(m_history, &History::changed, m_popup, &KlipperPopup::slotHistoryChanged);
     connect(m_history, &History::topIsUserSelectedSet, m_popup, &KlipperPopup::slotTopIsUserSelectedSet);
@@ -192,8 +193,8 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo
 
     m_repeatAction = m_collection->addAction(QStringLiteral("repeat_action"));
     m_repeatAction->setText(i18nc("@action:inmenu", "Manually Invoke Action on Current Clipboard"));
+    m_repeatAction->setIcon(QIcon::fromTheme(QStringLiteral("open-menu-symbolic")));
     KGlobalAccel::setGlobalShortcut(m_repeatAction, QKeySequence(Qt::META | Qt::CTRL | Qt::Key_R));
-
     connect(m_repeatAction, &QAction::triggered, this, &Klipper::slotRepeatAction);
 
     // add an edit-possibility
@@ -208,6 +209,7 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo
     // add barcode for mobile phones
     m_showBarcodeAction = m_collection->addAction(QStringLiteral("show-barcode"));
     m_showBarcodeAction->setText(i18nc("@action:inmenu", "&Show Barcodeā€¦"));
+    m_showBarcodeAction->setIcon(QIcon::fromTheme(QStringLiteral("view-barcode-qr")));
     KGlobalAccel::setGlobalShortcut(m_showBarcodeAction, QKeySequence());
     connect(m_showBarcodeAction, &QAction::triggered, this, [this]() {
         showBarcode(m_history->first());
@@ -216,16 +218,19 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo
     // Cycle through history
     m_cycleNextAction = m_collection->addAction(QStringLiteral("cycleNextAction"));
     m_cycleNextAction->setText(i18nc("@action:inmenu", "Next History Item"));
+    m_cycleNextAction->setIcon(QIcon::fromTheme(QStringLiteral("go-next")));
     KGlobalAccel::setGlobalShortcut(m_cycleNextAction, QKeySequence());
     connect(m_cycleNextAction, &QAction::triggered, this, &Klipper::slotCycleNext);
     m_cyclePrevAction = m_collection->addAction(QStringLiteral("cyclePrevAction"));
     m_cyclePrevAction->setText(i18nc("@action:inmenu", "Previous History Item"));
+    m_cyclePrevAction->setIcon(QIcon::fromTheme(QStringLiteral("go-previous")));
     KGlobalAccel::setGlobalShortcut(m_cyclePrevAction, QKeySequence());
     connect(m_cyclePrevAction, &QAction::triggered, this, &Klipper::slotCyclePrev);
 
-    // Action to show Klipper popup on mouse position
+    // Action to show items popup on mouse position
     m_showOnMousePos = m_collection->addAction(QStringLiteral("show-on-mouse-pos"));
-    m_showOnMousePos->setText(i18nc("@action:inmenu", "Open Klipper at Mouse Position"));
+    m_showOnMousePos->setText(i18nc("@action:inmenu", "Show Items at Mouse Position"));
+    m_showOnMousePos->setIcon(QIcon::fromTheme(QStringLiteral("view-list-text")));
     KGlobalAccel::setGlobalShortcut(m_showOnMousePos, QKeySequence(Qt::META | Qt::Key_V));
     connect(m_showOnMousePos, &QAction::triggered, this, &Klipper::slotPopupMenu);
 
@@ -233,14 +238,25 @@ Klipper::Klipper(QObject *parent, const KSharedConfigPtr &config, KlipperMode mo
     connect(m_popup, &QMenu::aboutToShow, this, &Klipper::slotStartShowTimer);
 
     if (m_mode == KlipperMode::Standalone) {
-        m_popup->plugAction(m_toggleURLGrabAction);
-        m_popup->plugAction(m_clearHistoryAction);
-        m_popup->plugAction(m_configureAction);
-        m_popup->plugAction(m_repeatAction);
-        m_popup->plugAction(m_editAction);
-        m_popup->plugAction(m_showBarcodeAction);
+        // system tray popup menu
+        m_actionsPopup = new QMenu;
+        m_actionsPopup->addSection(QIcon::fromTheme(QStringLiteral("klipper")),
+                                   i18nc("%1 is application display name", "%1 - Clipboard Tool", QGuiApplication::applicationDisplayName()));
+        m_actionsPopup->addAction(m_toggleURLGrabAction);
+        m_actionsPopup->addAction(m_clearHistoryAction);
+        m_actionsPopup->addAction(m_configureAction);
+        m_actionsPopup->addAction(m_repeatAction);
+        m_actionsPopup->addAction(m_editAction);
+        m_actionsPopup->addAction(m_showBarcodeAction);
+
+        m_actionsPopup->addSeparator();
+
+        QMenu *helpMenu = (new KHelpMenu(m_actionsPopup, KAboutData::applicationData(), false))->menu();
+        helpMenu->setIcon(QIcon::fromTheme(QStringLiteral("help-contents")));
+        m_actionsPopup->addMenu(helpMenu);
+
         Q_ASSERT(m_quitAction);
-        m_popup->plugAction(m_quitAction);
+        m_actionsPopup->addAction(m_quitAction);
     }
 
     // session manager interaction
diff --git a/klipper/klipper.h b/klipper/klipper.h
index 306c55538b..614fd05391 100644
--- a/klipper/klipper.h
+++ b/klipper/klipper.h
@@ -90,6 +90,11 @@ public:
 
     void saveSettings() const;
 
+    QMenu *actionsPopup() const
+    {
+        return m_actionsPopup;
+    }
+
     KlipperPopup *popup()
     {
         return m_popup;
@@ -230,6 +235,7 @@ private:
     bool blockFetchingNewData();
     QString cycleText() const;
     KActionCollection *m_collection;
+    QMenu *m_actionsPopup;
     KlipperMode m_mode;
     QTimer *m_saveFileTimer = nullptr;
     QPointer<KNotification> m_notification;
diff --git a/klipper/klipperpopup.cpp b/klipper/klipperpopup.cpp
index c7ca11117e..0f1d8849f4 100644
--- a/klipper/klipperpopup.cpp
+++ b/klipper/klipperpopup.cpp
@@ -25,6 +25,7 @@
 
 namespace
 {
+// Index 0 is the menu header, index 1 is the search widget.
 static const int TOP_HISTORY_ITEM_INDEX = 2;
 }
 
@@ -58,12 +59,9 @@ kdbgstream &operator<<(kdbgstream &stream, const QKeyEvent &e)
 KlipperPopup::KlipperPopup(History *history)
     : m_dirty(true)
     , m_history(history)
-    , m_helpMenu(nullptr)
     , m_popupProxy(nullptr)
     , m_filterWidget(nullptr)
     , m_filterWidgetAction(nullptr)
-    , m_nHistoryItems(0)
-    , m_showHelp(true)
     , m_lastEvent(nullptr)
 {
     ensurePolished();
@@ -81,10 +79,6 @@ KlipperPopup::KlipperPopup(History *history)
     connect(this, &KlipperPopup::aboutToShow, this, &KlipperPopup::slotAboutToShow);
 }
 
-KlipperPopup::~KlipperPopup()
-{
-}
-
 void KlipperPopup::slotAboutToShow()
 {
     if (m_filterWidget) {
@@ -98,7 +92,7 @@ void KlipperPopup::slotAboutToShow()
 
 void KlipperPopup::ensureClean()
 {
-    // If the history is unchanged since last menu build, the is no reason
+    // If the history is unchanged since last menu build, there is no reason
     // to rebuild it,
     if (m_dirty) {
         rebuild();
@@ -107,7 +101,8 @@ void KlipperPopup::ensureClean()
 
 void KlipperPopup::buildFromScratch()
 {
-    addSection(QIcon::fromTheme(QStringLiteral("klipper")), i18n("Klipper - Clipboard Tool"));
+    addSection(QIcon::fromTheme(QStringLiteral("klipper")),
+               i18nc("%1 is application display name", "%1 - Clipboard Items", QGuiApplication::applicationDisplayName()));
 
     m_filterWidget = new KLineEdit(this);
     m_filterWidget->setFocusPolicy(Qt::NoFocus);
@@ -116,18 +111,7 @@ void KlipperPopup::buildFromScratch()
     m_filterWidgetAction->setDefaultWidget(m_filterWidget);
     addAction(m_filterWidgetAction);
 
-    addSeparator();
-    for (int i = 0; i < m_actions.count(); i++) {
-        if (i + 1 == m_actions.count() && m_showHelp) {
-            if (!m_helpMenu) {
-                m_helpMenu = new KHelpMenu(this, i18n("KDE cut & paste history utility"), false);
-            }
-            addMenu(m_helpMenu->menu())->setIcon(QIcon::fromTheme(QStringLiteral("help-contents")));
-            addSeparator();
-        }
-
-        addAction(m_actions.at(i));
-    }
+    Q_ASSERT(actions().count() == TOP_HISTORY_ITEM_INDEX);
 }
 
 void KlipperPopup::showStatus(const QString &errorText)
@@ -142,9 +126,7 @@ void KlipperPopup::showStatus(const QString &errorText)
     } else { // there is an error
         palette.setColor(m_filterWidget->foregroundRole(), colorScheme.foreground(KColorScheme::NegativeText).color());
         palette.setColor(m_filterWidget->backgroundRole(), colorScheme.background(KColorScheme::NegativeBackground).color());
-        insertAction(actions().at(TOP_HISTORY_ITEM_INDEX), new QAction(errorText, this));
-
-        ++m_nHistoryItems; // account for the added error item
+        addAction(new QAction(errorText, this));
     }
 
     m_filterWidget->setPalette(palette);
@@ -155,13 +137,11 @@ void KlipperPopup::rebuild(const QString &filter)
     if (actions().isEmpty()) {
         buildFromScratch();
     } else {
-        for (int i = 0; i < m_nHistoryItems; i++) {
-            Q_ASSERT(TOP_HISTORY_ITEM_INDEX < actions().count());
-
+        while (actions().count() > TOP_HISTORY_ITEM_INDEX) {
             // The old actions allocated by KlipperPopup::rebuild()
             // and PopupProxy::tryInsertItem() are deleted here when
             // the menu is rebuilt.
-            QAction *action = actions().at(TOP_HISTORY_ITEM_INDEX);
+            QAction *action = actions().last();
             removeAction(action);
             action->deleteLater();
         }
@@ -185,10 +165,9 @@ void KlipperPopup::rebuild(const QString &filter)
     QString errorText;
     if (!filterexp.isValid()) {
         errorText = i18n("Invalid regular expression, %1", filterexp.errorString());
-        m_nHistoryItems = 0;
     } else {
-        m_nHistoryItems = m_popupProxy->buildParent(TOP_HISTORY_ITEM_INDEX, filterexp);
-        if (m_nHistoryItems == 0) {
+        const int nHistoryItems = m_popupProxy->buildParent(TOP_HISTORY_ITEM_INDEX, filterexp);
+        if (nHistoryItems == 0) {
             if (m_history->empty()) {
                 errorText = i18n("Clipboard is empty");
             } else {
@@ -209,19 +188,18 @@ void KlipperPopup::rebuild(const QString &filter)
 
 void KlipperPopup::slotTopIsUserSelectedSet()
 {
-    if (!m_dirty && m_nHistoryItems > 0 && history()->topIsUserSelected()) {
+    if (!m_dirty && actions().count() > TOP_HISTORY_ITEM_INDEX && history()->topIsUserSelected()) {
         QAction *topAction = actions().at(TOP_HISTORY_ITEM_INDEX);
         topAction->setCheckable(true);
         topAction->setChecked(true);
     }
 }
 
-void KlipperPopup::plugAction(QAction *action)
+void KlipperPopup::showEvent(QShowEvent *e)
 {
-    m_actions.append(action);
+    popup(QCursor::pos());
 }
 
-/* virtual */
 void KlipperPopup::keyPressEvent(QKeyEvent *e)
 {
     // Most events are send down directly to the m_filterWidget.
diff --git a/klipper/klipperpopup.h b/klipper/klipperpopup.h
index 047c562aa0..be578bf1a2 100644
--- a/klipper/klipperpopup.h
+++ b/klipper/klipperpopup.h
@@ -13,7 +13,6 @@ class QAction;
 class QWidgetAction;
 class QKeyEvent;
 
-class KHelpMenu;
 class KLineEdit;
 
 class PopupProxy;
@@ -29,8 +28,7 @@ class KlipperPopup : public QMenu
 
 public:
     explicit KlipperPopup(History *history);
-    ~KlipperPopup() override;
-    void plugAction(QAction *action);
+    ~KlipperPopup() override = default;
 
     /**
      * Normally, the popupmenu is only rebuilt just before showing.
@@ -48,10 +46,6 @@ public:
         return m_history;
     }
 
-    void setShowHelp(bool show)
-    {
-        m_showHelp = show;
-    }
 public Q_SLOTS:
     void slotHistoryChanged()
     {
@@ -71,6 +65,7 @@ private:
 
 protected:
     void keyPressEvent(QKeyEvent *e) override;
+    void showEvent(QShowEvent *e) override;
 
 private:
     bool m_dirty : 1; // true if menu contents needs to be rebuild.
@@ -80,16 +75,6 @@ private:
      */
     History *m_history;
 
-    /**
-     * The help menu
-     */
-    KHelpMenu *m_helpMenu;
-
-    /**
-     * (unowned) actions to plug into the primary popup menu
-     */
-    QList<QAction *> m_actions;
-
     /**
      * Proxy helper object used to track history items
      */
@@ -105,13 +90,6 @@ private:
      */
     QWidgetAction *m_filterWidgetAction;
 
-    /**
-     * The current number of history items in the clipboard
-     */
-    int m_nHistoryItems;
-
-    bool m_showHelp;
-
     /**
      * The last event which was received. Used to avoid an infinite event loop
      */
diff --git a/klipper/main.cpp b/klipper/main.cpp
index b58ba9e74e..1cd711caba 100644
--- a/klipper/main.cpp
+++ b/klipper/main.cpp
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
     KAboutData aboutData(QStringLiteral("klipper"),
                          i18n("Klipper"),
                          QStringLiteral(KLIPPER_VERSION_STRING),
-                         i18n("KDE cut & paste history utility"),
+                         i18n("Plasma cut & paste history utility"),
                          KAboutLicense::GPL,
                          i18n("(c) 1998, Andrew Stanley-Jones\n"
                               "1998-2002, Carsten Pfeiffer\n"
diff --git a/klipper/tray.cpp b/klipper/tray.cpp
index 174d0d18b0..8453ee3608 100644
--- a/klipper/tray.cpp
+++ b/klipper/tray.cpp
@@ -28,7 +28,7 @@ KlipperTray::KlipperTray()
     setStandardActionsEnabled(false);
 
     m_klipper = new Klipper(this, KSharedConfig::openConfig());
-    setContextMenu(m_klipper->popup());
+    setContextMenu(m_klipper->actionsPopup());
     setAssociatedWidget(m_klipper->popup());
     connect(m_klipper->history(), &History::changed, this, &KlipperTray::slotSetToolTipFromHistory);
     slotSetToolTipFromHistory();


More information about the kde-doc-english mailing list