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

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2017 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 #include <functional>
0008 #include <kacceleratormanager.h>
0009 
0010 #include <QMenu>
0011 #include <QPushButton>
0012 #include <QTest>
0013 
0014 #define QSL QStringLiteral
0015 
0016 static QStringList extractActionTexts(QMenu &menu, std::function<QString(const QAction *)> func)
0017 {
0018     menu.aboutToShow(); // signals are now public in Qt5, how convenient :-)
0019 
0020     QStringList ret;
0021     bool lastIsSeparator = false;
0022     const auto menuActions = menu.actions();
0023     for (const QAction *action : menuActions) {
0024         if (action->isSeparator()) {
0025             if (!lastIsSeparator) { // Qt gets rid of duplicate separators, so we should too
0026                 ret.append(QStringLiteral("separator"));
0027             }
0028             lastIsSeparator = true;
0029         } else {
0030             lastIsSeparator = false;
0031             if (action->menu()) {
0032                 ret.append(QStringLiteral("submenu"));
0033             } else {
0034                 const QString text = func(action);
0035                 ret.append(text);
0036             }
0037         }
0038     }
0039     return ret;
0040 }
0041 
0042 class KAcceleratorManagerTest : public QObject
0043 {
0044     Q_OBJECT
0045 
0046 private Q_SLOTS:
0047     void initTestCase()
0048     {
0049     }
0050 
0051     void testActionTexts_data()
0052     {
0053         QTest::addColumn<QStringList>("initialTexts");
0054         QTest::addColumn<QStringList>("expectedTexts");
0055 
0056         QTest::newRow("basic") << QStringList{QSL("Open"), QSL("Close"), QSL("Quit")} << QStringList{QSL("&Open"), QSL("&Close"), QSL("&Quit")};
0057         QTest::newRow("same_first") << QStringList{QSL("Open"), QSL("Close"), QSL("Clone"), QSL("Quit")}
0058                                     << QStringList{QSL("&Open"), QSL("&Close"), QSL("C&lone"), QSL("&Quit")};
0059         QTest::newRow("cjk") << QStringList{QSL("Open (&O)"), QSL("Close (&C)"), QSL("Clone (&C)"), QSL("Quit (&Q)")}
0060                              << QStringList{QSL("Open (&O)"), QSL("Close (&C)"), QSL("C&lone (C)"), QSL("Quit (&Q)")};
0061     }
0062 
0063     void testActionTexts()
0064     {
0065         // GIVEN
0066         QFETCH(QStringList, initialTexts);
0067         QFETCH(QStringList, expectedTexts);
0068         QMenu menu;
0069         for (const QString &text : std::as_const(initialTexts)) {
0070             menu.addAction(text);
0071         }
0072         // WHEN
0073         KAcceleratorManager::manage(&menu);
0074         // THEN
0075         const QStringList texts = extractActionTexts(menu, &QAction::text);
0076         QCOMPARE(texts, expectedTexts);
0077     }
0078 
0079     void testExistingActionsShortcutsAreTakenIntoAccount()
0080     {
0081         std::unique_ptr<QWidget> w(new QWidget());
0082 
0083         QPushButton *pb = new QPushButton(QSL("Open"), w.get());
0084 
0085         KAcceleratorManager::manage(w.get());
0086         QCOMPARE(pb->text(), QSL("&Open"));
0087 
0088         delete pb;
0089         pb = new QPushButton(QSL("Open"), w.get());
0090 
0091         QAction *a = new QAction();
0092         a->setShortcut(QSL("Alt+O"));
0093         w->addAction(a);
0094 
0095         KAcceleratorManager::manage(w.get());
0096         QCOMPARE(pb->text(), QSL("O&pen"));
0097     }
0098 
0099     void testActionIconTexts_data()
0100     {
0101         QTest::addColumn<QStringList>("initialTexts");
0102         QTest::addColumn<QStringList>("expectedTexts");
0103 
0104         QTest::newRow("basic") << QStringList{QSL("Open"), QSL("Close"), QSL("Quit")} << QStringList{QSL("Open"), QSL("Close"), QSL("Quit")};
0105         QTest::newRow("same_first") << QStringList{QSL("Open"), QSL("Close"), QSL("Clone"), QSL("Quit")}
0106                                     << QStringList{QSL("Open"), QSL("Close"), QSL("Clone"), QSL("Quit")};
0107         QTest::newRow("cjk") << QStringList{QSL("Open (&O)"), QSL("Close (&C)"), QSL("Clone (&C)"), QSL("Quit (&Q)")}
0108                              << QStringList{QSL("Open"), QSL("Close"), QSL("Clone"), QSL("Quit")};
0109     }
0110 
0111     void testActionIconTexts()
0112     {
0113         // GIVEN
0114         QFETCH(QStringList, initialTexts);
0115         QFETCH(QStringList, expectedTexts);
0116         QMenu menu;
0117         for (const QString &text : std::as_const(initialTexts)) {
0118             menu.addAction(text);
0119         }
0120         // WHEN
0121         KAcceleratorManager::manage(&menu);
0122         // THEN
0123         const QStringList iconTexts = extractActionTexts(menu, &QAction::iconText);
0124         QCOMPARE(iconTexts, expectedTexts);
0125     }
0126 };
0127 
0128 QTEST_MAIN(KAcceleratorManagerTest)
0129 
0130 #include "kacceleratormanagertest.moc"