File indexing completed on 2024-05-12 05:12:55

0001 /*
0002     This file is part of Akregator.
0003 
0004     SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0007 */
0008 
0009 #include "framemanager.h"
0010 #include "akregator_debug.h"
0011 #include "akregatorconfig.h"
0012 #include "frame.h"
0013 #include "openurlrequest.h"
0014 #include "webengine/webengineframe.h"
0015 #include <KConfigGroup>
0016 #include <KMacroExpander>
0017 #include <KProcess>
0018 #include <KShell>
0019 #include <QDesktopServices>
0020 #include <QStringList>
0021 
0022 using namespace Akregator;
0023 
0024 FrameManager::FrameManager(QObject *parent)
0025     : QObject(parent)
0026     , m_currentFrame(nullptr)
0027 {
0028 }
0029 
0030 FrameManager::~FrameManager() = default;
0031 
0032 Frame *FrameManager::currentFrame() const
0033 {
0034     return m_currentFrame;
0035 }
0036 
0037 void FrameManager::slotAddFrame(Frame *frame)
0038 {
0039     m_frames.insert(frame->id(), frame);
0040 
0041     connect(frame, &Frame::signalCanceled, this, &FrameManager::slotSetCanceled);
0042     connect(frame, &Frame::signalStarted, this, &FrameManager::slotSetStarted);
0043     connect(frame, &Frame::signalCaptionChanged, this, &FrameManager::slotSetCaption);
0044     connect(frame, &Frame::signalLoadingProgress, this, &FrameManager::slotSetProgress);
0045     connect(frame, &Frame::signalCompleted, this, &FrameManager::slotSetCompleted);
0046     connect(frame, &Frame::signalTitleChanged, this, &FrameManager::slotSetTitle);
0047     connect(frame, &Frame::signalStatusText, this, &FrameManager::slotSetStatusText);
0048 
0049     connect(frame, &Frame::signalOpenUrlRequest, this, [this](OpenUrlRequest &request) {
0050         slotOpenUrlRequest(request);
0051     });
0052 
0053     // setPartGuiActive(frame->part(), false);
0054 
0055     Q_EMIT signalFrameAdded(frame);
0056 
0057     if (m_frames.count() == 1) {
0058         slotChangeFrame(frame->id());
0059     }
0060 }
0061 
0062 void FrameManager::slotRemoveFrame(int id)
0063 {
0064     Frame *frame = m_frames.value(id);
0065 
0066     if (!frame || !frame->isRemovable()) {
0067         return;
0068     }
0069     frame->disconnect(this);
0070 
0071     if (m_currentFrame == frame) {
0072         slotChangeFrame(-1);
0073     }
0074 
0075     m_frames.insert(id, nullptr);
0076     m_frames.remove(id);
0077     Q_EMIT signalFrameRemoved(id);
0078     delete frame;
0079 }
0080 
0081 Frame *FrameManager::findFrameById(int id) const
0082 {
0083     return m_frames.value(id);
0084 }
0085 
0086 void FrameManager::slotChangeFrame(int frameId)
0087 {
0088     Frame *frame = m_frames.value(frameId);
0089     if (frame == m_currentFrame) {
0090         return;
0091     }
0092 
0093     Frame *oldFrame = m_currentFrame;
0094     m_currentFrame = frame;
0095 
0096     // if (oldFrame) {
0097     //    setPartGuiActive(oldFrame->part(), false);
0098     //}
0099 
0100     if (frame) {
0101         // setPartGuiActive(frame->part(), true);
0102 
0103         // TODO: handle removable flag
0104 
0105         switch (frame->state()) {
0106         case Frame::Started:
0107             Q_EMIT signalStarted();
0108             break;
0109         case Frame::Canceled:
0110             Q_EMIT signalCanceled(QString());
0111             break;
0112         case Frame::Idle:
0113         case Frame::Completed:
0114             Q_EMIT signalCompleted();
0115         }
0116 
0117         Q_EMIT signalCaptionChanged(frame->caption());
0118         Q_EMIT signalTitleChanged(frame->title());
0119         Q_EMIT signalLoadingProgress(frame->progress());
0120         Q_EMIT signalStatusText(frame->statusText());
0121     } else {
0122         Q_EMIT signalCompleted();
0123         Q_EMIT signalCaptionChanged(QString());
0124         Q_EMIT signalTitleChanged(QString());
0125         Q_EMIT signalLoadingProgress(100);
0126         Q_EMIT signalStatusText(QString());
0127     }
0128 
0129     Q_EMIT signalCurrentFrameChanged(oldFrame, frame);
0130 }
0131 
0132 void FrameManager::slotSetStarted(Frame *frame)
0133 {
0134     if (frame == m_currentFrame) {
0135         Q_EMIT signalStarted();
0136     }
0137 }
0138 
0139 void FrameManager::slotSetCanceled(Frame *frame, const QString &reason)
0140 {
0141     if (frame == m_currentFrame) {
0142         Q_EMIT signalCanceled(reason);
0143     }
0144 }
0145 
0146 void FrameManager::slotSetCompleted(Frame *frame)
0147 {
0148     if (frame == m_currentFrame) {
0149         Q_EMIT signalCompleted();
0150     }
0151 }
0152 
0153 void FrameManager::slotSetProgress(Frame *frame, int progress)
0154 {
0155     if (frame == m_currentFrame) {
0156         Q_EMIT signalLoadingProgress(progress);
0157     }
0158 }
0159 
0160 void FrameManager::slotSetCaption(Frame *frame, const QString &caption)
0161 {
0162     if (frame == m_currentFrame) {
0163         Q_EMIT signalCaptionChanged(caption);
0164     }
0165 }
0166 
0167 void FrameManager::slotSetTitle(Frame *frame, const QString &title)
0168 {
0169     if (frame == m_currentFrame) {
0170         Q_EMIT signalTitleChanged(title);
0171     }
0172 }
0173 
0174 void FrameManager::slotSetStatusText(Frame *frame, const QString &statusText)
0175 {
0176     if (frame == m_currentFrame) {
0177         Q_EMIT signalStatusText(statusText);
0178     }
0179 }
0180 
0181 void FrameManager::openUrl(OpenUrlRequest &request)
0182 {
0183     if (request.options() == OpenUrlRequest::NewTab || (m_currentFrame->id() == 0)) {
0184         int newFrameId = -1;
0185         Q_EMIT signalRequestNewFrame(newFrameId);
0186         request.setFrameId(newFrameId);
0187     } else {
0188         request.setFrameId(m_currentFrame->id());
0189     }
0190     if (m_frames.contains(request.frameId())) {
0191         Frame *frame = m_frames.value(request.frameId());
0192         if (frame->openUrl(request)) {
0193             request.setWasHandled(true);
0194         }
0195     }
0196 
0197     if (!request.openInBackground()) {
0198         Q_EMIT signalSelectFrame(request.frameId());
0199     }
0200 }
0201 
0202 void FrameManager::openInExternalBrowser(const OpenUrlRequest &request)
0203 {
0204     QUrl url = request.url();
0205     if (!url.isValid()) {
0206         return;
0207     }
0208 
0209     if (!Settings::externalBrowserUseKdeDefault()) {
0210         QHash<QChar, QString> map;
0211         map.insert(QLatin1Char('u'), url.url());
0212         const QString cmd = KMacroExpander::expandMacrosShellQuote(Settings::externalBrowserCustomCommand(), map);
0213         const QStringList args = KShell::splitArgs(cmd);
0214         if (!args.isEmpty()) {
0215             KProcess::startDetached(args);
0216             return;
0217         }
0218     }
0219 
0220     QDesktopServices::openUrl(url);
0221 }
0222 
0223 void FrameManager::slotOpenUrlRequest(OpenUrlRequest &request, bool useOpenInBackgroundSetting)
0224 {
0225     qCDebug(AKREGATOR_LOG) << "FrameManager::slotOpenUrlRequest():" << request.debugInfo();
0226 
0227     if (request.options() == OpenUrlRequest::ExternalBrowser) {
0228         openInExternalBrowser(request);
0229         return;
0230     }
0231 
0232     if (useOpenInBackgroundSetting) {
0233         // Honour user's preference for foreground/background tabs
0234         if (request.options() == OpenUrlRequest::NewTab) {
0235             request.setOpenInBackground(Settings::lMBBehaviour() == Settings::EnumLMBBehaviour::OpenInBackground);
0236         }
0237     }
0238     openUrl(request);
0239 }
0240 
0241 void FrameManager::saveProperties(KConfigGroup &config)
0242 {
0243     // write children
0244     QStringList strlst;
0245     QHash<int, Frame *>::const_iterator i;
0246     QHash<int, Frame *>::const_iterator end(m_frames.constEnd());
0247     for (i = m_frames.constBegin(); i != end; ++i) {
0248         // No need to save the main frame
0249         Frame *currentFrame = i.value();
0250         if (currentFrame && qobject_cast<WebEngineFrame *>(currentFrame)) {
0251             const QString newPrefix = QLatin1Char('T') + QString::number(i.key());
0252             if (currentFrame->saveConfig(config, newPrefix + QLatin1Char('_'))) {
0253                 strlst.append(newPrefix);
0254                 if (currentFrame == m_currentFrame) {
0255                     config.writeEntry(QStringLiteral("CurrentTab"), newPrefix);
0256                 }
0257             }
0258         }
0259     }
0260     config.writeEntry(QStringLiteral("Children"), strlst);
0261 }
0262 
0263 #include "moc_framemanager.cpp"