diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG index 23a6ad395..031c25a4a 100755 --- a/resources/text/CHANGELOG +++ b/resources/text/CHANGELOG @@ -1,6 +1,9 @@ 3.3.4 ————— +Added: +▪ RSS Guard now can be compiled WITHOUT QtWebEngine module. Minimal Qt required was also lowered to 5.6.0. + Changed: ▪ Big application core refactoring. Many functions rewritten, some bad code removed. diff --git a/rssguard.pro b/rssguard.pro index a0e50fef7..9c7d8e825 100755 --- a/rssguard.pro +++ b/rssguard.pro @@ -34,10 +34,14 @@ # make install # # Variables: +# USE_WEBENGINE - if specified, then QtWebEngine module for internal web browser is used. +# Otherwise simple text component is used and some features will be disabled. # PREFIX - specifies base folder to which files are copied during "make install" # step, defaults to "$$OUT_PWD/usr" on Linux and to "$$OUT_PWD/app" on Windows. # LRELEASE_EXECUTABLE - specifies the name/path of "lrelease" executable, defaults to "lrelease". # +# +# # Other information: # - supports Windows, Linux, Mac OS X, # - Qt 5.7 and higher is required, @@ -96,6 +100,10 @@ isEmpty(DESTDIR) { } } +isEmpty(USE_WEBENGINE) { + USE_WEBENGINE = true +} + message(rssguard: Shadow copy build directory \"$$OUT_PWD\".) isEmpty(LRELEASE_EXECUTABLE) { @@ -140,7 +148,7 @@ message(rssguard: Prefix directory: \"$$PREFIX\".) message(rssguard: Build revision: \"$$APP_REVISION\".) message(rssguard: lrelease executable name: \"$$LRELEASE_EXECUTABLE\".) -QT += core gui widgets webenginewidgets sql network xml printsupport +QT += core gui widgets sql network xml printsupport # webenginewidgets CONFIG *= c++11 debug_and_release warn_on DEFINES *= QT_USE_QSTRINGBUILDER QT_USE_FAST_CONCATENATION QT_USE_FAST_OPERATOR_PLUS UNICODE _UNICODE VERSION = $$APP_VERSION @@ -149,6 +157,15 @@ MOC_DIR = $$OUT_PWD/moc RCC_DIR = $$OUT_PWD/rcc UI_DIR = $$OUT_PWD/ui +equals(USE_WEBENGINE, true) { + message(rssguard: Application will be compiled WITH QtWebEngine module.) + QT += webenginewidgets + DEFINES += USE_WEBENGINE +} +else { + message(rssguard: Application will be compiled without QtWebEngine module. Some features will be disabled.) +} + # Make needed tweaks for RC file getting generated on Windows. win32 { RC_ICONS = resources/graphics/rssguard.ico @@ -265,12 +282,6 @@ HEADERS += src/core/feeddownloader.h \ src/services/tt-rss/ttrssrecyclebin.h \ src/services/tt-rss/ttrssserviceentrypoint.h \ src/services/tt-rss/ttrssserviceroot.h \ - src/gui/webviewer.h \ - src/gui/webbrowser.h \ - src/network-web/webpage.h \ - src/gui/locationlineedit.h \ - src/network-web/googlesuggest.h \ - src/gui/discoverfeedsbutton.h \ src/gui/settings/settingspanel.h \ src/gui/settings/settingsgeneral.h \ src/gui/settings/settingsdatabase.h \ @@ -386,12 +397,6 @@ SOURCES += src/core/feeddownloader.cpp \ src/services/tt-rss/ttrssrecyclebin.cpp \ src/services/tt-rss/ttrssserviceentrypoint.cpp \ src/services/tt-rss/ttrssserviceroot.cpp \ - src/gui/webviewer.cpp \ - src/gui/webbrowser.cpp \ - src/network-web/webpage.cpp \ - src/gui/locationlineedit.cpp \ - src/network-web/googlesuggest.cpp \ - src/gui/discoverfeedsbutton.cpp \ src/gui/settings/settingspanel.cpp \ src/gui/settings/settingsgeneral.cpp \ src/gui/settings/settingsdatabase.cpp \ @@ -428,6 +433,34 @@ FORMS += src/gui/toolbareditor.ui \ src/gui/settings/settingsfeedsmessages.ui \ src/gui/settings/settingsdownloads.ui +equals(USE_WEBENGINE, true) { + HEADERS += src/gui/locationlineedit.h \ + src/gui/webviewer.h \ + src/gui/webbrowser.h \ + src/gui/discoverfeedsbutton.h \ + src/network-web/googlesuggest.h \ + src/network-web/webpage.h + + SOURCES += src/gui/locationlineedit.cpp \ + src/gui/webviewer.cpp \ + src/gui/webbrowser.cpp \ + src/gui/discoverfeedsbutton.cpp \ + src/network-web/googlesuggest.cpp \ + src/network-web/webpage.cpp +} +else { + HEADERS += src/gui/messagepreviewer.h \ + src/gui/messagetextbrowser.h \ + src/gui/newspaperpreviewer.h + + SOURCES += src/gui/messagepreviewer.cpp \ + src/gui/messagetextbrowser.cpp \ + src/gui/newspaperpreviewer.cpp + + FORMS += src/gui/messagepreviewer.ui \ + src/gui/newspaperpreviewer.ui +} + TRANSLATIONS += localization/qtbase-cs.ts \ localization/qtbase-da.ts \ localization/qtbase-de.ts \ diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index c0ca29790..e7231c8b7 100755 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -88,17 +88,19 @@ void MessagesModel::loadMessages(RootItem *item) { } bool MessagesModel::setMessageImportantById(int id, RootItem::Importance important) { + Q_UNUSED(important) + for (int i = 0; i < rowCount(); i++) { int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); if (found_id == id) { - bool set = setData(index(i, MSG_DB_IMPORTANT_INDEX), important); + bool result; - if (set) { + if (result = switchMessageImportance(i)) { emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); } - return set; + return result; } } @@ -285,13 +287,13 @@ bool MessagesModel::setMessageReadById(int id, RootItem::ReadStatus read) { int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); if (found_id == id) { - bool set = setData(index(i, MSG_DB_READ_INDEX), read); + bool result; - if (set) { + if (result = setMessageRead(i, read)) { emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); } - return set; + return result; } } diff --git a/src/gui/dialogs/formmain.cpp b/src/gui/dialogs/formmain.cpp index a8d40602b..2d17084bf 100755 --- a/src/gui/dialogs/formmain.cpp +++ b/src/gui/dialogs/formmain.cpp @@ -173,7 +173,11 @@ QList FormMain::allActions() const { actions << m_ui->m_actionSelectPreviousMessage; actions << m_ui->m_actionSelectNextUnreadMessage; actions << m_ui->m_actionExpandCollapseItem; + +#if defined(USE_WEBENGINE) actions << m_ui->m_actionTabNewWebBrowser; +#endif + actions << m_ui->m_actionTabsCloseAll; actions << m_ui->m_actionTabsCloseAllExceptCurrent; @@ -200,6 +204,11 @@ void FormMain::prepareMenus() { qDebug("Creating tray icon menu."); } + +#if !defined(USE_WEBENGINE) + m_ui->m_menuWebBrowserTabs->removeAction(m_ui->m_actionTabNewWebBrowser); + m_ui->m_menuWebBrowserTabs->setTitle(tr("Tabs")); +#endif } void FormMain::switchFullscreenMode() { diff --git a/src/gui/feedmessageviewer.cpp b/src/gui/feedmessageviewer.cpp index 108774c91..232b95f09 100755 --- a/src/gui/feedmessageviewer.cpp +++ b/src/gui/feedmessageviewer.cpp @@ -37,11 +37,17 @@ #include "gui/messagebox.h" #include "gui/messagestoolbar.h" #include "gui/feedstoolbar.h" -#include "gui/webbrowser.h" + #include "gui/dialogs/formdatabasecleanup.h" #include "gui/dialogs/formmain.h" #include "exceptions/applicationexception.h" +#if defined(USE_WEBENGINE) +#include "gui/webbrowser.h" +#else +#include "gui/messagepreviewer.h" +#endif + #include #include #include @@ -65,7 +71,11 @@ FeedMessageViewer::FeedMessageViewer(QWidget *parent) m_toolBarMessages(new MessagesToolBar(tr("Toolbar for messages"), this)), m_messagesView(new MessagesView(this)), m_feedsView(new FeedsView(this)), +#if defined(USE_WEBENGINE) m_messagesBrowser(new WebBrowser(this)) { +#else + m_messagesBrowser(new MessagePreviewer(this)) { +#endif initialize(); initializeViews(); loadMessageViewerFonts(); @@ -76,9 +86,11 @@ FeedMessageViewer::~FeedMessageViewer() { qDebug("Destroying FeedMessageViewer instance."); } +#if defined(USE_WEBENGINE) WebBrowser *FeedMessageViewer::webBrowser() const { return m_messagesBrowser; } +#endif FeedsView *FeedMessageViewer::feedsView() const { return m_feedsView; @@ -200,11 +212,12 @@ void FeedMessageViewer::createConnections() { // Message changers. connect(m_messagesView, SIGNAL(currentMessageRemoved()), m_messagesBrowser, SLOT(clear())); connect(m_messagesView, SIGNAL(currentMessageChanged(Message,RootItem*)), m_messagesBrowser, SLOT(loadMessage(Message,RootItem*))); + connect(m_messagesBrowser, SIGNAL(markMessageRead(int,RootItem::ReadStatus)), m_messagesView->sourceModel(), SLOT(setMessageReadById(int,RootItem::ReadStatus))); connect(m_messagesBrowser, SIGNAL(markMessageImportant(int,RootItem::Importance)), m_messagesView->sourceModel(), SLOT(setMessageImportantById(int,RootItem::Importance))); - + // If user selects feeds, load their messages. connect(m_feedsView, SIGNAL(itemSelected(RootItem*)), m_messagesView, SLOT(loadItem(RootItem*))); diff --git a/src/gui/feedmessageviewer.h b/src/gui/feedmessageviewer.h index a2d117324..bd3623a99 100755 --- a/src/gui/feedmessageviewer.h +++ b/src/gui/feedmessageviewer.h @@ -24,8 +24,12 @@ #include - +#if defined(USE_WEBENGINE) class WebBrowser; +#else +class MessagePreviewer; +#endif + class MessagesView; class MessagesToolBar; class FeedsToolBar; @@ -44,7 +48,10 @@ class FeedMessageViewer : public TabContent { explicit FeedMessageViewer(QWidget *parent = 0); virtual ~FeedMessageViewer(); +#if defined(USE_WEBENGINE) WebBrowser *webBrowser() const; +#endif + FeedsView *feedsView() const; MessagesView *messagesView() const; MessagesToolBar *messagesToolBar() const; @@ -102,7 +109,12 @@ class FeedMessageViewer : public TabContent { FeedsView *m_feedsView; QWidget *m_feedsWidget; QWidget *m_messagesWidget; + +#if defined(USE_WEBENGINE) WebBrowser *m_messagesBrowser; +#else + MessagePreviewer *m_messagesBrowser; +#endif }; #endif // FEEDMESSAGEVIEWER_H diff --git a/src/gui/messagepreviewer.cpp b/src/gui/messagepreviewer.cpp new file mode 100755 index 000000000..59ccb8af8 --- /dev/null +++ b/src/gui/messagepreviewer.cpp @@ -0,0 +1,192 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2016 by Martin Rotter +// +// RSS Guard 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 3 of the License, or +// (at your option) any later version. +// +// RSS Guard 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 RSS Guard. If not, see . + +#include "gui/messagepreviewer.h" + +#include "miscellaneous/application.h" +#include "network-web/webfactory.h" +#include "miscellaneous/databasequeries.h" +#include "gui/messagebox.h" +#include "gui/dialogs/formmain.h" +#include "services/abstract/serviceroot.h" + +#include +#include +#include + + +void MessagePreviewer::createConnections() { + connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [=](const QUrl &url) { + if (!url.isEmpty()) { + // User clicked some URL. Open it in external browser or download? + MessageBox box(qApp->mainForm()); + + box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser.")); + box.setInformativeText(tr("What action do you want to take?")); + box.setDetailedText(url.toString()); + QAbstractButton *btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole); + QAbstractButton *btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole); + QAbstractButton *btn_cancel = box.addButton(QMessageBox::Cancel); + + box.setDefaultButton(QMessageBox::Cancel); + box.exec(); + + if (box.clickedButton() == btn_open) { + WebFactory::instance()->openUrlInExternalBrowser(url.toString()); + } + else if (box.clickedButton() == btn_download) { + qApp->downloadManager()->download(url); + } + + btn_download->deleteLater(); + btn_open->deleteLater(); + btn_cancel->deleteLater(); + } + else { + MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"), + tr("Selected hyperlink is invalid.")); + } + }); + connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")), + &QAction::triggered, + this, + &MessagePreviewer::markMessageAsRead); + connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")), + &QAction::triggered, + this, + &MessagePreviewer::markMessageAsUnread); + connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")), + &QAction::triggered, + this, + &MessagePreviewer::switchMessageImportance); + connect(m_ui->m_txtMessage, + static_cast(&QTextBrowser::highlighted), + [=](const QString &text) { + Q_UNUSED(text) + + QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this); + }); +} + +MessagePreviewer::MessagePreviewer(QWidget *parent) : QWidget(parent), + m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) { + m_ui->setupUi(this); + m_ui->m_txtMessage->viewport()->setAutoFillBackground(true); + m_toolBar = new QToolBar(this); + m_toolBar->setOrientation(Qt::Vertical); + m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1); + + createConnections(); + + m_actionSwitchImportance->setCheckable(true); + + reloadFontSettings(); + clear(); +} + +MessagePreviewer::~MessagePreviewer() { +} + +void MessagePreviewer::reloadFontSettings() { + const Settings *settings = qApp->settings(); + QFont fon; + + fon.fromString(settings->value(GROUP(Messages), + SETTING(Messages::PreviewerFontStandard)).toString()); + + m_ui->m_txtMessage->setFont(fon); +} + +void MessagePreviewer::clear() { + m_ui->m_txtMessage->clear(); + m_pictures.clear(); + hide(); +} + +void MessagePreviewer::hideToolbar() { + m_toolBar->setVisible(false); +} + +void MessagePreviewer::loadMessage(const Message &message, RootItem *root) { + m_message = message; + m_root = root; + + if (!m_root.isNull()) { + m_actionSwitchImportance->setChecked(m_message.m_isImportant); + m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message)); + + updateButtons(); + show(); + + m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum); + } +} + +void MessagePreviewer::markMessageAsRead() { + if (!m_root.isNull()) { + emit markMessageRead(m_message.m_id, RootItem::Read); + m_message.m_isRead = true; + updateButtons(); + } +} + +void MessagePreviewer::markMessageAsUnread() { + if (!m_root.isNull()) { + emit markMessageRead(m_message.m_id, RootItem::Unread); + m_message.m_isRead = false; + updateButtons(); + } +} + +void MessagePreviewer::switchMessageImportance(bool checked) { + if (!m_root.isNull()) { + emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant); + m_message.m_isImportant = checked; + } +} + +void MessagePreviewer::updateButtons() { + m_actionMarkRead->setEnabled(!m_message.m_isRead); + m_actionMarkUnread->setEnabled(m_message.m_isRead); +} + +QString MessagePreviewer::prepareHtmlForMessage(const Message &message) { + QString html = QString("

