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"