File indexing completed on 2024-04-28 15:31:56

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2002 Matthias Hölzer-Klüpfel <mhk@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KACCELERATORMANAGER_PRIVATE_H
0009 #define KACCELERATORMANAGER_PRIVATE_H
0010 
0011 #include <QObject>
0012 #include <QString>
0013 #include <QVector>
0014 
0015 class QStackedWidget;
0016 class QMenu;
0017 class QMenuBar;
0018 class QTabBar;
0019 class QDockWidget;
0020 
0021 /**
0022  * A string class handling accelerators.
0023  *
0024  * This class contains a string and knowledge about accelerators.
0025  * It keeps a list weights, telling how valuable each character
0026  * would be as an accelerator.
0027  *
0028  * @author Matthias Hölzer-Klüpfel <mhk@kde.org>
0029  */
0030 
0031 class KAccelString
0032 {
0033 public:
0034     KAccelString()
0035         : m_pureText()
0036         , m_accel(-1)
0037         , m_orig_accel(-1)
0038     {
0039     }
0040     explicit KAccelString(const QString &input, int initalWeight = -1);
0041 
0042     void calculateWeights(int initialWeight);
0043 
0044     const QString &pure() const
0045     {
0046         return m_pureText;
0047     }
0048     QString accelerated() const;
0049 
0050     int accel() const
0051     {
0052         return m_accel;
0053     }
0054     void setAccel(int accel)
0055     {
0056         m_accel = accel;
0057     }
0058 
0059     int originalAccel() const
0060     {
0061         return m_orig_accel;
0062     }
0063     QString originalText() const
0064     {
0065         return m_origText;
0066     }
0067 
0068     QChar accelerator() const;
0069 
0070     int maxWeight(int &index, const QString &used) const;
0071 
0072     bool operator==(const KAccelString &c) const
0073     {
0074         return m_pureText == c.m_pureText && m_accel == c.m_accel && m_orig_accel == c.m_orig_accel;
0075     }
0076 
0077 private:
0078     int stripAccelerator(QString &input);
0079 
0080     void dump();
0081 
0082     QString m_pureText;
0083     QString m_origText;
0084     int m_accel;
0085     int m_orig_accel;
0086     QVector<int> m_weight;
0087 };
0088 
0089 Q_DECLARE_TYPEINFO(KAccelString, Q_MOVABLE_TYPE);
0090 
0091 typedef QList<KAccelString> KAccelStringList;
0092 
0093 /**
0094  * This class encapsulates the algorithm finding the 'best'
0095  * distribution of accelerators in a hierarchy of widgets.
0096  *
0097  * @author Matthias Hölzer-Klüpfel <mhk@kde.org>
0098  */
0099 
0100 class KAccelManagerAlgorithm
0101 {
0102 public:
0103     enum {
0104         // Default control weight
0105         DEFAULT_WEIGHT = 50,
0106         // Additional weight for first character in string
0107         FIRST_CHARACTER_EXTRA_WEIGHT = 50,
0108         // Additional weight for the beginning of a word
0109         WORD_BEGINNING_EXTRA_WEIGHT = 50,
0110         // Additional weight for the dialog buttons (large, we basically never want these reassigned)
0111         DIALOG_BUTTON_EXTRA_WEIGHT = 300,
0112         // Additional weight for a 'wanted' accelerator
0113         WANTED_ACCEL_EXTRA_WEIGHT = 150,
0114         // Default weight for an 'action' widget (ie, pushbuttons)
0115         ACTION_ELEMENT_WEIGHT = 50,
0116         // Default weight for group boxes (lowest priority)
0117         GROUP_BOX_WEIGHT = -2000,
0118         // Default weight for checkable group boxes (low priority)
0119         CHECKABLE_GROUP_BOX_WEIGHT = 20,
0120         // Default weight for menu titles
0121         MENU_TITLE_WEIGHT = 250,
0122         // Additional weight for KDE standard accelerators
0123         STANDARD_ACCEL = 300,
0124     };
0125 
0126     static void findAccelerators(KAccelStringList &result, QString &used);
0127 };
0128 
0129 /**
0130  * This class manages a popup menu. It will notice if entries have been
0131  * added or changed, and will recalculate the accelerators accordingly.
0132  *
0133  * This is necessary for dynamic menus like for example in kicker.
0134  *
0135  * @author Matthias Hölzer-Klüpfel <mhk@kde.org>
0136  */
0137 
0138 class KPopupAccelManager : public QObject
0139 {
0140     Q_OBJECT
0141 
0142 public:
0143     static void manage(QMenu *popup);
0144 
0145 protected:
0146     KPopupAccelManager(QMenu *popup);
0147 
0148 private Q_SLOTS:
0149 
0150     void aboutToShow();
0151 
0152 private:
0153     void calculateAccelerators();
0154 
0155     void findMenuEntries(KAccelStringList &list);
0156     void setMenuEntries(const KAccelStringList &list);
0157 
0158     QMenu *m_popup;
0159     KAccelStringList m_entries;
0160     int m_count;
0161 };
0162 
0163 class QWidgetStackAccelManager : public QObject
0164 {
0165     Q_OBJECT
0166 
0167 public:
0168     static void manage(QStackedWidget *popup);
0169 
0170 protected:
0171     QWidgetStackAccelManager(QStackedWidget *popup);
0172 
0173 private Q_SLOTS:
0174 
0175     void currentChanged(int child);
0176     bool eventFilter(QObject *watched, QEvent *e) override;
0177 
0178 private:
0179     void calculateAccelerators();
0180 
0181     QStackedWidget *m_stack;
0182     KAccelStringList m_entries;
0183 };
0184 
0185 /*********************************************************************
0186 
0187  class KAcceleratorManagerPrivate - internal helper class
0188 
0189  This class does all the work to find accelerators for a hierarchy of
0190  widgets.
0191 
0192  *********************************************************************/
0193 
0194 class KAcceleratorManagerPrivate
0195 {
0196 public:
0197     static void manage(QWidget *widget);
0198     static bool programmers_mode;
0199     static void addStandardActionNames(const QStringList &strList);
0200     static bool standardName(const QString &str);
0201 
0202     static bool checkChange(const KAccelString &as)
0203     {
0204         QString t2 = as.accelerated();
0205         QString t1 = as.originalText();
0206         if (t1 != t2) {
0207             if (as.accel() == -1) {
0208                 removed_string += QLatin1String("<tr><td>") + t1.toHtmlEscaped() + QLatin1String("</td></tr>");
0209             } else if (as.originalAccel() == -1) {
0210                 added_string += QLatin1String("<tr><td>") + t2.toHtmlEscaped() + QLatin1String("</td></tr>");
0211             } else {
0212                 changed_string += QLatin1String("<tr><td>") + t1.toHtmlEscaped() + QLatin1String("</td>");
0213                 changed_string += QLatin1String("<td>") + t2.toHtmlEscaped() + QLatin1String("</td></tr>");
0214             }
0215             return true;
0216         }
0217         return false;
0218     }
0219     static QString changed_string;
0220     static QString added_string;
0221     static QString removed_string;
0222     static QMap<QWidget *, int> ignored_widgets;
0223     static QStringList standardNames;
0224 
0225 private:
0226     class Item;
0227 
0228 public:
0229     typedef QList<Item *> ItemList;
0230 
0231 private:
0232     static void traverseChildren(QWidget *widget, Item *item, QString &used);
0233 
0234     static void manageWidget(QWidget *widget, Item *item, QString &used);
0235     static void manageMenuBar(QMenuBar *mbar, Item *item);
0236     static void manageTabBar(QTabBar *bar, Item *item);
0237     static void manageDockWidget(QDockWidget *dock, Item *item);
0238 
0239     static void calculateAccelerators(Item *item, QString &used);
0240 
0241     class Item
0242     {
0243     public:
0244         Item()
0245             : m_widget(nullptr)
0246             , m_children(nullptr)
0247             , m_index(-1)
0248         {
0249         }
0250         ~Item();
0251 
0252         Item(const Item &) = delete;
0253         Item &operator=(const Item &) = delete;
0254 
0255         void addChild(Item *item);
0256 
0257         QWidget *m_widget;
0258         KAccelString m_content;
0259         ItemList *m_children;
0260         int m_index;
0261     };
0262 };
0263 
0264 #endif // KACCELERATORMANAGER_PRIVATE_H