File indexing completed on 2025-09-14 03:53:00
0001 /* 0002 SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "parttest.h" 0008 #include <qtest_widgets.h> 0009 0010 #include <KSharedConfig> 0011 #include <QSignalSpy> 0012 #include <QTest> 0013 #include <QWidget> 0014 #include <kparts/guiactivateevent.h> 0015 #include <kparts/openurlarguments.h> 0016 #include <kparts/readonlypart.h> 0017 0018 QTEST_MAIN(PartTest) 0019 0020 class TestPart : public KParts::ReadOnlyPart 0021 { 0022 public: 0023 TestPart(QObject *parent, QWidget *parentWidget) 0024 : KParts::ReadOnlyPart(parent) 0025 , m_openFileCalled(false) 0026 { 0027 setWidget(new QWidget(parentWidget)); 0028 connect(this, &KParts::ReadOnlyPart::urlChanged, this, &TestPart::logUrlChanged); 0029 } 0030 0031 bool openFileCalled() const 0032 { 0033 return m_openFileCalled; 0034 } 0035 0036 void logUrlChanged(const QUrl &url) 0037 { 0038 qDebug() << "url changed: " << url; 0039 } 0040 0041 bool m_guiActivationEventTriggered = false; 0042 0043 protected: 0044 bool openFile() override 0045 { 0046 m_openFileCalled = true; 0047 return true; 0048 } 0049 void guiActivateEvent(KParts::GUIActivateEvent * /*event*/) override 0050 { 0051 m_guiActivationEventTriggered = true; 0052 } 0053 0054 private: 0055 bool m_openFileCalled; 0056 }; 0057 0058 void PartTest::testAutoDeletePart() 0059 { 0060 KParts::Part *part = new TestPart(nullptr, nullptr); 0061 QPointer<KParts::Part> partPointer(part); 0062 delete part->widget(); 0063 QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); 0064 QVERIFY(partPointer.isNull()); 0065 } 0066 0067 void PartTest::testAutoDeleteWidget() 0068 { 0069 KParts::Part *part = new TestPart(nullptr, nullptr); 0070 QPointer<KParts::Part> partPointer(part); 0071 QPointer<QWidget> widgetPointer(part->widget()); 0072 delete part; 0073 QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); 0074 QVERIFY(widgetPointer.isNull()); 0075 } 0076 0077 void PartTest::testNoAutoDeletePart() 0078 { 0079 KParts::Part *part = new TestPart(nullptr, nullptr); 0080 part->setAutoDeletePart(false); 0081 QPointer<KParts::Part> partPointer(part); 0082 delete part->widget(); 0083 QVERIFY(part->widget() == nullptr); 0084 QCOMPARE(static_cast<KParts::Part *>(partPointer), part); 0085 delete part; 0086 } 0087 0088 void PartTest::testNoAutoDeleteWidget() 0089 { 0090 KParts::Part *part = new TestPart(nullptr, nullptr); 0091 part->setAutoDeleteWidget(false); 0092 QWidget *widget = part->widget(); 0093 QVERIFY(widget); 0094 QPointer<QWidget> widgetPointer(part->widget()); 0095 delete part; 0096 QCOMPARE(static_cast<QWidget *>(widgetPointer), widget); 0097 delete widget; 0098 } 0099 0100 // There is no operator== in OpenUrlArguments because it's only useful in unit tests 0101 static bool compareArgs(const KParts::OpenUrlArguments &arg1, const KParts::OpenUrlArguments &arg2) 0102 { 0103 return arg1.mimeType() == arg2.mimeType() && // 0104 arg1.xOffset() == arg2.xOffset() && // 0105 arg1.yOffset() == arg2.yOffset() && // 0106 arg1.reload() == arg2.reload(); 0107 } 0108 0109 void PartTest::testOpenUrlArguments() 0110 { 0111 TestPart *part = new TestPart(nullptr, nullptr); 0112 QVERIFY(part->closeUrl()); // nothing to do, no error 0113 QVERIFY(part->arguments().mimeType().isEmpty()); 0114 KParts::OpenUrlArguments args; 0115 args.setMimeType(QStringLiteral("application/xml")); 0116 args.setXOffset(50); 0117 args.setYOffset(10); 0118 args.setReload(true); 0119 part->setArguments(args); 0120 QVERIFY(compareArgs(args, part->arguments())); 0121 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp"))); 0122 QVERIFY(part->openFileCalled()); 0123 QVERIFY(compareArgs(args, part->arguments())); 0124 0125 // Explicit call to closeUrl: arguments are cleared 0126 part->closeUrl(); 0127 QVERIFY(part->arguments().mimeType().isEmpty()); 0128 0129 // Calling openUrl with local file: mimetype is determined 0130 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp"))); 0131 QCOMPARE(part->arguments().mimeType(), QStringLiteral("text/x-c++src")); 0132 // (for a remote url it would be determined during downloading) 0133 0134 delete part; 0135 } 0136 0137 void PartTest::testAutomaticMimeType() 0138 { 0139 TestPart *part = new TestPart(nullptr, nullptr); 0140 QVERIFY(part->closeUrl()); // nothing to do, no error 0141 QVERIFY(part->arguments().mimeType().isEmpty()); 0142 // open a file, and test the detected mimetype 0143 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop"))); 0144 QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop")); 0145 0146 // manually closing, no mimetype should be stored now 0147 part->closeUrl(); 0148 QVERIFY(part->arguments().mimeType().isEmpty()); 0149 0150 // open a new file, and test again its (autdetected) mimetype 0151 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp"))); 0152 QCOMPARE(part->arguments().mimeType(), QStringLiteral("text/x-c++src")); 0153 0154 // open a new file, but without explicitly close the first 0155 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop"))); 0156 // test again its (autdetected) mimetype 0157 QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop")); 0158 0159 // open a new file, but manually forcing a mimetype 0160 KParts::OpenUrlArguments args; 0161 args.setMimeType(QStringLiteral("application/xml")); 0162 part->setArguments(args); 0163 QVERIFY(compareArgs(args, part->arguments())); 0164 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp"))); 0165 QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/xml")); 0166 0167 // clear the args and open a new file, reactivating the automatic mimetype detection again 0168 part->setArguments(KParts::OpenUrlArguments()); 0169 part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop"))); 0170 // test again its (autdetected) mimetype 0171 QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop")); 0172 0173 delete part; 0174 } 0175 0176 void PartTest::testEmptyUrlAfterCloseUrl() 0177 { 0178 TestPart *part = new TestPart(nullptr, nullptr); 0179 0180 QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop")))); 0181 QSignalSpy spy(part, &KParts::ReadOnlyPart::urlChanged); 0182 QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp")))); 0183 QVERIFY(!part->url().isEmpty()); 0184 QCOMPARE(spy.count(), 1); 0185 spy.clear(); 0186 QVERIFY(part->closeUrl()); 0187 QVERIFY(part->url().isEmpty()); 0188 QCOMPARE(spy.count(), 1); 0189 0190 delete part; 0191 } 0192 0193 #include <KConfigGroup> 0194 #include <KToggleToolBarAction> 0195 #include <KToolBar> 0196 #include <kparts/mainwindow.h> 0197 class MyMainWindow : public KParts::MainWindow 0198 { 0199 public: 0200 MyMainWindow() 0201 : KParts::MainWindow() 0202 { 0203 tb = new KToolBar(this); 0204 tb->setObjectName(QStringLiteral("testtbvisibility")); 0205 } 0206 0207 // createGUI and saveAutoSaveSettings are protected, so the whole test is here: 0208 void testToolbarVisibility() 0209 { 0210 QVERIFY(tb->isVisible()); 0211 0212 TestPart *part = new TestPart(nullptr, nullptr); 0213 // TODO define xml with a toolbar for the part 0214 // and put some saved settings into qttestrc in order to test 0215 // r347935+r348051, i.e. the fact that KParts::MainWindow::createGUI 0216 // will apply the toolbar settings (and that they won't have been 0217 // erased by the previous call to saveMainWindowSettings...) 0218 this->createGUI(part); 0219 0220 QVERIFY(tb->isVisible()); 0221 this->saveAutoSaveSettings(); 0222 0223 // Hide the toolbar using the action (so that setSettingsDirty is called, too) 0224 KToggleToolBarAction action(tb, QString(), nullptr); 0225 action.trigger(); 0226 QVERIFY(!tb->isVisible()); 0227 0228 // Switch the active part, and check that 0229 // the toolbar doesn't magically reappear, 0230 // as it did when createGUI was calling applyMainWindowSettings 0231 this->createGUI(nullptr); 0232 QVERIFY(!tb->isVisible()); 0233 this->createGUI(part); 0234 QVERIFY(!tb->isVisible()); 0235 0236 // All ok, show it again so that test can be run again :) 0237 action.trigger(); 0238 QVERIFY(tb->isVisible()); 0239 close(); 0240 } 0241 0242 private: 0243 KToolBar *tb; 0244 }; 0245 0246 // A KParts::MainWindow unit test 0247 void PartTest::testToolbarVisibility() 0248 { 0249 // The bug was: hide a toolbar in konqueror, 0250 // then switch tabs -> the toolbar shows again 0251 // (unless you waited for the autosave timer to kick in) 0252 MyMainWindow window; 0253 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("kxmlgui_unittest")); 0254 window.setAutoSaveSettings(cg.name()); 0255 window.show(); 0256 window.testToolbarVisibility(); 0257 } 0258 0259 void PartTest::testShouldNotCrashAfterDelete() 0260 { 0261 TestPart *part = new TestPart(nullptr, nullptr); 0262 QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop")))); 0263 QVERIFY(part->openFileCalled()); 0264 delete part; 0265 } 0266 0267 void PartTest::testActivationEvent() 0268 { 0269 TestPart *part = new TestPart(nullptr, nullptr); 0270 QVERIFY(!part->m_guiActivationEventTriggered); 0271 part->event(new QEvent(QEvent::MouseButtonPress)); 0272 QVERIFY(!part->m_guiActivationEventTriggered); 0273 part->event(new KParts::GUIActivateEvent(true)); 0274 QVERIFY(part->m_guiActivationEventTriggered); 0275 delete part; 0276 } 0277 0278 #include "moc_parttest.cpp"