diff --git a/src/articleviewerwidget.cpp b/src/articleviewerwidget.cpp index 29110b67..ffce9fd4 100644 --- a/src/articleviewerwidget.cpp +++ b/src/articleviewerwidget.cpp @@ -1,423 +1,422 @@ /* This file is part of Akregator. Copyright (C) 2004 Teemu Rytilahti 2005 Frank Osterfeld This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "articleviewerwidget.h" #include "akregatorconfig.h" #include "aboutdata.h" #include "actionmanager.h" #include "actions.h" #include "article.h" #include "articleformatter.h" #include "articlejobs.h" #include "articlematcher.h" #include "feed.h" #include "folder.h" #include "treenode.h" #include "utils.h" #include "openurlrequest.h" #include "akregator_debug.h" #include "akregator-version.h" #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Akregator; using namespace Akregator::Filters; ArticleViewerWidget::ArticleViewerWidget(const QString &grantleeDirectory, KActionCollection *ac, QWidget *parent) : QWidget(parent), m_imageDir(QUrl::fromLocalFile(QString(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/akregator/Media/")))), m_node(0), m_viewMode(NormalView), m_articleViewerWidgetNg(new Akregator::ArticleViewerWebEngineWidgetNg(ac, this)), m_grantleeDirectory(grantleeDirectory) { QGridLayout *layout = new QGridLayout(this); layout->setMargin(0); layout->addWidget(m_articleViewerWidgetNg); m_articleHtmlWriter = new Akregator::ArticleHtmlWebEngineWriter(m_articleViewerWidgetNg->articleViewerNg(), this); connect(m_articleViewerWidgetNg->articleViewerNg(), &ArticleViewerWebEngine::signalOpenUrlRequest, this, &ArticleViewerWidget::signalOpenUrlRequest); connect(m_articleViewerWidgetNg->articleViewerNg(), &ArticleViewerWebEngine::showStatusBarMessage, this, &ArticleViewerWidget::showStatusBarMessage); } ArticleViewerWidget::~ArticleViewerWidget() { } QSharedPointer ArticleViewerWidget::normalViewFormatter() { if (!m_normalViewFormatter.data()) { m_normalViewFormatter = QSharedPointer(new DefaultNormalViewFormatter(m_grantleeDirectory, m_imageDir, m_articleViewerWidgetNg->articleViewerNg())); } return m_normalViewFormatter; } QSharedPointer ArticleViewerWidget::combinedViewFormatter() { if (!m_combinedViewFormatter.data()) { m_combinedViewFormatter = QSharedPointer(new DefaultCombinedViewFormatter(m_grantleeDirectory, m_imageDir, m_articleViewerWidgetNg->articleViewerNg())); } return m_combinedViewFormatter; } void ArticleViewerWidget::slotZoomChangeInFrame(qreal value) { m_articleViewerWidgetNg->articleViewerNg()->setZoomFactor(value); } void ArticleViewerWidget::slotCopy() { m_articleViewerWidgetNg->articleViewerNg()->slotCopy(); } void ArticleViewerWidget::slotSelectionChanged() { ActionManager::getInstance()->action(QStringLiteral("viewer_copy"))->setEnabled(!m_articleViewerWidgetNg->articleViewerNg()->selectedText().isEmpty()); } void ArticleViewerWidget::slotPrint() { m_articleViewerWidgetNg->slotPrint(); } void ArticleViewerWidget::slotPrintPreview() { m_articleViewerWidgetNg->slotPrintPreview(); } void ArticleViewerWidget::connectToNode(TreeNode *node) { if (node) { if (m_viewMode == CombinedView) { connect(node, &TreeNode::signalChanged, this, &ArticleViewerWidget::slotUpdateCombinedView); connect(node, &TreeNode::signalArticlesAdded, this, &ArticleViewerWidget::slotArticlesAdded); connect(node, &TreeNode::signalArticlesRemoved, this, &ArticleViewerWidget::slotArticlesRemoved); connect(node, &TreeNode::signalArticlesUpdated, this, &ArticleViewerWidget::slotArticlesUpdated); } else if (m_viewMode == SummaryView) { connect(node, &TreeNode::signalChanged, this, &ArticleViewerWidget::slotShowSummary); } connect(node, &TreeNode::signalDestroyed, this, &ArticleViewerWidget::slotClear); } } void ArticleViewerWidget::disconnectFromNode(TreeNode *node) { if (node) { node->disconnect(this); } } void ArticleViewerWidget::renderContent(const QString &text) { m_currentText = text; reload(); } void ArticleViewerWidget::beginWriting() { m_articleHtmlWriter->begin(); } void ArticleViewerWidget::endWriting() { m_articleHtmlWriter->end(); } void ArticleViewerWidget::slotShowSummary(TreeNode *node) { m_viewMode = SummaryView; if (!node) { slotClear(); return; } if (node != m_node) { disconnectFromNode(m_node); connectToNode(node); m_node = node; } const QString summary = normalViewFormatter()->formatSummary(node); m_link.clear(); renderContent(summary); setArticleActionsEnabled(false); } void ArticleViewerWidget::showArticle(const Akregator::Article &article) { if (article.isNull() || article.isDeleted()) { slotClear(); return; } m_viewMode = NormalView; disconnectFromNode(m_node); m_article = article; m_node = 0; m_link = article.link(); if (article.feed()->loadLinkedWebsite()) { openUrl(article.link()); } else { renderContent(normalViewFormatter()->formatArticles(QVector() << article, ArticleFormatter::ShowIcon)); } setArticleActionsEnabled(true); } bool ArticleViewerWidget::openUrl(const QUrl &url) { if (!m_article.isNull() && m_article.feed()->loadLinkedWebsite()) { m_articleViewerWidgetNg->articleViewerNg()->load(url); } else { reload(); } return true; } void ArticleViewerWidget::setFilters(const std::vector< QSharedPointer > &filters) { if (filters == m_filters) { return; } m_filters = filters; slotUpdateCombinedView(); } void ArticleViewerWidget::slotUpdateCombinedView() { if (m_viewMode != CombinedView) { return; } if (!m_node) { return slotClear(); } m_articleViewerWidgetNg->saveCurrentPosition(); QString text; int num = 0; QTime spent; spent.start(); const std::vector< QSharedPointer >::const_iterator filterEnd = m_filters.cend(); QVector
articles; for (const Article &i : qAsConst(m_articles)) { if (i.isDeleted()) { continue; } auto func = [i](const QSharedPointer &matcher) -> bool { return !matcher->matches(i); }; if (std::find_if(m_filters.cbegin(), filterEnd, func) != filterEnd) { continue; } articles << i; ++num; } text = combinedViewFormatter()->formatArticles(articles, ArticleFormatter::NoIcon); qCDebug(AKREGATOR_LOG) << "Combined view rendering: (" << num << " articles):" << "generating HTML:" << spent.elapsed() << "ms"; renderContent(text); qCDebug(AKREGATOR_LOG) << "HTML rendering:" << spent.elapsed() << "ms"; } void ArticleViewerWidget::slotArticlesUpdated(TreeNode * /*node*/, const QVector
& /*list*/) { if (m_viewMode == CombinedView) { //TODO slotUpdateCombinedView(); } } void ArticleViewerWidget::slotArticlesAdded(TreeNode * /*node*/, const QVector
&list) { if (m_viewMode == CombinedView) { //TODO sort list, then merge m_articles << list; std::sort(m_articles.begin(), m_articles.end()); slotUpdateCombinedView(); } } void ArticleViewerWidget::slotArticlesRemoved(TreeNode * /*node*/, const QVector
&list) { Q_UNUSED(list) if (m_viewMode == CombinedView) { //TODO slotUpdateCombinedView(); } } void ArticleViewerWidget::slotClear() { disconnectFromNode(m_node); m_node = 0; m_article = Article(); m_articles.clear(); renderContent(QString()); } void ArticleViewerWidget::showNode(TreeNode *node) { m_viewMode = CombinedView; if (node != m_node) { disconnectFromNode(m_node); } connectToNode(node); m_articles.clear(); m_article = Article(); m_node = node; delete m_listJob; m_listJob = node->createListJob(); connect(m_listJob.data(), &ArticleListJob::finished, this, &ArticleViewerWidget::slotArticlesListed); m_listJob->start(); slotUpdateCombinedView(); } qreal ArticleViewerWidget::zoomFactor() const { return m_articleViewerWidgetNg->articleViewerNg()->zoomFactor(); } void ArticleViewerWidget::slotArticlesListed(KJob *job) { Q_ASSERT(job); Q_ASSERT(job == m_listJob); TreeNode *node = m_listJob->node(); if (job->error() || !node) { if (!node) { qCWarning(AKREGATOR_LOG) << "Node to be listed is already deleted"; } else { qCWarning(AKREGATOR_LOG) << job->errorText(); } slotUpdateCombinedView(); return; } m_articles = m_listJob->articles(); std::sort(m_articles.begin(), m_articles.end()); if (node && !m_articles.isEmpty()) { m_link = m_articles.first().link(); } else { m_link = QUrl(); } slotUpdateCombinedView(); } void ArticleViewerWidget::keyPressEvent(QKeyEvent *e) { e->ignore(); } void ArticleViewerWidget::updateAfterConfigChanged() { switch (m_viewMode) { case NormalView: if (!m_article.isNull()) { renderContent(normalViewFormatter()->formatArticles(QVector() << m_article, ArticleFormatter::ShowIcon)); } break; case CombinedView: slotUpdateCombinedView(); break; case SummaryView: slotShowSummary(m_node); break; } } void ArticleViewerWidget::reload() { beginWriting(); m_articleHtmlWriter->queue(m_currentText); endWriting(); } QSize ArticleViewerWidget::sizeHint() const { // Increase height a bit so that we can (roughly) read 25 lines of text QSize sh = QWidget::sizeHint(); sh.setHeight(qMax(sh.height(), 25 * fontMetrics().height())); return sh; } void ArticleViewerWidget::displayAboutPage() { m_articleViewerWidgetNg->articleViewerNg()->showAboutPage(); } void ArticleViewerWidget::setArticleActionsEnabled(bool enabled) { ActionManager::getInstance()->setArticleActionsEnabled(enabled); } Akregator::ArticleViewerWebEngineWidgetNg *ArticleViewerWidget::articleViewerWidgetNg() const { return m_articleViewerWidgetNg; } diff --git a/src/frame/frame.cpp b/src/frame/frame.cpp index fc2a0b9b..59630094 100644 --- a/src/frame/frame.cpp +++ b/src/frame/frame.cpp @@ -1,210 +1,208 @@ /* This file is part of Akregator. Copyright (C) 2004 Sashmit Bhaduri This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "frame.h" #include "utils.h" #include #include #include #include "akregator_debug.h" #include #include -#include -#include #include using namespace Akregator; Frame::Frame(QWidget *parent) : QWidget(parent) { m_title = i18n("Untitled"); m_state = Idle; m_progress = -1; m_progressItem = 0; m_isRemovable = true; m_loading = false; m_id = m_idCounter++; } void Frame::slotSetTitle(const QString &s) { if (m_title != s) { m_title = s; Q_EMIT signalTitleChanged(this, s); } } bool Frame::isLoading() const { return m_loading; } void Frame::slotSetCaption(const QString &s) { if (m_progressItem) { m_progressItem->setLabel(s); } m_caption = s; Q_EMIT signalCaptionChanged(this, s); } void Frame::slotSetStatusText(const QString &s) { m_statusText = s; m_statusText = Akregator::Utils::stripTags(m_statusText); Q_EMIT signalStatusText(this, m_statusText); } void Frame::slotSetProgress(int a) { if (m_progressItem) { m_progressItem->setProgress((int)a); } m_progress = a; Q_EMIT signalLoadingProgress(this, a); } void Frame::slotSetState(State state) { m_state = state; switch (m_state) { case Frame::Started: Q_EMIT signalStarted(this); break; case Frame::Canceled: Q_EMIT signalCanceled(this, QString()); break; case Frame::Idle: case Frame::Completed: default: Q_EMIT signalCompleted(this); } } int Frame::m_idCounter = 0; int Frame::id() const { return m_id; } void Frame::setRemovable(bool removable) { m_isRemovable = removable; } bool Frame::isRemovable() const { return m_isRemovable; } Frame::~Frame() { if (m_progressItem) { m_progressItem->setComplete(); } } Frame::State Frame::state() const { return m_state; } QString Frame::title() const { return m_title; } QString Frame::caption() const { return m_caption; } QString Frame::statusText() const { return m_statusText; } QIcon Frame::icon() const { return m_icon; } void Frame::setIcon(const QIcon &icon) { m_icon = icon; } void Frame::slotSetStarted() { m_loading = true; if (m_progressId.isNull() || m_progressId.isEmpty()) { m_progressId = KPIM::ProgressManager::getUniqueID(); } m_progressItem = KPIM::ProgressManager::createProgressItem(m_progressId, title(), QString(), false); m_progressItem->setStatus(i18n("Loading...")); m_state = Started; Q_EMIT signalStarted(this); } void Frame::slotStop() { if (m_loading) { m_loading = false; } } void Frame::slotSetCanceled(const QString &s) { m_loading = false; if (m_progressItem) { m_progressItem->setStatus(i18n("Loading canceled")); m_progressItem->setComplete(); m_progressItem = 0; } m_state = Canceled; Q_EMIT signalCanceled(this, s); } void Frame::slotSetCompleted() { m_loading = false; if (m_progressItem) { m_progressItem->setStatus(i18n("Loading completed")); m_progressItem->setComplete(); m_progressItem = 0; } m_state = Completed; Q_EMIT signalCompleted(this); } int Frame::progress() const { return m_progress; } diff --git a/src/frame/framemanager.cpp b/src/frame/framemanager.cpp index c20fb62b..100dedc6 100644 --- a/src/frame/framemanager.cpp +++ b/src/frame/framemanager.cpp @@ -1,292 +1,290 @@ /* This file is part of Akregator. Copyright (C) 2005 Frank Osterfeld This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "framemanager.h" #include "config-akregator.h" #include "akregatorconfig.h" #include "frame.h" #include "actionmanager.h" #include "openurlrequest.h" #include #include #include #include #include #include -#include -#include #include "akregator_debug.h" #include #include #include #include using namespace Akregator; FrameManager::FrameManager(QObject *parent) : QObject(parent), m_currentFrame(0) { } FrameManager::~FrameManager() { } Frame *FrameManager::currentFrame() const { return m_currentFrame; } void FrameManager::slotAddFrame(Frame *frame) { m_frames.insert(frame->id(), frame); connect(frame, &Frame::signalCanceled, this, &FrameManager::slotSetCanceled); connect(frame, &Frame::signalStarted, this, &FrameManager::slotSetStarted); connect(frame, &Frame::signalCaptionChanged, this, &FrameManager::slotSetCaption); connect(frame, &Frame::signalLoadingProgress, this, &FrameManager::slotSetProgress); connect(frame, &Frame::signalCompleted, this, &FrameManager::slotSetCompleted); connect(frame, &Frame::signalTitleChanged, this, &FrameManager::slotSetTitle); connect(frame, &Frame::signalStatusText, this, &FrameManager::slotSetStatusText); connect(frame, SIGNAL(signalOpenUrlRequest(Akregator::OpenUrlRequest&)), this, SLOT(slotOpenUrlRequest(Akregator::OpenUrlRequest&))); //setPartGuiActive(frame->part(), false); Q_EMIT signalFrameAdded(frame); if (m_frames.count() == 1) { slotChangeFrame(frame->id()); } } void FrameManager::slotRemoveFrame(int id) { Frame *frame = m_frames.value(id); if (!frame || !frame->isRemovable()) { return; } frame->disconnect(this); if (m_currentFrame == frame) { slotChangeFrame(-1); } m_frames.insert(id, 0); m_frames.remove(id); Q_EMIT signalFrameRemoved(id); delete frame; } Frame *FrameManager::findFrameById(int id) const { return m_frames.value(id); } void FrameManager::slotChangeFrame(int frameId) { Frame *frame = m_frames.value(frameId); if (frame == m_currentFrame) { return; } Frame *oldFrame = m_currentFrame; m_currentFrame = frame; //if (oldFrame) { // setPartGuiActive(oldFrame->part(), false); //} if (frame) { //setPartGuiActive(frame->part(), true); // TODO: handle removable flag switch (frame->state()) { case Frame::Started: Q_EMIT signalStarted(); break; case Frame::Canceled: Q_EMIT signalCanceled(QString()); break; case Frame::Idle: case Frame::Completed: default: Q_EMIT signalCompleted(); } Q_EMIT signalCaptionChanged(frame->caption()); Q_EMIT signalTitleChanged(frame->title()); Q_EMIT signalLoadingProgress(frame->progress()); Q_EMIT signalStatusText(frame->statusText()); } else { Q_EMIT signalCompleted(); Q_EMIT signalCaptionChanged(QString()); Q_EMIT signalTitleChanged(QString()); Q_EMIT signalLoadingProgress(100); Q_EMIT signalStatusText(QString()); } Q_EMIT signalCurrentFrameChanged(oldFrame, frame); } void FrameManager::slotSetStarted(Frame *frame) { if (frame == m_currentFrame) { Q_EMIT signalStarted(); } } void FrameManager::slotSetCanceled(Frame *frame, const QString &reason) { if (frame == m_currentFrame) { Q_EMIT signalCanceled(reason); } } void FrameManager::slotSetCompleted(Frame *frame) { if (frame == m_currentFrame) { Q_EMIT signalCompleted(); } } void FrameManager::slotSetProgress(Frame *frame, int progress) { if (frame == m_currentFrame) { Q_EMIT signalLoadingProgress(progress); } } void FrameManager::slotSetCaption(Frame *frame, const QString &caption) { if (frame == m_currentFrame) { Q_EMIT signalCaptionChanged(caption); } } void FrameManager::slotSetTitle(Frame *frame, const QString &title) { if (frame == m_currentFrame) { Q_EMIT signalTitleChanged(title); } } void FrameManager::slotSetStatusText(Frame *frame, const QString &statusText) { if (frame == m_currentFrame) { Q_EMIT signalStatusText(statusText); } } void FrameManager::openUrl(OpenUrlRequest &request) { if (request.browserArgs().newTab() || request.browserArgs().forcesNewWindow() || request.options() == OpenUrlRequest::NewTab || (m_currentFrame->id() == 0)) { int newFrameId = -1; Q_EMIT signalRequestNewFrame(newFrameId); request.setFrameId(newFrameId); } else { request.setFrameId(m_currentFrame->id()); } if (m_frames.contains(request.frameId())) { Frame *frame = m_frames.value(request.frameId()); if (frame->openUrl(request)) { request.setWasHandled(true); } } if (!request.openInBackground()) { Q_EMIT signalSelectFrame(request.frameId()); } } void FrameManager::openInExternalBrowser(const OpenUrlRequest &request) { QUrl url = request.url(); if (!url.isValid()) { return; } if (!Settings::externalBrowserUseKdeDefault()) { QHash map; map.insert(QLatin1Char('u'), url.url()); const QString cmd = KMacroExpander::expandMacrosShellQuote(Settings::externalBrowserCustomCommand(), map); const QStringList args = KShell::splitArgs(cmd); if (!args.isEmpty()) { KProcess::startDetached(args); return; } } if (request.args().mimeType().isEmpty()) { QDesktopServices::openUrl(url); } else { KRun::runUrl(url, request.args().mimeType(), 0 /*window*/, false, false); } } void FrameManager::slotOpenUrlRequest(OpenUrlRequest &request, bool useOpenInBackgroundSetting) { qCDebug(AKREGATOR_LOG) << "FrameManager::slotOpenUrlRequest():" << request.debugInfo(); if (request.options() == OpenUrlRequest::ExternalBrowser) { openInExternalBrowser(request); return; } if (useOpenInBackgroundSetting) { // Honour user's preference for foreground/background tabs if (request.options() == OpenUrlRequest::NewTab || request.browserArgs().newTab()) { request.setOpenInBackground(Settings::lMBBehaviour() == Settings::EnumLMBBehaviour::OpenInBackground); } } openUrl(request); } void FrameManager::saveProperties(KConfigGroup &config) { //write children QStringList strlst; QHash::const_iterator i; QHash::const_iterator end(m_frames.constEnd()); for (i = m_frames.constBegin(); i != end; ++i) { // No need to save the main frame Frame *currentFrame = i.value(); if (currentFrame && qobject_cast(currentFrame)) { QString newPrefix = QLatin1Char('T') + QString::number(i.key()); if (currentFrame->saveConfig(config, newPrefix + QLatin1Char('_'))) { strlst.append(newPrefix); if (currentFrame == m_currentFrame) { config.writeEntry(QStringLiteral("CurrentTab"), newPrefix); } } } } config.writeEntry(QStringLiteral("Children"), strlst); }