rssguard/src/gui/webbrowser.cpp
2016-08-15 11:09:03 +02:00

308 lines
11 KiB
C++
Executable File

// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 by Martin Rotter <rotter.martinos@gmail.com>
//
// 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 <http://www.gnu.org/licenses/>.
#include "gui/webbrowser.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "network-web/networkfactory.h"
#include "network-web/webfactory.h"
#include "gui/messagebox.h"
#include "gui/webviewer.h"
#include "gui/discoverfeedsbutton.h"
#include "gui/locationlineedit.h"
#include "services/abstract/serviceroot.h"
#include <QScrollBar>
#include <QToolBar>
#include <QWebEngineSettings>
#include <QToolTip>
#include <QWidgetAction>
void WebBrowser::createConnections() {
connect(m_webView, &WebViewer::messageStatusChangeRequested, this, &WebBrowser::receiveMessageStatusChangeRequest);
connect(m_txtLocation,SIGNAL(submitted(QString)), this, SLOT(loadUrl(QString)));
connect(m_webView, SIGNAL(urlChanged(QUrl)), this, SLOT(updateUrl(QUrl)));
// Change location textbox status according to webpage status.
connect(m_webView, SIGNAL(loadStarted()), this, SLOT(onLoadingStarted()));
connect(m_webView, SIGNAL(loadProgress(int)), this, SLOT(onLoadingProgress(int)));
connect(m_webView, SIGNAL(loadFinished(bool)), this, SLOT(onLoadingFinished(bool)));
// Forward title/icon changes.
connect(m_webView, SIGNAL(titleChanged(QString)), this, SLOT(onTitleChanged(QString)));
connect(m_webView, SIGNAL(iconChanged(QIcon)), this, SLOT(onIconChanged(QIcon)));
}
void WebBrowser::updateUrl(const QUrl &url) {
QString url_string = url.toString();
m_txtLocation->setText(url_string);
//setNavigationBarVisible(url_string != INTERNAL_URL_EMPTY && url_string != INTERNAL_URL_NEWSPAPER);
}
void WebBrowser::loadUrl(const QUrl &url) {
if (url.isValid()) {
m_webView->load(url);
}
}
WebBrowser::WebBrowser(QWidget *parent) : TabContent(parent),
m_layout(new QVBoxLayout(this)),
m_toolBar(new QToolBar(tr("Navigation panel"), this)),
m_webView(new WebViewer(this)),
m_txtLocation(new LocationLineEdit(this)),
m_btnDiscoverFeeds(new DiscoverFeedsButton(this)),
m_actionBack(m_webView->pageAction(QWebEnginePage::Back)),
m_actionForward(m_webView->pageAction(QWebEnginePage::Forward)),
m_actionReload(m_webView->pageAction(QWebEnginePage::Reload)),
m_actionStop(m_webView->pageAction(QWebEnginePage::Stop)) {
// Initialize the components and layout.
initializeLayout();
setFocusProxy(m_txtLocation);
setTabOrder(m_txtLocation, m_toolBar);
setTabOrder(m_toolBar, m_webView);
createConnections();
reloadFontSettings();
}
WebBrowser::~WebBrowser() {
// Delete members. Do not use scoped pointers here.
delete m_layout;
}
void WebBrowser::reloadFontSettings() {
QFont fon;
fon.fromString(qApp->settings()->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString());
QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::StandardFont, fon.family());
QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::DefaultFontSize, fon.pointSize());
}
void WebBrowser::increaseZoom() {
m_webView->increaseWebPageZoom();
}
void WebBrowser::decreaseZoom() {
m_webView->decreaseWebPageZoom();
}
void WebBrowser::resetZoom() {
m_webView->resetWebPageZoom();
}
void WebBrowser::clear() {
m_webView->clear();
m_messages.clear();
hide();
}
void WebBrowser::loadUrl(const QString &url) {
return loadUrl(QUrl::fromUserInput(url));
}
void WebBrowser::loadMessages(const QList<Message> &messages, RootItem *root) {
if (m_messages.size() == messages.size()) {
for (int i = 0; i < messages.size(); i++) {
if (m_messages.at(i).m_id != messages.at(i).m_id) {
break;
}
if (i == messages.size() - 1) {
// We checked last items, both collections contain the same messages.
return;
}
}
}
m_messages = messages;
m_root = root;
if (!m_root.isNull()) {
m_webView->loadMessages(messages);
show();
}
}
void WebBrowser::loadMessage(const Message &message, RootItem *root) {
loadMessages(QList<Message>() << message, root);
}
void WebBrowser::receiveMessageStatusChangeRequest(int message_id, WebPage::MessageStatusChange change) {
switch (change) {
case WebPage::MarkRead:
markMessageAsRead(message_id, true);
break;
case WebPage::MarkUnread:
markMessageAsRead(message_id, false);
break;
case WebPage::MarkStarred:
switchMessageImportance(message_id, true);
break;
case WebPage::MarkUnstarred:
switchMessageImportance(message_id, false);
break;
default:
break;
}
}
void WebBrowser::onTitleChanged(const QString &new_title) {
if (new_title.isEmpty()) {
//: Webbrowser tab title when no title is available.
emit titleChanged(m_index, tr("No title"));
}
else {
emit titleChanged(m_index, new_title);
}
}
void WebBrowser::onIconChanged(const QIcon &icon) {
emit iconChanged(m_index, icon);
}
void WebBrowser::initializeLayout() {
m_toolBar->setFloatable(false);
m_toolBar->setMovable(false);
m_toolBar->setAllowedAreas(Qt::TopToolBarArea);
// Modify action texts.
m_actionBack->setText(tr("Back"));
m_actionBack->setToolTip(tr("Go back."));
m_actionForward->setText(tr("Forward"));
m_actionForward->setToolTip(tr("Go forward."));
m_actionReload->setText(tr("Reload"));
m_actionReload->setToolTip(tr("Reload current web page."));
m_actionStop->setText(tr("Stop"));
m_actionStop->setToolTip(tr("Stop web page loading."));
QWidgetAction *act_discover = new QWidgetAction(this);
act_discover->setDefaultWidget(m_btnDiscoverFeeds);
// Add needed actions into toolbar.
m_toolBar->addAction(m_actionBack);
m_toolBar->addAction(m_actionForward);
m_toolBar->addAction(m_actionReload);
m_toolBar->addAction(m_actionStop);
m_toolBar->addAction(act_discover);
m_toolBar->addWidget(m_txtLocation);
m_loadingProgress = new QProgressBar(this);
m_loadingProgress->setFixedHeight(5);
m_loadingProgress->setMinimum(0);
m_loadingProgress->setTextVisible(false);
m_loadingProgress->setMaximum(100);
m_loadingProgress->setAttribute(Qt::WA_TranslucentBackground);
// Setup layout.
m_layout->addWidget(m_toolBar);
m_layout->addWidget(m_webView);
m_layout->addWidget(m_loadingProgress);
m_layout->setMargin(0);
m_layout->setSpacing(0);
}
void WebBrowser::onLoadingStarted() {
m_btnDiscoverFeeds->clearFeedAddresses();
m_loadingProgress->show();
}
void WebBrowser::onLoadingProgress(int progress) {
m_loadingProgress->setValue(progress);
}
void WebBrowser::onLoadingFinished(bool success) {
if (success) {
// Let's check if there are any feeds defined on the web and eventually
// display "Add feeds" button.
m_webView->page()->toHtml([this](const QString &result){
this->m_btnDiscoverFeeds->setFeedAddresses(NetworkFactory::extractFeedLinksFromHtmlPage(m_webView->url(), result));
});
}
else {
m_btnDiscoverFeeds->clearFeedAddresses();
}
m_loadingProgress->hide();
m_loadingProgress->setValue(0);
}
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<Message>() << *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<Message>() << *msg,
read ? RootItem::Read : RootItem::Unread);
emit markMessageRead(msg->m_id, read ? RootItem::Read : RootItem::Unread);
msg->m_isRead = read ? RootItem::Read : RootItem::Unread;
}
}
}
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>() << 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>() << 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;
}
}
}
Message *WebBrowser::findMessage(int id) {
for (int i = 0; i < m_messages.size(); i++) {
if (m_messages.at(i).m_id == id) {
return &m_messages[i];
}
}
return nullptr;
}