%1

").arg(message.m_title); + + html += QString("[url] %1
").arg(message.m_url); + + foreach (const Enclosure &enc, message.m_enclosures) { + html += QString("[%2] %1
").arg(enc.m_url, enc.m_mimeType); + } + + int offset = 0; + QRegExp imgTagRegex("\\]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); + + imgTagRegex.setMinimal(true); + + while( (offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1){ + m_pictures.append(imgTagRegex.cap(1)); + + offset += imgTagRegex.matchedLength(); + html += QString("[%2] %1
").arg(imgTagRegex.cap(1), tr("image")); + } + + html += "
"; + html += message.m_contents; + + return html; +} diff --git a/src/gui/messagepreviewer.h b/src/gui/messagepreviewer.h new file mode 100755 index 000000000..35f8fedd8 --- /dev/null +++ b/src/gui/messagepreviewer.h @@ -0,0 +1,77 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2016 by Martin Rotter +// +// RSS Guard 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 3 of the License, or +// (at your option) any later version. +// +// RSS Guard 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 RSS Guard. If not, see . + +#ifndef MESSAGEPREVIEWER_H +#define MESSAGEPREVIEWER_H + +#include + +#include "ui_messagepreviewer.h" + +#include "core/message.h" +#include "services/abstract/rootitem.h" + +#include + + +namespace Ui { + class MessagePreviewer; +} + +class QToolBar; + +class MessagePreviewer : public QWidget { + Q_OBJECT + + public: + explicit MessagePreviewer(QWidget *parent = 0); + virtual ~MessagePreviewer(); + + void reloadFontSettings(); + + public slots: + void clear(); + void hideToolbar(); + void loadMessage(const Message &message, RootItem *root); + + private slots: + void markMessageAsRead(); + void markMessageAsUnread(); + void switchMessageImportance(bool checked); + + signals: + void markMessageRead(int id, RootItem::ReadStatus read); + void markMessageImportant(int id, RootItem::Importance important); + void requestMessageListReload(bool mark_current_as_read); + + private: + void createConnections(); + void updateButtons(); + QString prepareHtmlForMessage(const Message &message); + + QToolBar *m_toolBar; + QScopedPointer m_ui; + Message m_message; + QStringList m_pictures; + QPointer m_root; + + QAction *m_actionMarkRead; + QAction *m_actionMarkUnread; + QAction *m_actionSwitchImportance; +}; + +#endif // MESSAGEPREVIEWER_H diff --git a/src/gui/messagepreviewer.ui b/src/gui/messagepreviewer.ui new file mode 100755 index 000000000..2fc7b7604 --- /dev/null +++ b/src/gui/messagepreviewer.ui @@ -0,0 +1,56 @@ + + + MessagePreviewer + + + + 0 + 0 + 502 + 396 + + + + + + + true + + + + 0 + + + 0 + + + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + true + + + false + + + + + + + + MessageTextBrowser + QTextBrowser +
messagetextbrowser.h
+
+
+ + +
diff --git a/src/gui/messagesview.cpp b/src/gui/messagesview.cpp index 49f1001b8..f8712afee 100755 --- a/src/gui/messagesview.cpp +++ b/src/gui/messagesview.cpp @@ -25,7 +25,7 @@ #include "network-web/webfactory.h" #include "gui/dialogs/formmain.h" #include "gui/messagebox.h" -#include "gui/webbrowser.h" + #include "gui/styleditemdelegatewithoutfocus.h" #include @@ -194,7 +194,9 @@ void MessagesView::mousePressEvent(QMouseEvent *event) { const QModelIndex mapped_index = m_proxyModel->mapToSource(clicked_index); if (mapped_index.column() == MSG_DB_IMPORTANT_INDEX) { - m_sourceModel->switchMessageImportance(mapped_index.row()); + if (m_sourceModel->switchMessageImportance(mapped_index.row())) { + emit currentMessageChanged(m_sourceModel->messageAt(mapped_index.row()), m_sourceModel->loadedItem()); + } } } @@ -502,17 +504,6 @@ void MessagesView::filterMessages(MessagesModel::MessageHighlighter filter) { m_sourceModel->highlightMessages(filter); } -void MessagesView::createNewspaperView(RootItem *selected_item, const QList &messages) { - WebBrowser *prev = new WebBrowser(this); - int index = qApp->mainForm()->tabWidget()->addTab(prev, - qApp->icons()->fromTheme(QSL("text-x-script")), - tr("Newspaper view"), - TabBar::Closable); - - qApp->mainForm()->tabWidget()->setCurrentIndex(index); - prev->loadMessages(messages, selected_item); -} - void MessagesView::adjustColumns() { if (header()->count() > 0 && !m_columnsAdjusted) { m_columnsAdjusted = true; diff --git a/src/gui/messagesview.h b/src/gui/messagesview.h index f553f511b..5c5f66bec 100755 --- a/src/gui/messagesview.h +++ b/src/gui/messagesview.h @@ -78,8 +78,6 @@ class MessagesView : public QTreeView { void searchMessages(const QString &pattern); void filterMessages(MessagesModel::MessageHighlighter filter); - void createNewspaperView(RootItem *selected_item, const QList &messages); - private slots: // Marks given indexes as selected. void reselectIndexes(const QModelIndexList &indexes); diff --git a/src/gui/messagetextbrowser.cpp b/src/gui/messagetextbrowser.cpp new file mode 100755 index 000000000..9e7dd7441 --- /dev/null +++ b/src/gui/messagetextbrowser.cpp @@ -0,0 +1,35 @@ +#include "gui/messagetextbrowser.h" + +#include "miscellaneous/application.h" +#include "miscellaneous/iconfactory.h" +#include "network-web/networkfactory.h" + + +MessageTextBrowser::MessageTextBrowser(QWidget *parent) : QTextBrowser(parent) { +} + +MessageTextBrowser::~MessageTextBrowser() { +} + +QVariant MessageTextBrowser::loadResource(int type, const QUrl &name) { + Q_UNUSED(name) + + switch (type) { + case QTextDocument::ImageResource: { + if (m_imagePlaceholder.isNull()) { + m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation); + } + + emit imageRequested(name.toString()); + return m_imagePlaceholder; + } + + default: + return QVariant(); + } +} + +void MessageTextBrowser::wheelEvent(QWheelEvent *e) { + QTextBrowser::wheelEvent(e); + qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString()); +} diff --git a/src/gui/messagetextbrowser.h b/src/gui/messagetextbrowser.h new file mode 100755 index 000000000..92f74a422 --- /dev/null +++ b/src/gui/messagetextbrowser.h @@ -0,0 +1,27 @@ +#ifndef MESSAGETEXTBROWSER_H +#define MESSAGETEXTBROWSER_H + +#include + + + +class MessageTextBrowser : public QTextBrowser { + Q_OBJECT + + public: + explicit MessageTextBrowser(QWidget *parent = 0); + virtual ~MessageTextBrowser(); + + QVariant loadResource(int type, const QUrl &name); + + signals: + void imageRequested(const QString &image_url); + + protected: + void wheelEvent(QWheelEvent *e); + + private: + QPixmap m_imagePlaceholder; +}; + +#endif // MESSAGETEXTBROWSER_H diff --git a/src/gui/newspaperpreviewer.cpp b/src/gui/newspaperpreviewer.cpp new file mode 100755 index 000000000..a289b069e --- /dev/null +++ b/src/gui/newspaperpreviewer.cpp @@ -0,0 +1,66 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2016 by Martin Rotter +// +// RSS Guard 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 3 of the License, or +// (at your option) any later version. +// +// RSS Guard 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 RSS Guard. If not, see . + +#include "gui/newspaperpreviewer.h" + +#include "gui/messagepreviewer.h" +#include "gui/dialogs/formmain.h" +#include "miscellaneous/application.h" + +#include + + +NewspaperPreviewer::NewspaperPreviewer(RootItem *root, QList messages, QWidget *parent) + : TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) { + m_ui->setupUi(this); + connect(m_ui->m_btnShowMoreMessages, SIGNAL(clicked(bool)), this, SLOT(showMoreMessages())); + showMoreMessages(); +} + +NewspaperPreviewer::~NewspaperPreviewer() { +} + +void NewspaperPreviewer::showMoreMessages() { + if (!m_root.isNull()) { + int current_scroll = m_ui->scrollArea->verticalScrollBar()->value(); + + for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) { + Message msg = m_messages.takeFirst(); + MessagePreviewer *prev = new MessagePreviewer(this); + QMargins margins = prev->layout()->contentsMargins(); + + connect(prev, SIGNAL(requestMessageListReload(bool)), this, SIGNAL(requestMessageListReload(bool))); + + margins.setRight(0); + prev->hideToolbar(); + prev->layout()->setContentsMargins(margins); + prev->setFixedHeight(300); + prev->loadMessage(msg, m_root); + m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev); + } + + m_ui->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size())); + m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty()); + m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll); + } + else { + qApp->showGuiMessage(tr("Cannot show more messages"), + tr("Cannot show more messages because parent feed was removed."), + QSystemTrayIcon::Warning, + qApp->mainForm(), true); + } +} diff --git a/src/gui/newspaperpreviewer.h b/src/gui/newspaperpreviewer.h new file mode 100755 index 000000000..253201659 --- /dev/null +++ b/src/gui/newspaperpreviewer.h @@ -0,0 +1,58 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2016 by Martin Rotter +// +// RSS Guard 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 3 of the License, or +// (at your option) any later version. +// +// RSS Guard 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 RSS Guard. If not, see . + +#ifndef NEWSPAPERPREVIEWER_H +#define NEWSPAPERPREVIEWER_H + +#include + +#include "gui/tabcontent.h" + +#include "ui_newspaperpreviewer.h" + +#include "core/message.h" +#include "services/abstract/rootitem.h" + +#include + + +namespace Ui { + class NewspaperPreviewer; +} + +class RootItem; + +class NewspaperPreviewer : public TabContent { + Q_OBJECT + + public: + explicit NewspaperPreviewer(RootItem *root, QList messages, QWidget *parent = 0); + virtual ~NewspaperPreviewer(); + + private slots: + void showMoreMessages(); + + signals: + void requestMessageListReload(bool mark_current_as_read); + + private: + QScopedPointer m_ui; + QPointer m_root; + QList m_messages; +}; + +#endif // NEWSPAPERPREVIEWER_H diff --git a/src/gui/newspaperpreviewer.ui b/src/gui/newspaperpreviewer.ui new file mode 100755 index 000000000..6dfc2f57b --- /dev/null +++ b/src/gui/newspaperpreviewer.ui @@ -0,0 +1,102 @@ + + + NewspaperPreviewer + + + + 0 + 0 + 400 + 300 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + + 0 + 0 + 398 + 298 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 246 + + + + + + + + + + + + + diff --git a/src/gui/tabcontent.h b/src/gui/tabcontent.h index 06a3af685..57172dd50 100755 --- a/src/gui/tabcontent.h +++ b/src/gui/tabcontent.h @@ -20,8 +20,9 @@ #include - +#if defined(USE_WEBENGINE) class WebBrowser; +#endif // Base class for all widgets which are placed inside tabs of TabWidget class TabContent : public QWidget { @@ -43,9 +44,11 @@ class TabContent : public QWidget { m_index = index; } +#if defined(USE_WEBENGINE) // Obtains instance contained in this TabContent or nullptr. // This can be used for obtaining the menu from the instance and so on. virtual WebBrowser *webBrowser() const = 0; +#endif protected: int m_index; diff --git a/src/gui/tabwidget.cpp b/src/gui/tabwidget.cpp index 8c91c6084..23d7db777 100755 --- a/src/gui/tabwidget.cpp +++ b/src/gui/tabwidget.cpp @@ -26,10 +26,17 @@ #include "gui/messagesview.h" #include "gui/feedsview.h" #include "gui/feedmessageviewer.h" -#include "gui/webbrowser.h" + #include "gui/plaintoolbutton.h" #include "gui/dialogs/formmain.h" +#if defined(USE_WEBENGINE) +#include "gui/webbrowser.h" +#else +#include "network-web/webfactory.h" +#include "gui/newspaperpreviewer.h" +#endif + #include #include @@ -200,11 +207,19 @@ void TabWidget::closeAllTabs() { } int TabWidget::addNewspaperView(RootItem *root, const QList &messages) { +#if defined(USE_WEBENGINE) WebBrowser *prev = new WebBrowser(this); +#else + NewspaperPreviewer *prev = new NewspaperPreviewer(root, messages, this); +#endif + int index = addTab(prev, qApp->icons()->fromTheme(QSL("format-justify-fill")), tr("Newspaper view"), TabBar::Closable); setCurrentIndex(index); + +#if defined(USE_WEBENGINE) prev->loadMessages(messages, root); +#endif return index; } @@ -222,6 +237,8 @@ int TabWidget::addLinkedBrowser(const QString &initial_url) { } int TabWidget::addBrowser(bool move_after_current, bool make_active, const QUrl &initial_url) { +#if defined(USE_WEBENGINE) + // Create new WebBrowser. WebBrowser *browser = new WebBrowser(this); int final_index; @@ -258,6 +275,14 @@ int TabWidget::addBrowser(bool move_after_current, bool make_active, const QUrl } return final_index; +#else + Q_UNUSED(move_after_current) + Q_UNUSED(make_active) + + WebFactory::instance()->openUrlInExternalBrowser(initial_url.toString()); + + return -1; +#endif } void TabWidget::removeTab(int index, bool clear_from_memory) { diff --git a/src/gui/webbrowser.cpp b/src/gui/webbrowser.cpp index c9abb4584..6f3e21862 100755 --- a/src/gui/webbrowser.cpp +++ b/src/gui/webbrowser.cpp @@ -262,19 +262,8 @@ void WebBrowser::markMessageAsRead(int id, bool read) { if (!m_root.isNull()) { Message *msg = findMessage(id); - if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), - QList() << *msg, - read ? RootItem::Read : RootItem::Unread)) { - DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(msg->m_id), - read ? RootItem::Read : RootItem::Unread); - m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), - QList() << *msg, - read ? RootItem::Read : RootItem::Unread); - - emit markMessageRead(msg->m_id, read ? RootItem::Read : RootItem::Unread); - msg->m_isRead = read ? RootItem::Read : RootItem::Unread; - } + emit markMessageRead(msg->m_id, read ? RootItem::Read : RootItem::Unread); + msg->m_isRead = read ? RootItem::Read : RootItem::Unread; } } @@ -282,23 +271,8 @@ void WebBrowser::switchMessageImportance(int id, bool checked) { if (!m_root.isNull()) { Message *msg = findMessage(id); - if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(*msg, - msg->m_isImportant ? - RootItem::NotImportant : - RootItem::Important))) { - DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(msg->m_id)); - - m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(*msg, - msg->m_isImportant ? - RootItem::NotImportant : - RootItem::Important)); - - emit markMessageImportant(msg->m_id, msg->m_isImportant ? RootItem::NotImportant : RootItem::Important); - msg->m_isImportant = checked; - } + emit markMessageImportant(msg->m_id, msg->m_isImportant ? RootItem::NotImportant : RootItem::Important); + msg->m_isImportant = checked; } } diff --git a/src/gui/webviewer.cpp b/src/gui/webviewer.cpp index 9be6fc20c..2c639c569 100755 --- a/src/gui/webviewer.cpp +++ b/src/gui/webviewer.cpp @@ -137,7 +137,14 @@ void WebViewer::clear() { QWebEngineView *WebViewer::createWindow(QWebEnginePage::WebWindowType type) { Q_UNUSED(type) - return qApp->mainForm()->tabWidget()->widget(qApp->mainForm()->tabWidget()->addBrowser(false, false))->webBrowser()->viewer(); + int index = qApp->mainForm()->tabWidget()->addBrowser(false, false); + + if (index >= 0) { + return qApp->mainForm()->tabWidget()->widget(qApp->mainForm()->tabWidget()->addBrowser(false, false))->webBrowser()->viewer(); + } + else { + return nullptr; + } } void WebViewer::wheelEvent(QWheelEvent *event) { diff --git a/src/miscellaneous/application.cpp b/src/miscellaneous/application.cpp index a59bbe596..5a5a48058 100755 --- a/src/miscellaneous/application.cpp +++ b/src/miscellaneous/application.cpp @@ -37,9 +37,11 @@ #include #include #include + +#if defined(USE_WEBENGINE) #include #include - +#endif Application::Application(const QString &id, bool run_minimal_without_gui, int &argc, char **argv) : QtSingleApplication(id, argc, argv), @@ -50,8 +52,11 @@ Application::Application(const QString &id, bool run_minimal_without_gui, int &a connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit())); connect(this, SIGNAL(commitDataRequest(QSessionManager&)), this, SLOT(onCommitData(QSessionManager&))); connect(this, SIGNAL(saveStateRequest(QSessionManager&)), this, SLOT(onSaveState(QSessionManager&))); + +#if defined(USE_WEBENGINE) connect(QWebEngineProfile::defaultProfile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)), this, SLOT(downloadRequested(QWebEngineDownloadItem*))); +#endif } Application::~Application() { @@ -361,11 +366,13 @@ void Application::onAboutToQuit() { } } +#if defined(USE_WEBENGINE) void Application::downloadRequested(QWebEngineDownloadItem *download_item) { downloadManager()->download(download_item->url()); download_item->cancel(); download_item->deleteLater(); } +#endif void Application::onFeedUpdatesStarted() { } diff --git a/src/miscellaneous/application.h b/src/miscellaneous/application.h index 5db25a4bc..8dfe30bae 100755 --- a/src/miscellaneous/application.h +++ b/src/miscellaneous/application.h @@ -115,7 +115,10 @@ class Application : public QtSingleApplication { void onCommitData(QSessionManager &manager); void onSaveState(QSessionManager &manager); void onAboutToQuit(); + +#if defined(USE_WEBENGINE) void downloadRequested(QWebEngineDownloadItem*download_item); +#endif void onFeedUpdatesStarted(); void onFeedUpdatesProgress(const Feed *feed, int current, int total); diff --git a/src/network-web/downloadmanager.h b/src/network-web/downloadmanager.h index 8572856f6..d8664581b 100755 --- a/src/network-web/downloadmanager.h +++ b/src/network-web/downloadmanager.h @@ -91,6 +91,10 @@ class DownloadItem : public QWidget { bool m_canceledFileSelect; }; +#if defined(USE_WEBENGINE) +class WebBrowser; +#endif + class DownloadManager : public TabContent { Q_OBJECT Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) @@ -108,9 +112,11 @@ class DownloadManager : public TabContent { explicit DownloadManager(QWidget *parent = 0); virtual ~DownloadManager(); +#if defined(USE_WEBENGINE) WebBrowser *webBrowser() const { return nullptr; } +#endif QNetworkAccessManager *networkManager() const;