File indexing completed on 2024-04-28 04:58:08
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "konqviewmgrtest.h" 0008 #include <konqmainwindowfactory.h> 0009 #include "../src/konqsettingsxt.h" 0010 #include <QToolBar> 0011 #include <QProcess> 0012 #include <QScrollArea> 0013 #include <qtestkeyboard.h> 0014 #include <qtest_gui.h> 0015 #include <qtestmouse.h> 0016 #include <QLabel> 0017 0018 #include <konqframe.h> 0019 #include <konqmainwindow.h> 0020 #include <konqviewmanager.h> 0021 #include <konqview.h> 0022 #include <konqtabs.h> 0023 #include <konqframevisitor.h> 0024 #include <konqsessionmanager.h> 0025 #include <kconfiggroup.h> 0026 #include <kio/job.h> 0027 #include <ksycoca.h> 0028 #include <KLocalizedString> 0029 0030 //#define TEST_KHTML 1 0031 0032 #ifdef TEST_KHTML 0033 #include <khtml_part.h> 0034 #include <khtmlview.h> 0035 #else 0036 #include <webenginepart.h> 0037 #include <webengineview.h> 0038 #include "../webenginepart/autotests/webengine_testutils.h" 0039 #endif 0040 0041 #include <QStandardPaths> 0042 #include <KSharedConfig> 0043 #include <QSignalSpy> 0044 0045 QTEST_MAIN(ViewMgrTest) 0046 0047 #if 0 0048 // could be used to load dummy parts; or to check that the right parts are being loaded 0049 // (and to detect the case where a part is loaded and then replaced with another one for no good reason) 0050 class KonqTestFactory : public KonqAbstractFactory 0051 { 0052 public: 0053 virtual KonqViewFactory createView(const QString &serviceType, 0054 const QString &serviceName = QString(), 0055 KService::Ptr *serviceImpl = 0, 0056 KService::List *partServiceOffers = 0, 0057 KService::List *appServiceOffers = 0, 0058 bool forceAutoEmbed = false); 0059 0060 }; 0061 #endif 0062 0063 0064 // Return the main widget for the given KonqView; used for clicking onto it 0065 // Duplicated from konqhtmltest.cpp -> move to KonqView? 0066 static QWidget *partWidget(KonqView *view) 0067 { 0068 QWidget *widget = view->part()->widget(); 0069 #ifdef TEST_KHTML 0070 KHTMLPart *htmlPart = qobject_cast<KHTMLPart *>(view->part()); 0071 #else 0072 WebEnginePart *htmlPart = qobject_cast<WebEnginePart *>(view->part()); 0073 #endif 0074 if (htmlPart) { 0075 widget = htmlPart->view(); // khtmlview != widget() nowadays, due to find bar 0076 } 0077 if (QScrollArea *scrollArea = qobject_cast<QScrollArea *>(widget)) { 0078 widget = scrollArea->widget(); 0079 } 0080 if (widget && widget->focusProxy()) { // for WebEngine's RenderWidgetHostViewQtDelegateWidget 0081 return widget->focusProxy(); 0082 } 0083 return widget; 0084 } 0085 0086 void ViewMgrTest::sendAllPendingResizeEvents(QWidget *mainWindow) 0087 { 0088 bool foundOne = true; 0089 while (foundOne) { 0090 foundOne = false; 0091 QList<QWidget *> allChildWidgets = mainWindow->findChildren<QWidget *>(); 0092 allChildWidgets.prepend(mainWindow); 0093 for (QWidget *w: allChildWidgets) { 0094 if (w->testAttribute(Qt::WA_PendingResizeEvent)) { 0095 w->setAttribute(Qt::WA_WState_Created, true); // hack: avoid assert in Qt-4.6 0096 //qDebug() << "Resizing" << w << " to " << w->size() << endl; 0097 QResizeEvent e(w->size(), QSize()); 0098 QApplication::sendEvent(w, &e); 0099 w->setAttribute(Qt::WA_PendingResizeEvent, false); 0100 // hack: make QTabWidget think it's visible; no layout otherwise 0101 w->setAttribute(Qt::WA_WState_Visible, true); 0102 foundOne = true; 0103 } 0104 } 0105 // Process LayoutRequest events, in particular 0106 qApp->sendPostedEvents(); 0107 //qDebug() << "Loop done, checking again"; 0108 0109 if (!foundOne) { // about to exit, reset visible flag, to avoid crashes in qt 0110 for (QWidget *w: allChildWidgets) { 0111 w->setAttribute(Qt::WA_WState_Visible, false); 0112 } 0113 } 0114 } 0115 } 0116 0117 class DebugFrameVisitor : public KonqFrameVisitor 0118 { 0119 public: 0120 DebugFrameVisitor() {} 0121 QString output() const 0122 { 0123 return m_output; 0124 } 0125 bool visit(KonqFrame *) override 0126 { 0127 m_output += 'F'; 0128 return true; 0129 } 0130 bool visit(KonqFrameContainer *) override 0131 { 0132 m_output += QLatin1String("C("); 0133 return true; 0134 } 0135 bool visit(KonqFrameTabs *) override 0136 { 0137 m_output += QLatin1String("T["); 0138 return true; 0139 } 0140 bool visit(KonqMainWindow *) override 0141 { 0142 m_output += 'M'; 0143 return true; 0144 } 0145 bool endVisit(KonqFrameContainer *) override 0146 { 0147 m_output += ')'; 0148 return true; 0149 } 0150 bool endVisit(KonqFrameTabs *) override 0151 { 0152 m_output += ']'; 0153 return true; 0154 } 0155 bool endVisit(KonqMainWindow *) override 0156 { 0157 m_output += '.'; 0158 return true; 0159 } 0160 0161 static QString inspect(KonqMainWindow *mainWindow) 0162 { 0163 DebugFrameVisitor dfv; 0164 bool ok = mainWindow->accept(&dfv); 0165 if (!ok) { 0166 return QStringLiteral("ERROR: visitor returned false"); 0167 } 0168 return dfv.output(); 0169 } 0170 0171 private: 0172 QString m_output; 0173 }; 0174 0175 void ViewMgrTest::initTestCase() 0176 { 0177 KLocalizedString::setApplicationDomain("konqviewmgrtest"); 0178 0179 QStandardPaths::setTestModeEnabled(true); 0180 QDir(KonqSessionManager::self()->autosaveDirectory()).removeRecursively(); 0181 QString configLocationDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); 0182 const QLatin1String expConfigDir(".qttest/config"); 0183 QString msg = QString("Can't remove the config file because it isn't in the %1 directory but in %2").arg(expConfigDir).arg(configLocationDir); 0184 QVERIFY2(configLocationDir.endsWith(expConfigDir), msg.toLatin1().constData()); 0185 QDir(configLocationDir).remove("konquerorrc"); 0186 0187 KonqSessionManager::self()->disableAutosave(); 0188 QCOMPARE(KonqSettings::mmbOpensTab(), true); 0189 QCOMPARE(KonqSettings::popupsWithinTabs(), false); 0190 KonqSettings::setAlwaysHavePreloaded(false); // it would confuse the mainwindow counting 0191 0192 // Ensure the tests use webenginepart (not khtml or webkit) 0193 // This code is inspired by settings/konqhtml/generalopts.cpp 0194 KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); 0195 KConfigGroup addedServices(profile, "Added KDE Service Associations"); 0196 bool needsUpdate = false; 0197 for (const QString &mimeType : QStringList{"text/html", "application/xhtml+xml", "application/xml"}) { 0198 QStringList services = addedServices.readXdgListEntry(mimeType); 0199 const QString wanted = QStringLiteral("webenginepart.desktop"); 0200 if (services.isEmpty() || services.at(0) != wanted) { 0201 services.removeAll(wanted); 0202 services.prepend(wanted); // make it the preferred one 0203 addedServices.writeXdgListEntry(mimeType, services); 0204 needsUpdate = true; 0205 } 0206 } 0207 if (needsUpdate) { 0208 profile->sync(); 0209 // kbuildsycoca is the one reading mimeapps.list, so we need to run it now 0210 QProcess::execute(QStandardPaths::findExecutable(KBUILDSYCOCA_EXENAME), {}); 0211 } 0212 } 0213 0214 void ViewMgrTest::testCreateFirstView() 0215 { 0216 KonqMainWindow mainWindow; 0217 KonqViewManager *viewManager = mainWindow.viewManager(); 0218 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0219 QVERIFY(view); 0220 QVERIFY(viewManager->tabContainer()); 0221 0222 // Use DebugFrameVisitor to find out the structure of the frame hierarchy 0223 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, one tab, one frame 0224 QCOMPARE(mainWindow.linkableViewsCount(), 1); 0225 0226 // Check widget parents: part's widget -> frame -> [tabwidget's stack] -> tabwidget -> mainWindow 0227 QWidget *partWidget = view->part()->widget(); 0228 QCOMPARE(partWidget->window(), &mainWindow); 0229 QWidget *frame = view->frame()->asQWidget(); 0230 QCOMPARE(partWidget->parentWidget(), frame); 0231 QWidget *tabWidget = viewManager->tabContainer()->asQWidget(); 0232 QCOMPARE(frame->parentWidget()->parentWidget(), tabWidget); 0233 0234 // Check frame geometry, to check that all layouts are there 0235 // (the mainWindow is resized to 700x480 in its constructor) 0236 // But pending resize events are only sent by show(), and we don't want to see 0237 // widgets from unit tests. 0238 // So we iterate over all widgets and ensure the pending resize events are sent. 0239 sendAllPendingResizeEvents(&mainWindow); 0240 for (QWidget *w = partWidget; w; w = w->parentWidget()) { 0241 qDebug() << w << w->geometry(); 0242 } 0243 //const QList<QToolBar*> toolbars = mainWindow.findChildren<QToolBar *>(); 0244 //foreach( QToolBar* toolbar, toolbars ) { 0245 // if (!toolbar->isHidden()) 0246 // qDebug() << toolbar << toolbar->geometry(); 0247 //} 0248 //qDebug() << "frame geom: " << frame->geometry(); 0249 QVERIFY(frame->width() > 680); 0250 QVERIFY(frame->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown 0251 //qDebug() << "partWidget geom:" << partWidget->geometry(); 0252 QVERIFY(partWidget->width() > 680); 0253 QVERIFY(partWidget->height() > frame->height() - 50 /*statusbar*/); 0254 //qDebug() << "tabWidget geom: " << tabWidget->geometry(); 0255 QVERIFY(tabWidget->width() > 680); 0256 QVERIFY(tabWidget->height() >= frame->height()); // equal, unless there's a border in the frame 0257 0258 // Part widget should have focus, not location bar 0259 QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), partWidget->focusWidget()->metaObject()->className()); 0260 } 0261 0262 void ViewMgrTest::testEmptyWindow() 0263 { 0264 QScopedPointer<KonqMainWindow> emptyWindow(KonqMainWindowFactory::createNewWindow()); 0265 QCOMPARE(emptyWindow->currentView()->url().url(), QString("konq:konqueror")); 0266 QCOMPARE(emptyWindow->focusWidget()->metaObject()->className(), "KonqCombo"); 0267 } 0268 0269 void ViewMgrTest::testRemoveFirstView() 0270 { 0271 KonqMainWindow mainWindow; 0272 KonqViewManager *viewManager = mainWindow.viewManager(); 0273 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0274 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame 0275 viewManager->removeView(view); 0276 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // removing not allowed 0277 // real test for removeView is part of testSplitView 0278 } 0279 0280 void ViewMgrTest::testSplitView() 0281 { 0282 KonqMainWindow mainWindow; 0283 KonqViewManager *viewManager = mainWindow.viewManager(); 0284 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0285 0286 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame 0287 // mainWindow.show(); 0288 // qApp->processEvents(); 0289 KonqView *view2 = viewManager->splitView(view, Qt::Horizontal); 0290 QVERIFY(view2); 0291 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0292 0293 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0294 0295 // Check widget parents 0296 //mainWindow.dumpObjectTree(); 0297 QWidget *partWidget = view->part()->widget(); 0298 QCOMPARE(partWidget->window(), &mainWindow); 0299 QWidget *frame = view->frame()->asQWidget(); 0300 QCOMPARE(partWidget->parentWidget(), frame); 0301 QVERIFY(!frame->isHidden()); 0302 0303 QWidget *part2Widget = view2->part()->widget(); 0304 QCOMPARE(part2Widget->window(), &mainWindow); 0305 QWidget *frame2 = view2->frame()->asQWidget(); 0306 QCOMPARE(part2Widget->parentWidget(), frame2); 0307 QVERIFY(!frame2->isHidden()); 0308 0309 // Check container 0310 QCOMPARE(view->frame()->parentContainer()->frameType(), KonqFrameBase::Container); 0311 KonqFrameContainer *container = static_cast<KonqFrameContainer *>(view->frame()->parentContainer()); 0312 QVERIFY(container); 0313 QCOMPARE(container->count(), 2); 0314 QCOMPARE(container, view2->frame()->parentContainer()); 0315 QCOMPARE(container->firstChild(), view->frame()); 0316 QCOMPARE(container->secondChild(), view2->frame()); 0317 QCOMPARE(container->widget(0), view->frame()->asQWidget()); 0318 QCOMPARE(container->widget(1), view2->frame()->asQWidget()); 0319 0320 // mainWindow.show(); 0321 // qApp->processEvents(); 0322 // Check frame geometries 0323 sendAllPendingResizeEvents(&mainWindow); 0324 //for ( QWidget* w = partWidget; w; w = w->parentWidget() ) 0325 // qDebug() << w << w->geometry() << "visible:" << w->isVisible(); 0326 0327 //qDebug() << "view geom:" << frame->geometry(); 0328 QVERIFY(frame->width() > 300 && frame->width() < 400); // horiz split, so half the mainWindow width 0329 QVERIFY(frame->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown 0330 //qDebug() << "view2 geom:" << frame2->geometry(); 0331 QVERIFY(frame2->width() > 300 && frame2->width() < 400); // horiz split, so half the mainWindow width 0332 QVERIFY(frame2->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown 0333 // Both frames should have the same size; well, if the width was odd then there can be an off-by-one... 0334 QCOMPARE(frame->height(), frame2->height()); 0335 // qDebug() << "FRAME WIDTH" << frame->width() << "FRAME2 WIDTH" << frame2->width(); 0336 // qDebug() << "FRAME MINIMUM WIDTH" << frame->minimumSizeHint() << "FRAME2 MINIMIUM WIDTH" << frame2->minimumSizeHint(); 0337 QVERIFY(qAbs(frame->width() - frame2->width()) <= 1); // e.g. 173 and 172 are "close enough" 0338 //qDebug() << "partWidget geom:" << partWidget->geometry(); 0339 QVERIFY(partWidget->width() > 300 && partWidget->width() < 400); // horiz split, so half the mainWindow width 0340 QVERIFY(partWidget->height() > 220); // frame minus statusbar height 0341 QVERIFY(part2Widget->width() > 300 && part2Widget->width() < 400); // horiz split, so half the mainWindow width 0342 QVERIFY(part2Widget->height() > 220); 0343 0344 //KonqFrameContainerBase* container = view->frame()->parentContainer(); 0345 //QVERIFY( container ); 0346 //qDebug() << "container geom: " << container->asQWidget()->geometry(); 0347 0348 // Split again 0349 int widthFrame2 = frame2->width(); 0350 KonqView *view3 = viewManager->splitView(view, Qt::Horizontal); 0351 QVERIFY(view3); 0352 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(C(FF)F)].")); 0353 // Check that the width of the second frame has not changed (bug 160407) 0354 QCOMPARE(frame2->width(), widthFrame2); 0355 QCOMPARE(mainWindow.linkableViewsCount(), 3); 0356 0357 // Now test removing the first view 0358 viewManager->removeView(view); 0359 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0360 // Check again that the width of the second frame has not changed (bug 160407 comments 18-20) 0361 QCOMPARE(frame2->width(), widthFrame2); 0362 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0363 0364 // Now test removing the last view 0365 viewManager->removeView(view3); 0366 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame 0367 QCOMPARE(mainWindow.linkableViewsCount(), 1); 0368 } 0369 0370 void ViewMgrTest::testSplitMainContainer() 0371 { 0372 KonqMainWindow mainWindow; 0373 KonqViewManager *viewManager = mainWindow.viewManager(); 0374 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepage")); 0375 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame 0376 KonqFrameContainerBase *tabContainer = view->frame()->parentContainer(); 0377 KonqView *view2 = viewManager->splitMainContainer(view, Qt::Horizontal, QStringLiteral("text/html"), QStringLiteral("webenginepart"), true); 0378 QVERIFY(view2); 0379 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MC(FT[F]).")); // mainWindow, splitter, frame, tab widget, one frame 0380 0381 // Check widget parents 0382 QWidget *partWidget = view->part()->widget(); 0383 QCOMPARE(partWidget->window(), &mainWindow); 0384 QWidget *frame = view->frame()->asQWidget(); 0385 QCOMPARE(partWidget->parentWidget(), frame); 0386 QVERIFY(!frame->isHidden()); 0387 0388 QWidget *part2Widget = view2->part()->widget(); 0389 QCOMPARE(part2Widget->window(), &mainWindow); 0390 QWidget *frame2 = view2->frame()->asQWidget(); 0391 QCOMPARE(part2Widget->parentWidget(), frame2); 0392 QVERIFY(!frame2->isHidden()); 0393 0394 // Check container 0395 QCOMPARE(view->frame()->parentContainer()->frameType(), KonqFrameBase::Tabs); 0396 QCOMPARE(view2->frame()->parentContainer()->frameType(), KonqFrameBase::Container); 0397 KonqFrameContainer *container = static_cast<KonqFrameContainer *>(view2->frame()->parentContainer()); 0398 QVERIFY(container); 0399 QCOMPARE(container->count(), 2); 0400 QCOMPARE(container, view2->frame()->parentContainer()); 0401 QCOMPARE(container->firstChild(), view2->frame()); 0402 QCOMPARE(container->secondChild(), tabContainer); 0403 QCOMPARE(container->widget(0), view2->frame()->asQWidget()); 0404 QCOMPARE(container->widget(1), tabContainer->asQWidget()); 0405 0406 // Now test removing the view we added last 0407 viewManager->removeView(view2); 0408 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame 0409 } 0410 0411 static void openHtmlWithLink(KonqMainWindow &mainWindow) 0412 { 0413 // Much like KonqHtmlTest::loadSimpleHtml. 0414 // We use text/plain as the linked file, in order to test #67956 (switching parts in new tab) 0415 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <a href=\"data:text/plain, Link target\" id=\"linkid\">Click me</a>")), QStringLiteral("text/html")); 0416 KonqView *view = mainWindow.currentView(); 0417 QVERIFY(view); 0418 QSignalSpy spyCompleted(view, &KonqView::viewCompleted); 0419 QVERIFY(spyCompleted.wait(20000)); 0420 QCOMPARE(view->serviceType(), QString("text/html")); 0421 } 0422 0423 void ViewMgrTest::testLinkedViews() 0424 { 0425 KonqMainWindow mainWindow; 0426 openHtmlWithLink(mainWindow); 0427 KonqView *view = mainWindow.currentView(); 0428 WebEnginePart *part = qobject_cast<WebEnginePart *>(view->part()); 0429 QVERIFY(part); 0430 // Split it 0431 qDebug() << "SPLITTING"; 0432 mainWindow.slotSplitViewHorizontal(); 0433 KonqView *view2 = mainWindow.currentView(); 0434 QVERIFY(view2); 0435 QCOMPARE(view2->serviceType(), QString("text/html")); 0436 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0437 QSignalSpy spyCompleted(view2, &KonqView::viewCompleted); 0438 QVERIFY(spyCompleted.wait(20000)); 0439 const QUrl origUrl = view->url(); 0440 QCOMPARE(view2->url().url(), origUrl.url()); 0441 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0442 view->setLinkedView(true); 0443 view2->setLinkedView(true); 0444 view->setLockedLocation(true); 0445 0446 mainWindow.show(); 0447 0448 // "Click" on the link 0449 qDebug() << "ACTIVATING LINK"; 0450 0451 #ifdef TEST_KHTML 0452 KHTMLPart *part = qobject_cast<KHTMLPart *>(view->part()); 0453 QVERIFY(part); 0454 DOM::HTMLAnchorElement anchor = part->htmlDocument().getElementsByTagName(DOM::DOMString("a")).item(0); 0455 QVERIFY(!anchor.isNull()); 0456 anchor.focus(); 0457 QKeyEvent ev(QKeyEvent::KeyPress, Qt::Key_Return, 0, "\n"); 0458 QApplication::sendEvent(part->view(), &ev); 0459 qApp->processEvents(); // openUrlRequestDelayed 0460 QTest::qWait(0); 0461 #else 0462 QTest::mouseClick(part->view()->focusProxy(), Qt::LeftButton, Qt::KeyboardModifiers(), 0463 elementCenter(part->view()->page(), QStringLiteral("linkid"))); 0464 0465 // Check that the link opened in the 2nd view, not the first one 0466 #endif 0467 QCOMPARE(view->url().url(), origUrl.url()); 0468 #ifndef TEST_KHTML 0469 QEXPECT_FAIL("", "Broken feature right now, requires URLs to be opened by konq rather than the part", Abort); 0470 #endif 0471 QTRY_COMPARE_WITH_TIMEOUT(view2->url().url(), QUrl("data:text/plain, Link target").url(), 400); 0472 } 0473 0474 void ViewMgrTest::testPopupNewTab() // RMB, "Open in new tab" 0475 { 0476 KonqMainWindow mainWindow; 0477 openHtmlWithLink(mainWindow); 0478 KonqFrameTabs *tabs = mainWindow.viewManager()->tabContainer(); 0479 QCOMPARE(tabs->currentIndex(), 0); 0480 KFileItem item(QUrl(QStringLiteral("data:text/html, hello")), QStringLiteral("text/html"), S_IFREG); 0481 mainWindow.prepareForPopupMenu(KFileItemList() << item, KParts::OpenUrlArguments(), BrowserArguments()); 0482 QMetaObject::invokeMethod(&mainWindow, "slotPopupNewTab"); 0483 QTest::qWait(1000); 0484 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0485 QCOMPARE(KMainWindow::memberList().count(), 1); 0486 QCOMPARE(mainWindow.linkableViewsCount(), 1); 0487 0488 if (KonqSettings::newTabsInFront()) { 0489 QCOMPARE(tabs->currentIndex(), 1); 0490 } 0491 } 0492 0493 static void checkSecondWindowHasOneTab(bool fromPopup) // and delete it. 0494 { 0495 QTRY_COMPARE(KMainWindow::memberList().count(), 2); 0496 QScopedPointer<KonqMainWindow> newWindow(qobject_cast<KonqMainWindow *>(KMainWindow::memberList().last())); 0497 QVERIFY(newWindow.data()); 0498 QTRY_COMPARE(DebugFrameVisitor::inspect(newWindow.data()), QString("MT[F].")); // mainWindow, tab widget, one tab 0499 QTabWidget *tabWidget = newWindow->findChild<QTabWidget *>(); 0500 QVERIFY(tabWidget); 0501 // The location bar shouldn't get focus (#208821) 0502 QTRY_VERIFY(newWindow->focusWidget()); 0503 QTRY_VERIFY_WITH_TIMEOUT(tabWidget->focusWidget(), 200); 0504 QCOMPARE(newWindow->focusWidget()->metaObject()->className(), tabWidget->focusWidget()->metaObject()->className()); 0505 } 0506 0507 void ViewMgrTest::testPopupNewWindow() // RMB, "Open new window" 0508 { 0509 KonqMainWindow mainWindow; 0510 openHtmlWithLink(mainWindow); 0511 KFileItem item(QUrl(QStringLiteral("data:text/html, hello")), QStringLiteral("text/html"), S_IFREG); 0512 mainWindow.prepareForPopupMenu(KFileItemList() << item, KParts::OpenUrlArguments(), BrowserArguments()); 0513 QMetaObject::invokeMethod(&mainWindow, "slotPopupNewWindow"); 0514 QTRY_COMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab 0515 QVERIFY(KMainWindow::memberList().last() != &mainWindow); 0516 checkSecondWindowHasOneTab(true); 0517 } 0518 0519 void ViewMgrTest::testCtrlClickOnLink() 0520 { 0521 KonqMainWindow mainWindow; 0522 openHtmlWithLink(mainWindow); 0523 KonqFrameTabs *tabs = mainWindow.viewManager()->tabContainer(); 0524 KonqView *view = mainWindow.currentView(); 0525 mainWindow.show(); 0526 qDebug() << "CLICKING NOW"; 0527 QTest::mouseClick(partWidget(view), Qt::LeftButton, Qt::ControlModifier, QPoint(10, 10)); 0528 QTest::qWait(100); 0529 KonqView *newView = nullptr; 0530 // Expected behavior for Ctrl+click: 0531 // new tab, if mmbOpensTab 0532 // new window, if !mmbOpensTab 0533 // (this code is called for both cases) 0534 if (KonqSettings::mmbOpensTab()) { 0535 QCOMPARE(KMainWindow::memberList().count(), 1); 0536 QTRY_COMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0537 if (KonqSettings::newTabsInFront()) { // when called by sameTestsWithNewTabsInFront 0538 QCOMPARE(tabs->currentIndex(), 1); 0539 QVERIFY(mainWindow.currentView() != view); 0540 QVERIFY(mainWindow.viewManager()->activePart() != view->part()); 0541 } else { // the default case 0542 QCOMPARE(tabs->currentIndex(), 0); 0543 QCOMPARE(mainWindow.currentView(), view); 0544 QCOMPARE(mainWindow.viewManager()->activePart(), view->part()); 0545 } 0546 KonqFrame *newFrame = dynamic_cast<KonqFrame *>(mainWindow.viewManager()->tabContainer()->tabAt(1)); 0547 QVERIFY(newFrame); 0548 newView = newFrame->activeChildView(); 0549 QVERIFY(newView); 0550 //QVERIFY(newView->supportsMimeType("text/plain")); 0551 } else { 0552 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab 0553 checkSecondWindowHasOneTab(false); 0554 } 0555 } 0556 0557 void ViewMgrTest::sameTestsWithNewTabsInFront() 0558 { 0559 // Redo testCtrlClickOnLink, 0560 // but with the option "NewTabsInFront" set to true. 0561 QVERIFY(!KonqSettings::newTabsInFront()); // default setting = false 0562 KonqSettings::setNewTabsInFront(true); 0563 testPopupNewTab(); 0564 testCtrlClickOnLink(); 0565 KonqSettings::setNewTabsInFront(false); 0566 } 0567 0568 void ViewMgrTest::sameTestsWithMmbOpenTabsFalse() 0569 { 0570 // Redo testPopupNewTab, testPopupNewWindow and testCtrlClickOnLink, 0571 // but as if the user (e.g. Pino) had disabled the setting "Open links in new tabs". 0572 KonqSettings::setMmbOpensTab(false); 0573 testPopupNewTab(); 0574 testPopupNewWindow(); 0575 testCtrlClickOnLink(); 0576 KonqSettings::setMmbOpensTab(true); 0577 } 0578 0579 static void openTabWithTitle(KonqMainWindow &mainWindow, const QString &title, KonqView *&view) 0580 { 0581 KonqViewManager *viewManager = mainWindow.viewManager(); 0582 view = viewManager->addTab(QStringLiteral("text/html")); 0583 QVERIFY(view); 0584 QVERIFY(view->supportsMimeType("text/html")); 0585 QVERIFY(!view->supportsMimeType("text/plain")); 0586 // correct since it's a subclass of text/html, khtml can display it 0587 QVERIFY(view->supportsMimeType("application/x-netscape-bookmarks")); 0588 // Tab caption test 0589 view->openUrl(QUrl(QStringLiteral("data:text/html, <title>") + title + QStringLiteral("</title>")), QStringLiteral("http://loc.bar.url")); 0590 QSignalSpy spyCompleted(view, &KonqView::viewCompleted); 0591 QVERIFY(spyCompleted.wait(10000)); 0592 QCOMPARE(view->caption(), title); 0593 QCOMPARE(view->locationBarURL(), QString("http://loc.bar.url")); 0594 } 0595 0596 void ViewMgrTest::testAddTabs() 0597 { 0598 KonqMainWindow mainWindow; 0599 KonqViewManager *viewManager = mainWindow.viewManager(); 0600 0601 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0602 QVERIFY(view); 0603 // The testcase was "konqueror www.kde.org www.google.fr bugs.kde.org www.cuil.com www.davidfaure.fr" 0604 const QStringList titles { 0605 "K Desktop Environment - Be free", 0606 "Google", 0607 "KDE Bug Tracking System", 0608 "Cuil", 0609 "http://www.davidfaure.fr/" }; 0610 view->setCaption(titles.at(0)); 0611 0612 KTabWidget *tabWidget = mainWindow.findChild<KTabWidget *>(); 0613 QVERIFY(tabWidget); 0614 KonqView *viewTab1, *viewTab2, *viewTab3, *viewTab4; 0615 openTabWithTitle(mainWindow, titles.at(1), viewTab1); 0616 openTabWithTitle(mainWindow, titles.at(2), viewTab2); 0617 openTabWithTitle(mainWindow, titles.at(3), viewTab3); 0618 openTabWithTitle(mainWindow, titles.at(4), viewTab4); 0619 for (int i = 0; i < titles.count(); ++i) { 0620 QCOMPARE(tabWidget->tabText(i), QString(titles.at(i))); 0621 } 0622 QPointer<KonqView> viewTab2Pointer(viewTab2); 0623 QPointer<KParts::ReadOnlyPart> tab2PartPointer(viewTab2->part()); 0624 0625 // Ensure tabwidget has a nice size 0626 mainWindow.resize(1000, 699); 0627 sendAllPendingResizeEvents(&mainWindow); 0628 0629 // Remove active tab (#170470) 0630 tabWidget->setCurrentIndex(2); 0631 KonqFrameBase *frame = dynamic_cast<KonqFrameBase *>(viewManager->tabContainer()->currentWidget()); 0632 QVERIFY(frame); 0633 viewManager->removeTab(frame); 0634 QVERIFY(viewTab2Pointer.isNull()); // check the view got deleted 0635 QVERIFY(tab2PartPointer.isNull()); // check the part got deleted too, since pino is a non-believer :) 0636 QList<int> expectedTitles{0, 1, 3, 4}; 0637 for (int i = 0; i < expectedTitles.count(); ++i) { 0638 QCOMPARE(tabWidget->tabText(i), titles.at(expectedTitles[i])); 0639 } 0640 for (int i = 0; i < expectedTitles.count(); ++i) { 0641 QCOMPARE(tabWidget->QTabWidget::tabText(i).left(10), titles.at(expectedTitles[i]).left(10)); 0642 } 0643 0644 tabWidget->removeTab(0); 0645 expectedTitles.removeAt(0); 0646 for (int i = 0; i < expectedTitles.count(); ++i) { 0647 QCOMPARE(tabWidget->tabText(i), QString(titles.at(expectedTitles[i]))); 0648 } 0649 } 0650 0651 void ViewMgrTest::testDuplicateTab() 0652 { 0653 KonqMainWindow mainWindow; 0654 KonqViewManager *viewManager = mainWindow.viewManager(); 0655 /*KonqView* view =*/ viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0656 viewManager->duplicateTab(0); // should return a KonqFrameBase? 0657 0658 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0659 // TODO check serviceType and serviceName of the new view 0660 } 0661 0662 void ViewMgrTest::testDuplicateSplittedTab() 0663 { 0664 KonqMainWindow mainWindow; 0665 KonqViewManager *viewManager = mainWindow.viewManager(); 0666 KonqView *view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0667 KonqView *view2 = viewManager->splitView(view, Qt::Vertical); 0668 QVERIFY(view2); 0669 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0670 0671 KonqFrameContainer *container = static_cast<KonqFrameContainer *>(view->frame()->parentContainer()); 0672 QVERIFY(container); 0673 QCOMPARE(container->parentContainer()->frameType(), KonqFrameBase::Tabs); 0674 0675 viewManager->duplicateTab(0); // TODO shouldn't it return a KonqFrameBase? 0676 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)C(FF)].")); // mainWindow, tab widget, two tabs 0677 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0678 0679 // While we're here, let's test Ctrl+Tab navigation 0680 view->setProperty("num", 0); 0681 view2->setProperty("num", 1); 0682 KonqFrameTabs *tabs = viewManager->tabContainer(); 0683 KonqFrameBase *tab2base = tabs->tabAt(1); 0684 QVERIFY(tab2base->isContainer()); 0685 KonqFrameContainer *tab2 = dynamic_cast<KonqFrameContainer *>(tab2base); 0686 QVERIFY(tab2); 0687 KonqView *view3 = tab2->firstChild()->activeChildView(); 0688 QVERIFY(view3); 0689 KonqView *view4 = tab2->secondChild()->activeChildView(); 0690 QVERIFY(view4); 0691 QVERIFY(view3 != view); 0692 QVERIFY(view4 != view2); 0693 view3->setProperty("num", 2); 0694 view4->setProperty("num", 3); 0695 QCOMPARE(mainWindow.currentView()->property("num").toInt(), 3); 0696 QCOMPARE(tabs->currentIndex(), 1); 0697 QVERIFY(mainWindow.focusWidget()); 0698 QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); 0699 QCOMPARE(mainWindow.currentView()->property("num").toInt(), 0); 0700 QCOMPARE(tabs->currentIndex(), 0); 0701 QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); 0702 QCOMPARE(mainWindow.currentView()->property("num").toInt(), 1); 0703 QCOMPARE(tabs->currentIndex(), 0); 0704 QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); 0705 QCOMPARE(mainWindow.currentView()->property("num").toInt(), 2); 0706 QCOMPARE(tabs->currentIndex(), 1); 0707 QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); 0708 QCOMPARE(mainWindow.currentView()->property("num").toInt(), 3); 0709 QCOMPARE(tabs->currentIndex(), 1); 0710 0711 viewManager->removeTab(container); 0712 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one tab 0713 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0714 } 0715 0716 // Like in https://bugs.kde.org/show_bug.cgi?id=153533, 0717 // where the part deletes itself. 0718 void ViewMgrTest::testDeletePartInTab() 0719 { 0720 QPointer<KonqMainWindow> mainWindow = new KonqMainWindow; 0721 QVERIFY(mainWindow->testAttribute(Qt::WA_DeleteOnClose)); 0722 KonqViewManager *viewManager = mainWindow->viewManager(); 0723 QPointer<KonqView> view = viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0724 QVERIFY(!view.isNull()); 0725 QPointer<QWidget> partWidget = view->part()->widget(); 0726 0727 QPointer<KonqView> viewTab2 = viewManager->addTab(QStringLiteral("text/html")); 0728 QPointer<QWidget> partWidget2 = viewTab2->part()->widget(); 0729 QVERIFY(!viewTab2.isNull()); 0730 QCOMPARE(DebugFrameVisitor::inspect(mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0731 0732 delete viewTab2->part(); 0733 QVERIFY(viewTab2.isNull()); 0734 QVERIFY(partWidget2.isNull()); 0735 QCOMPARE(DebugFrameVisitor::inspect(mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab 0736 0737 delete view->part(); 0738 QVERIFY(view.isNull()); 0739 QVERIFY(partWidget.isNull()); 0740 qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete); 0741 QVERIFY(mainWindow.isNull()); 0742 } 0743 0744 void ViewMgrTest::testSaveProfile() 0745 { 0746 KonqMainWindow mainWindow; 0747 const QUrl url(QStringLiteral("data:text/html, <p>Hello World</p>")); 0748 mainWindow.openUrl(nullptr, url, QStringLiteral("text/html")); 0749 KonqViewManager *viewManager = mainWindow.viewManager(); 0750 KonqView *view2 = viewManager->addTab(QStringLiteral("text/html")); 0751 const QUrl url2(QStringLiteral("data:text/html, <p>view2</p>")); 0752 view2->openUrl(url2, QStringLiteral("2")); 0753 QTabWidget *tabWidget = mainWindow.findChild<QTabWidget *>(); 0754 QVERIFY(tabWidget); 0755 0756 // Save a profile with two tabs (via KonqSessionManager) 0757 KonqSessionManager *sessionMgr = KonqSessionManager::self(); 0758 const QString filePath = QDir::currentPath() + "unittest_profile"; 0759 sessionMgr->saveCurrentSessionToFile(filePath); 0760 QVERIFY(QFile::exists(filePath)); 0761 0762 { 0763 KConfig cfg(filePath, KConfig::SimpleConfig); 0764 KConfigGroup profileGroup(&cfg, "Window0"); 0765 QCOMPARE(profileGroup.readEntry("RootItem"), QString("Tabs0")); 0766 QCOMPARE(profileGroup.readEntry("Tabs0_Children"), QString("ViewT0,ViewT1")); 0767 QCOMPARE(profileGroup.readEntry("HistoryItemViewT0_0Url"), url.url()); 0768 QCOMPARE(profileGroup.readEntry("HistoryItemViewT1_0Url"), url2.url()); 0769 } 0770 0771 // Now close a tab and save again - to check that the stuff from the old 0772 // tab isn't lying around. 0773 viewManager->removeTab(view2->frame()); 0774 sessionMgr->saveCurrentSessionToFile(filePath); 0775 { 0776 KConfig cfg(filePath, KConfig::SimpleConfig); 0777 KConfigGroup profileGroup(&cfg, "Window0"); 0778 QCOMPARE(profileGroup.readEntry("RootItem"), QString("Tabs0")); 0779 QCOMPARE(profileGroup.readEntry("Tabs0_Children"), QString("ViewT0")); 0780 QCOMPARE(profileGroup.readEntry("HistoryItemViewT0_0Url"), url.url()); 0781 QVERIFY(!profileGroup.hasKey("HistoryItemViewT1_0Url")); 0782 } 0783 QFile::remove(filePath); 0784 } 0785 0786 void ViewMgrTest::testDuplicateWindow() 0787 { 0788 KonqMainWindow mainWindow; 0789 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <p>Hello World</p>")), QStringLiteral("text/html")); 0790 KonqViewManager *viewManager = mainWindow.viewManager(); 0791 KonqView *viewTab2 = viewManager->addTab(QStringLiteral("text/html")); 0792 KonqView *splitted = viewManager->splitView(viewTab2, Qt::Horizontal); 0793 Q_UNUSED(splitted); 0794 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FC(FF)].")); // mainWindow, tab widget, first tab = one frame, second tab = splitter with two frames 0795 QScopedPointer<KonqMainWindow> secondWindow(viewManager->duplicateWindow()); 0796 QCOMPARE(DebugFrameVisitor::inspect(secondWindow.data()), QString("MT[FC(FF)].")); // mainWindow, tab widget, first tab = one frame, second tab = splitter with two frames 0797 } 0798 0799 void ViewMgrTest::testCloseOtherTabs() 0800 { 0801 KonqMainWindow mainWindow; 0802 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <p>Hello World</p>")), QStringLiteral("text/html")); 0803 KonqViewManager *viewManager = mainWindow.viewManager(); 0804 QTabWidget *tabWidget = mainWindow.findChild<QTabWidget *>(); 0805 QVERIFY(tabWidget); 0806 QVERIFY(tabWidget->focusWidget()); 0807 QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), tabWidget->focusWidget()->metaObject()->className()); 0808 viewManager->addTab(QStringLiteral("text/html")); 0809 KonqView *viewTab2 = viewManager->addTab(QStringLiteral("text/html")); 0810 viewManager->splitView(viewTab2, Qt::Horizontal); 0811 viewManager->addTab(QStringLiteral("text/html")); 0812 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFC(FF)F].")); // mainWindow, tab widget, first tab = one frame, second tab = one frame, third tab = splitter with two frames, fourth tab = one frame 0813 QCOMPARE(tabWidget->count(), 4); 0814 tabWidget->setCurrentIndex(2); 0815 QCOMPARE(mainWindow.linkableViewsCount(), 2); 0816 tabWidget->setCurrentIndex(3); 0817 QCOMPARE(mainWindow.linkableViewsCount(), 1); 0818 // Switching to an empty tab -> focus goes to location bar (#84867) 0819 QEXPECT_FAIL("", "Known bug with unknown causes. Worked around it with commit 78f47b4d4ce97f7ff0278b16c04182e7d80c8dba", Continue); 0820 QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), "KonqCombo"); 0821 0822 // Check that removeOtherTabs deals with split views correctly 0823 mainWindow.viewManager()->removeOtherTabs(2); 0824 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, first tab = splitter with two frames 0825 } 0826 0827 void ViewMgrTest::testCloseTabsFast() // #210551/#150162 0828 { 0829 KonqMainWindow mainWindow; 0830 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <p>Hello World</p>")), QStringLiteral("text/html")); 0831 KonqViewManager *viewManager = mainWindow.viewManager(); 0832 viewManager->addTab(QStringLiteral("text/html")); 0833 viewManager->addTab(QStringLiteral("text/html")); 0834 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFF].")); // mainWindow, tab widget, 3 simple tabs 0835 QTabWidget *tabWidget = mainWindow.findChild<QTabWidget *>(); 0836 tabWidget->setCurrentIndex(2); 0837 0838 mainWindow.setWorkingTab(1); 0839 mainWindow.slotRemoveTabPopup(); 0840 mainWindow.slotRemoveTabPopup(); 0841 QTest::qWait(100); // process the delayed invocations 0842 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, 1 tab left 0843 } 0844 0845 void ViewMgrTest::testBrowserArgumentsNewTab() 0846 { 0847 KonqMainWindow mainWindow; 0848 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <p>Hello World</p>")), QStringLiteral("text/html")); 0849 KParts::OpenUrlArguments urlArgs; 0850 BrowserArguments browserArgs; 0851 browserArgs.setNewTab(true); 0852 KonqView *view = mainWindow.currentView(); 0853 BrowserExtension *ext = qobject_cast<BrowserExtension *>(view->browserExtension()); 0854 QVERIFY(ext); 0855 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0856 emit ext->openUrlRequest(QUrl(QStringLiteral("data:text/html, <p>Second tab test</p>")), urlArgs, browserArgs); 0857 #else 0858 emit ext->browserOpenUrlRequest(QUrl(QStringLiteral("data:text/html, <p>Second tab test</p>")), urlArgs, browserArgs); 0859 #endif 0860 QTest::qWait(5000); 0861 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0862 QCOMPARE(view->url(), QUrl("data:text/html, <p>Hello World</p>")); 0863 0864 // compare the url of the new view... how to? 0865 // QCOMPARE(view->url(), QUrl("data:text/html, <p>Second tab test</p>")); 0866 } 0867 0868 void ViewMgrTest::testBreakOffTab() 0869 { 0870 KonqMainWindow mainWindow; 0871 KonqViewManager *viewManager = mainWindow.viewManager(); 0872 /*KonqView* firstView =*/ viewManager->createFirstView(QStringLiteral("text/html"), QStringLiteral("webenginepart")); 0873 0874 //KonqFrameBase* tab = firstView->frame(); 0875 viewManager->duplicateTab(0); 0876 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0877 0878 // Break off a tab 0879 0880 KonqMainWindow *mainWindow2 = viewManager->breakOffTab(0, mainWindow.size()); 0881 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, one tab, one frame 0882 QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[F].")); // mainWindow, one tab, one frame 0883 0884 // Verify that the new tab container has an active child and that duplicating the tab in the new window does not crash (bug 203069) 0885 0886 QVERIFY(mainWindow2->viewManager()->tabContainer()->activeChild()); 0887 mainWindow2->viewManager()->duplicateTab(0); 0888 QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[FF].")); // mainWindow, tab widget, two tabs 0889 0890 delete mainWindow2; 0891 0892 // Now split the remaining view, duplicate the tab and verify that breaking off a split tab does not crash (bug 174292). 0893 // Also check that the tab container of the new main window has an active child. 0894 0895 KonqView *view = mainWindow.activeChildView(); 0896 viewManager->splitView(view, Qt::Vertical); 0897 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0898 // KonqFrameContainerBase* container = view->frame()->parentContainer(); 0899 viewManager->duplicateTab(0); 0900 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)C(FF)].")); // mainWindow, tab widget, two tabs with split views 0901 mainWindow2 = viewManager->breakOffTab(0, mainWindow.size()); 0902 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0903 QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames 0904 QVERIFY(mainWindow2->viewManager()->tabContainer()->activeChild()); 0905 0906 delete mainWindow2; 0907 } 0908 0909 void ViewMgrTest::moveTabLeft() 0910 { 0911 KonqMainWindow mainWindow; 0912 mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, <p>Hello World</p>")), QStringLiteral("text/html")); 0913 KonqViewManager *viewManager = mainWindow.viewManager(); 0914 KonqView *view1 = viewManager->addTab(QStringLiteral("text/html")); 0915 view1->openUrl(QUrl(QStringLiteral("data:text/html, <p>view1</p>")), QStringLiteral("1")); 0916 KonqView *view2 = viewManager->addTab(QStringLiteral("text/html")); 0917 view2->openUrl(QUrl(QStringLiteral("data:text/html, <p>view2</p>")), QStringLiteral("2")); 0918 QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFF].")); // mainWindow, tab widget, 3 simple tabs 0919 QTabWidget *tabWidget = mainWindow.findChild<QTabWidget *>(); 0920 tabWidget->setCurrentIndex(2); 0921 view2->part()->widget()->setFocus(); 0922 //qDebug() << mainWindow.focusWidget() << view2->part()->widget()->focusWidget(); 0923 QCOMPARE(mainWindow.focusWidget(), view2->part()->widget()->focusWidget()); 0924 viewManager->moveTabBackward(); 0925 // Now we should have the views (tabs) in the order 0, 2, 1 0926 QList<KonqView *> views = KonqViewCollector::collect(&mainWindow); 0927 QCOMPARE(views[1], view2); 0928 QCOMPARE(views[2], view1); 0929 QCOMPARE(tabWidget->currentIndex(), 1); 0930 QCOMPARE(mainWindow.currentView(), view2); 0931 qDebug() << mainWindow.focusWidget() << view2->part()->widget()->focusWidget(); 0932 // the focus should stay with that view (#208821) 0933 QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), view2->part()->widget()->focusWidget()->metaObject()->className()); 0934 QCOMPARE(mainWindow.focusWidget(), view2->part()->widget()->focusWidget()); 0935 } 0936