#include "kactioncollectiontest.h" #include #include #include #include #include #include void tst_KActionCollection::init() { collection = new KActionCollection(static_cast(nullptr)); } void tst_KActionCollection::cleanup() { delete collection; collection = nullptr; } void tst_KActionCollection::clear() { QPointer action1 = collection->add(QStringLiteral("test1")); QPointer action2 = collection->add(QStringLiteral("test2")); QPointer action3 = collection->add(QStringLiteral("test3")); QPointer action4 = collection->add(QStringLiteral("test4")); QPointer action5 = collection->add(QStringLiteral("test5")); QPointer action6 = collection->add(QStringLiteral("test6")); QPointer action7 = collection->add(QStringLiteral("test7")); collection->clear(); QVERIFY(collection->isEmpty()); QVERIFY(action1.isNull()); QVERIFY(action2.isNull()); QVERIFY(action3.isNull()); QVERIFY(action4.isNull()); QVERIFY(action5.isNull()); QVERIFY(action6.isNull()); QVERIFY(action7.isNull()); } void tst_KActionCollection::addStandardActionFunctorSignal() { bool received = false; QAction *a = collection->addAction(KStandardActions::New, QStringLiteral("test"), this, [&]() { received = true; }); a->trigger(); QVERIFY(received); delete a; QVERIFY(collection->isEmpty()); } void tst_KActionCollection::deleted() { // Delete action -> automatically removed from collection QAction *a = collection->add(QStringLiteral("test")); delete a; QVERIFY(collection->isEmpty()); // Delete action's parent -> automatically removed from collection QWidget *myWidget = new QWidget(nullptr); QPointer action = new QAction(/*i18n()*/ QStringLiteral("Foo"), myWidget); collection->addAction(QStringLiteral("foo"), action); delete myWidget; QVERIFY(collection->isEmpty()); QVERIFY(action.isNull()); // Delete action's parent, but the action was added to another widget with setAssociatedWidget // and that widget gets deleted first. myWidget = new QWidget(nullptr); QWidget *myAssociatedWidget = new QWidget(myWidget); // child widget action = new QAction(/*i18n()*/ QStringLiteral("Foo"), myWidget); // child action collection->addAction(QStringLiteral("foo"), action); collection->addAssociatedWidget(myAssociatedWidget); QVERIFY(myAssociatedWidget->actions().contains(action)); delete myAssociatedWidget; // would be done by the line below, but let's make sure it happens first delete myWidget; QVERIFY(collection->isEmpty()); QVERIFY(action.isNull()); } void tst_KActionCollection::take() { QAction *a = collection->add(QStringLiteral("test")); collection->takeAction(a); QVERIFY(collection->isEmpty()); delete a; } void tst_KActionCollection::writeSettings() { KConfigGroup cfg = clearConfig(); QList defaultShortcut; defaultShortcut << Qt::Key_A << Qt::Key_B; QList temporaryShortcut; temporaryShortcut << Qt::Key_C << Qt::Key_D; QAction *actionWithDifferentShortcut = new QAction(this); KActionCollection::setDefaultShortcuts(actionWithDifferentShortcut, defaultShortcut); actionWithDifferentShortcut->setShortcuts(temporaryShortcut); collection->addAction(QStringLiteral("actionWithDifferentShortcut"), actionWithDifferentShortcut); QAction *immutableAction = new QAction(this); KActionCollection::setDefaultShortcuts(immutableAction, defaultShortcut); immutableAction->setShortcuts(temporaryShortcut); KActionCollection::setShortcutsConfigurable(immutableAction, false); collection->addAction(QStringLiteral("immutableAction"), immutableAction); QAction *actionWithSameShortcut = new QAction(this); KActionCollection::setDefaultShortcuts(actionWithSameShortcut, defaultShortcut); collection->addAction(QStringLiteral("actionWithSameShortcut"), actionWithSameShortcut); cfg.writeEntry("actionToDelete", QStringLiteral("Foobar")); QAction *actionToDelete = new QAction(this); KActionCollection::setDefaultShortcuts(actionToDelete, defaultShortcut); collection->addAction(QStringLiteral("actionToDelete"), actionToDelete); collection->writeSettings(&cfg); QCOMPARE(cfg.readEntry("actionWithDifferentShortcut", QString()), QKeySequence::listToString(actionWithDifferentShortcut->shortcuts())); QCOMPARE(cfg.readEntry("immutableAction", QString()), QString()); QCOMPARE(cfg.readEntry("actionWithSameShortcut", QString()), QString()); QCOMPARE(cfg.readEntry("actionToDelete", QString()), QString()); qDeleteAll(collection->actions()); } void tst_KActionCollection::readSettings() { KConfigGroup cfg = clearConfig(); QList defaultShortcut; defaultShortcut << Qt::Key_A << Qt::Key_B; QList temporaryShortcut; temporaryShortcut << Qt::Key_C << Qt::Key_D; cfg.writeEntry("normalAction", QKeySequence::listToString(defaultShortcut)); cfg.writeEntry("immutable", QKeySequence::listToString(defaultShortcut)); cfg.writeEntry("empty", QString()); QAction *normal = new QAction(this); collection->addAction(QStringLiteral("normalAction"), normal); QAction *immutable = new QAction(this); immutable->setShortcuts(temporaryShortcut); KActionCollection::setDefaultShortcuts(immutable, temporaryShortcut); KActionCollection::setShortcutsConfigurable(immutable, false); collection->addAction(QStringLiteral("immutable"), immutable); QAction *empty = new QAction(this); collection->addAction(QStringLiteral("empty"), empty); KActionCollection::setDefaultShortcuts(empty, defaultShortcut); empty->setShortcuts(temporaryShortcut); QCOMPARE(QKeySequence::listToString(empty->shortcuts()), QKeySequence::listToString(temporaryShortcut)); collection->readSettings(&cfg); QCOMPARE(QKeySequence::listToString(normal->shortcuts()), QKeySequence::listToString(defaultShortcut)); QCOMPARE(QKeySequence::listToString(empty->shortcuts()), QKeySequence::listToString(defaultShortcut)); QCOMPARE(QKeySequence::listToString(immutable->shortcuts()), QKeySequence::listToString(temporaryShortcut)); qDeleteAll(collection->actions()); } void tst_KActionCollection::insertReplaces1() { QAction *a = new QAction(nullptr); QAction *b = new QAction(nullptr); collection->addAction(QStringLiteral("a"), a); QVERIFY(collection->actions().contains(a)); QVERIFY(collection->action(QStringLiteral("a")) == a); collection->addAction(QStringLiteral("a"), b); QVERIFY(!collection->actions().contains(a)); QVERIFY(collection->actions().contains(b)); QVERIFY(collection->action(QStringLiteral("a")) == b); delete a; delete b; } /** * Check that a action added twice under different names only ends up once in * the collection */ void tst_KActionCollection::insertReplaces2() { QAction *a = new QAction(nullptr); collection->addAction(QStringLiteral("a"), a); QVERIFY(collection->actions().contains(a)); QVERIFY(collection->action(QStringLiteral("a")) == a); // Simple test: Just add it twice collection->addAction(QStringLiteral("b"), a); QVERIFY(collection->actions().contains(a)); QVERIFY(!collection->action(QStringLiteral("a"))); QVERIFY(collection->action(QStringLiteral("b")) == a); // Complex text: Mesh with the objectname a->setObjectName(QStringLiteral("c")); collection->addAction(QStringLiteral("d"), a); QVERIFY(collection->actions().contains(a)); QVERIFY(!collection->action(QStringLiteral("b"))); QVERIFY(!collection->action(QStringLiteral("c"))); QVERIFY(collection->action(QStringLiteral("d")) == a); delete a; } KConfigGroup tst_KActionCollection::clearConfig() { KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); cfg->deleteGroup(collection->configGroup()); return KConfigGroup(cfg, collection->configGroup()); } void tst_KActionCollection::testSetShortcuts() { QAction *action = new QAction(/*i18n*/ (QStringLiteral("Next Unread &Folder")), this); collection->addAction(QStringLiteral("go_next_unread_folder"), action); KActionCollection::setDefaultShortcut(action, QKeySequence(Qt::ALT | Qt::Key_Plus)); QList shortcut = action->shortcuts(); shortcut << QKeySequence(Qt::CTRL | Qt::Key_Plus); action->setShortcuts(shortcut); QCOMPARE(QKeySequence::listToString(action->shortcuts()), QStringLiteral("Alt++; Ctrl++")); // Simpler way: QList shortcut2; shortcut2 << QKeySequence(Qt::ALT | Qt::Key_Plus) << QKeySequence(Qt::CTRL | Qt::Key_Plus); QCOMPARE(QKeySequence::listToString(shortcut2), QStringLiteral("Alt++; Ctrl++")); } void tst_KActionCollection::implicitStandardActionInsertionUsingCreate() { KActionCollection collection(static_cast(nullptr)); QAction *a = KStandardActions::create(KStandardActions::Undo, qApp, &QCoreApplication::quit, &collection); QVERIFY(a); QVERIFY(a->parent() == &collection); QVERIFY(collection.action(KStandardActions::name(KStandardActions::Undo)) == a); } void tst_KActionCollection::implicitStandardActionInsertionUsingCut() { KActionCollection collection(static_cast(nullptr)); QAction *cut = KStandardAction::cut(&collection); QAction *a = collection.action(KStandardActions::name(KStandardActions::Cut)); QVERIFY(a); QVERIFY(a == cut); } void tst_KActionCollection::shouldEmitSignals() { QAction *a = new QAction(nullptr); QAction *b = new QAction(nullptr); QSignalSpy insertedSpy(collection, &KActionCollection::inserted); QSignalSpy changedSpy(collection, &KActionCollection::changed); // Insert "first" collection->addAction(QStringLiteral("first"), a); QVERIFY(collection->actions().contains(a)); QCOMPARE(insertedSpy.count(), 1); QCOMPARE(insertedSpy.at(0).at(0).value(), a); QCOMPARE(changedSpy.count(), 1); insertedSpy.clear(); changedSpy.clear(); // Replace "first" collection->addAction(QStringLiteral("first"), b); QVERIFY(!collection->actions().contains(a)); QVERIFY(collection->actions().contains(b)); QCOMPARE(insertedSpy.count(), 1); QCOMPARE(insertedSpy.at(0).at(0).value(), b); QCOMPARE(changedSpy.count(), 2); // once for removing a, once for inserting b insertedSpy.clear(); changedSpy.clear(); // Insert "second" collection->addAction(QStringLiteral("second"), a); QCOMPARE(insertedSpy.count(), 1); QCOMPARE(insertedSpy.at(0).at(0).value(), a); QCOMPARE(changedSpy.count(), 1); insertedSpy.clear(); changedSpy.clear(); // Remove and delete "second" (which is a) collection->removeAction(a); QCOMPARE(changedSpy.count(), 1); changedSpy.clear(); // Delete b directly, should automatically remove it from the collection and emit changed delete b; QCOMPARE(changedSpy.count(), 1); changedSpy.clear(); } QTEST_MAIN(tst_KActionCollection) #include "moc_kactioncollectiontest.cpp"