File indexing completed on 2024-05-05 05:00:27
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org> 0003 SPDX-FileCopyrightText: 2007 Eduardo Robles Elvira <edulix@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "konqviewmanager.h" 0009 0010 #include "konqcloseditem.h" 0011 #include "konqundomanager.h" 0012 #include "konqmisc.h" 0013 #include "konqview.h" 0014 #include "konqframestatusbar.h" 0015 #include "konqtabs.h" 0016 #include "konqsettingsxt.h" 0017 #include "konqframevisitor.h" 0018 #include <konq_events.h> 0019 #include "konqurl.h" 0020 #include <KX11Extras> 0021 0022 #include <QFileInfo> 0023 #include <QDBusMessage> 0024 #include <QDBusConnection> 0025 0026 #include <KParts/PartActivateEvent> 0027 0028 #include <kactionmenu.h> 0029 0030 #include <kstringhandler.h> 0031 #include "konqdebug.h" 0032 #include <QTemporaryFile> 0033 #include <KLocalizedString> 0034 #include <kmessagebox.h> 0035 #include <QMenu> 0036 #include <QApplication> 0037 #include <QStandardPaths> 0038 #include <KSharedConfig> 0039 #include <KWindowConfig> 0040 #include <QMimeDatabase> 0041 #include <QMimeType> 0042 #include <QScreen> 0043 0044 //#define DEBUG_VIEWMGR 0045 0046 KonqViewManager::KonqViewManager(KonqMainWindow *mainWindow) 0047 : KParts::PartManager(mainWindow) 0048 { 0049 m_pMainWindow = mainWindow; 0050 0051 m_bLoadingProfile = false; 0052 m_tabContainer = nullptr; 0053 0054 setIgnoreExplictFocusRequests(true); 0055 0056 connect(this, SIGNAL(activePartChanged(KParts::Part*)), 0057 this, SLOT(slotActivePartChanged(KParts::Part*))); 0058 0059 //When closing a window, tabs will be removed one by one, meaning each one will be activated: 0060 //this would trigger their delayed loading, which we don't want. So, when the main window is closed 0061 //disconnect the delayedLoadTab slot 0062 connect(mainWindow, &KonqMainWindow::closing, this, [this](){ 0063 disconnect(m_tabContainer, &QTabWidget::currentChanged, this, &KonqViewManager::delayedLoadTab); 0064 } 0065 ); 0066 } 0067 0068 KonqView *KonqViewManager::createFirstView(const QString &mimeType, const QString &serviceName) 0069 { 0070 //qCDebug(KONQUEROR_LOG) << serviceName; 0071 KPluginMetaData service; 0072 QVector<KPluginMetaData> partServiceOffers; 0073 KService::List appServiceOffers; 0074 KonqViewFactory newViewFactory = createView(mimeType, serviceName, service, partServiceOffers, appServiceOffers, true /*forceAutoEmbed*/); 0075 if (newViewFactory.isNull()) { 0076 qCDebug(KONQUEROR_LOG) << "No suitable factory found."; 0077 return nullptr; 0078 } 0079 0080 KonqView *childView = setupView(tabContainer(), newViewFactory, service, partServiceOffers, appServiceOffers, mimeType, false); 0081 0082 setActivePart(childView->part()); 0083 0084 m_tabContainer->asQWidget()->show(); 0085 return childView; 0086 } 0087 0088 KonqViewManager::~KonqViewManager() 0089 { 0090 clear(); 0091 } 0092 0093 KonqView *KonqViewManager::splitView(KonqView *currentView, 0094 Qt::Orientation orientation, 0095 bool newOneFirst, bool forceAutoEmbed) 0096 { 0097 #ifdef DEBUG_VIEWMGR 0098 qCDebug(KONQUEROR_LOG); 0099 m_pMainWindow->dumpViewList(); 0100 printFullHierarchy(); 0101 #endif 0102 0103 KonqFrame *splitFrame = currentView->frame(); 0104 const QString serviceType = currentView->serviceType(); 0105 0106 KPluginMetaData service; 0107 QVector<KPluginMetaData> partServiceOffers; 0108 KService::List appServiceOffers; 0109 0110 KonqViewFactory newViewFactory = createView(serviceType, currentView->service().pluginId(), service, partServiceOffers, appServiceOffers, forceAutoEmbed); 0111 0112 if (newViewFactory.isNull()) { 0113 return nullptr; //do not split at all if we can't create the new view 0114 } 0115 0116 Q_ASSERT(splitFrame); 0117 0118 KonqFrameContainerBase *parentContainer = splitFrame->parentContainer(); 0119 0120 // We need the sizes of the views in the parentContainer to restore these after the new container is inserted. 0121 // To access the sizes via QSplitter::sizes(), a pointer to a KonqFrameContainerBase is not sufficient. 0122 // We need a pointer to a KonqFrameContainer which is derived from QSplitter. 0123 KonqFrameContainer *parentKonqFrameContainer = dynamic_cast<KonqFrameContainer *>(parentContainer); 0124 QList<int> parentSplitterSizes; 0125 if (parentKonqFrameContainer) { 0126 parentSplitterSizes = parentKonqFrameContainer->sizes(); 0127 } 0128 0129 KonqFrameContainer *newContainer = parentContainer->splitChildFrame(splitFrame, orientation); 0130 0131 //qCDebug(KONQUEROR_LOG) << "Create new child"; 0132 KonqView *newView = setupView(newContainer, newViewFactory, service, partServiceOffers, appServiceOffers, serviceType, false); 0133 0134 #ifndef DEBUG 0135 //printSizeInfo( splitFrame, parentContainer, "after child insert" ); 0136 #endif 0137 0138 newContainer->insertWidget(newOneFirst ? 0 : 1, newView->frame()); 0139 if (newOneFirst) { 0140 newContainer->swapChildren(); 0141 } 0142 0143 Q_ASSERT(newContainer->count() == 2); 0144 0145 int width = std::max(newContainer->widget(0)->minimumSizeHint().width(), newContainer->widget(1)->minimumSizeHint().width()); 0146 newContainer->setSizes(QList<int>{width, width}); 0147 0148 splitFrame->show(); 0149 newContainer->show(); 0150 0151 if (parentKonqFrameContainer) { 0152 parentKonqFrameContainer->setSizes(parentSplitterSizes); 0153 } 0154 0155 Q_ASSERT(newView->frame()); 0156 Q_ASSERT(newView->part()); 0157 newContainer->setActiveChild(newView->frame()); 0158 setActivePart(newView->part()); 0159 0160 #ifdef DEBUG_VIEWMGR 0161 m_pMainWindow->dumpViewList(); 0162 printFullHierarchy(); 0163 qCDebug(KONQUEROR_LOG) << "done"; 0164 #endif 0165 0166 return newView; 0167 } 0168 0169 KonqView *KonqViewManager::splitMainContainer(KonqView *currentView, 0170 Qt::Orientation orientation, 0171 const QString &serviceType, // This can be Browser/View, not necessarily a mimetype 0172 const QString &serviceName, 0173 bool newOneFirst) 0174 { 0175 //qCDebug(KONQUEROR_LOG); 0176 0177 KPluginMetaData service; 0178 QVector<KPluginMetaData> partServiceOffers; 0179 KService::List appServiceOffers; 0180 0181 KonqViewFactory newViewFactory = createView(serviceType, serviceName, service, partServiceOffers, appServiceOffers); 0182 0183 if (newViewFactory.isNull()) { 0184 return nullptr; //do not split at all if we can't create the new view 0185 } 0186 0187 // Get main frame. Note: this is NOT necessarily m_tabContainer! 0188 // When having tabs plus a konsole, the main frame is a splitter (KonqFrameContainer). 0189 KonqFrameBase *mainFrame = m_pMainWindow->childFrame(); 0190 0191 KonqFrameContainer *newContainer = m_pMainWindow->splitChildFrame(mainFrame, orientation); 0192 0193 KonqView *childView = setupView(newContainer, newViewFactory, service, partServiceOffers, appServiceOffers, serviceType, true); 0194 0195 newContainer->insertWidget(newOneFirst ? 0 : 1, childView->frame()); 0196 if (newOneFirst) { 0197 newContainer->swapChildren(); 0198 } 0199 0200 newContainer->show(); 0201 newContainer->setActiveChild(mainFrame); 0202 0203 childView->duplicateView(currentView); 0204 // childView->openUrl(currentView->url(), currentView->locationBarURL()); 0205 0206 #ifdef DEBUG_VIEWMGR 0207 m_pMainWindow->dumpViewList(); 0208 printFullHierarchy(); 0209 qCDebug(KONQUEROR_LOG) << "done"; 0210 #endif 0211 0212 return childView; 0213 } 0214 0215 KonqView *KonqViewManager::addTab(const QString &serviceType, const QString &serviceName, bool passiveMode, bool openAfterCurrentPage, int pos) 0216 { 0217 #ifdef DEBUG_VIEWMGR 0218 qCDebug(KONQUEROR_LOG) << "------------- KonqViewManager::addTab starting -------------"; 0219 m_pMainWindow->dumpViewList(); 0220 printFullHierarchy(); 0221 #endif 0222 0223 KPluginMetaData service; 0224 QVector<KPluginMetaData> partServiceOffers; 0225 KService::List appServiceOffers; 0226 0227 Q_ASSERT(!serviceType.isEmpty()); 0228 0229 QString actualServiceName = serviceName; 0230 if (actualServiceName.isEmpty()) { 0231 // Use same part as the current view (e.g. khtml/webkit). 0232 // This is down here in this central method because it should work for 0233 // MMB-opens-tab, window.open (createNewWindow), and more. 0234 KonqView *currentView = m_pMainWindow->currentView(); 0235 // Don't use supportsMimeType("text/html"), it's true for katepart too. 0236 // (Testcase: view text file, ctrl+shift+n, was showing about page in katepart) 0237 if (currentView) { 0238 QMimeType mime = currentView->mimeType(); 0239 if (mime.isValid() && mime.inherits(serviceType)) { 0240 actualServiceName = currentView->service().pluginId(); 0241 } 0242 } 0243 } 0244 0245 KonqViewFactory newViewFactory = createView(serviceType, actualServiceName, service, partServiceOffers, appServiceOffers, true /*forceAutoEmbed*/); 0246 0247 if (newViewFactory.isNull()) { 0248 return nullptr; //do not split at all if we can't create the new view 0249 } 0250 0251 KonqView *childView = setupView(tabContainer(), newViewFactory, service, partServiceOffers, appServiceOffers, serviceType, passiveMode, openAfterCurrentPage, pos); 0252 0253 #ifdef DEBUG_VIEWMGR 0254 m_pMainWindow->dumpViewList(); 0255 printFullHierarchy(); 0256 qCDebug(KONQUEROR_LOG) << "------------- KonqViewManager::addTab done -------------"; 0257 #endif 0258 0259 return childView; 0260 } 0261 0262 KonqView *KonqViewManager::addTabFromHistory(KonqView *currentView, int steps, bool openAfterCurrentPage) 0263 { 0264 int oldPos = currentView->historyIndex(); 0265 int newPos = oldPos + steps; 0266 0267 const HistoryEntry *he = currentView->historyAt(newPos); 0268 if (!he) { 0269 return nullptr; 0270 } 0271 0272 KonqView *newView = nullptr; 0273 newView = addTab(he->strServiceType, he->strServiceName, false, openAfterCurrentPage); 0274 0275 if (!newView) { 0276 return nullptr; 0277 } 0278 0279 newView->copyHistory(currentView); 0280 newView->setHistoryIndex(newPos); 0281 newView->restoreHistory(); 0282 0283 return newView; 0284 } 0285 0286 void KonqViewManager::duplicateTab(int tabIndex, bool openAfterCurrentPage) 0287 { 0288 #ifdef DEBUG_VIEWMGR 0289 qCDebug(KONQUEROR_LOG) << tabIndex; 0290 m_pMainWindow->dumpViewList(); 0291 printFullHierarchy(); 0292 #endif 0293 0294 QTemporaryFile tempFile; 0295 tempFile.open(); 0296 KConfig config(tempFile.fileName()); 0297 KConfigGroup profileGroup(&config, "Profile"); 0298 0299 KonqFrameBase *tab = tabContainer()->tabAt(tabIndex); 0300 QString prefix = KonqFrameBase::frameTypeToString(tab->frameType()) + QString::number(0); // always T0 0301 profileGroup.writeEntry("RootItem", prefix); 0302 prefix.append(QLatin1Char('_')); 0303 KonqFrameBase::Options flags = KonqFrameBase::SaveHistoryItems; 0304 tab->saveConfig(profileGroup, prefix, flags, nullptr, 0, 1); 0305 0306 loadRootItem(profileGroup, tabContainer(), QUrl(), true, QUrl(), QString(), openAfterCurrentPage); 0307 0308 if (openAfterCurrentPage) { 0309 m_tabContainer->setCurrentIndex(m_tabContainer->currentIndex() + 1); 0310 } else { 0311 m_tabContainer->setCurrentIndex(m_tabContainer->count() - 1); 0312 } 0313 0314 #ifdef DEBUG_VIEWMGR 0315 m_pMainWindow->dumpViewList(); 0316 printFullHierarchy(); 0317 #endif 0318 } 0319 0320 KonqMainWindow *KonqViewManager::breakOffTab(int tab, const QSize &windowSize) 0321 { 0322 #ifdef DEBUG_VIEWMGR 0323 qCDebug(KONQUEROR_LOG) << "tab=" << tab; 0324 m_pMainWindow->dumpViewList(); 0325 printFullHierarchy(); 0326 #endif 0327 0328 QTemporaryFile tempFile; 0329 tempFile.open(); 0330 KSharedConfigPtr config = KSharedConfig::openConfig(tempFile.fileName()); 0331 KConfigGroup profileGroup(config, "Profile"); 0332 0333 KonqFrameBase *tabFrame = tabContainer()->tabAt(tab); 0334 QString prefix = KonqFrameBase::frameTypeToString(tabFrame->frameType()) + QString::number(0); // always T0 0335 profileGroup.writeEntry("RootItem", prefix); 0336 prefix.append(QLatin1Char('_')); 0337 KonqFrameBase::Options flags = KonqFrameBase::SaveHistoryItems; 0338 tabFrame->saveConfig(profileGroup, prefix, flags, nullptr, 0, 1); 0339 0340 KonqMainWindow *mainWindow = new KonqMainWindow; 0341 0342 KonqFrameTabs *newTabContainer = mainWindow->viewManager()->tabContainer(); 0343 mainWindow->viewManager()->loadRootItem(profileGroup, newTabContainer, QUrl(), true, QUrl()); 0344 0345 removeTab(tabFrame, false); 0346 0347 mainWindow->enableAllActions(true); 0348 mainWindow->resize(windowSize); 0349 mainWindow->activateChild(); 0350 mainWindow->show(); 0351 0352 #ifdef DEBUG_VIEWMGR 0353 m_pMainWindow->dumpViewList(); 0354 printFullHierarchy(); 0355 #endif 0356 0357 return mainWindow; 0358 } 0359 0360 void KonqViewManager::openClosedWindow(const KonqClosedWindowItem &closedWindowItem) 0361 { 0362 openSavedWindow(closedWindowItem.configGroup())->show(); 0363 } 0364 0365 KonqMainWindow *KonqViewManager::openSavedWindow(const KConfigGroup &configGroup) 0366 { 0367 // TODO factorize to avoid code duplication with loadViewProfileFromGroup 0368 KonqMainWindow *mainWindow = new KonqMainWindow; 0369 0370 if (configGroup.readEntry("FullScreen", false)) { 0371 // Full screen on 0372 mainWindow->showFullScreen(); 0373 } else { 0374 // Full screen off 0375 if (mainWindow->isFullScreen()) { 0376 mainWindow->showNormal(); 0377 } 0378 // Window size comes from the applyMainWindowSettings call below 0379 } 0380 0381 mainWindow->viewManager()->loadRootItem(configGroup, mainWindow, QUrl(), true, QUrl()); 0382 mainWindow->applyMainWindowSettings(configGroup); 0383 mainWindow->activateChild(); 0384 0385 #ifdef DEBUG_VIEWMGR 0386 mainWindow->viewManager()->printFullHierarchy(); 0387 #endif 0388 return mainWindow; 0389 } 0390 0391 KonqMainWindow *KonqViewManager::openSavedWindow(const KConfigGroup &configGroup, 0392 bool openTabsInsideCurrentWindow) 0393 { 0394 if (!openTabsInsideCurrentWindow) { 0395 return KonqViewManager::openSavedWindow(configGroup); 0396 } else { 0397 loadRootItem(configGroup, tabContainer(), QUrl(), true, QUrl()); 0398 #ifndef NDEBUG 0399 printFullHierarchy(); 0400 #endif 0401 return m_pMainWindow; 0402 } 0403 } 0404 0405 void KonqViewManager::removeTab(KonqFrameBase *currentFrame, bool emitAboutToRemoveSignal) 0406 { 0407 Q_ASSERT(currentFrame); 0408 #ifdef DEBUG_VIEWMGR 0409 qCDebug(KONQUEROR_LOG) << currentFrame; 0410 m_pMainWindow->dumpViewList(); 0411 printFullHierarchy(); 0412 #endif 0413 0414 if (m_tabContainer->count() == 1) { 0415 m_pMainWindow->slotAddTab(); // #214378 0416 } 0417 0418 if (emitAboutToRemoveSignal) { 0419 emit aboutToRemoveTab(currentFrame); 0420 } 0421 0422 if (currentFrame->asQWidget() == m_tabContainer->currentWidget()) { 0423 setActivePart(nullptr); 0424 } 0425 0426 const QList<KonqView *> viewList = KonqViewCollector::collect(currentFrame); 0427 for (KonqView *view: viewList) { 0428 if (view == m_pMainWindow->currentView()) { 0429 setActivePart(nullptr); 0430 } 0431 m_pMainWindow->removeChildView(view); 0432 delete view; 0433 } 0434 0435 m_tabContainer->childFrameRemoved(currentFrame); 0436 0437 delete currentFrame; 0438 0439 m_tabContainer->slotCurrentChanged(m_tabContainer->currentIndex()); 0440 0441 m_pMainWindow->viewCountChanged(); 0442 0443 #ifdef DEBUG_VIEWMGR 0444 m_pMainWindow->dumpViewList(); 0445 printFullHierarchy(); 0446 #endif 0447 } 0448 0449 void KonqViewManager::reloadAllTabs() 0450 { 0451 for(KonqFrameBase *frame: tabContainer()->childFrameList()) { 0452 if (frame && frame->activeChildView()) { 0453 if (!frame->activeChildView()->locationBarURL().isEmpty()) { 0454 //TODO KF6: check whether requestedUrl or realUrl is more suitable here. Do we want to download again a file? I think so 0455 frame->activeChildView()->openUrl(frame->activeChildView()->url(), frame->activeChildView()->locationBarURL()); 0456 } 0457 } 0458 } 0459 } 0460 0461 void KonqViewManager::removeOtherTabs(int tabIndex) 0462 { 0463 QList<KonqFrameBase *> tabs = m_tabContainer->childFrameList(); 0464 for (int i = 0; i < tabs.count(); ++i) { 0465 if (i != tabIndex) { 0466 removeTab(tabs.at(i)); 0467 } 0468 } 0469 } 0470 0471 void KonqViewManager::moveTabBackward() 0472 { 0473 if (m_tabContainer->count() == 1) { 0474 return; 0475 } 0476 0477 int iTab = m_tabContainer->currentIndex(); 0478 m_tabContainer->moveTabBackward(iTab); 0479 } 0480 0481 void KonqViewManager::moveTabForward() 0482 { 0483 if (m_tabContainer->count() == 1) { 0484 return; 0485 } 0486 0487 int iTab = m_tabContainer->currentIndex(); 0488 m_tabContainer->moveTabForward(iTab); 0489 } 0490 0491 void KonqViewManager::activateNextTab() 0492 { 0493 if (m_tabContainer->count() == 1) { 0494 return; 0495 } 0496 0497 int iTab = m_tabContainer->currentIndex(); 0498 0499 iTab++; 0500 0501 if (iTab == m_tabContainer->count()) { 0502 iTab = 0; 0503 } 0504 0505 m_tabContainer->setCurrentIndex(iTab); 0506 } 0507 0508 void KonqViewManager::activatePrevTab() 0509 { 0510 if (m_tabContainer->count() == 1) { 0511 return; 0512 } 0513 0514 int iTab = m_tabContainer->currentIndex(); 0515 0516 iTab--; 0517 0518 if (iTab == -1) { 0519 iTab = m_tabContainer->count() - 1; 0520 } 0521 0522 m_tabContainer->setCurrentIndex(iTab); 0523 } 0524 0525 int KonqViewManager::currentTabIndex() const 0526 { 0527 return m_tabContainer->currentIndex(); 0528 } 0529 0530 int KonqViewManager::tabsCount() const 0531 { 0532 return m_tabContainer->count(); 0533 } 0534 0535 void KonqViewManager::activateTab(int position) 0536 { 0537 if (position < 0 || m_tabContainer->count() == 1 || position >= m_tabContainer->count()) { 0538 return; 0539 } 0540 0541 m_tabContainer->setCurrentIndex(position); 0542 } 0543 0544 void KonqViewManager::showTab(KonqView *view) 0545 { 0546 if (m_tabContainer->currentWidget() != view->frame()) { 0547 m_tabContainer->setCurrentIndex(m_tabContainer->indexOf(view->frame())); 0548 } 0549 } 0550 0551 void KonqViewManager::showTab(int tabIndex) 0552 { 0553 if (m_tabContainer->currentIndex() != tabIndex) { 0554 m_tabContainer->setCurrentIndex(tabIndex); 0555 } 0556 } 0557 0558 void KonqViewManager::updatePixmaps() 0559 { 0560 const QList<KonqView *> viewList = KonqViewCollector::collect(tabContainer()); 0561 for (KonqView *view: viewList) { 0562 view->setTabIcon(QUrl::fromUserInput(view->locationBarURL())); 0563 } 0564 } 0565 0566 void KonqViewManager::openClosedTab(const KonqClosedTabItem &closedTab) 0567 { 0568 qCDebug(KONQUEROR_LOG); 0569 loadRootItem(closedTab.configGroup(), m_tabContainer, QUrl(), true, QUrl(), QString(), false, closedTab.pos()); 0570 0571 int pos = (closedTab.pos() < m_tabContainer->count()) ? closedTab.pos() : m_tabContainer->count() - 1; 0572 qCDebug(KONQUEROR_LOG) << "pos, m_tabContainer->count():" << pos << m_tabContainer->count() - 1; 0573 0574 m_tabContainer->setCurrentIndex(pos); 0575 } 0576 0577 void KonqViewManager::removeView(KonqView *view) 0578 { 0579 #ifdef DEBUG_VIEWMGR 0580 qCDebug(KONQUEROR_LOG) << view; 0581 m_pMainWindow->dumpViewList(); 0582 printFullHierarchy(); 0583 #endif 0584 0585 if (!view) { 0586 return; 0587 } 0588 0589 KonqFrame *frame = view->frame(); 0590 KonqFrameContainerBase *parentContainer = frame->parentContainer(); 0591 0592 qCDebug(KONQUEROR_LOG) << "view=" << view << "frame=" << frame << "parentContainer=" << parentContainer; 0593 0594 if (parentContainer->frameType() == KonqFrameBase::Container) { 0595 setActivePart(nullptr); 0596 0597 qCDebug(KONQUEROR_LOG) << "parentContainer is a KonqFrameContainer"; 0598 0599 KonqFrameContainerBase *grandParentContainer = parentContainer->parentContainer(); 0600 qCDebug(KONQUEROR_LOG) << "grandParentContainer=" << grandParentContainer; 0601 0602 KonqFrameBase *otherFrame = static_cast<KonqFrameContainer *>(parentContainer)->otherChild(frame); 0603 if (!otherFrame) { 0604 qCWarning(KONQUEROR_LOG) << "This shouldn't happen!"; 0605 return; 0606 } 0607 0608 static_cast<KonqFrameContainer *>(parentContainer)->setAboutToBeDeleted(); 0609 0610 // If the grand parent is a KonqFrameContainer, we need the sizes of the views inside it to restore these after 0611 // the parent is replaced. To access the sizes via QSplitter::sizes(), a pointer to a KonqFrameContainerBase 0612 // is not sufficient. We need a pointer to a KonqFrameContainer which is derived from QSplitter. 0613 KonqFrameContainer *grandParentKonqFrameContainer = dynamic_cast<KonqFrameContainer *>(grandParentContainer); 0614 QList<int> grandParentSplitterSizes; 0615 if (grandParentKonqFrameContainer) { 0616 grandParentSplitterSizes = grandParentKonqFrameContainer->sizes(); 0617 } 0618 0619 m_pMainWindow->removeChildView(view); 0620 0621 //qCDebug(KONQUEROR_LOG) << "--- Deleting view" << view; 0622 grandParentContainer->replaceChildFrame(parentContainer, otherFrame); 0623 0624 //qCDebug(KONQUEROR_LOG) << "--- Removing otherFrame from parentContainer"; 0625 parentContainer->childFrameRemoved(otherFrame); 0626 0627 delete view; // This deletes the view, which deletes the part, which deletes its widget 0628 0629 delete parentContainer; 0630 0631 if (grandParentKonqFrameContainer) { 0632 grandParentKonqFrameContainer->setSizes(grandParentSplitterSizes); 0633 } 0634 0635 grandParentContainer->setActiveChild(otherFrame); 0636 grandParentContainer->activateChild(); 0637 m_pMainWindow->viewCountChanged(); 0638 } else if (parentContainer->frameType() == KonqFrameBase::Tabs) { 0639 qCDebug(KONQUEROR_LOG) << "parentContainer" << parentContainer << "is a KonqFrameTabs"; 0640 0641 removeTab(frame); 0642 } else if (parentContainer->frameType() == KonqFrameBase::MainWindow) { 0643 qCDebug(KONQUEROR_LOG) << "parentContainer is a KonqMainWindow. This shouldn't be removable, not removing."; 0644 } else { 0645 qCDebug(KONQUEROR_LOG) << "Unrecognized frame type, not removing."; 0646 } 0647 0648 #ifdef DEBUG_VIEWMGR 0649 printFullHierarchy(); 0650 m_pMainWindow->dumpViewList(); 0651 0652 qCDebug(KONQUEROR_LOG) << "done"; 0653 #endif 0654 } 0655 0656 // reimplemented from PartManager 0657 void KonqViewManager::removePart(KParts::Part *part) 0658 { 0659 //qCDebug(KONQUEROR_LOG) << part; 0660 // This is called when a part auto-deletes itself (case 1), or when 0661 // the "delete view" above deletes, in turn, the part (case 2) 0662 0663 KParts::PartManager::removePart(part); 0664 0665 // If we were called by PartManager::slotObjectDestroyed, then the inheritance has 0666 // been deleted already... Can't use inherits(). 0667 0668 KonqView *view = m_pMainWindow->childView(static_cast<KParts::ReadOnlyPart *>(part)); 0669 if (view) { // the child view still exists, so we are in case 1 0670 qCDebug(KONQUEROR_LOG) << "Found a child view"; 0671 0672 // Make sure that deleting the frame won't delete the part's widget; 0673 // that's already taken care of by the part. 0674 view->part()->widget()->hide(); 0675 view->part()->widget()->setParent(nullptr); 0676 0677 view->partDeleted(); // tell the child view that the part auto-deletes itself 0678 0679 if (m_pMainWindow->mainViewsCount() == 1) { 0680 qCDebug(KONQUEROR_LOG) << "Deleting last view -> closing the window"; 0681 clear(); 0682 qCDebug(KONQUEROR_LOG) << "Closing m_pMainWindow" << m_pMainWindow; 0683 m_pMainWindow->close(); // will delete it 0684 return; 0685 } else { // normal case 0686 removeView(view); 0687 } 0688 } 0689 0690 //qCDebug(KONQUEROR_LOG) << part << "done"; 0691 } 0692 0693 void KonqViewManager::slotPassiveModePartDeleted() 0694 { 0695 // Passive mode parts aren't registered to the part manager, 0696 // so we have to handle suicidal ones ourselves 0697 KParts::ReadOnlyPart *part = const_cast<KParts::ReadOnlyPart *>(static_cast<const KParts::ReadOnlyPart *>(sender())); 0698 disconnect(part, SIGNAL(destroyed()), this, SLOT(slotPassiveModePartDeleted())); 0699 qCDebug(KONQUEROR_LOG) << "part=" << part; 0700 KonqView *view = m_pMainWindow->childView(part); 0701 qCDebug(KONQUEROR_LOG) << "view=" << view; 0702 if (view != nullptr) { // the child view still exists, so the part suicided 0703 view->partDeleted(); // tell the child view that the part deleted itself 0704 removeView(view); 0705 } 0706 } 0707 0708 void KonqViewManager::viewCountChanged() 0709 { 0710 bool bShowActiveViewIndicator = (m_pMainWindow->viewCount() > 1); 0711 bool bShowLinkedViewIndicator = (m_pMainWindow->linkableViewsCount() > 1); 0712 0713 const KonqMainWindow::MapViews mapViews = m_pMainWindow->viewMap(); 0714 KonqMainWindow::MapViews::ConstIterator it = mapViews.begin(); 0715 KonqMainWindow::MapViews::ConstIterator end = mapViews.end(); 0716 for (; it != end; ++it) { 0717 KonqFrameStatusBar *sb = it.value()->frame()->statusbar(); 0718 sb->showActiveViewIndicator(bShowActiveViewIndicator && !it.value()->isPassiveMode()); 0719 sb->showLinkedViewIndicator(bShowLinkedViewIndicator && !it.value()->isFollowActive()); 0720 } 0721 } 0722 0723 void KonqViewManager::clear() 0724 { 0725 //qCDebug(KONQUEROR_LOG); 0726 setActivePart(nullptr); 0727 0728 if (m_pMainWindow->childFrame() == nullptr) { 0729 return; 0730 } 0731 0732 const QList<KonqView *> viewList = KonqViewCollector::collect(m_pMainWindow); 0733 if (!viewList.isEmpty()) { 0734 //qCDebug(KONQUEROR_LOG) << viewList.count() << "items"; 0735 0736 for (KonqView *view: viewList) { 0737 m_pMainWindow->removeChildView(view); 0738 //qCDebug(KONQUEROR_LOG) << "Deleting" << view; 0739 delete view; 0740 } 0741 } 0742 0743 KonqFrameBase *frame = m_pMainWindow->childFrame(); 0744 Q_ASSERT(frame); 0745 //qCDebug(KONQUEROR_LOG) << "deleting mainFrame "; 0746 m_pMainWindow->childFrameRemoved(frame); // will set childFrame() to NULL 0747 delete frame; 0748 // tab container was deleted by the above 0749 m_tabContainer = nullptr; 0750 m_pMainWindow->viewCountChanged(); 0751 } 0752 0753 KonqView *KonqViewManager::chooseNextView(KonqView *view) 0754 { 0755 //qCDebug(KONQUEROR_LOG) << view; 0756 0757 int it = 0; 0758 const QList<KonqView *> viewList = KonqViewCollector::collect(m_pMainWindow); 0759 if (viewList.isEmpty()) { 0760 return nullptr; // We have no view at all - this used to happen with totally-empty-profiles 0761 } 0762 0763 if (view) { // find it in the list 0764 it = viewList.indexOf(view); 0765 } 0766 0767 // the view should always be in the list 0768 if (it == -1) { 0769 qCWarning(KONQUEROR_LOG) << "View" << view << "is not in list!"; 0770 it = 0; 0771 } 0772 0773 bool rewinded = false; 0774 const int startIndex = it; 0775 const int end = viewList.count(); 0776 0777 //qCDebug(KONQUEROR_LOG) << "count=" << end; 0778 while (true) { 0779 //qCDebug(KONQUEROR_LOG) << "going next"; 0780 if (++it == end) { // move to next 0781 // end reached: restart from begin (but only once) 0782 if (!rewinded) { 0783 it = 0; 0784 rewinded = true; 0785 } else { 0786 break; // nothing found, probably buggy profile 0787 } 0788 } 0789 0790 if (it == startIndex && view) { 0791 break; // no next view found 0792 } 0793 0794 KonqView *nextView = viewList.at(it);; 0795 if (nextView && !nextView->isPassiveMode()) { 0796 return nextView; 0797 } 0798 //qCDebug(KONQUEROR_LOG) << "nextView=" << nextView << "passive=" << nextView->isPassiveMode(); 0799 } 0800 0801 //qCDebug(KONQUEROR_LOG) << "returning 0"; 0802 return nullptr; // no next view found 0803 } 0804 0805 KonqViewFactory KonqViewManager::createView(const QString &serviceType, 0806 const QString &serviceName, 0807 KPluginMetaData &service, 0808 QVector<KPluginMetaData> &partServiceOffers, 0809 KService::List &appServiceOffers, 0810 bool forceAutoEmbed) 0811 { 0812 KonqViewFactory viewFactory; 0813 0814 QString _serviceType(serviceType); 0815 QString _serviceName(serviceName); 0816 0817 if (serviceType.isEmpty() && m_pMainWindow->currentView()) { 0818 //clone current view 0819 KonqView *cv = m_pMainWindow->currentView(); 0820 if (cv->service().pluginId() == QLatin1String("konq_sidebartng")) { 0821 _serviceType = QStringLiteral("text/html"); 0822 _serviceName.clear(); 0823 } else { 0824 _serviceType = cv->serviceType(); 0825 _serviceName = cv->service().pluginId(); 0826 } 0827 } 0828 0829 KonqFactory konqFactory; 0830 viewFactory = konqFactory.createView(_serviceType, _serviceName, &service, &partServiceOffers, &appServiceOffers, forceAutoEmbed); 0831 0832 return viewFactory; 0833 } 0834 0835 KonqView* KonqViewManager::setupView(KonqFrameContainerBase* parentContainer, bool passiveMode, bool openAfterCurrentPage, int pos) 0836 { 0837 KonqViewFactory factory; 0838 return setupView(parentContainer, factory, {}, {}, {}, {}, passiveMode, openAfterCurrentPage, pos); 0839 } 0840 0841 KonqView *KonqViewManager::setupView(KonqFrameContainerBase *parentContainer, 0842 KonqViewFactory &viewFactory, 0843 const KPluginMetaData &service, 0844 const QVector<KPluginMetaData> &partServiceOffers, 0845 const KService::List &appServiceOffers, 0846 const QString &serviceType, 0847 bool passiveMode, 0848 bool openAfterCurrentPage, 0849 int pos) 0850 { 0851 //qCDebug(KONQUEROR_LOG) << "passiveMode=" << passiveMode; 0852 0853 QString sType = serviceType; 0854 0855 if (sType.isEmpty() && m_pMainWindow->currentView()) { // TODO remove this -- after checking all callers; splitMainContainer seems to need this logic 0856 sType = m_pMainWindow->currentView()->serviceType(); 0857 } 0858 0859 //qCDebug(KONQUEROR_LOG) << "creating KonqFrame with parent=" << parentContainer; 0860 KonqFrame *newViewFrame = new KonqFrame(parentContainer->asQWidget(), parentContainer); 0861 newViewFrame->setGeometry(0, 0, m_pMainWindow->width(), m_pMainWindow->height()); 0862 0863 //qCDebug(KONQUEROR_LOG) << "Creating KonqView"; 0864 // KonqView *v = new KonqView(newViewFrame, m_pMainWindow); 0865 KonqView *v = nullptr; 0866 if (!viewFactory.isNull()) { 0867 v = new KonqView(viewFactory, newViewFrame, m_pMainWindow, service, partServiceOffers, appServiceOffers, sType, passiveMode); 0868 } else { 0869 v = new KonqView(newViewFrame, m_pMainWindow); 0870 } 0871 //qCDebug(KONQUEROR_LOG) << "KonqView created - v=" << v << "v->part()=" << v->part(); 0872 0873 connect(v, &KonqView::sigPartChanged, m_pMainWindow, &KonqMainWindow::slotPartChanged); 0874 // QObject::connect(v, SIGNAL(sigPartChanged(KonqView*,KParts::ReadOnlyPart*,KParts::ReadOnlyPart*)), 0875 // m_pMainWindow, SLOT(slotPartChanged(KonqView*,KParts::ReadOnlyPart*,KParts::ReadOnlyPart*))); 0876 0877 m_pMainWindow->insertChildView(v); 0878 0879 int index = -1; 0880 if (openAfterCurrentPage) { 0881 index = m_tabContainer->currentIndex() + 1; 0882 } else if (pos > -1) { 0883 index = pos; 0884 } 0885 0886 parentContainer->insertChildFrame(newViewFrame, index); 0887 0888 if (parentContainer->frameType() != KonqFrameBase::Tabs) { 0889 newViewFrame->show(); 0890 } 0891 0892 // Don't register passive views to the part manager 0893 if (!v->isPassiveMode()) { // note that KonqView's constructor could set this to true even if passiveMode is false 0894 addPart(v->part(), false); 0895 } else { 0896 // Passive views aren't registered, but we still want to detect the suicidal ones 0897 connect(v->part(), SIGNAL(destroyed()), this, SLOT(slotPassiveModePartDeleted())); 0898 } 0899 0900 if (!m_bLoadingProfile) { 0901 m_pMainWindow->viewCountChanged(); 0902 } 0903 0904 //qCDebug(KONQUEROR_LOG) << "done"; 0905 return v; 0906 } 0907 0908 0909 void KonqViewManager::saveViewConfigToGroup(KConfigGroup &profileGroup, KonqFrameBase::Options options) 0910 { 0911 if (m_pMainWindow->childFrame()) { 0912 QString prefix = KonqFrameBase::frameTypeToString(m_pMainWindow->childFrame()->frameType()) 0913 + QString::number(0); 0914 profileGroup.writeEntry("RootItem", prefix); 0915 prefix.append(QLatin1Char('_')); 0916 m_pMainWindow->saveConfig(profileGroup, prefix, options, tabContainer(), 0, 1); 0917 } 0918 0919 profileGroup.writeEntry("FullScreen", m_pMainWindow->fullScreenMode()); 0920 0921 m_pMainWindow->saveMainWindowSettings(profileGroup); 0922 } 0923 0924 void KonqViewManager::loadViewConfigFromGroup(const KConfigGroup &profileGroup, const QString &filename, 0925 const QUrl &forcedUrl, const KonqOpenURLRequest &req, 0926 bool openUrl) 0927 { 0928 Q_UNUSED(filename); // could be useful in case of error messages 0929 0930 QUrl defaultURL; 0931 if (m_pMainWindow->currentView()) { 0932 defaultURL = m_pMainWindow->currentView()->url(); 0933 } 0934 0935 clear(); 0936 0937 if (!KonqUrl::isKonqBlank(forcedUrl)) { 0938 loadRootItem(profileGroup, m_pMainWindow, defaultURL, openUrl && forcedUrl.isEmpty(), forcedUrl, req.serviceName); 0939 } else { 0940 // ## in this case we won't resize the window, so bool resetWindow could be useful after all? 0941 m_pMainWindow->disableActionsNoView(); 0942 m_pMainWindow->action("clear_location")->trigger(); 0943 } 0944 0945 //qCDebug(KONQUEROR_LOG) << "after loadRootItem"; 0946 0947 // Set an active part first so that we open the URL in the current view 0948 // (to set the location bar correctly and asap) 0949 KonqView *nextChildView = nullptr; 0950 nextChildView = m_pMainWindow->activeChildView(); 0951 if (nextChildView == nullptr) { 0952 nextChildView = chooseNextView(nullptr); 0953 } 0954 setActivePart(nextChildView ? nextChildView->part() : nullptr); 0955 0956 // #71164 0957 if (!req.browserArgs.frameName.isEmpty() && nextChildView) { 0958 nextChildView->setViewName(req.browserArgs.frameName); 0959 } 0960 0961 if (openUrl && !forcedUrl.isEmpty()) { 0962 KonqOpenURLRequest _req(req); 0963 _req.openAfterCurrentPage = KonqSettings::openAfterCurrentPage(); 0964 _req.forceAutoEmbed = true; // it's a new window, let's use it 0965 0966 m_pMainWindow->openUrl(nextChildView /* can be 0 for an empty profile */, 0967 forcedUrl, _req.args.mimeType(), _req, _req.browserArgs.trustedSource); 0968 0969 // TODO choose a linked view if any (instead of just the first one), 0970 // then open the same URL in any non-linked one 0971 } else { 0972 if (forcedUrl.isEmpty() && m_pMainWindow->locationBarURL().isEmpty()) { 0973 // No URL -> the user will want to type one 0974 m_pMainWindow->focusLocationBar(); 0975 } 0976 } 0977 0978 // Window size 0979 if (profileGroup.readEntry("FullScreen", false)) { 0980 // Full screen on 0981 m_pMainWindow->setWindowState(m_pMainWindow->windowState() | Qt::WindowFullScreen); 0982 } else { 0983 // Full screen off 0984 m_pMainWindow->setWindowState(m_pMainWindow->windowState() & ~Qt::WindowFullScreen); 0985 applyWindowSize(profileGroup); 0986 } 0987 0988 //qCDebug(KONQUEROR_LOG) << "done"; 0989 } 0990 0991 void KonqViewManager::setActivePart(KParts::Part *part, QWidget *) 0992 { 0993 doSetActivePart(static_cast<KParts::ReadOnlyPart *>(part)); 0994 } 0995 0996 void KonqViewManager::doSetActivePart(KParts::ReadOnlyPart *part) 0997 { 0998 if (part) { 0999 qCDebug(KONQUEROR_LOG) << part << part->url(); 1000 } 1001 1002 KParts::Part *mainWindowActivePart = m_pMainWindow->currentView() 1003 ? m_pMainWindow->currentView()->part() : nullptr; 1004 if (part == activePart() && mainWindowActivePart == part) { 1005 //qCDebug(KONQUEROR_LOG) << "Part is already active!"; 1006 return; 1007 } 1008 1009 // ## is this the right currentView() already? 1010 if (m_pMainWindow->currentView()) { 1011 m_pMainWindow->currentView()->setLocationBarURL(m_pMainWindow->locationBarURL()); 1012 } 1013 1014 KParts::PartManager::setActivePart(part); 1015 1016 if (part && part->widget()) { 1017 part->widget()->setFocus(); 1018 1019 // However in case of an error URL we want to make it possible for the user to fix it 1020 KonqView *view = m_pMainWindow->viewMap().value(part); 1021 if (view && view->isErrorUrl()) { 1022 m_pMainWindow->focusLocationBar(); 1023 } 1024 } 1025 1026 emitActivePartChanged(); // This is what triggers KonqMainWindow::slotPartActivated 1027 } 1028 1029 void KonqViewManager::slotActivePartChanged(KParts::Part *newPart) 1030 { 1031 //qCDebug(KONQUEROR_LOG) << newPart; 1032 if (newPart == nullptr) { 1033 //qCDebug(KONQUEROR_LOG) << "newPart = 0L , returning"; 1034 return; 1035 } 1036 // Send event to mainwindow - this is useful for plugins (like searchbar) 1037 KParts::PartActivateEvent ev(true, newPart, newPart->widget()); 1038 QApplication::sendEvent(m_pMainWindow, &ev); 1039 1040 KonqView *view = m_pMainWindow->childView(static_cast<KParts::ReadOnlyPart *>(newPart)); 1041 if (view == nullptr) { 1042 qCDebug(KONQUEROR_LOG) << "No view associated with this part"; 1043 return; 1044 } 1045 if (view->frame()->parentContainer() == nullptr) { 1046 return; 1047 } 1048 if (!m_bLoadingProfile) { 1049 view->frame()->statusbar()->updateActiveStatus(); 1050 view->frame()->parentContainer()->setActiveChild(view->frame()); 1051 } 1052 //qCDebug(KONQUEROR_LOG) << "done"; 1053 } 1054 1055 void KonqViewManager::emitActivePartChanged() 1056 { 1057 m_pMainWindow->slotPartActivated(activePart()); 1058 } 1059 1060 // Read default size from profile (e.g. Width=80%) 1061 static QSize readDefaultSize(const KConfigGroup &cfg, QWidget *widget) 1062 { 1063 QString widthStr = cfg.readEntry("Width"); 1064 QString heightStr = cfg.readEntry("Height"); 1065 int width = -1; 1066 int height = -1; 1067 const QRect geom = widget->screen()->geometry(); 1068 1069 bool ok; 1070 if (widthStr.endsWith('%')) { 1071 widthStr.truncate(widthStr.length() - 1); 1072 const int relativeWidth = widthStr.toInt(&ok); 1073 if (ok) { 1074 width = relativeWidth * geom.width() / 100; 1075 } 1076 } else { 1077 width = widthStr.toInt(&ok); 1078 if (!ok) { 1079 width = -1; 1080 } 1081 } 1082 1083 if (heightStr.endsWith('%')) { 1084 heightStr.truncate(heightStr.length() - 1); 1085 int relativeHeight = heightStr.toInt(&ok); 1086 if (ok) { 1087 height = relativeHeight * geom.height() / 100; 1088 } 1089 } else { 1090 height = heightStr.toInt(&ok); 1091 if (!ok) { 1092 height = -1; 1093 } 1094 } 1095 1096 return QSize(width, height); 1097 } 1098 1099 void KonqViewManager::applyWindowSize(const KConfigGroup &profileGroup) 1100 { 1101 const QSize size = readDefaultSize(profileGroup, m_pMainWindow); // example: "Width=80%" 1102 if (size.isValid()) { 1103 m_pMainWindow->resize(size); 1104 } 1105 KWindowConfig::restoreWindowSize(m_pMainWindow->windowHandle(), profileGroup); // example: "Width 1400=1120" 1106 } 1107 1108 void KonqViewManager::loadRootItem(const KConfigGroup &cfg, KonqFrameContainerBase *parent, 1109 const QUrl &defaultURL, bool openUrl, 1110 const QUrl &forcedUrl, const QString &forcedService, 1111 bool openAfterCurrentPage, 1112 int pos) 1113 { 1114 const QString rootItem = cfg.readEntry("RootItem", "empty"); 1115 1116 // This flag is used by KonqView, to distinguish manual view creation 1117 // from profile loading (e.g. in switchView) 1118 m_bLoadingProfile = true; 1119 1120 loadItem(cfg, parent, rootItem, {defaultURL, forcedUrl, forcedService, openUrl}, openAfterCurrentPage, pos); 1121 1122 m_bLoadingProfile = false; 1123 1124 //Actually perform delayed loading of the current tab 1125 if (m_tabContainer) { 1126 KonqFrameBase *frm = m_tabContainer->currentTab(); 1127 QList<KonqView*> views = KonqViewCollector::collect(frm); 1128 for (KonqView *v : views) { 1129 v->loadDelayed(); 1130 } 1131 } 1132 1133 m_pMainWindow->enableAllActions(true); 1134 1135 // This flag disables calls to viewCountChanged while creating the views, 1136 // so we do it once at the end: 1137 viewCountChanged(); 1138 } 1139 1140 void KonqViewManager::loadItem(const KConfigGroup &cfg, KonqFrameContainerBase *parent, 1141 const QString &name, const LoadViewUrlData &viewData, 1142 bool openAfterCurrentPage, int pos) 1143 { 1144 QString prefix; 1145 if (name != QLatin1String("InitialView")) { // InitialView is old stuff, not in use anymore 1146 prefix = name + QLatin1Char('_'); 1147 } 1148 1149 #ifdef DEBUG_VIEWMGR 1150 qCDebug(KONQUEROR_LOG) << "begin name=" << name << "openUrl=" << openUrl; 1151 #endif 1152 1153 if (name.startsWith(QLatin1String("View")) || name == QLatin1String("empty")) { 1154 loadViewItem(cfg, prefix, parent, name, viewData, openAfterCurrentPage, pos); 1155 } else if (name.startsWith(QLatin1String("Container"))) { 1156 //qCDebug(KONQUEROR_LOG) << "Item is Container"; 1157 loadContainerItem(cfg, prefix, parent, name, openAfterCurrentPage, pos, viewData); 1158 } else if (name.startsWith(QLatin1String("Tabs"))) { 1159 //qCDebug(KONQUEROR_LOG) << "Item is a Tabs"; 1160 loadTabsItem(cfg, prefix, parent, viewData); 1161 } else { 1162 qCWarning(KONQUEROR_LOG) << "Profile Loading Error: Unknown item" << name; 1163 } 1164 1165 //qCDebug(KONQUEROR_LOG) << "end" << name; 1166 } 1167 1168 void KonqViewManager::loadTabsItem(const KConfigGroup& cfg, const QString& prefix, KonqFrameContainerBase *parent, 1169 const LoadViewUrlData &viewData) 1170 { 1171 int index = cfg.readEntry(QStringLiteral("activeChildIndex").prepend(prefix), 0); 1172 if (!m_tabContainer) { 1173 createTabContainer(parent->asQWidget(), parent); 1174 parent->insertChildFrame(m_tabContainer); 1175 } 1176 1177 const QStringList childList = cfg.readEntry(QStringLiteral("Children").prepend(prefix), QStringList()); 1178 for (QStringList::const_iterator it = childList.begin(); it != childList.end(); ++it) { 1179 loadItem(cfg, tabContainer(), *it, viewData); 1180 QWidget *currentPage = m_tabContainer->currentWidget(); 1181 if (currentPage != nullptr) { 1182 KonqView *activeChildView = dynamic_cast<KonqFrameBase *>(currentPage)->activeChildView(); 1183 if (activeChildView != nullptr) { 1184 activeChildView->setCaption(activeChildView->caption()); 1185 activeChildView->setTabIcon(activeChildView->url()); 1186 } 1187 } 1188 } 1189 1190 QWidget *w = m_tabContainer->widget(index); 1191 if (w) { 1192 m_tabContainer->setActiveChild(dynamic_cast<KonqFrameBase *>(w)); 1193 m_tabContainer->setCurrentIndex(index); 1194 m_tabContainer->show(); 1195 } else { 1196 qCWarning(KONQUEROR_LOG) << "Profile Loading Error: Unknown current item index" << index; 1197 } 1198 } 1199 1200 void KonqViewManager::loadContainerItem(const KConfigGroup& cfg, const QString& prefix, KonqFrameContainerBase* parent, 1201 const QString &name, bool openAfterCurrentPage, int pos, const LoadViewUrlData& viewData) 1202 { 1203 //load container config 1204 QString ostr = cfg.readEntry(QStringLiteral("Orientation").prepend(prefix), QString()); 1205 //qCDebug(KONQUEROR_LOG) << "Orientation:" << ostr; 1206 Qt::Orientation o; 1207 if (ostr == QLatin1String("Vertical")) { 1208 o = Qt::Vertical; 1209 } else if (ostr == QLatin1String("Horizontal")) { 1210 o = Qt::Horizontal; 1211 } else { 1212 qCWarning(KONQUEROR_LOG) << "Profile Loading Error: No orientation specified in" << name; 1213 o = Qt::Horizontal; 1214 } 1215 1216 QList<int> sizes = cfg.readEntry(QStringLiteral("SplitterSizes").prepend(prefix), QList<int>()); 1217 1218 int index = cfg.readEntry(QStringLiteral("activeChildIndex").prepend(prefix), -1); 1219 QStringList childList = cfg.readEntry(QStringLiteral("Children").prepend(prefix), QStringList()); 1220 1221 if (childList.count() < 2) { 1222 qCWarning(KONQUEROR_LOG) << "Profile Loading Error: Less than two children in" << name; 1223 // fallback to defaults 1224 loadItem(cfg, parent, QStringLiteral("InitialView"), viewData); 1225 return; 1226 } 1227 1228 KonqFrameContainer *newContainer = new KonqFrameContainer(o, parent->asQWidget(), parent); 1229 1230 int tabindex = pos; 1231 if (openAfterCurrentPage && parent->frameType() == KonqFrameBase::Tabs) { // Need to honor it, if possible 1232 tabindex = static_cast<KonqFrameTabs *>(parent)->currentIndex() + 1; 1233 } 1234 parent->insertChildFrame(newContainer, tabindex); 1235 1236 loadItem(cfg, newContainer, childList.at(0), viewData); 1237 loadItem(cfg, newContainer, childList.at(1), viewData); 1238 1239 //qCDebug(KONQUEROR_LOG) << "setSizes" << sizes; 1240 newContainer->setSizes(sizes); 1241 1242 if (index == 1) { 1243 newContainer->setActiveChild(newContainer->secondChild()); 1244 } else if (index == 0) { 1245 newContainer->setActiveChild(newContainer->firstChild()); 1246 } 1247 1248 newContainer->show(); 1249 } 1250 1251 //Helper function for KonqViewManager::loadViewItem which determines whether the 1252 // given frame is the tab container or is (directly or not) contained in the tab container 1253 bool hasTabAncestor(KonqFrameContainerBase *frm) { 1254 while (frm) { 1255 if (frm && frm->frameType() == KonqFrameBase::Tabs) { 1256 return true; 1257 } 1258 frm = frm->parentContainer(); 1259 } 1260 return false; 1261 } 1262 1263 void KonqViewManager::loadViewItem(const KConfigGroup& cfg, const QString &prefix, KonqFrameContainerBase* parent, 1264 const QString& name, const LoadViewUrlData &data, bool openAfterCurrentPage, int pos) 1265 { 1266 // load view config 1267 1268 QString serviceType; 1269 QString serviceName; 1270 if (name == QLatin1String("empty")) { 1271 // An empty profile is an empty KHTML part. Makes all KHTML actions available, avoids crashes, 1272 // makes it easy to DND a URL onto it, and makes it fast to load a website from there. 1273 serviceType = QStringLiteral("text/html"); 1274 serviceName = data.forcedService; // coming e.g. from the cmdline, otherwise empty 1275 } else { 1276 serviceType = cfg.readEntry(QStringLiteral("ServiceType").prepend(prefix), QStringLiteral("inode/directory")); 1277 serviceName = cfg.readEntry(QStringLiteral("ServiceName").prepend(prefix), QString()); 1278 if (serviceName == QLatin1String("konq_aboutpage")) { 1279 if ((!data.forcedUrl.isEmpty() && !KonqUrl::hasKonqScheme(data.forcedUrl)) || 1280 (data.forcedUrl.isEmpty() && data.openUrl == false)) { // e.g. window.open 1281 // No point in loading the about page if we're going to replace it with a KHTML part right away 1282 serviceType = QStringLiteral("text/html"); 1283 serviceName = data.forcedService; // coming e.g. from the cmdline, otherwise empty 1284 } 1285 } 1286 } 1287 1288 //qCDebug(KONQUEROR_LOG) << "serviceType" << serviceType << serviceName; 1289 1290 bool passiveMode = cfg.readEntry(QStringLiteral("PassiveMode").prepend(prefix), false); 1291 1292 //qCDebug(KONQUEROR_LOG) << "Creating View Stuff; parent=" << parent; 1293 if (parent == m_pMainWindow) { 1294 parent = tabContainer(); 1295 } 1296 1297 QUrl url; 1298 if (data.openUrl) { 1299 const QString urlKey = QStringLiteral("URL").prepend(prefix); 1300 if (cfg.hasKey(urlKey)) { 1301 url = QUrl(cfg.readPathEntry(urlKey, KonqUrl::string(KonqUrl::Type::Blank))); 1302 } else { 1303 url = data.defaultUrl; 1304 } 1305 } 1306 1307 bool lockedLocation = cfg.readEntry(QStringLiteral("LockedLocation").prepend(prefix), false); 1308 bool linkedView = cfg.readEntry(QStringLiteral("LinkedView").prepend(prefix), false); 1309 const bool isToggleView = cfg.readEntry(QStringLiteral("ToggleView").prepend(prefix), false); 1310 1311 KonqView *childView = nullptr; 1312 1313 //Don't use delayed loading for views which aren't (directly or indirectly) contained in the tabs widget 1314 //This is the case, for example, of the sidebar view or the terminal emulator. Since they don't belong 1315 //to any tab, they're always visible, so there's no reason to delay loading them (besides, it wouldn't 1316 //work, as the delayed loading would never trigger). See BUG 478255 1317 if (hasTabAncestor(parent)) { 1318 childView = setupView(parent, passiveMode, openAfterCurrentPage, pos); 1319 childView->storeDelayedLoadingData(serviceType, serviceName, data.openUrl, url, lockedLocation, cfg, prefix); 1320 } 1321 else { 1322 KPluginMetaData service; 1323 QVector<KPluginMetaData> partServiceOffers; 1324 KService::List appServiceOffers; 1325 KonqFactory konqFactory; 1326 KonqViewFactory viewFactory = konqFactory.createView(serviceType, serviceName, &service, &partServiceOffers, &appServiceOffers, true /*forceAutoEmbed*/); 1327 if (viewFactory.isNull()) { 1328 qCWarning(KONQUEROR_LOG) << "Profile Loading Error: View creation failed"; 1329 return; //ugh.. 1330 } 1331 childView = setupView(parent, viewFactory, service, partServiceOffers, appServiceOffers, serviceType, passiveMode, openAfterCurrentPage, pos); 1332 if (data.openUrl) { 1333 restoreViewOutsideTabContainer(childView, cfg, prefix, data.defaultUrl, serviceType); 1334 } 1335 } 1336 1337 if (!childView->isFollowActive()) { 1338 childView->setLinkedView(linkedView); 1339 } 1340 childView->setToggleView(isToggleView); 1341 if (isToggleView /*100373*/ || !cfg.readEntry(QStringLiteral("ShowStatusBar").prepend(prefix), true)) { 1342 childView->frame()->statusbar()->hide(); 1343 } 1344 1345 if (parent == m_tabContainer && m_tabContainer->count() == 1) { 1346 // First tab, make it the active one 1347 parent->setActiveChild(childView->frame()); 1348 } 1349 } 1350 1351 void KonqViewManager::restoreViewOutsideTabContainer(KonqView* view, const KConfigGroup& cfg, const QString &prefix, const QUrl &defaultURL, const QString &serviceType) 1352 { 1353 const QString keyHistoryItems = QStringLiteral("NumberOfHistoryItems").prepend(prefix); 1354 if (cfg.hasKey(keyHistoryItems)) { 1355 view->loadHistoryConfig(cfg, prefix); 1356 m_pMainWindow->updateHistoryActions(); 1357 } else { 1358 // determine URL 1359 const QString urlKey = QStringLiteral("URL").prepend(prefix); 1360 QUrl url; 1361 if (cfg.hasKey(urlKey)) { 1362 url = QUrl(cfg.readPathEntry(urlKey, KonqUrl::string(KonqUrl::Type::Blank))); 1363 } else if (urlKey == QLatin1String("empty_URL")) { // old stuff, not in use anymore 1364 url = KonqUrl::url(KonqUrl::Type::Blank); 1365 } else { 1366 url = defaultURL; 1367 } 1368 1369 if (!url.isEmpty()) { 1370 //qCDebug(KONQUEROR_LOG) << "calling openUrl" << url; 1371 //childView->openUrl( url, url.toDisplayString() ); 1372 // We need view-follows-view (for the dirtree, for instance) 1373 KonqOpenURLRequest req; 1374 if (!KonqUrl::hasKonqScheme(url)) { 1375 req.typedUrl = url.toDisplayString(); 1376 } 1377 m_pMainWindow->openView(serviceType, url, view, req); 1378 } 1379 //else qCDebug(KONQUEROR_LOG) << "url is empty"; 1380 } 1381 } 1382 1383 void KonqViewManager::setLoading(KonqView *view, bool loading) 1384 { 1385 tabContainer()->setLoading(view->frame(), loading); 1386 } 1387 1388 ///////////////// Debug stuff //////////////// 1389 1390 #ifndef NDEBUG 1391 void KonqViewManager::printSizeInfo(KonqFrameBase *frame, 1392 KonqFrameContainerBase *parent, 1393 const char *msg) 1394 { 1395 const QRect r = frame->asQWidget()->geometry(); 1396 qCDebug(KONQUEROR_LOG) << "Child size" << msg << r; 1397 if (parent->frameType() == KonqFrameBase::Container) { 1398 const QList<int> sizes = static_cast<KonqFrameContainer *>(parent)->sizes(); 1399 printf("Parent sizes %s :", msg); 1400 for (int i: sizes) { 1401 printf(" %d", i); 1402 } 1403 printf("\n"); 1404 } 1405 } 1406 1407 class KonqDebugFrameVisitor : public KonqFrameVisitor 1408 { 1409 public: 1410 KonqDebugFrameVisitor() {} 1411 bool visit(KonqFrame *frame) override 1412 { 1413 QString className; 1414 if (!frame->part()) { 1415 className = QStringLiteral("NoPart!"); 1416 } else if (!frame->part()->widget()) { 1417 className = QStringLiteral("NoWidget!"); 1418 } else { 1419 className = frame->part()->widget()->metaObject()->className(); 1420 } 1421 qCDebug(KONQUEROR_LOG) << m_spaces << frame 1422 << "parent=" << frame->parentContainer() 1423 << (frame->isHidden() ? "hidden" : "shown") 1424 << "containing view" << frame->childView() 1425 << "and part" << frame->part() 1426 << "whose widget is a" << className; 1427 return true; 1428 } 1429 bool visit(KonqFrameContainer *container) override 1430 { 1431 qCDebug(KONQUEROR_LOG) << m_spaces << container 1432 << (container->isHidden() ? "hidden" : "shown") 1433 << (container->orientation() == Qt::Horizontal ? "horizontal" : "vertical") 1434 << "sizes=" << container->sizes() 1435 << "parent=" << container->parentContainer() 1436 << "activeChild=" << container->activeChild(); 1437 1438 if (!container->activeChild()) { 1439 qCDebug(KONQUEROR_LOG) << "WARNING:" << container << "has a null active child!"; 1440 } 1441 1442 m_spaces += QLatin1String(" "); 1443 return true; 1444 } 1445 bool visit(KonqFrameTabs *tabs) override 1446 { 1447 qCDebug(KONQUEROR_LOG) << m_spaces << "KonqFrameTabs" << tabs 1448 << "visible=" << tabs->isVisible() 1449 << "activeChild=" << tabs->activeChild(); 1450 if (!tabs->activeChild()) { 1451 qCDebug(KONQUEROR_LOG) << "WARNING:" << tabs << "has a null active child!"; 1452 } 1453 m_spaces += QLatin1String(" "); 1454 return true; 1455 } 1456 bool visit(KonqMainWindow *) override 1457 { 1458 return true; 1459 } 1460 bool endVisit(KonqFrameTabs *) override 1461 { 1462 m_spaces.resize(m_spaces.size() - 2); 1463 return true; 1464 } 1465 bool endVisit(KonqFrameContainer *) override 1466 { 1467 m_spaces.resize(m_spaces.size() - 2); 1468 return true; 1469 } 1470 bool endVisit(KonqMainWindow *) override 1471 { 1472 return true; 1473 } 1474 private: 1475 QString m_spaces; 1476 }; 1477 1478 void KonqViewManager::printFullHierarchy() 1479 { 1480 qCDebug(KONQUEROR_LOG) << "currentView=" << m_pMainWindow->currentView(); 1481 KonqDebugFrameVisitor visitor; 1482 m_pMainWindow->accept(&visitor); 1483 } 1484 #endif 1485 1486 KonqFrameTabs *KonqViewManager::tabContainer() 1487 { 1488 if (!m_tabContainer) { 1489 createTabContainer(m_pMainWindow /*as widget*/, m_pMainWindow /*as container*/); 1490 m_pMainWindow->insertChildFrame(m_tabContainer); 1491 } 1492 return m_tabContainer; 1493 } 1494 1495 bool KonqViewManager::isTabBarVisible() const 1496 { 1497 if (!m_tabContainer) { 1498 return false; 1499 } 1500 return !m_tabContainer->tabBar()->isHidden(); 1501 } 1502 1503 void KonqViewManager::forceHideTabBar(bool force) 1504 { 1505 if (m_tabContainer) { 1506 m_tabContainer->forceHideTabBar(force); 1507 } 1508 } 1509 1510 1511 void KonqViewManager::createTabContainer(QWidget *parent, KonqFrameContainerBase *parentContainer) 1512 { 1513 #ifdef DEBUG_VIEWMGR 1514 qCDebug(KONQUEROR_LOG) << "createTabContainer" << parent << parentContainer; 1515 #endif 1516 m_tabContainer = new KonqFrameTabs(parent, parentContainer, this); 1517 // Delay the opening of the URL for #106641 1518 bool ok = connect(m_tabContainer, SIGNAL(openUrl(KonqView*,QUrl)), m_pMainWindow, SLOT(openUrl(KonqView*,QUrl)), Qt::QueuedConnection); 1519 connect(m_tabContainer, &QTabWidget::currentChanged, this, &KonqViewManager::delayedLoadTab); 1520 Q_ASSERT(ok); 1521 Q_UNUSED(ok); 1522 applyConfiguration(); 1523 } 1524 1525 void KonqViewManager::applyConfiguration() 1526 { 1527 tabContainer()->setAlwaysTabbedMode(KonqSettings::alwaysTabbedMode()); 1528 tabContainer()->setTabsClosable(KonqSettings::permanentCloseButton()); 1529 } 1530 1531 KonqMainWindow *KonqViewManager::duplicateWindow() 1532 { 1533 QTemporaryFile tempFile; 1534 tempFile.open(); 1535 KConfig config(tempFile.fileName()); 1536 KConfigGroup group(&config, "Profile"); 1537 KonqFrameBase::Options flags = KonqFrameBase::SaveHistoryItems; 1538 saveViewConfigToGroup(group, flags); 1539 1540 KonqMainWindow *mainWindow = openSavedWindow(group); 1541 #ifndef NDEBUG 1542 mainWindow->viewManager()->printFullHierarchy(); 1543 #endif 1544 return mainWindow; 1545 } 1546 1547 void KonqViewManager::reparseConfiguration() 1548 { 1549 if (m_tabContainer) { 1550 m_tabContainer->reparseConfiguration(); 1551 } 1552 } 1553 1554 void KonqViewManager::delayedLoadTab(int idx) 1555 { 1556 if (!m_tabContainer || m_bLoadingProfile) { 1557 return; 1558 } 1559 KonqFrameBase *frm = m_tabContainer->tabAt(idx); 1560 QList<KonqView*> views = KonqViewCollector::collect(frm); 1561 for (KonqView *v : views) { 1562 if (v && v->isDelayed()) { 1563 v->loadDelayed(); 1564 } 1565 } 1566 }