File indexing completed on 2024-04-14 04:53:16

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 1998-2005 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "konqview.h"
0009 
0010 #include "KonqViewAdaptor.h"
0011 #include "konqsettingsxt.h"
0012 #include "konqframestatusbar.h"
0013 #include "urlloader.h"
0014 #include <konq_events.h>
0015 #include "konqviewmanager.h"
0016 #include "konqtabs.h"
0017 #include "konqhistorymanager.h"
0018 #include "konqpixmapprovider.h"
0019 #include "implementations/konqbrowserwindowinterface.h"
0020 #include "interfaces/downloaderextension.h"
0021 #include "browserarguments.h"
0022 #include "browserextension.h"
0023 #include "placeholderpart.h"
0024 #include "konqurl.h"
0025 
0026 #include <kio/job.h>
0027 #include <kio/jobuidelegate.h>
0028 #include "konqdebug.h"
0029 #include <kcursor.h>
0030 #include <kmessagebox.h>
0031 #include <KLocalizedString>
0032 #include <ktoggleaction.h>
0033 #include <kjobuidelegate.h>
0034 #include <KUrlMimeData>
0035 #include <KIO/CopyJob>
0036 #include <KFileUtils>
0037 
0038 #include <QApplication>
0039 #include <QArgument>
0040 #include <QFile>
0041 #include <QDropEvent>
0042 #include <QDBusConnection>
0043 #include <QMimeData>
0044 #include <QFileInfo>
0045 #include <QDir>
0046 
0047 #include <config-konqueror.h>
0048 
0049 #ifdef KActivities_FOUND
0050 #if QT_VERSION_MAJOR < 6
0051 #include <KActivities/ResourceInstance>
0052 #else //QT_VERSION_MAJOR
0053 #include <PlasmaActivities/ResourceInstance>
0054 #endif //QT_VERSION_MAJOR
0055 #endif //KActivities_FOUND
0056 
0057 #include <kparts_version.h>
0058 
0059 #include <KJobWidgets>
0060 #include <KParts/Part>
0061 #include <KParts/StatusBarExtension>
0062 #include <KParts/ReadOnlyPart>
0063 #include <KParts/OpenUrlEvent>
0064 #include <KParts/OpenUrlArguments>
0065 #include <QMimeDatabase>
0066 
0067 //#define DEBUG_HISTORY
0068 
0069 KonqView::KonqView(KonqFrame *viewFrame, KonqMainWindow *mainWindow) :
0070     m_pPart{nullptr},
0071     m_pageSecurity{KonqMainWindow::NotCrypted},
0072     m_lstHistoryIndex{-1},
0073     m_doPost{false},
0074     m_pMainWindow{mainWindow},
0075     m_loader{nullptr},
0076     m_pKonqFrame{viewFrame},
0077     m_bLoading{false},
0078     m_bLockedLocation{false},
0079     m_bPassiveMode{false},
0080     m_bLinkedView{false},
0081     m_bToggleView{false},
0082     m_bLockHistory{false},
0083     m_bAborted{false},
0084     m_bGotIconURL{false},
0085     m_bPopupMenuEnabled{true},
0086     m_bFollowActive{false},
0087     m_bPendingRedirection{false},
0088     m_bBuiltinView{true},
0089     m_bURLDropHandling{false},
0090     m_bDisableScrolling{false},
0091     m_bErrorURL{false}
0092 #if QT_VERSION_MAJOR < 6
0093 #ifdef KActivities_FOUND
0094     , m_activityResourceInstance{new KActivities::ResourceInstance(mainWindow->winId(), this)}
0095 #endif
0096 #endif
0097 {
0098     m_pKonqFrame->setView(this);
0099     KonqViewFactory factory;
0100     switchView(factory, true);
0101 }
0102 
0103 KonqView::KonqView(KonqViewFactory &viewFactory,
0104                    KonqFrame *viewFrame,
0105                    KonqMainWindow *mainWindow,
0106                    const KPluginMetaData &service,
0107                    const QVector<KPluginMetaData> &partServiceOffers,
0108                    const KService::List &appServiceOffers,
0109                    const QString &serviceType,
0110                    bool passiveMode
0111                   )
0112 {
0113     m_pKonqFrame = viewFrame;
0114     m_pKonqFrame->setView(this);
0115 
0116     m_sLocationBarURL = QLatin1String("");
0117     m_pageSecurity = KonqMainWindow::NotCrypted;
0118     m_bLockHistory = false;
0119     m_doPost = false;
0120     m_pMainWindow = mainWindow;
0121     m_loader = nullptr;
0122     m_pPart = nullptr;
0123 
0124     m_service = service;
0125     m_partServiceOffers = partServiceOffers;
0126     m_appServiceOffers = appServiceOffers;
0127     m_serviceType = serviceType;
0128 
0129     m_lstHistoryIndex = -1;
0130     m_bLoading = false;
0131     m_bPendingRedirection = false;
0132     m_bPassiveMode = passiveMode;
0133     m_bLockedLocation = false;
0134     m_bLinkedView = false;
0135     m_bAborted = false;
0136     m_bToggleView = false;
0137     m_bDisableScrolling = false;
0138     m_bGotIconURL = false;
0139     m_bPopupMenuEnabled = true;
0140     m_bFollowActive = false;
0141     m_bBuiltinView = false;
0142     m_bURLDropHandling = false;
0143     m_bErrorURL = false;
0144 
0145 #if QT_VERSION_MAJOR < 6
0146 #ifdef KActivities_FOUND
0147     m_activityResourceInstance = new KActivities::ResourceInstance(mainWindow->winId(), this);
0148 #endif
0149 #endif
0150 
0151     switchView(viewFactory);
0152 }
0153 
0154 KonqView::~KonqView()
0155 {
0156     //qCDebug(KONQUEROR_LOG) << "part=" << m_pPart;
0157 
0158     // We did so ourselves for passive views
0159     if (m_pPart != nullptr) {
0160         finishedWithCurrentURL();
0161         if (isPassiveMode()) {
0162             disconnect(m_pPart, SIGNAL(destroyed()), m_pMainWindow->viewManager(), SLOT(slotObjectDestroyed()));
0163         }
0164 
0165         if (m_pPart->manager()) {
0166             m_pPart->manager()->removePart(m_pPart);    // ~Part does this, but we have to do it before (#213876, #207173)
0167         }
0168 
0169         delete m_pPart;
0170     }
0171 
0172     qDeleteAll(m_lstHistory);
0173     m_lstHistory.clear();
0174 
0175     setUrlLoader(nullptr);
0176     //qCDebug(KONQUEROR_LOG) << this << "done";
0177 }
0178 
0179 bool KonqView::isWebEngineView() const
0180 {
0181     return m_service.pluginId() == QLatin1String("webenginepart");
0182 }
0183 
0184 void KonqView::openUrl(const QUrl &url, const QString &locationBarURL,
0185                        const QString &nameFilter, bool tempFile, const QUrl &requestedUrl)
0186 {
0187     qCDebug(KONQUEROR_LOG) << "url=" << url << "locationBarURL=" << locationBarURL;
0188 
0189     setPartMimeType();
0190 
0191     KParts::OpenUrlArguments args;
0192     if (m_pPart) {
0193         args = m_pPart->arguments();
0194     }
0195 
0196     KParts::NavigationExtension *ext = browserExtension();
0197     BrowserArguments browserArgs;
0198     if (BrowserExtension *browserExtension = qobject_cast<BrowserExtension *>(ext)) {
0199         browserArgs = browserExtension->browserArguments();
0200     }
0201 
0202     // Typing "Enter" again after the URL of an aborted view, triggers a reload.
0203     if (m_bAborted && m_pPart && m_pPart->url() == url && !browserArgs.doPost()) {
0204         if (!prepareReload(args, browserArgs, false /* not softReload */)) {
0205             return;
0206         }
0207         m_pPart->setArguments(args);
0208     }
0209 
0210 #ifdef DEBUG_HISTORY
0211     qCDebug(KONQUEROR_LOG) << "m_bLockedLocation=" << m_bLockedLocation << "browserArgs.lockHistory()=" << browserArgs.lockHistory();
0212 #endif
0213     if (browserArgs.lockHistory()) {
0214         lockHistory();
0215     }
0216 
0217     if (!m_bLockHistory) {
0218         // Store this new URL in the history, removing any existing forward history.
0219         // We do this first so that everything is ready if a part calls completed().
0220         createHistoryEntry();
0221     } else {
0222         m_bLockHistory = false;
0223     }
0224 
0225     if (m_pPart) {
0226         m_pPart->setProperty("nameFilter", nameFilter);
0227     }
0228 
0229     if (m_bDisableScrolling) {
0230         callExtensionMethod("disableScrolling");
0231     }
0232 
0233     // Set location-bar URL, except for error urls, where we know the browser component
0234     // will set back the url with the error anyway.
0235     if (url.scheme() != QLatin1String("error")) {
0236         setLocationBarURL(locationBarURL);
0237     }
0238 
0239     setPageSecurity(KonqMainWindow::NotCrypted);
0240 
0241     if (!args.reload()) {
0242         // Save the POST data that is necessary to open this URL
0243         // (so that reload can re-post it)
0244         m_doPost = browserArgs.doPost();
0245         m_postContentType = browserArgs.contentType();
0246         m_postData = browserArgs.postData;
0247         // Save the referrer
0248         m_pageReferrer = args.metaData()[QStringLiteral("referrer")];
0249     }
0250 
0251     if (tempFile) {
0252         // Store the path to the tempfile. Yes, we could store a bool only,
0253         // but this would be more dangerous. If anything goes wrong in the code,
0254         // we might end up deleting a real file.
0255         if (url.isLocalFile()) {
0256             m_tempFile = url.toLocalFile();
0257         } else {
0258             qCWarning(KONQUEROR_LOG) << "Tempfile option is set, but URL is remote:" << url;
0259         }
0260     }
0261 
0262     m_requestedUrl = !requestedUrl.isEmpty() ? requestedUrl : url;
0263     aboutToOpenURL(url, args);
0264 
0265     if (args.metaData().contains("urlRequestedByApp") && isWebEngineView()) {
0266         m_pPart->setProperty("urlRequestedByApp", url);
0267     }
0268     m_pPart->openUrl(url);
0269 
0270     updateHistoryEntry(true);
0271     // add pending history entry
0272     KonqHistoryManager::kself()->addPending(url, locationBarURL, QString());
0273 
0274 #ifdef DEBUG_HISTORY
0275     qCDebug(KONQUEROR_LOG) << "Current position:" << historyIndex();
0276 #endif
0277 
0278 #ifdef KActivities_FOUND
0279 #if QT_VERSION_MAJOR < 6
0280     m_activityResourceInstance->setUri(url);
0281 
0282     if (m_pPart->widget()->hasFocus()) {
0283         m_activityResourceInstance->notifyFocusedIn();
0284     }
0285 #else
0286     KActivities::ResourceInstance::notifyAccessed(url);
0287 #endif
0288 #endif
0289 }
0290 
0291 void KonqView::switchEmbeddingPart(const QString& newPluginId, const QString& newInternalViewMode)
0292 {
0293     if (service().pluginId() == newPluginId) {
0294         return;
0295     }
0296     //We don't want to delete the temporary file, otherwise the new part won't have a file to display
0297     stop(true);
0298     lockHistory();
0299     const QUrl origUrl = realUrl();
0300     const QString locationBarURL = m_sLocationBarURL;
0301     bool tempFile = !m_tempFile.isEmpty();
0302     changePart(serviceType(), newPluginId);
0303     openUrl(origUrl, locationBarURL, {}, tempFile, url());
0304     if (!newInternalViewMode.isEmpty() && newInternalViewMode != internalViewMode()){
0305         setInternalViewMode(newInternalViewMode);
0306     }
0307 }
0308 
0309 void KonqView::switchView(KonqViewFactory &viewFactory, bool allowPlaceholder)
0310 {
0311     //qCDebug(KONQUEROR_LOG);
0312     KParts::ReadOnlyPart *oldPart = m_pPart;
0313     KParts::ReadOnlyPart *part = m_pKonqFrame->attach(viewFactory, allowPlaceholder);   // creates the part
0314     if (!part) {
0315         return;
0316     }
0317     
0318     m_pPart = part;
0319 
0320     // Set the statusbar in the BE asap to avoid a KMainWindow statusbar being created.
0321     KParts::StatusBarExtension *sbext = statusBarExtension();
0322     if (sbext) {
0323         sbext->setStatusBar(frame()->statusbar());
0324     }
0325 
0326     // Activate the new part
0327     if (oldPart) {
0328         m_pPart->setObjectName(oldPart->objectName());
0329         emit sigPartChanged(this, oldPart, m_pPart);
0330         delete oldPart;
0331     }
0332 
0333     connectPart();
0334 
0335     if (m_service.value(QStringLiteral("X-KDE-BrowserView-FollowActive"), false)) {
0336         //qCDebug(KONQUEROR_LOG) << "X-KDE-BrowserView-FollowActive -> setFollowActive";
0337         setFollowActive(true);
0338     }
0339 
0340     m_bBuiltinView = m_service.value(QStringLiteral("X-KDE-BrowserView-Built-Into"), QString()) == QLatin1String("konqueror");
0341 
0342     if (!m_pMainWindow->viewManager()->isLoadingProfile()) {
0343         // Honor "non-removable passive mode" (like the dirtree)
0344         if (m_service.value(QStringLiteral("X-KDE-BrowserView-PassiveMode"), false)) {
0345             qCDebug(KONQUEROR_LOG) << "X-KDE-BrowserView-PassiveMode -> setPassiveMode";
0346             setPassiveMode(true);   // set as passive
0347         }
0348 
0349         // Honor "linked view"
0350         if (m_service.value(QStringLiteral("X-KDE-BrowserView-LinkedView"), false)) {
0351             setLinkedView(true);   // set as linked
0352             // Two views : link both
0353             if (m_pMainWindow->viewCount() <= 2) { // '1' can happen if this view is not yet in the map
0354                 KonqView *otherView = m_pMainWindow->otherView(this);
0355                 if (otherView) {
0356                     otherView->setLinkedView(true);
0357                 }
0358             }
0359         }
0360     }
0361 }
0362 
0363 bool KonqView::ensureViewSupports(const QString &mimeType,
0364                                   bool forceAutoEmbed)
0365 {
0366     if (supportsMimeType(mimeType)) {
0367         // could be more specific, let's store it so that OpenUrlArguments::mimeType is correct
0368         // testcase: http://acid3.acidtests.org/svg.xml should be opened as image/svg+xml
0369         m_serviceType = mimeType;
0370         return true;
0371     }
0372     return changePart(mimeType, QString(), forceAutoEmbed);
0373 }
0374 
0375 bool KonqView::changePart(const QString &mimeType,
0376                           const QString &serviceName,
0377                           bool forceAutoEmbed)
0378 {
0379     // Caller should call stop first.
0380     Q_ASSERT(!m_bLoading);
0381 
0382     //qCDebug(KONQUEROR_LOG) << "mimeType=" << mimeType
0383     //             << "requested serviceName=" << serviceName
0384     //             << "current service name=" << m_service->desktopEntryName();
0385 
0386     if (serviceName == m_service.pluginId()) {
0387         m_serviceType = mimeType;
0388         return true;
0389     }
0390 
0391     if (isLockedViewMode()) {
0392         //qCDebug(KONQUEROR_LOG) << "This view's mode is locked - can't change";
0393         return false; // we can't do that if our view mode is locked
0394     }
0395 
0396     QVector<KPluginMetaData> partServiceOffers;
0397     KService::List appServiceOffers;
0398     KPluginMetaData service;
0399     KonqFactory konqFactory;
0400     KonqViewFactory viewFactory = konqFactory.createView(mimeType, serviceName, &service, &partServiceOffers, &appServiceOffers, forceAutoEmbed);
0401 
0402     if (viewFactory.isNull()) {
0403         return false;
0404     }
0405 
0406     m_serviceType = mimeType;
0407     m_partServiceOffers = partServiceOffers;
0408     m_appServiceOffers = appServiceOffers;
0409 
0410     // Check if that's already the kind of part we have -> no need to recreate it
0411     // Note: we should have an operator== for KService...
0412     if (m_service.isValid() && m_service.pluginId() == service.pluginId()) {
0413         qCDebug(KONQUEROR_LOG) << "Reusing service. Service type set to" << m_serviceType;
0414         if (m_pMainWindow->currentView() == this) {
0415             m_pMainWindow->updateViewModeActions();
0416         }
0417     } else {
0418         m_service = service;
0419 
0420         switchView(viewFactory);
0421     }
0422 
0423     return true;
0424 }
0425 
0426 void KonqView::connectPart()
0427 {
0428     //qCDebug(KONQUEROR_LOG);
0429     connect(m_pPart, SIGNAL(started(KIO::Job*)),
0430             this, SLOT(slotStarted(KIO::Job*)));
0431     connect(m_pPart, SIGNAL(completed()),
0432             this, SLOT(slotCompleted()));
0433     connect(m_pPart, &KParts::ReadOnlyPart::completedWithPendingAction, this, [this](){slotCompleted(true);});
0434     connect(m_pPart, SIGNAL(canceled(QString)),
0435             this, SLOT(slotCanceled(QString)));
0436     connect(m_pPart, SIGNAL(setWindowCaption(QString)),
0437             this, SLOT(setCaption(QString)));
0438     if (!internalViewMode().isEmpty()) {
0439         // Update checked action in "View Mode" menu when switching view mode in dolphin
0440         connect(m_pPart, SIGNAL(viewModeChanged()),
0441                 m_pMainWindow, SLOT(slotInternalViewModeChanged()));
0442     }
0443 
0444     if (m_pPart) {
0445         KonqInterfaces::DownloaderExtension *dext = KonqInterfaces::DownloaderExtension::downloader(m_pPart);
0446         if (dext) {
0447             connect(dext, &KonqInterfaces::DownloaderExtension::downloadAndOpenUrl, m_pMainWindow, [dext, this](const QUrl &url, int id, const KParts::OpenUrlArguments &args, const BrowserArguments &bargs, bool temp){
0448                     KonqOpenURLRequest req(args, bargs, dext->part(), true, id);
0449                     req.tempFile = temp;
0450                     m_pMainWindow->slotOpenURLRequest(url, req);
0451                 });
0452         }
0453     }
0454 
0455     KParts::NavigationExtension *ext = browserExtension();
0456     if (ext) {
0457 
0458 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0459         KonqBrowserWindowInterface *bi = new KonqBrowserWindowInterface(mainWindow(), m_pPart);
0460         ext->setBrowserInterface(bi);
0461 
0462         connect(ext, &KParts::NavigationExtension::openUrlRequestDelayed, ext,
0463                 [ext, this](const QUrl &url, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments &bargs){
0464                     KonqOpenURLRequest req(args, bargs, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0465                     m_pMainWindow->slotOpenURLRequest(url, req);
0466                 });
0467 #else
0468         
0469         if (auto browserExtension = qobject_cast<BrowserExtension *>(ext)) {
0470             connect(browserExtension, &BrowserExtension::browserOpenUrlRequestDelayed, m_pMainWindow, [ext, this](const QUrl &url, const KParts::OpenUrlArguments &arguments, const BrowserArguments &browserArguments){
0471                 KonqOpenURLRequest req(arguments, browserArguments, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0472                     m_pMainWindow->slotOpenURLRequest(url, req);
0473             });
0474             KonqBrowserWindowInterface *bi = new KonqBrowserWindowInterface(mainWindow(), m_pPart);
0475             browserExtension->setBrowserInterface(bi);
0476         } else {
0477             connect(ext, &BrowserExtension::openUrlRequestDelayed, m_pMainWindow,
0478                 [ext, this](const QUrl &url, const KParts::OpenUrlArguments &args){
0479                     KonqOpenURLRequest req(args, {}, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0480                     m_pMainWindow->slotOpenURLRequest(url, req);
0481                 });
0482         }
0483 #endif
0484 
0485 
0486         if (m_bPopupMenuEnabled) {
0487             m_bPopupMenuEnabled = false; // force
0488             enablePopupMenu(true);
0489         }
0490 
0491         connect(ext, SIGNAL(setLocationBarUrl(QString)),
0492                 this, SLOT(setLocationBarURL(QString)));
0493 
0494         connect(ext, SIGNAL(setIconUrl(QUrl)),
0495                 this, SLOT(setIconURL(QUrl)));
0496 
0497         connect(ext, SIGNAL(setPageSecurity(int)),
0498                 this, SLOT(setPageSecurity(int)));
0499 
0500 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0501         connect(ext, &KParts::NavigationExtension::createNewWindow, ext,
0502                 [ext, this] (const QUrl &url, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments &bargs, const KParts::WindowArgs &wargs ,KParts::ReadOnlyPart** part) {
0503                     KonqOpenURLRequest req(args, bargs, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0504                     m_pMainWindow->slotCreateNewWindow(url, req, wargs, part);
0505                 });
0506 #else
0507         if (auto browserExtension = qobject_cast<BrowserExtension *>(ext)) {
0508             connect(browserExtension, &BrowserExtension::browserCreateNewWindow, ext,
0509                     [ext, this] (const QUrl &url, const KParts::OpenUrlArguments &args, const BrowserArguments &bargs, const WindowArgs &wargs ,KParts::ReadOnlyPart** part) {
0510                         KonqOpenURLRequest req(args, bargs, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0511                         m_pMainWindow->slotCreateNewWindow(url, req, wargs, part);
0512                     });
0513         } else {
0514             connect(ext, &KParts::NavigationExtension::createNewWindow, ext,
0515                     [ext, this] (const QUrl &url) {
0516                         KonqOpenURLRequest req({}, {}, qobject_cast<KParts::ReadOnlyPart*>(ext->parent()));
0517                         m_pMainWindow->slotCreateNewWindow(url, req);
0518                     });
0519         }
0520 #endif
0521 
0522         connect(ext, SIGNAL(loadingProgress(int)),
0523                 m_pKonqFrame->statusbar(), SLOT(slotLoadingProgress(int)));
0524 
0525         connect(ext, SIGNAL(speedProgress(int)),
0526                 m_pKonqFrame->statusbar(), SLOT(slotSpeedProgress(int)));
0527 
0528         connect(ext, SIGNAL(selectionInfo(KFileItemList)),
0529                 this, SLOT(slotSelectionInfo(KFileItemList)));
0530 
0531         connect(ext, SIGNAL(mouseOverInfo(KFileItem)),
0532                 this, SLOT(slotMouseOverInfo(KFileItem)));
0533 
0534         connect(ext, SIGNAL(openUrlNotify()),
0535                 this, SLOT(slotOpenURLNotify()));
0536 
0537         connect(ext, SIGNAL(enableAction(const char*,bool)),
0538                 this, SLOT(slotEnableAction(const char*,bool)));
0539 
0540         connect(ext, SIGNAL(setActionText(const char*,QString)),
0541                 this, SLOT(slotSetActionText(const char*,QString)));
0542 
0543         connect(ext, SIGNAL(moveTopLevelWidget(int,int)),
0544                 this, SLOT(slotMoveTopLevelWidget(int,int)));
0545 
0546         connect(ext, SIGNAL(resizeTopLevelWidget(int,int)),
0547                 this, SLOT(slotResizeTopLevelWidget(int,int)));
0548 
0549         connect(ext, SIGNAL(requestFocus(KParts::ReadOnlyPart*)),
0550                 this, SLOT(slotRequestFocus(KParts::ReadOnlyPart*)));
0551 
0552         if (service().pluginId() != QLatin1String("konq_sidebartng")) {
0553             connect(ext, &KParts::NavigationExtension::infoMessage, m_pKonqFrame->statusbar(), &KonqFrameStatusBar::message);
0554 
0555             //Must use this form of connect because slotAddWebSideBar is private
0556             connect(ext, SIGNAL(addWebSideBar(QUrl,QString)), m_pMainWindow, SLOT(slotAddWebSideBar(QUrl,QString)));
0557         }
0558     }
0559 
0560     QVariant urlDropHandling;
0561 
0562     if (ext) {
0563         urlDropHandling = ext->property("urlDropHandling");
0564     } else {
0565         urlDropHandling = QVariant(true);
0566     }
0567 
0568     // Handle url drops if
0569     //  a) either the property says "ok"
0570     //  or
0571     //  b) the part is a plain krop (no BE)
0572     m_bURLDropHandling = (urlDropHandling.type() == QVariant::Bool &&
0573                           urlDropHandling.toBool());
0574     if (m_bURLDropHandling) {
0575         m_pPart->widget()->setAcceptDrops(true);
0576     }
0577 
0578     m_pPart->widget()->installEventFilter(this);
0579 }
0580 
0581 void KonqView::slotEnableAction(const char *name, bool enabled)
0582 {
0583     if (m_pMainWindow->currentView() == this) {
0584         m_pMainWindow->enableAction(name, enabled);
0585     }
0586     // Otherwise, we don't have to do anything, the state of the action is
0587     // stored inside the browser-extension.
0588 }
0589 
0590 void KonqView::slotSetActionText(const char *name, const QString &text)
0591 {
0592     if (m_pMainWindow->currentView() == this) {
0593         m_pMainWindow->setActionText(name, text);
0594     }
0595     // Otherwise, we don't have to do anything, the state of the action is
0596     // stored inside the browser-extension.
0597 }
0598 
0599 void KonqView::slotMoveTopLevelWidget(int x, int y)
0600 {
0601     KonqFrameContainerBase *container = frame()->parentContainer();
0602     // If tabs are shown, only accept to move the whole window if there's only one tab.
0603     if (container->frameType() != KonqFrameBase::Tabs || static_cast<KonqFrameTabs *>(container)->count() == 1) {
0604         m_pMainWindow->move(x, y);
0605     }
0606 }
0607 
0608 void KonqView::slotResizeTopLevelWidget(int w, int h)
0609 {
0610     KonqFrameContainerBase *container = frame()->parentContainer();
0611     // If tabs are shown, only accept to resize the whole window if there's only one tab.
0612     // ### Maybe we could store the size requested by each tab and resize the window to the biggest one.
0613     if (container->frameType() != KonqFrameBase::Tabs || static_cast<KonqFrameTabs *>(container)->count() == 1) {
0614         m_pMainWindow->resize(w, h);
0615     }
0616 }
0617 
0618 void KonqView::slotStarted(KIO::Job *job)
0619 {
0620     //qCDebug(KONQUEROR_LOG) << job;
0621     setLoading(true);
0622 
0623     if (job) {
0624         // Manage passwords properly...
0625         //qCDebug(KONQUEROR_LOG) << "Window ID =" << m_pMainWindow->window()->winId();
0626         KJobWidgets::setWindow(job, m_pMainWindow->window());
0627 
0628         connect(job, SIGNAL(percent(KJob*,ulong)), this, SLOT(slotPercent(KJob*,ulong)));
0629         connect(job, SIGNAL(speed(KJob*,ulong)), this, SLOT(slotSpeed(KJob*,ulong)));
0630         connect(job, SIGNAL(infoMessage(KJob*,QString,QString)), this, SLOT(slotInfoMessage(KJob*,QString)));
0631     }
0632 }
0633 
0634 void KonqView::slotRequestFocus(KParts::ReadOnlyPart *)
0635 {
0636     m_pMainWindow->viewManager()->showTab(this);
0637 }
0638 
0639 void KonqView::setLoading(bool loading, bool hasPending /*= false*/)
0640 {
0641     //qCDebug(KONQUEROR_LOG) << "loading=" << loading << "hasPending=" << hasPending;
0642     m_bLoading = loading;
0643     m_bPendingRedirection = hasPending;
0644     if (m_pMainWindow->currentView() == this) {
0645         m_pMainWindow->updateToolBarActions(hasPending);
0646         // Make sure the focus is restored on the part's widget and not the combo
0647         // box if it starts loading a request. See #304933.
0648         if (loading) {
0649             QWidget *partWidget = (m_pPart ? m_pPart->widget() : nullptr);
0650             if (partWidget && !partWidget->hasFocus()) {
0651                 //qCDebug(KONQUEROR_LOG) << "SET FOCUS on the widget";
0652                 partWidget->setFocus();
0653             }
0654         }
0655     }
0656 
0657     m_pMainWindow->viewManager()->setLoading(this, loading || hasPending);
0658 }
0659 
0660 void KonqView::slotPercent(KJob *, unsigned long percent)
0661 {
0662     m_pKonqFrame->statusbar()->slotLoadingProgress(percent);
0663 }
0664 
0665 void KonqView::slotSpeed(KJob *, unsigned long bytesPerSecond)
0666 {
0667     m_pKonqFrame->statusbar()->slotSpeedProgress(bytesPerSecond);
0668 }
0669 
0670 void KonqView::slotInfoMessage(KJob *, const QString &msg)
0671 {
0672     m_pKonqFrame->statusbar()->message(msg);
0673 }
0674 
0675 void KonqView::slotCompleted()
0676 {
0677     slotCompleted(false);
0678 }
0679 
0680 void KonqView::slotCompleted(bool hasPending)
0681 {
0682     //qCDebug(KONQUEROR_LOG) << "hasPending=" << hasPending;
0683     m_pKonqFrame->statusbar()->slotLoadingProgress(-1);
0684 
0685     if (! m_bLockHistory) {
0686         // Success... update history entry
0687         updateHistoryEntry(false);
0688 
0689         if (m_bAborted) { // remove the pending entry on error
0690             KonqHistoryManager::kself()->removePending(url());
0691         } else if (currentHistoryEntry()) // register as proper history entry
0692             KonqHistoryManager::kself()->confirmPending(url(), typedUrl(),
0693                     currentHistoryEntry()->title);
0694 
0695         emit viewCompleted(this);
0696     }
0697     setLoading(false, hasPending);
0698 
0699     if (!m_bGotIconURL && !m_bAborted) {
0700         if (KonqSettings::enableFavicon() == true) {
0701             // Try to get /favicon.ico. KonqPixmapProvider::downloadHostIcon does nothing if the URL is not http(s)
0702             if (supportsMimeType(QStringLiteral("text/html"))) {
0703                 KonqPixmapProvider::self()->downloadHostIcon(url());
0704             }
0705         }
0706     }
0707 }
0708 
0709 void KonqView::slotCanceled(const QString &errorMsg)
0710 {
0711     //qCDebug(KONQUEROR_LOG);
0712     // The errorMsg comes from the ReadOnlyPart (usually from its kio job, but not necessarily).
0713     // It should probably be used in a KMessageBox
0714     // Let's use the statusbar for now
0715     m_pKonqFrame->statusbar()->setMessage(errorMsg, KonqStatusBarMessageLabel::Error);
0716     m_bAborted = true;
0717     slotCompleted();
0718 }
0719 
0720 void KonqView::slotSelectionInfo(const KFileItemList &items)
0721 {
0722     m_selectedItems = items;
0723     KonqFileSelectionEvent ev(items, m_pPart);
0724     QApplication::sendEvent(m_pMainWindow, &ev);
0725 }
0726 
0727 void KonqView::slotMouseOverInfo(const KFileItem &item)
0728 {
0729     KonqFileMouseOverEvent ev(item, m_pPart);
0730     QApplication::sendEvent(m_pMainWindow, &ev);
0731 }
0732 
0733 void KonqView::setLocationBarURL(const QUrl &locationBarURL)
0734 {
0735     setLocationBarURL(locationBarURL.url(QUrl::PreferLocalFile));
0736 }
0737 
0738 void KonqView::setLocationBarURL(const QString &locationBarURL)
0739 {
0740     //qCDebug(KONQUEROR_LOG) << locationBarURL << "this=" << this;
0741     m_sLocationBarURL = locationBarURL;
0742     if (m_pMainWindow->currentView() == this) {
0743         //qCDebug(KONQUEROR_LOG) << "is current view" << this;
0744         m_pMainWindow->setLocationBarURL(m_sLocationBarURL);
0745         m_pMainWindow->setPageSecurity(m_pageSecurity);
0746     }
0747     if (!m_bPassiveMode) {
0748         setTabIcon(QUrl::fromUserInput(m_sLocationBarURL));
0749     }
0750 }
0751 
0752 void KonqView::setIconURL(const QUrl &iconURL)
0753 // This function sets the favIcon in konqui's window if enabled,
0754 // thus it is responsible for the icon in the taskbar.
0755 // It does not set the tab's favIcon.
0756 {
0757     if (KonqSettings::enableFavicon()) {
0758         KonqPixmapProvider::self()->setIconForUrl(QUrl(m_sLocationBarURL), iconURL);
0759         m_bGotIconURL = true;
0760     }
0761 }
0762 
0763 void KonqView::setPageSecurity(int pageSecurity)
0764 {
0765     m_pageSecurity = static_cast<KonqMainWindow::PageSecurity>(pageSecurity);
0766 
0767     if (m_pMainWindow->currentView() == this) {
0768         m_pMainWindow->setPageSecurity(m_pageSecurity);
0769     }
0770 }
0771 
0772 void KonqView::setTabIcon(const QUrl &url)
0773 {
0774     if (!m_bPassiveMode && url.isValid()) {
0775         frame()->setTabIcon(url, nullptr);
0776     }
0777 }
0778 
0779 void KonqView::setCaption(const QString &caption)
0780 {
0781     if (caption.isEmpty()) {
0782         return;
0783     }
0784 
0785     QString adjustedCaption = caption;
0786     const QUrl captionUrl(QUrl::fromUserInput(caption));
0787 
0788     // If the URL and the real URL are different, then we don't want to use
0789     // the caption provided by the part (if it is a URL) because it refers to the
0790     // real URL, which is an implementation detail and should be hidden from the user
0791     // Problem: if caption is not itself a URL, but it refers to the part's URL,
0792     // this doesn't work. There's no way around it, however
0793     if (url() != realUrl() && captionUrl.isValid()) {
0794         adjustedCaption = url().toString();
0795     } else if (url().isLocalFile() && captionUrl.isValid() && captionUrl.path() == url().path()) {
0796         // For local URLs we prefer to use only the file name
0797         adjustedCaption = captionUrl.adjusted(QUrl::StripTrailingSlash).fileName();
0798         if (adjustedCaption.isEmpty()) {
0799             adjustedCaption = QLatin1Char('/');
0800         }
0801     }
0802 
0803     m_caption = adjustedCaption;
0804     if (!m_bPassiveMode) {
0805         frame()->setTitle(adjustedCaption, nullptr);
0806     }
0807 }
0808 
0809 void KonqView::slotOpenURLNotify()
0810 {
0811 #ifdef DEBUG_HISTORY
0812     qCDebug(KONQUEROR_LOG);
0813 #endif
0814     updateHistoryEntry(false);
0815     createHistoryEntry();
0816     updateHistoryEntry(true);
0817     if (m_pMainWindow->currentView() == this) {
0818         m_pMainWindow->updateToolBarActions();
0819     }
0820 }
0821 
0822 void KonqView::createHistoryEntry()
0823 {
0824     // First, remove any forward history
0825     HistoryEntry *current = currentHistoryEntry();
0826     if (current) {
0827 #ifdef DEBUG_HISTORY
0828         qCDebug(KONQUEROR_LOG) << "Truncating history";
0829 #endif
0830         while (current != m_lstHistory.last()) {
0831             delete m_lstHistory.takeLast();
0832         }
0833     }
0834     // Append a new entry
0835 #ifdef DEBUG_HISTORY
0836     qCDebug(KONQUEROR_LOG) << "Append a new entry";
0837 #endif
0838     appendHistoryEntry(new HistoryEntry);
0839     setHistoryIndex(m_lstHistory.count() - 1); // made current
0840 #ifdef DEBUG_HISTORY
0841     qCDebug(KONQUEROR_LOG) << "at=" << historyIndex() << "count=" << m_lstHistory.count();
0842 #endif
0843 }
0844 
0845 void KonqView::appendHistoryEntry(HistoryEntry *historyEntry)
0846 {
0847     // If there are too many HistoryEntries remove old ones
0848     while (m_lstHistory.count() > 0 && m_lstHistory.count() >= KonqSettings::maximumHistoryEntriesPerView()) {
0849         delete m_lstHistory.takeFirst();
0850     }
0851 
0852     m_lstHistory.append(historyEntry);
0853 }
0854 
0855 void KonqView::updateHistoryEntry(bool needsReload)
0856 {
0857     Q_ASSERT(!m_bLockHistory);   // should never happen
0858 
0859     HistoryEntry *current = currentHistoryEntry();
0860     if (!current) {
0861         return;
0862     }
0863 
0864     QUrl url = m_requestedUrl;
0865 
0866 #ifdef DEBUG_HISTORY
0867     qCDebug(KONQUEROR_LOG) << "Saving part URL:" << url << "in history position" << historyIndex();
0868 #endif
0869 
0870     current->reload = needsReload; // We have a state for it now.
0871     if (!needsReload && browserExtension()) {
0872         current->buffer = QByteArray(); // Start with empty buffer.
0873         QDataStream stream(&current->buffer, QIODevice::WriteOnly);
0874 
0875         browserExtension()->saveState(stream);
0876     }
0877 
0878 #ifdef DEBUG_HISTORY
0879     qCDebug(KONQUEROR_LOG) << "Saving part URL:" << url << "in history position" << historyIndex();
0880 #endif
0881     current->url = url;
0882 
0883     if (!needsReload) {
0884 #ifdef DEBUG_HISTORY
0885         qCDebug(KONQUEROR_LOG) << "Saving location bar URL:" << m_sLocationBarURL << "in history position" << historyIndex();
0886 #endif
0887         current->locationBarURL = m_sLocationBarURL;
0888         current->pageSecurity = m_pageSecurity;
0889     }
0890 #ifdef DEBUG_HISTORY
0891     qCDebug(KONQUEROR_LOG) << "Saving title:" << m_caption << "in history position" << historyIndex();
0892 #endif
0893     current->title = m_caption;
0894     current->strServiceType = m_serviceType;
0895     current->strServiceName = m_service.pluginId();
0896 
0897     current->doPost = m_doPost;
0898     current->postData = m_doPost ? m_postData : QByteArray();
0899     current->postContentType = m_doPost ? m_postContentType : QString();
0900     current->pageReferrer = m_pageReferrer;
0901 }
0902 
0903 void KonqView::go(int steps)
0904 {
0905     if (!steps) { // [WildFox] i bet there are sites on the net with stupid devs who do that :)
0906 #ifdef DEBUG_HISTORY
0907         qCDebug(KONQUEROR_LOG) << "go(0) -> reload";
0908 #endif
0909         // [David] and you're right. And they expect that it reloads, apparently.
0910         // [George] I'm going to make nspluginviewer rely on this too. :-)
0911         m_pMainWindow->slotReload();
0912         return;
0913     }
0914 
0915     int newPos = historyIndex() + steps;
0916 #ifdef DEBUG_HISTORY
0917     qCDebug(KONQUEROR_LOG) << "steps=" << steps
0918              << "newPos=" << newPos
0919              << "m_lstHistory.count()=" << m_lstHistory.count();
0920 #endif
0921     if (newPos < 0 || newPos >= m_lstHistory.count()) {
0922         return;
0923     }
0924 
0925     stop();
0926 
0927     setHistoryIndex(newPos);   // sets current item
0928 
0929 #ifdef DEBUG_HISTORY
0930     qCDebug(KONQUEROR_LOG) << "New position" << historyIndex();
0931 #endif
0932 
0933     restoreHistory();
0934 }
0935 
0936 void KonqView::restoreHistory()
0937 {
0938     HistoryEntry h(*currentHistoryEntry());   // make a copy of the current history entry, as the data
0939     // the pointer points to will change with the following calls
0940 
0941 #ifdef DEBUG_HISTORY
0942     qCDebug(KONQUEROR_LOG) << "Restoring servicetype/name, and location bar URL from history:" << h.locationBarURL;
0943 #endif
0944     setLocationBarURL(h.locationBarURL);
0945     setPageSecurity(h.pageSecurity);
0946     m_sTypedURL.clear();
0947 
0948     if (!changePart(h.strServiceType, h.strServiceName)) {
0949         qCWarning(KONQUEROR_LOG) << "Couldn't change view mode to" << h.strServiceType << h.strServiceName;
0950         return /*false*/;
0951     }
0952 
0953     setPartMimeType();
0954 
0955     m_requestedUrl = h.url;
0956     aboutToOpenURL(h.url);
0957 
0958     if (h.reload == false && browserExtension() && historyIndex() > 0) {
0959         //qCDebug(KONQUEROR_LOG) << "Restoring view from stream";
0960         QDataStream stream(h.buffer);
0961 
0962         browserExtension()->restoreState(stream);
0963 
0964         m_doPost = h.doPost;
0965         m_postContentType = h.postContentType;
0966         m_postData = h.postData;
0967         m_pageReferrer = h.pageReferrer;
0968     } else {
0969         m_pPart->openUrl(h.url);
0970     }
0971 
0972     if (m_pMainWindow->currentView() == this) {
0973         m_pMainWindow->updateToolBarActions();
0974     }
0975 
0976 #ifdef DEBUG_HISTORY
0977     qCDebug(KONQUEROR_LOG) << "New position (2)" << historyIndex();
0978 #endif
0979 }
0980 
0981 const HistoryEntry *KonqView::historyAt(int pos)
0982 {
0983     return m_lstHistory.value(pos);
0984 }
0985 
0986 void KonqView::copyHistory(KonqView *other)
0987 {
0988     if (!other) {
0989         return;
0990     }
0991 
0992     qDeleteAll(m_lstHistory);
0993     m_lstHistory.clear();
0994 
0995     for (HistoryEntry *he: other->m_lstHistory) {
0996         appendHistoryEntry(new HistoryEntry(*he));
0997     }
0998     setHistoryIndex(other->historyIndex());
0999 }
1000 
1001 QUrl KonqView::realUrl() const
1002 {
1003     Q_ASSERT(m_pPart);
1004     return m_pPart->url();
1005 }
1006 
1007 QUrl KonqView::upUrl() const
1008 {
1009     QUrl currentURL;
1010     if (m_loader) {
1011         currentURL = m_loader->url();
1012     } else {
1013         currentURL = QUrl::fromUserInput(m_sLocationBarURL);
1014     }
1015     return KIO::upUrl(currentURL);
1016 }
1017 
1018 void KonqView::setUrlLoader(UrlLoader *run)
1019 {
1020     if (m_loader) {
1021         // Tell the UrlLoader to abort, but don't delete it ourselves.
1022         // It could be showing a message box right now. It will delete itself anyway.
1023         m_loader->abort();
1024         // finish() will be emitted later (when back to event loop)
1025         // and we don't want it to call slotRunFinished (which stops the animation and stop button).
1026         m_loader->disconnect(m_pMainWindow);
1027         if (!run) {
1028             frame()->unsetCursor();
1029         }
1030     } else if (run) {
1031         frame()->setCursor(Qt::BusyCursor);
1032     }
1033     m_loader = run;
1034 }
1035 
1036 void KonqView::stop(bool keepTemporaryFile)
1037 {
1038     //qCDebug(KONQUEROR_LOG);
1039     m_bAborted = false;
1040 
1041     //Don't remove the temporary file if we're just changing the part used to display it
1042     if (!keepTemporaryFile) {
1043         finishedWithCurrentURL();
1044     }
1045     if (m_bLoading || m_bPendingRedirection) {
1046         // aborted -> confirm the pending url. We might as well remove it, but
1047         // we decided to keep it :)
1048         KonqHistoryManager::kself()->confirmPending(url(), m_sTypedURL);
1049 
1050         //qCDebug(KONQUEROR_LOG) << "m_pPart->closeUrl()";
1051         m_pPart->closeUrl();
1052         m_bAborted = true;
1053         m_pKonqFrame->statusbar()->slotLoadingProgress(-1);
1054         setLoading(false, false);
1055     }
1056     if (m_loader) {
1057         // Revert to working URL - unless the URL was typed manually
1058         // This is duplicated with KonqMainWindow::slotRunFinished, but we can't call it
1059         //   since it relies on sender()...
1060         if (currentHistoryEntry() && m_loader->request().typedUrl.isEmpty()) {   // not typed
1061             setLocationBarURL(currentHistoryEntry()->locationBarURL);
1062             setPageSecurity(currentHistoryEntry()->pageSecurity);
1063         }
1064 
1065         setUrlLoader(nullptr);
1066         m_pKonqFrame->statusbar()->slotLoadingProgress(-1);
1067     }
1068     if (!m_bLockHistory && m_lstHistory.count() > 0) {
1069         updateHistoryEntry(false);
1070     }
1071 }
1072 
1073 void KonqView::finishedWithCurrentURL()
1074 {
1075     if (!m_tempFile.isEmpty()) {
1076         qCDebug(KONQUEROR_LOG) << "######### Deleting tempfile after use:" << m_tempFile;
1077         QFile::remove(m_tempFile);
1078         m_tempFile.clear();
1079     }
1080 }
1081 
1082 void KonqView::setPassiveMode(bool mode)
1083 {
1084     // In theory, if m_bPassiveMode is true and mode is false,
1085     // the part should be removed from the part manager,
1086     // and if the other way round, it should be readded to the part manager...
1087     m_bPassiveMode = mode;
1088 
1089     if (mode && m_pMainWindow->viewCount() > 1 && m_pMainWindow->currentView() == this) {
1090         KParts::Part *part = m_pMainWindow->viewManager()->chooseNextView(this)->part();    // switch active part
1091         m_pMainWindow->viewManager()->setActivePart(part);
1092     }
1093 
1094     // Update statusbar stuff
1095     m_pMainWindow->viewManager()->viewCountChanged();
1096 }
1097 
1098 void KonqView::setLinkedView(bool mode)
1099 {
1100     m_bLinkedView = mode;
1101     if (m_pMainWindow->currentView() == this) {
1102         m_pMainWindow->linkViewAction()->setChecked(mode);
1103     }
1104     frame()->statusbar()->setLinkedView(mode);
1105 }
1106 
1107 void KonqView::setLockedLocation(bool b)
1108 {
1109     m_bLockedLocation = b;
1110 }
1111 
1112 void KonqView::aboutToOpenURL(const QUrl &url, const KParts::OpenUrlArguments &args)
1113 {
1114     m_bErrorURL = url.scheme() == QLatin1String("error");
1115 
1116     KParts::OpenUrlEvent ev(m_pPart, url, args);
1117     QApplication::sendEvent(m_pMainWindow, &ev);
1118 
1119     m_bGotIconURL = false;
1120     m_bAborted = false;
1121 }
1122 
1123 void KonqView::setPartMimeType()
1124 {
1125     KParts::OpenUrlArguments args(m_pPart->arguments());
1126     args.setMimeType(m_serviceType);
1127     m_pPart->setArguments(args);
1128 }
1129 
1130 bool KonqView::callExtensionMethod(const char *methodName)
1131 {
1132     QObject *obj = KParts::NavigationExtension::childObject(m_pPart);
1133     if (!obj) { // not all views have a browser extension !
1134         return false;
1135     }
1136 
1137     return QMetaObject::invokeMethod(obj, methodName,  Qt::DirectConnection);
1138 }
1139 
1140 bool KonqView::callExtensionBoolMethod(const char *methodName, bool value)
1141 {
1142     QObject *obj = KParts::NavigationExtension::childObject(m_pPart);
1143     if (!obj) { // not all views have a browser extension !
1144         return false;
1145     }
1146 
1147     return QMetaObject::invokeMethod(obj, methodName,  Qt::DirectConnection, Q_ARG(bool, value));
1148 }
1149 
1150 bool KonqView::callExtensionURLMethod(const char *methodName, const QUrl &value)
1151 {
1152     QObject *obj = KParts::NavigationExtension::childObject(m_pPart);
1153     if (!obj) { // not all views have a browser extension !
1154         return false;
1155     }
1156 
1157     return QMetaObject::invokeMethod(obj, methodName,  Qt::DirectConnection, Q_ARG(QUrl, value));
1158 }
1159 
1160 void KonqView::setViewName(const QString &name)
1161 {
1162     //qCDebug(KONQUEROR_LOG) << this << "name=" << name;
1163     if (m_pPart) {
1164         m_pPart->setObjectName(name);
1165     }
1166 }
1167 
1168 QString KonqView::viewName() const
1169 {
1170     return m_pPart ? m_pPart->objectName() : QString();
1171 }
1172 
1173 void KonqView::enablePopupMenu(bool b)
1174 {
1175     Q_ASSERT(m_pMainWindow);
1176 
1177     KParts::NavigationExtension *ext = browserExtension();
1178 
1179     if (!ext) {
1180         return;
1181     }
1182 
1183     if (m_bPopupMenuEnabled == b) {
1184         return;
1185     }
1186 
1187 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1188     //Store signal and slot overloads in variable so that they can be reused in both branches
1189     using namespace KParts;
1190     auto sigOverloadFileItem = QOverload<const QPoint&, const KFileItemList&, const OpenUrlArguments &, const BrowserArguments&,
1191         NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&NavigationExtension::popupMenu);
1192     auto slotOverloadFileItem = QOverload<const QPoint&, const KFileItemList&, const OpenUrlArguments &, const BrowserArguments&,
1193         NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&KonqMainWindow::slotPopupMenu);
1194     auto sigOverloadUrl = QOverload<const QPoint&, const QUrl&, mode_t, const OpenUrlArguments& , const BrowserArguments& ,
1195         NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&NavigationExtension::popupMenu);
1196     auto slotOverloadUrl = QOverload<const QPoint&, const QUrl&, mode_t, const OpenUrlArguments& , const BrowserArguments& ,
1197         NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&KonqMainWindow::slotPopupMenu);
1198     if (b) { // enable context popup
1199         m_bPopupMenuEnabled = true;
1200         connect(ext,sigOverloadFileItem, m_pMainWindow, slotOverloadFileItem);
1201         connect(ext, sigOverloadUrl, m_pMainWindow, slotOverloadUrl);
1202     } else { // disable context popup
1203         m_bPopupMenuEnabled = false;
1204         disconnect(ext,sigOverloadFileItem, m_pMainWindow, slotOverloadFileItem);
1205         disconnect(ext, sigOverloadUrl, m_pMainWindow, slotOverloadUrl);
1206     }
1207 #else
1208     if (auto browserExtension = qobject_cast<BrowserExtension *>(ext)) {
1209         if (b) {
1210             m_bPopupMenuEnabled = true;
1211             connect(browserExtension, &BrowserExtension::browserPopupMenuFromFiles, this, &KonqView::slotBrowserPopupMenuFiles);
1212             connect(browserExtension, &BrowserExtension::browserPopupMenuFromUrl, this, &KonqView::slotBrowserPopupMenuUrl);
1213         } else {
1214              m_bPopupMenuEnabled = false;
1215             disconnect(browserExtension, &BrowserExtension::browserPopupMenuFromFiles, this, &KonqView::slotBrowserPopupMenuFiles);
1216             disconnect(browserExtension, &BrowserExtension::browserPopupMenuFromUrl, this, &KonqView::slotBrowserPopupMenuUrl);
1217         }
1218     } else {
1219         //Store signal and slot overloads in variable so that they can be reused in both branches
1220         using namespace KParts;
1221         auto sigOverloadFileItem = QOverload<const QPoint&, const KFileItemList&, const OpenUrlArguments &,
1222             NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&NavigationExtension::popupMenu);
1223         auto sigOverloadUrl = QOverload<const QPoint&, const QUrl&, mode_t, const OpenUrlArguments& ,
1224             NavigationExtension::PopupFlags, const NavigationExtension::ActionGroupMap&>::of(&NavigationExtension::popupMenu);
1225         if (b) { // enable context popup
1226             m_bPopupMenuEnabled = true;
1227             connect(ext,sigOverloadFileItem, this, &KonqView::slotPopupMenuFiles);
1228             connect(ext, sigOverloadUrl, this, &KonqView::slotPopupMenuUrl);
1229         } else { // disable context popup
1230             m_bPopupMenuEnabled = false;
1231             disconnect(ext,sigOverloadFileItem, this, &KonqView::slotPopupMenuFiles);
1232             disconnect(ext, sigOverloadUrl, this, &KonqView::slotPopupMenuUrl);
1233         }
1234     }
1235 #endif
1236 }
1237 
1238 #if QT_VERSION_MAJOR > 5
1239 void KonqView::slotBrowserPopupMenuFiles(const QPoint& global, const KFileItemList& items,
1240                                          const KParts::OpenUrlArguments& args, const BrowserArguments& bargs,
1241                                          KParts::NavigationExtension::PopupFlags flags,
1242                                          const KParts::NavigationExtension::ActionGroupMap& actionGroups)
1243 {
1244     m_pMainWindow->slotPopupMenu(global, items, args, bargs, flags, actionGroups, this);
1245 }
1246 
1247 void KonqView::slotBrowserPopupMenuUrl(const QPoint& global, const QUrl& url, mode_t mode,
1248                                        const KParts::OpenUrlArguments& args, const BrowserArguments& bargs,
1249                                        KParts::NavigationExtension::PopupFlags flags,
1250                                        const KParts::NavigationExtension::ActionGroupMap& actionGroups)
1251 {
1252     m_pMainWindow->slotPopupMenu(global, url, mode, args, bargs, flags, actionGroups, this);
1253 }
1254 #endif
1255 
1256 void KonqView::slotPopupMenuFiles(const QPoint &global, const KFileItemList &items,
1257                                   const KParts::OpenUrlArguments &args, KParts::NavigationExtension::PopupFlags flags,
1258                                   const KParts::NavigationExtension::ActionGroupMap &actionGroups)
1259 {
1260 #if QT_VERSION_MAJOR < 6
1261     m_pMainWindow->slotPopupMenu(global, items, args, {}, flags, actionGroups);
1262 #else
1263     m_pMainWindow->slotPopupMenu(global, items, args, {}, flags, actionGroups, this);
1264 #endif
1265 }
1266 
1267 void KonqView::slotPopupMenuUrl(const QPoint &global, const QUrl &url, mode_t mode, const KParts::OpenUrlArguments &arguments,
1268                                 KParts::NavigationExtension::PopupFlags flags,
1269                                 const KParts::NavigationExtension::ActionGroupMap &actionGroups)
1270 {
1271 #if QT_VERSION_MAJOR < 6
1272     m_pMainWindow->slotPopupMenu(global, url, mode, arguments, {}, flags, actionGroups);
1273 #else
1274     m_pMainWindow->slotPopupMenu(global, url, mode, arguments, {}, flags, actionGroups, this);
1275 #endif
1276 }
1277 
1278 void KonqView::reparseConfiguration()
1279 {
1280     callExtensionMethod("reparseConfiguration");
1281 }
1282 
1283 void KonqView::disableScrolling()
1284 {
1285     m_bDisableScrolling = true;
1286     callExtensionMethod("disableScrolling");
1287 }
1288 
1289 QString KonqView::dbusObjectPath()
1290 {
1291     // TODO maybe this can be improved?
1292     // E.g. using the part's name, but we'd have to update the name in setViewName maybe?
1293     // And to make sure it's a valid dbus object path like in kmainwindow...
1294     static int s_viewNumber = 0;
1295     if (m_dbusObjectPath.isEmpty()) {
1296         m_dbusObjectPath = m_pMainWindow->dbusName() + '/' + QString::number(++s_viewNumber);
1297         new KonqViewAdaptor(this);
1298         QDBusConnection::sessionBus().registerObject(m_dbusObjectPath, this);
1299     }
1300     return m_dbusObjectPath;
1301 }
1302 
1303 QString KonqView::partObjectPath()
1304 {
1305     if (!m_pPart) {
1306         return QString();
1307     }
1308 
1309     const QVariant dcopProperty = m_pPart->property("dbusObjectPath");
1310     return dcopProperty.toString();
1311 }
1312 
1313 bool KonqView::eventFilter(QObject *obj, QEvent *e)
1314 {
1315     if (!m_pPart) {
1316         return false;
1317     }
1318 //  qCDebug(KONQUEROR_LOG) << "--" << obj->className() << "--" << e->type() << "--" ;
1319     if (e->type() == QEvent::DragEnter && m_bURLDropHandling && obj == m_pPart->widget()) {
1320         QDragEnterEvent *ev = static_cast<QDragEnterEvent *>(e);
1321         const QMimeData *mimeData = ev->mimeData();
1322         if (mimeData->hasUrls()) {
1323             QList<QUrl> lstDragURLs = KUrlMimeData::urlsFromMimeData(mimeData);
1324 
1325             const QList<QObject *> children = m_pPart->widget()->findChildren<QObject *>();   // ### slow, better write a isChildOf with a loop...
1326 
1327             if (!lstDragURLs.isEmpty()
1328                     && !lstDragURLs.first().url().startsWith(QLatin1String("javascript:"), Qt::CaseInsensitive) &&   // ### this looks like a hack to me
1329                     ev->source() != m_pPart->widget() &&
1330                     !children.contains(ev->source())) {
1331                 ev->acceptProposedAction();
1332             }
1333         }
1334     } else if (e->type() == QEvent::Drop && m_bURLDropHandling && obj == m_pPart->widget()) {
1335         QDropEvent *ev = static_cast<QDropEvent *>(e);
1336         const QMimeData *mimeData = ev->mimeData();
1337 
1338         QList<QUrl> lstDragURLs = KUrlMimeData::urlsFromMimeData(mimeData);
1339         KParts::NavigationExtension *ext = browserExtension();
1340         if (!lstDragURLs.isEmpty() && ext && lstDragURLs.first().isValid()) {
1341             emit ext->openUrlRequest(lstDragURLs.first());    // this will call m_pMainWindow::slotOpenURLRequest delayed
1342         }
1343     }
1344 
1345 #if QT_VERSION_MAJOR < 6
1346 #ifdef KActivities_FOUND
1347     if (e->type() == QEvent::FocusIn) {
1348         m_activityResourceInstance->notifyFocusedIn();
1349     }
1350 
1351     if (e->type() == QEvent::FocusOut) {
1352         m_activityResourceInstance->notifyFocusedOut();
1353     }
1354 #endif
1355 #endif
1356 
1357     return false;
1358 }
1359 
1360 bool KonqView::prepareReload(KParts::OpenUrlArguments &args, BrowserArguments &browserArgs, bool softReload)
1361 {
1362     args.setReload(true);
1363     if (softReload) {
1364         browserArgs.softReload = true;
1365     }
1366 
1367     // Repost form data if this URL is the result of a POST HTML form.
1368     if (m_doPost && !browserArgs.redirectedRequest()) {
1369         if (KMessageBox::warningContinueCancel(nullptr, i18n(
1370                 "The page you are trying to view is the result of posted form data. "
1371                 "If you resend the data, any action the form carried out (such as search or online purchase) will be repeated. "),
1372                                                i18nc("@title:window", "Warning"), KGuiItem(i18n("Resend"))) == KMessageBox::Continue) {
1373             browserArgs.setDoPost(true);
1374             browserArgs.setContentType(m_postContentType);
1375             browserArgs.postData = m_postData;
1376         } else {
1377             return false;
1378         }
1379     }
1380     // Re-set referrer
1381     args.metaData()[QStringLiteral("referrer")] = m_pageReferrer;
1382 
1383     return true;
1384 }
1385 
1386 KParts::NavigationExtension *KonqView::browserExtension() const
1387 {
1388     return m_pPart ? KParts::NavigationExtension::childObject(m_pPart) : nullptr;
1389 }
1390 
1391 KParts::StatusBarExtension *KonqView::statusBarExtension() const
1392 {
1393     return KParts::StatusBarExtension::childObject(m_pPart);
1394 }
1395 
1396 QMimeType KonqView::mimeType() const
1397 {
1398     QMimeDatabase db;
1399     return db.mimeTypeForName(serviceType());
1400 }
1401 
1402 bool KonqView::supportsMimeType(const QString &mimeType) const
1403 {
1404     QMimeDatabase db;
1405     QMimeType mime = db.mimeTypeForName(mimeType);
1406     if (!mime.isValid()) {
1407         return false;
1408     }
1409     const QStringList lst = m_service.mimeTypes();
1410     QStringList::const_iterator found = std::find_if(lst.constBegin(), lst.constEnd(), [mime](const QString &name){return mime.inherits(name);});
1411     return found != lst.constEnd();
1412 }
1413 
1414 bool KonqView::isWebBrowsingPart() const
1415 {
1416     if (!m_pPart) {
1417         return false;
1418     }
1419     const QString partName = m_pPart->componentName();
1420     return partName == QLatin1String("webenginepart") || partName == QLatin1String("khtml") || partName == QLatin1String("kwebkitpart");
1421 }
1422 
1423 
1424 void HistoryEntry::saveConfig(KConfigGroup &config, const QString &prefix, const KonqFrameBase::Options &options)
1425 {
1426     if (options & KonqFrameBase::SaveUrls) {
1427         config.writeEntry(QStringLiteral("Url").prepend(prefix), url.url());
1428         config.writeEntry(QStringLiteral("LocationBarURL").prepend(prefix), locationBarURL);
1429         config.writeEntry(QStringLiteral("Title").prepend(prefix), title);
1430         config.writeEntry(QStringLiteral("StrServiceType").prepend(prefix), strServiceType);
1431         config.writeEntry(QStringLiteral("StrServiceName").prepend(prefix), strServiceName);
1432     } else if (options & KonqFrameBase::SaveHistoryItems) {
1433         config.writeEntry(QStringLiteral("Url").prepend(prefix), url.url());
1434         config.writeEntry(QStringLiteral("LocationBarURL").prepend(prefix), locationBarURL);
1435         config.writeEntry(QStringLiteral("LocationBarURL").prepend(prefix), locationBarURL);
1436         config.writeEntry(QStringLiteral("Title").prepend(prefix), title);
1437         config.writeEntry(QStringLiteral("Buffer").prepend(prefix), buffer);
1438         config.writeEntry(QStringLiteral("StrServiceType").prepend(prefix), strServiceType);
1439         config.writeEntry(QStringLiteral("StrServiceName").prepend(prefix), strServiceName);
1440         config.writeEntry(QStringLiteral("PostData").prepend(prefix), postData);
1441         config.writeEntry(QStringLiteral("PostContentType").prepend(prefix), postContentType);
1442         config.writeEntry(QStringLiteral("DoPost").prepend(prefix), doPost);
1443         config.writeEntry(QStringLiteral("PageReferrer").prepend(prefix), pageReferrer);
1444         config.writeEntry(QStringLiteral("PageSecurity").prepend(prefix), static_cast<int>(pageSecurity));
1445     }
1446 }
1447 
1448 HistoryEntry* HistoryEntry::fromDelayedLoadingData(const KConfigGroup& config, const QString& prefix, const KonqFrameBase::Options& options)
1449 {
1450     HistoryEntry *entry = new HistoryEntry;
1451     if (options & (KonqFrameBase::SaveUrls|KonqFrameBase::SaveHistoryItems)) { // eitentryr one
1452         entry->url = QUrl(config.readEntry(QStringLiteral("Url").prepend(prefix), ""));
1453         entry->locationBarURL = config.readEntry(QStringLiteral("LocationBarURL").prepend(prefix), "");
1454         entry->title = config.readEntry(QStringLiteral("Title").prepend(prefix), "");
1455         entry->strServiceType = config.readEntry(QStringLiteral("StrServiceType").prepend(prefix), "");
1456         entry->strServiceName = config.readEntry(QStringLiteral("StrServiceName").prepend(prefix), "");
1457     }
1458     if (options & KonqFrameBase::SaveUrls) {
1459         entry->reload = true;
1460     } else if (options & KonqFrameBase::SaveHistoryItems) {
1461         entry->buffer = config.readEntry(QStringLiteral("Buffer").prepend(prefix), QByteArray());
1462         entry->postData = config.readEntry(QStringLiteral("PostData").prepend(prefix), QByteArray());
1463         entry->postContentType = config.readEntry(QStringLiteral("PostContentType").prepend(prefix), "");
1464         entry->doPost = config.readEntry(QStringLiteral("DoPost").prepend(prefix), false);
1465         entry->pageReferrer = config.readEntry(QStringLiteral("PageReferrer").prepend(prefix), "");
1466         entry->pageSecurity = static_cast<KonqMainWindow::PageSecurity>(config.readEntry(QStringLiteral("PageSecurity").prepend(prefix), 0));
1467         entry->reload = false;
1468     }
1469     return entry;
1470 }
1471 
1472 void HistoryEntry::loadItem(const KConfigGroup &config, const QString &prefix, const KonqFrameBase::Options &options)
1473 {
1474     if (options & (KonqFrameBase::SaveUrls|KonqFrameBase::SaveHistoryItems)) { // either one
1475         url = QUrl(config.readEntry(QStringLiteral("Url").prepend(prefix), ""));
1476         locationBarURL = config.readEntry(QStringLiteral("LocationBarURL").prepend(prefix), "");
1477         title = config.readEntry(QStringLiteral("Title").prepend(prefix), "");
1478         strServiceType = config.readEntry(QStringLiteral("StrServiceType").prepend(prefix), "");
1479         strServiceName = config.readEntry(QStringLiteral("StrServiceName").prepend(prefix), "");
1480     }
1481     if (options & KonqFrameBase::SaveUrls) {
1482         reload = true;
1483     } else if (options & KonqFrameBase::SaveHistoryItems) {
1484         buffer = config.readEntry(QStringLiteral("Buffer").prepend(prefix), QByteArray());
1485         postData = config.readEntry(QStringLiteral("PostData").prepend(prefix), QByteArray());
1486         postContentType = config.readEntry(QStringLiteral("PostContentType").prepend(prefix), "");
1487         doPost = config.readEntry(QStringLiteral("DoPost").prepend(prefix), false);
1488         pageReferrer = config.readEntry(QStringLiteral("PageReferrer").prepend(prefix), "");
1489         pageSecurity = static_cast<KonqMainWindow::PageSecurity>(config.readEntry(
1490                            QStringLiteral("PageSecurity").prepend(prefix), 0));
1491         reload = false;
1492     }
1493 }
1494 
1495 Konq::PlaceholderPart* KonqView::placeholderPart() const
1496 {
1497     return qobject_cast<Konq::PlaceholderPart*>(m_pPart);
1498 }
1499 
1500 void KonqView::saveConfig(KConfigGroup &config, const QString &prefix, const KonqFrameBase::Options &options)
1501 {
1502     //If the view has been delayed, these property can't be got from the part (which will be a PlaceholderPart):
1503     //They need to be taken from m_delayedLoadingData.
1504     //This can happen when loading a session with several tabs, then saving it again without activating all the
1505     //tabs
1506     Konq::PlaceholderPart *plPart = placeholderPart();
1507     QString mimeType = plPart ? plPart->delayedLoadingData().mimeType : serviceType();
1508     QString serviceName = plPart ? plPart->delayedLoadingData().serviceName : service().pluginId();
1509     bool locked = plPart ? plPart->delayedLoadingData().lockedLocation : isLockedLocation();
1510 
1511     config.writeEntry(QStringLiteral("ServiceType").prepend(prefix), mimeType);
1512     config.writeEntry(QStringLiteral("ServiceName").prepend(prefix), serviceName);
1513     config.writeEntry(QStringLiteral("PassiveMode").prepend(prefix), isPassiveMode());
1514     config.writeEntry(QStringLiteral("LinkedView").prepend(prefix), isLinkedView());
1515     config.writeEntry(QStringLiteral("ToggleView").prepend(prefix), isToggleView());
1516     config.writeEntry(QStringLiteral("LockedLocation").prepend(prefix), locked);
1517 
1518     if (options & KonqFrameBase::SaveUrls) {
1519         config.writePathEntry(QStringLiteral("URL").prepend(prefix), url().url());
1520     } else if (options & KonqFrameBase::SaveHistoryItems) {
1521         QList<HistoryEntry *>::Iterator it = m_lstHistory.begin();
1522         for (int i = 0; it != m_lstHistory.end(); ++it, ++i) {
1523             // In order to not end up with a huge config file, we only save full
1524             // history for current history item
1525             KonqFrameBase::Options options;
1526             if (i == m_lstHistoryIndex) {
1527                 options = KonqFrameBase::SaveHistoryItems;
1528             } else {
1529                 options = KonqFrameBase::SaveUrls;
1530             }
1531 
1532             (*it)->saveConfig(config, QLatin1String("HistoryItem")
1533                               + QString::number(i).prepend(prefix), options);
1534         }
1535         config.writeEntry(QStringLiteral("CurrentHistoryItem").prepend(prefix), m_lstHistoryIndex);
1536         config.writeEntry(QStringLiteral("NumberOfHistoryItems").prepend(prefix), historyLength());
1537     }
1538 }
1539 
1540 void KonqView::storeDelayedLoadingData(const QString& mimeType, const QString& serviceName, bool openUrl, const QUrl& url, bool lockedLocation, const KConfigGroup& grp, const QString& prefix)
1541 {
1542     Konq::PlaceholderPart *plPart = placeholderPart();
1543     if (!plPart) {
1544         return;
1545     }
1546     plPart->setDelayedLoadingData({mimeType, serviceName, openUrl, url, lockedLocation});
1547 
1548     const QString keyHistoryItems = QStringLiteral("NumberOfHistoryItems").prepend(prefix);
1549 
1550     int historySize = grp.readEntry(keyHistoryItems, 0);
1551     if (historySize < 1) {
1552         //Note: this won't really open the URL because the part will be a PlaceholderPart
1553         m_requestedUrl = url;
1554         m_pPart->openUrl(url);
1555         return;
1556     }
1557 
1558     loadHistoryConfig(grp, prefix);
1559     if (!m_lstHistory.isEmpty()) {
1560         //Note: this won't really open the URL because the part will be a PlaceholderPart
1561         QUrl histUrl = m_lstHistory.at(m_lstHistoryIndex)->url;
1562         m_requestedUrl = histUrl;
1563         m_pPart->openUrl(histUrl);
1564     }
1565 }
1566 
1567 bool KonqView::isDelayed() const
1568 {
1569     return qobject_cast<Konq::PlaceholderPart*>(m_pPart) != nullptr;
1570 }
1571 
1572 void KonqView::loadDelayed()
1573 {
1574     Konq::PlaceholderPart *plPart = placeholderPart();
1575     if (!plPart) {
1576         return;
1577     }
1578 
1579     Konq::PlaceholderPart::DelayedLoadingData data = plPart->delayedLoadingData();
1580     changePart(data.mimeType, data.serviceName, true);
1581 
1582     if (data.openUrl) {
1583         if (m_lstHistory.isEmpty()) {
1584             QUrl url = data.url;
1585             KonqOpenURLRequest req;
1586             if (!KonqUrl::hasKonqScheme(url)) {
1587                 req.typedUrl = url.toDisplayString();
1588             }
1589             m_pMainWindow->openView(data.mimeType, url, this, req);
1590         } else {
1591             restoreHistory();
1592         }
1593     }
1594     setLockedLocation(data.lockedLocation);
1595     data = {};
1596 }
1597 
1598 void KonqView::loadHistoryConfig(const KConfigGroup &config, const QString &prefix)
1599 {
1600     // First, remove any history
1601     qDeleteAll(m_lstHistory);
1602     m_lstHistory.clear();
1603 
1604     int historySize = config.readEntry(QStringLiteral("NumberOfHistoryItems").prepend(prefix), 0);
1605     int currentIndex = config.readEntry(QStringLiteral("CurrentHistoryItem").prepend(prefix), historySize - 1);
1606 
1607     // No history to restore..
1608     if (historySize == 0) {
1609         createHistoryEntry();
1610         return;
1611     }
1612 
1613     // restore history list
1614     for (int i = 0; i < historySize; ++i) {
1615 
1616         // Only current history item saves completely its HistoryEntry
1617         KonqFrameBase::Options options = i == currentIndex ? KonqFrameBase::SaveHistoryItems : KonqFrameBase::SaveUrls;
1618 
1619         HistoryEntry *historyEntry = HistoryEntry::fromDelayedLoadingData(config, QLatin1String("HistoryItem") + QString::number(i).prepend(prefix), options);
1620 
1621         appendHistoryEntry(historyEntry);
1622     }
1623 
1624     // Shouldn't happen, but just in case..
1625     if (currentIndex >= historyLength()) {
1626         currentIndex = historyLength() - 1;
1627     }
1628 
1629     // set and load the correct history index
1630     setHistoryIndex(currentIndex);
1631 }
1632 
1633 QString KonqView::internalViewMode() const
1634 {
1635     const QVariant viewModeProperty = m_pPart->property("currentViewMode");
1636     return viewModeProperty.toString();
1637 }
1638 
1639 void KonqView::setInternalViewMode(const QString &viewMode)
1640 {
1641     m_pPart->setProperty("currentViewMode", viewMode);
1642 }
1643 
1644 QString KonqView::nameFilter() const
1645 {
1646     const QVariant nameFilterProperty = m_pPart->property("nameFilter");
1647     return nameFilterProperty.toString();
1648 }
1649 
1650 bool KonqView::showsDirectory() const
1651 {
1652     return supportsMimeType(QStringLiteral("inode/directory"));
1653 }
1654 
1655 bool KonqView::isModified() const
1656 {
1657     if (m_pPart && (m_pPart->metaObject()->indexOfProperty("modified") != -1)) {
1658         const QVariant prop = m_pPart->property("modified");
1659         return prop.isValid() && prop.toBool();
1660     }
1661     return false;
1662 }
1663 
1664 void KonqView::setFocus()
1665 {
1666     if (m_pPart && m_pPart->widget() && !isErrorUrl()) {
1667         m_pPart->widget()->setFocus();
1668     }
1669 }
1670 
1671 bool KonqView::isErrorUrl() const
1672 {
1673     return m_bErrorURL;
1674 }
1675 
1676 bool KonqView::canNavigateTo(const QUrl& newUrl) const
1677 {
1678     if (m_bFollowActive) {
1679         return m_pMainWindow->currentView()->url() == newUrl;
1680     }
1681     return !m_bLockedLocation || newUrl == url();
1682 }
1683 
1684 void KonqView::duplicateView(KonqView* otherView)
1685 {
1686     // openUrl(otherView->requestedUrl(), otherView->locationBarURL(), otherView->nameFilter(), !otherView->m_tempFile.isEmpty());
1687 
1688     //If requested and real URLs are the same, otherView isn't displaying a downloaded file, so just call openUrl
1689     if (otherView->url() == otherView->realUrl()) {
1690         openUrl(otherView->url(), otherView->locationBarURL());
1691         return;
1692     }
1693 
1694     //otherView is displaying a downloaded file. In this case, for efficiency sake, we don't download it again: rather, we create
1695     //a copy of the file (using KIO::copy) and open it
1696     QString existingFile = QFileInfo(otherView->realUrl().path()).fileName();
1697     QUrl dest = QUrl::fromLocalFile(KFileUtils::suggestName(QUrl::fromLocalFile(QDir::tempPath()), existingFile));
1698     KIO::CopyJob *j = KIO::copy(otherView->realUrl(), dest);
1699 
1700     const QString locBarUrl = otherView->locationBarURL();
1701     //If displaying a downloaded URL, the reaul URL will always be a temporary one
1702     bool temp = true;
1703     const QString nameFilter = otherView->nameFilter();
1704     const QUrl reqUrl = otherView->m_requestedUrl;
1705 
1706     auto doOpening = [this, dest, temp, nameFilter, reqUrl, locBarUrl](KJob *job) {
1707         if (!job->error()) {
1708             openUrl(dest, locBarUrl, nameFilter, temp, reqUrl);
1709         }
1710     };
1711     connect(j, &KJob::result, this, doOpening);
1712 }