/* This file is part of the KDE libraries Copyright 2007-2009 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "qtest_kde.h" #include "kxmlgui_unittest.h" #include #include #include #include #include #include "testxmlguiwindow.h" #include "testguiclient.h" #include "moc_kxmlgui_unittest.cpp" #include #include // it's not exported, so we need to include the code here #include #include QTEST_KDEMAIN(KXmlGui_UnitTest, GUI) enum Flags { NoFlags = 0, AddToolBars = 1, AddModifiedToolBars = 2, AddActionProperties = 4, AddModifiedMenus = 8 // next item is 16 }; static void createXmlFile(QFile& file, int version, int flags, const QByteArray& toplevelTag = "gui") { const QByteArray xml = "\n" "\n" "<" + toplevelTag + " version=\"" + QByteArray::number(version) + "\" name=\"foo\" >\n" "\n"; file.write(xml); if (flags & AddModifiedMenus) { file.write( "\n" "&File\n" "\n" "\n" ); } file.write("\n"); if (flags & AddToolBars) { file.write( "\n" " Main Toolbar\n" " \n" "\n" "\n" " Bookmark Toolbar\n" "\n" ); } if (flags & AddModifiedToolBars) { file.write( "\n" " Main Toolbar\n" " \n" "\n" "\n" " Modified toolbars\n" "\n" ); } if (flags & AddActionProperties) { file.write( "\n" " \n" "\n" ); } file.write("\n"); } void KXmlGui_UnitTest::testFindVersionNumber_data() { QTest::addColumn("xml"); QTest::addColumn("version"); QTest::newRow("simple test") << "\n" "\n" "\n" << "3"; QTest::newRow("two digits") << "\n" "\n" << "42"; QTest::newRow("with spaces") << // as found in dirfilterplugin.rc for instance "\n" "\n" << "1"; QTest::newRow("with a dot") << // as was found in autorefresh.rc "\n" "\n" << QString() /*error*/; QTest::newRow("with a comment") << // as found in kmail.rc "\n" "\n" "\n" << "452"; } void KXmlGui_UnitTest::testFindVersionNumber() { QFETCH(QString, xml); QFETCH(QString, version); QCOMPARE(KXmlGuiVersionHandler::findVersionNumber(xml), version); } void KXmlGui_UnitTest::testVersionHandlerSameVersion() { // This emulates the case where the user has modified stuff locally // and the application hasn't changed since, so the version number is unchanged. KTemporaryFile userFile; QVERIFY(userFile.open()); createXmlFile(userFile, 2, AddActionProperties | AddModifiedToolBars); const QString firstFile = userFile.fileName(); KTemporaryFile appFile; QVERIFY(appFile.open()); createXmlFile(appFile, 2, AddToolBars); const QString secondFile = appFile.fileName(); QStringList files; files << firstFile << secondFile; userFile.close(); appFile.close(); KXmlGuiVersionHandler versionHandler(files); QCOMPARE(versionHandler.finalFile(), firstFile); QString finalDoc = versionHandler.finalDocument(); QVERIFY(finalDoc.startsWith("")); QVERIFY(finalDoc.contains("sidebartng")); // Check that the toolbars modified by the user were kept QVERIFY(finalDoc.contains(" fileToVersionMap; // makes QCOMPARE failures more readable than just temp filenames QFile fileV2(KStandardDirs::locateLocal("appdata", "testui.rc")); QVERIFY(fileV2.open(QIODevice::WriteOnly)); createXmlFile(fileV2, 2, NoFlags); fileToVersionMap.insert(fileV2.fileName(), 2); KTemporaryFile fileV5; QVERIFY(fileV5.open()); createXmlFile(fileV5, 5, NoFlags); fileToVersionMap.insert(fileV5.fileName(), 5); // The highest version is neither the first nor last one in the list, // to make sure the code really selects the highest version, not just by chance :) // (This is why we add the v1 version at the end of the list) KTemporaryFile fileV1; QVERIFY(fileV1.open()); createXmlFile(fileV1, 1, NoFlags); fileToVersionMap.insert(fileV1.fileName(), 1); QStringList files; files << fileV2.fileName() << fileV5.fileName() << fileV1.fileName(); fileV2.close(); fileV5.close(); fileV1.close(); KXmlGuiVersionHandler versionHandler(files); QCOMPARE(fileToVersionMap.value(versionHandler.finalFile()), 5); QString finalDoc = versionHandler.finalDocument(); QVERIFY(finalDoc.startsWith(" fileToVersionMap; // makes QCOMPARE failures more readable than just temp filenames // local file QFile fileV2(KStandardDirs::locateLocal("appdata", "testui.rc")); QVERIFY(fileV2.open(QIODevice::WriteOnly)); createXmlFile(fileV2, 2, AddActionProperties | AddModifiedToolBars); fileToVersionMap.insert(fileV2.fileName(), 2); // more-global file KTemporaryFile fileV5; QVERIFY(fileV5.open()); createXmlFile(fileV5, 5, AddToolBars | AddModifiedMenus, "kpartgui"); fileToVersionMap.insert(fileV5.fileName(), 5); // The highest version is neither the first nor last one in the list, // to make sure the code really selects the highest version, not just by chance :) // (This is why we add the v1 version at the end of the list) KTemporaryFile fileV1; QVERIFY(fileV1.open()); createXmlFile(fileV1, 1, AddToolBars); fileToVersionMap.insert(fileV1.fileName(), 1); QStringList files; files << fileV2.fileName() << fileV5.fileName() << fileV1.fileName(); fileV2.close(); fileV5.close(); fileV1.close(); KXmlGuiVersionHandler versionHandler(files); // We end up with the local file, so in our map it has version 2. // But of course by now it says "version=5" in it :) QCOMPARE(fileToVersionMap.value(versionHandler.finalFile()), 2); const QString finalDoc = versionHandler.finalDocument(); //kDebug() << finalDoc; QVERIFY(finalDoc.startsWith("")); QVERIFY(finalDoc.contains("sidebartng")); // Check that the menus modified by the app are still there QVERIFY(finalDoc.contains(" containers = factory.containers("Menu"); QStringList containerNames; Q_FOREACH(QWidget* w, containers) { containerNames << w->objectName(); } return containerNames; } #if 0 static void debugActions(const QList& actions) { Q_FOREACH(QAction* action, actions) kDebug() << (action->isSeparator() ? QString("separator") : action->objectName()); } #endif static void checkActions(const QList& actions, const QStringList& expectedActions) { for (int i = 0; i < expectedActions.count(); ++i) { QAction* action = actions[i]; if (action->isSeparator()) QCOMPARE(QString("separator"), expectedActions[i]); else QCOMPARE(action->objectName(), expectedActions[i]); } QCOMPARE(actions.count(), expectedActions.count()); } void KXmlGui_UnitTest::testPartMerging() { const QByteArray hostXml = "\n" "\n" "\n" "\n" " &Go\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " &File\n" " \n" " \n" "\n" "\n"; TestGuiClient hostClient; hostClient.createActions(QStringList() << "go_up" << "go_back" << "go_forward" << "go_home" << "host_after_merge" << "host_after_merge_2" << "last_from_host" << "file_new" << "file_open" << "file_quit"); hostClient.createGUI(hostXml, true /*ui_standards.rc*/); KMainWindow mainWindow; KXMLGUIBuilder builder(&mainWindow); KXMLGUIFactory factory(&builder); factory.addClient(&hostClient); QWidget* goMenuW = factory.container("go", &hostClient); QVERIFY(goMenuW); QMenu* goMenu = qobject_cast(goMenuW); QVERIFY(goMenu); QMenu* fileMenu = qobject_cast(factory.container("file", &hostClient)); //debugActions(goMenu->actions()); checkActions(goMenu->actions(), QStringList() << "go_up" << "go_back" << "go_forward" << "go_home" << "separator" << "host_after_merge" << "host_after_merge_2" << "separator" << "last_from_host"); checkActions(fileMenu->actions(), QStringList() << "file_new" << "file_open" << "separator" << "file_quit"); kDebug() << "Now merging the part"; const QByteArray partXml = "\n" "\n" "\n" " &Go\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " &File\n" " \n" " \n" " \n" "\n" "\n"; TestGuiClient partClient(partXml); partClient.createActions(QStringList() << "go_previous" << "go_next" << "first_page" << "last_page" << "last_from_part" << "action_in_merge_group" << "undefined_group" << "action_in_placed_merge" << "other_file_action" ); factory.addClient(&partClient); //debugActions(goMenu->actions()); checkActions(goMenu->actions(), QStringList() << "go_up" << "go_back" << "go_forward" << "go_home" << "separator" // Contents of the : << "go_previous" << "go_next" << "separator" << "first_page" << "last_page" << "separator" << "undefined_group" << "last_from_part" // End of << "host_after_merge" << "host_after_merge_2" << "separator" // Contents of << "action_in_merge_group" // End of << "last_from_host" ); checkActions(fileMenu->actions(), QStringList() << "file_new" << "action_in_placed_merge" << "file_open" << "separator" << "file_quit" << "other_file_action"); factory.removeClient(&partClient); factory.removeClient(&hostClient); } void KXmlGui_UnitTest::testPartMergingSettings() // #252911 { const QByteArray hostXml = "\n" "\n" "\n" "\n" // The solution was to remove the duplicated definition // " &Settings\n" // " \n" // " \n" // " \n" // " \n" // " \n" // " \n" "\n"; TestGuiClient hostClient; hostClient.createActions(QStringList() << "options_configure_keybinding" << "options_configure_toolbars"); hostClient.createGUI(hostXml, true /*ui_standards.rc*/); //kDebug() << hostClient.domDocument().toString(); KMainWindow mainWindow; KXMLGUIBuilder builder(&mainWindow); KXMLGUIFactory factory(&builder); factory.addClient(&hostClient); QWidget* settingsMenu = qobject_cast(factory.container("settings", &hostClient)); QVERIFY(settingsMenu); //debugActions(settingsMenu->actions()); const QByteArray partXml = "\n" "\n" "\n" "\n" " &Settings\n" " \n" " \n" "\n"; TestGuiClient partClient(partXml); partClient.createActions(QStringList() << "configure_klinkstatus"); factory.addClient(&partClient); //debugActions(settingsMenu->actions()); checkActions(settingsMenu->actions(), QStringList() << "separator" // that's ok, QMenuPrivate::filterActions won't show it << "options_configure_keybinding" << "options_configure_toolbars" << "configure_klinkstatus"); factory.removeClient(&partClient); factory.removeClient(&hostClient); } void KXmlGui_UnitTest::testUiStandardsMerging_data() { QTest::addColumn("xml"); QTest::addColumn("actions"); QTest::addColumn("expectedMenus"); const QByteArray xmlBegin = "\n" "\n" "\n"; const QByteArray xmlEnd = "\n" ""; // Merging an empty menu (or a menu with only non-existing actions) would make // the empty menu appear at the end after all other menus (fixed for KDE-4.2) QTest::newRow("empty file menu, implicit settings menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "options_configure_toolbars") << (QStringList() << "settings"); QTest::newRow("file menu with non existing action, implicit settings menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "options_configure_toolbars") << (QStringList() << "settings"); QTest::newRow("file menu with existing action, implicit settings menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "open" << "options_configure_toolbars") << (QStringList() << "file" << "settings"); QTest::newRow("implicit file and settings menu") << QByteArray(xmlBegin + xmlEnd) << (QStringList() << "file_open" << "options_configure_toolbars") << (QStringList() << "file" << "settings"); // we could check that file_open is in the mainToolBar, too // Check that unknown non-empty menus are added at the "MergeLocal" position (before settings). QTest::newRow("foo menu added at the end") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open" << "options_configure_toolbars" << "foo_action") << (QStringList() << "file" << "foo" << "settings"); QTest::newRow("Bille's testcase: menu patch + menu edit") << QByteArray(xmlBegin + "\n" + "\n" + xmlEnd) << (QStringList() << "file_open" << "patch_generate" << "edit_foo") << (QStringList() << "file" << "edit" << "patch"); QTest::newRow("Bille's testcase: menu patch + menu edit, lowercase tag") << QByteArray(xmlBegin + "\n" + "\n" + xmlEnd) << (QStringList() << "file_open" << "patch_generate" << "edit_foo") << (QStringList() << "file" << "edit" << "patch"); // Check that allows to insert menus at specific positions QTest::newRow("Menu append") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open" << "options_configure_toolbars" << "foo_action" << "help_contents") << (QStringList() << "file" << "settings" << "foo" << "help"); QTest::newRow("Custom first menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "edit_undo" << "foo_action" << "help_contents") << (QStringList() << "foo" << "edit" << "help"); // Tests for noMerge="1" QTest::newRow("noMerge empty file menu, implicit settings menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open" << "options_configure_toolbars") << (QStringList() << "file" << "settings"); // we keep empty menus, see #186382 QTest::newRow("noMerge empty file menu, file_open moved elsewhere") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open") << (QStringList() << "file" << "foo"); QTest::newRow("noMerge file menu with open before new") << QByteArray(xmlBegin + "" + xmlEnd) << (QStringList() << "file_open" << "file_new") << (QStringList() << "file"); // TODO check the order of the actions in the menu? how? // Tests for deleted="true" QTest::newRow("deleted file menu, implicit settings menu") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open" << "options_configure_toolbars") << (QStringList() << "settings"); QTest::newRow("deleted file menu, file_open moved elsewhere") << QByteArray(xmlBegin + "\n" + xmlEnd) << (QStringList() << "file_open") << (QStringList() << "foo"); QTest::newRow("deleted file menu with actions (contradiction)") << QByteArray(xmlBegin + "" + xmlEnd) << (QStringList() << "file_open" << "file_new") << (QStringList()); } void KXmlGui_UnitTest::testUiStandardsMerging() { QFETCH(QByteArray, xml); QFETCH(QStringList, actions); QFETCH(QStringList, expectedMenus); TestGuiClient client; client.createActions(actions); client.createGUI(xml, true /*ui_standards.rc*/); const QDomDocument domDocument = client.domDocument(); const QDomElement docElem = domDocument.documentElement(); QCOMPARE(docElem.attribute("name"), QString("foo")); // not standard_containers from ui_standards.rc QCOMPARE(docElem.attribute("version"), QString("1")); // not standard_containers from ui_standards.rc KMainWindow mainWindow; KXMLGUIBuilder builder(&mainWindow); KXMLGUIFactory factory(&builder); factory.addClient(&client); const QStringList containerNames = collectMenuNames(factory); //kDebug() << containerNames; QCOMPARE(containerNames, expectedMenus); factory.removeClient(&client); } void KXmlGui_UnitTest::testActionListAndSeparator() { const QByteArray xml = "\n" "\n" "\n" "\n" " Add to Group\n" " \n" " " " \n" " \n" "\n" ""; TestGuiClient client(xml); client.createActions(QStringList() << "view_add_to_new_group"); KMainWindow mainWindow; KXMLGUIBuilder builder(&mainWindow); KXMLGUIFactory factory(&builder); factory.addClient(&client); QWidget* menuW = factory.container("groups", &client); QVERIFY(menuW); QMenu* menu = qobject_cast(menuW); QVERIFY(menu); //debugActions(menu->actions()); checkActions(menu->actions(), QStringList() << "separator" // that's ok, QMenuPrivate::filterActions won't show it << "view_add_to_new_group"); kDebug() << "Now plugging the actionlist"; KAction* action1 = new KAction(this); action1->setObjectName("action1"); action1->setShortcut(KShortcut("Ctrl+2")); QList actionList; actionList << action1; client.plugActionList("view_groups_list", actionList); QCOMPARE(action1->shortcut().toString(), QString("Ctrl+2")); //debugActions(menu->actions()); checkActions(menu->actions(), QStringList() << "action1" << "separator" << "view_add_to_new_group"); kDebug() << "Now remove+add gui client"; // While I'm here, what happens with the action list if I remove+add the guiclient, // like KXmlGuiWindow::newToolBarConfig does? factory.removeClient(&client); factory.addClient(&client); // We need to get the container widget again, it was re-created. menuW = factory.container("groups", &client); QVERIFY(menuW); menu = qobject_cast(menuW); //debugActions(menu->actions()); checkActions(menu->actions(), QStringList() << "separator" // yep, it removed the actionlist thing... << "view_add_to_new_group"); kDebug() << "Now plugging the actionlist again"; client.plugActionList("view_groups_list", actionList); checkActions(menu->actions(), QStringList() << "action1" << "separator" << "view_add_to_new_group"); factory.removeClient(&client); } void KXmlGui_UnitTest::testHiddenToolBar() { const QByteArray xml = "\n" "\n" "\n" "\n" "\n" "\n" "\n" " \n" "\n" "\n" "\n"; KConfigGroup cg(KGlobal::config(), "testHiddenToolBar"); TestXmlGuiWindow mainWindow(xml); mainWindow.setAutoSaveSettings(cg); mainWindow.createActions(QStringList() << "go_up"); mainWindow.createGUI(); KToolBar* mainToolBar = mainWindow.toolBarByName("mainToolBar"); QVERIFY(mainToolBar->isHidden()); KXMLGUIFactory* factory = mainWindow.guiFactory(); QVERIFY(!factory->container("visibleToolBar", &mainWindow)->isHidden()); KToolBar* hiddenToolBar = qobject_cast(factory->container("hiddenToolBar", &mainWindow)); kDebug() << hiddenToolBar; QVERIFY(hiddenToolBar->isHidden()); // Now open KEditToolBar (#105525) KEditToolBar editToolBar(factory); // KEditToolBar loads the stuff in showEvent... QShowEvent ev; qApp->sendEvent(&editToolBar, &ev); editToolBar.button(KDialog::Apply)->setEnabled(true); editToolBar.button(KDialog::Apply)->click(); QVERIFY(qobject_cast(factory->container("hiddenToolBar", &mainWindow))->isHidden()); mainWindow.close(); } // taken from KMainWindow_UnitTest::testAutoSaveSettings() void KXmlGui_UnitTest::testAutoSaveSettings() { const QByteArray xml = "\n" "\n" "\n" "\n" "\n" "\n" " \n" "\n" "\n" " \n" "\n" "\n"; { // do not interfere with the "toolbarVisibility" unit test KConfigGroup cg(KGlobal::config(), "testAutoSaveSettings"); TestXmlGuiWindow mw(xml); mw.setAutoSaveSettings(cg); // Test resizing first (like show() does). mw.reallyResize(400, 400); mw.createActions(QStringList() << "go_up"); mw.createGUI(); // Resize again, should be saved mw.reallyResize(800, 600); KToolBar* mainToolBar = mw.toolBarByName("mainToolBar"); QCOMPARE(mw.toolBarArea(mainToolBar), Qt::TopToolBarArea); KToolBar* secondToolBar = mw.toolBarByName("secondToolBar"); QCOMPARE(mw.toolBarArea(secondToolBar), Qt::TopToolBarArea); // REFERENCE #1 (see below) // Move second toolbar to bottom const QPoint oldPos = secondToolBar->pos(); mw.addToolBar(Qt::BottomToolBarArea, secondToolBar); const QPoint newPos = secondToolBar->pos(); QCOMPARE(mw.toolBarArea(secondToolBar), Qt::BottomToolBarArea); // Calling to addToolBar is not enough to trigger the event filter for move events // in KMainWindow, because there is no layouting happening in hidden mainwindows. QMoveEvent moveEvent(newPos, oldPos); QApplication::sendEvent(secondToolBar, &moveEvent); mw.close(); } { KConfigGroup cg(KGlobal::config(), "testAutoSaveSettings"); TestXmlGuiWindow mw2(xml); mw2.setAutoSaveSettings(cg); // Check window size was restored QCOMPARE(mw2.size(), QSize(800, 600)); mw2.createActions(QStringList() << "go_up"); mw2.createGUI(); // Force window layout to happen mw2.reallyResize(800, 600); // Check toolbar positions were restored KToolBar* mainToolBar = mw2.toolBarByName("mainToolBar"); QCOMPARE(mw2.toolBarArea(mainToolBar), Qt::TopToolBarArea); KToolBar* secondToolBar = mw2.toolBarByName("secondToolBar"); QCOMPARE(mw2.toolBarArea(secondToolBar), Qt::BottomToolBarArea); mw2.applyMainWindowSettings(mw2.autoSaveConfigGroup()); QCOMPARE(mw2.toolBarArea(secondToolBar), Qt::BottomToolBarArea); } } void KXmlGui_UnitTest::testDeletedContainers() // deleted="true" { const QByteArray xml = "\n" "\n" "\n" "\n" " \n" "\n" "\n" " \n" "\n" "\n" " \n" "\n" "\n" " \n" "\n" "\n"; KConfigGroup cg(KGlobal::config(), "testDeletedToolBar"); TestXmlGuiWindow mainWindow(xml); mainWindow.setAutoSaveSettings(cg); mainWindow.createActions(QStringList() << "go_up" << "file_new" << "game_new"); mainWindow.createGUI(); KXMLGUIFactory* factory = mainWindow.guiFactory(); //qDebug() << "containers:" << factory->containers("ToolBar"); QVERIFY(!factory->container("mainToolBar", &mainWindow)); QVERIFY(!factory->container("visibleToolBar", &mainWindow)->isHidden()); QVERIFY(!factory->container("deletedToolBar", &mainWindow)); QVERIFY(factory->container("file", &mainWindow)); // File menu was created QVERIFY(!factory->container("game", &mainWindow)); // Game menu was not created // Now open KEditToolBar, just to check it doesn't crash. KEditToolBar editToolBar(factory); // KEditToolBar loads the stuff in showEvent... QShowEvent ev; qApp->sendEvent(&editToolBar, &ev); editToolBar.button(KDialog::Apply)->setEnabled(true); editToolBar.button(KDialog::Apply)->click(); QVERIFY(!factory->container("mainToolBar", &mainWindow)); QVERIFY(!factory->container("visibleToolBar", &mainWindow)->isHidden()); QVERIFY(!factory->container("deletedToolBar", &mainWindow)); QVERIFY(factory->container("file", &mainWindow)); QVERIFY(!factory->container("game", &mainWindow)); mainWindow.close(); } void KXmlGui_UnitTest::testTopLevelSeparator() { const QByteArray xml = "\n" "\n" "\n" "\n" " Before Separator\n" " \n" " After Separator\n" "\n" ""; TestXmlGuiWindow mainWindow(xml); mainWindow.createGUI(); checkActions(mainWindow.menuBar()->actions(), QStringList() << "before_separator" << "separator" << "after_separator" << "separator" << "help"); } // Check that the objectName() of the menus is set from the name in the XML file void KXmlGui_UnitTest::testMenuNames() { const QByteArray xml = "\n" "\n" "\n" "\n" " File Menu\n" "\n" ""; TestXmlGuiWindow mainWindow(xml); mainWindow.createGUI(); checkActions(mainWindow.menuBar()->actions(), QStringList() << "filemenu" << "separator" << "help" ); } // Test what happens when the application's rc file isn't found // We want a warning to be printed, but we don't want to see all menus from ui_standards.rc void KXmlGui_UnitTest::testMenusNoXmlFile() { TestXmlGuiWindow mainWindow; mainWindow.createGUIBad(); checkActions(mainWindow.menuBar()->actions(), QStringList() << "help" ); } void KXmlGui_UnitTest::testXMLFileReplacement() { // to differentiate "original" and replacement xml file, one is created with "modified" toolbars KTemporaryFile fileOrig; QVERIFY(fileOrig.open()); createXmlFile(fileOrig, 2, AddToolBars); const QString filenameOrig = fileOrig.fileName(); fileOrig.close(); KTemporaryFile fileReplace; QVERIFY(fileReplace.open()); createXmlFile(fileReplace, 2, AddModifiedToolBars); const QString filenameReplace = fileReplace.fileName(); fileReplace.close(); // finally, our local xml file has QFile fileLocal(KStandardDirs::locateLocal("appdata", "testui.rc")); QVERIFY(fileLocal.open(QIODevice::WriteOnly)); createXmlFile(fileLocal, 1, AddActionProperties); const QString filenameLocal = fileLocal.fileName(); fileLocal.close(); TestGuiClient client; // first make sure that the "original" file is loaded, correctly client.setXMLFilePublic(filenameOrig); QString xml = client.domDocument().toString(); //qDebug() << xml; QVERIFY(xml.contains("")); // now test the replacement (+ local file) client.replaceXMLFile(filenameReplace, filenameLocal); xml = client.domDocument().toString(); QVERIFY(!xml.contains("")); // re-check after a reload client.reloadXML(); QString reloadedXml = client.domDocument().toString(); QVERIFY(!reloadedXml.contains("")); // Check what happens when the local file doesn't exist TestGuiClient client2; QFile::remove(filenameLocal); client2.replaceXMLFile(filenameReplace, filenameLocal); xml = client2.domDocument().toString(); //qDebug() << xml; QVERIFY(!xml.contains("")); // but no local xml file } void KXmlGui_UnitTest::testClientDestruction() { // #170806 const QByteArray hostXml = "\n" "\n" "\n" "\n" " &File\n" " \n" " \n" "\n" ""; const QByteArray xml = "\n" "\n" "\n" "\n" " &File\n" " \n" " \n" " \n" "\n" ""; TestXmlGuiWindow mainWindow(hostXml); TestGuiClient* client = new TestGuiClient(xml); client->createActions(QStringList() << "file_open" << "file_quit"); mainWindow.insertChildClient(client); mainWindow.createGUI(); checkActions(mainWindow.menuBar()->actions(), QStringList() << "file" << "separator" << "help" ); QVERIFY(mainWindow.factory()->clients().contains(client)); delete client; QVERIFY(!mainWindow.factory()->clients().contains(client)); // No change, because deletion is fast, it doesn't do manual unplugging. checkActions(mainWindow.menuBar()->actions(), QStringList() << "file" << "separator" << "help" ); }