Work on better msg viewing experience.

This commit is contained in:
Martin Rotter 2016-06-06 19:58:34 +02:00
parent 76f869d93b
commit ef2a94980b
11 changed files with 641 additions and 896 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -30,31 +30,14 @@
void MessagePreviewer::createConnections() {
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);
// TODO: TODO.
}
MessagePreviewer::MessagePreviewer(QWidget *parent) : QWidget(parent),
MessagePreviewer::MessagePreviewer(QWidget *parent) : TabContent(parent),
m_ui(new Ui::MessagePreviewer) {
m_ui->setupUi(this);
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();
}
@ -68,24 +51,27 @@ void MessagePreviewer::reloadFontSettings() {
}
void MessagePreviewer::clear() {
m_ui->m_webMessage->setHtml("<html><body</body></html>", QUrl(INTERNAL_URL_BLANK));
m_ui->m_webMessage->setHtml("<!DOCTYPE html><html><body</body></html>", QUrl(INTERNAL_URL_BLANK));
hide();
}
void MessagePreviewer::loadMessage(const Message &message, RootItem *root) {
m_message = message;
void MessagePreviewer::loadMessages(const QList<Message> &messages, RootItem *root) {
m_messages = messages;
m_root = root;
if (!m_root.isNull()) {
m_actionSwitchImportance->setChecked(m_message.m_isImportant);
m_ui->m_webMessage->loadMessage(message);
updateButtons();
m_ui->m_webMessage->loadMessages(messages);
show();
}
}
void MessagePreviewer::loadMessage(const Message &message, RootItem *root) {
loadMessages(QList<Message>() << message, root);
}
void MessagePreviewer::markMessageAsRead() {
if (!m_root.isNull()) {
/*
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
RootItem::Read)) {
@ -98,13 +84,14 @@ void MessagePreviewer::markMessageAsRead() {
emit requestMessageListReload(false);
m_message.m_isRead = true;
updateButtons();
}
*/
}
}
void MessagePreviewer::markMessageAsUnread() {
if (!m_root.isNull()) {
/*
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
RootItem::Unread)) {
@ -117,13 +104,14 @@ void MessagePreviewer::markMessageAsUnread() {
emit requestMessageListReload(false);
m_message.m_isRead = false;
updateButtons();
}
*/
}
}
void MessagePreviewer::switchMessageImportance(bool checked) {
if (!m_root.isNull()) {
/*
if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.m_isImportant ?
@ -141,10 +129,6 @@ void MessagePreviewer::switchMessageImportance(bool checked) {
emit requestMessageListReload(false);
m_message.m_isImportant = checked;
}
*/
}
}
void MessagePreviewer::updateButtons() {
m_actionMarkRead->setEnabled(!m_message.m_isRead);
m_actionMarkUnread->setEnabled(m_message.m_isRead);
}

View File

@ -18,7 +18,7 @@
#ifndef MESSAGEPREVIEWER_H
#define MESSAGEPREVIEWER_H
#include <QWidget>
#include "gui/tabcontent.h"
#include "ui_messagepreviewer.h"
@ -34,7 +34,7 @@ namespace Ui {
class QToolBar;
class MessagePreviewer : public QWidget {
class MessagePreviewer : public TabContent {
Q_OBJECT
public:
@ -45,6 +45,7 @@ class MessagePreviewer : public QWidget {
public slots:
void clear();
void loadMessages(const QList<Message> &messages, RootItem *root);
void loadMessage(const Message &message, RootItem *root);
private slots:
@ -57,16 +58,10 @@ class MessagePreviewer : public QWidget {
private:
void createConnections();
void updateButtons();
QToolBar *m_toolBar;
QScopedPointer<Ui::MessagePreviewer> m_ui;
Message m_message;
QList<Message> m_messages;
QPointer<RootItem> m_root;
QAction *m_actionMarkRead;
QAction *m_actionMarkUnread;
QAction *m_actionSwitchImportance;
};
#endif // MESSAGEPREVIEWER_H

View File

@ -17,9 +17,6 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" name="m_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
@ -31,7 +28,7 @@
<customwidgets>
<customwidget>
<class>MessageBrowser</class>
<extends>QWebEngineView</extends>
<extends>QWidget</extends>
<header>messagebrowser.h</header>
</customwidget>
</customwidgets>

View File

@ -24,7 +24,7 @@
#include "network-web/webfactory.h"
#include "gui/dialogs/formmain.h"
#include "gui/messagebox.h"
#include "gui/newspaperpreviewer.h"
#include "gui/messagepreviewer.h"
#include "gui/styleditemdelegatewithoutfocus.h"
#include <QKeyEvent>
@ -468,14 +468,20 @@ void MessagesView::filterMessages(MessagesModel::MessageHighlighter filter) {
}
void MessagesView::createNewspaperView(RootItem *selected_item, const QList<Message> &messages) {
NewspaperPreviewer *prev = new NewspaperPreviewer(selected_item, messages, this);
MessagePreviewer *prev = new MessagePreviewer(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);
qApp->mainForm()->tabWidget()->setCurrentIndex(index);
connect(prev, SIGNAL(requestMessageListReload(bool)), this, SLOT(reloadSelections(bool)));
prev->loadMessages(messages, selected_item);
QTimer::singleShot(100, [&prev, &messages, &selected_item]() {
});
}
void MessagesView::adjustColumns() {

View File

@ -1,61 +0,0 @@
// 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/newspaperpreviewer.h"
#include "gui/messagepreviewer.h"
#include "gui/dialogs/formmain.h"
#include "miscellaneous/application.h"
#include <QScrollBar>
NewspaperPreviewer::NewspaperPreviewer(RootItem *root, QList<Message> 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);
connect(prev, SIGNAL(requestMessageListReload(bool)), this, SIGNAL(requestMessageListReload(bool)));
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);
}
}

View File

@ -1,58 +0,0 @@
// 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/>.
#ifndef NEWSPAPERPREVIEWER_H
#define NEWSPAPERPREVIEWER_H
#include <QWidget>
#include "gui/tabcontent.h"
#include "ui_newspaperpreviewer.h"
#include "core/message.h"
#include "services/abstract/rootitem.h"
#include <QPointer>
namespace Ui {
class NewspaperPreviewer;
}
class RootItem;
class NewspaperPreviewer : public TabContent {
Q_OBJECT
public:
explicit NewspaperPreviewer(RootItem *root, QList<Message> messages, QWidget *parent = 0);
virtual ~NewspaperPreviewer();
private slots:
void showMoreMessages();
signals:
void requestMessageListReload(bool mark_current_as_read);
private:
QScopedPointer<Ui::NewspaperPreviewer> m_ui;
QPointer<RootItem> m_root;
QList<Message> m_messages;
};
#endif // NEWSPAPERPREVIEWER_H

View File

@ -1,102 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewspaperPreviewer</class>
<widget class="QWidget" name="NewspaperPreviewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>298</height>
</rect>
</property>
<layout class="QVBoxLayout" name="m_layout">
<item>
<layout class="QHBoxLayout" name="m_btnLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_btnShowMoreMessages">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>246</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -49,33 +49,7 @@ void SkinFactory::loadCurrentSkin() {
}
}
bool SkinFactory::loadSkinFromData(const Skin &skin) {
const QStringList skin_parts = skin.m_baseName.split(QL1C('/'), QString::SkipEmptyParts);
// Skin does not contain leading folder name or the actual skin file name.
if (skin_parts.size() != 2) {
qDebug("Loading of sking '%s' failed because skin name does not contain "
"base folder name or the actual skin name.",
qPrintable(skin.m_baseName));
return false;
}
else {
qDebug("Loading skin '%s'.", qPrintable(skin.m_baseName));
}
// Create needed variables and create QFile object representing skin contents.
const QString skin_folder = skin_parts.at(0);
// Here we use "/" instead of QDir::separator() because CSS2.1 url field
// accepts '/' as path elements separator.
//
// "##" is placeholder for the actual path to skin file. This is needed for using
// images within the QSS file.
// So if one uses "##/images/border.png" in QSS then it is
// replaced by fully absolute path and target file can
// be safely loaded.
QString raw_data = skin.m_rawData;
void SkinFactory::loadSkinFromData(const Skin &skin) {
// Iterate supported styles and load one.
foreach (const QString &style, skin.m_stylesNames) {
if (qApp->setStyle(style) != 0) {
@ -84,12 +58,9 @@ bool SkinFactory::loadSkinFromData(const Skin &skin) {
}
}
if (!raw_data.isEmpty()) {
const QString parsed_data = raw_data.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_folder);
qApp->setStyleSheet(parsed_data);
if (!skin.m_rawData.isEmpty()) {
qApp->setStyleSheet(skin.m_rawData);
}
return true;
}
void SkinFactory::setCurrentSkinName(const QString &skin_name) {
@ -119,10 +90,6 @@ Skin SkinFactory::skinInfo(const QString &skin_name, bool *ok) const {
// Obtain visible skin name.
skin.m_visibleName = skin_node.namedItem(QSL("name")).toElement().text();
// Obtain skin raw data.
skin.m_rawData = skin_node.namedItem(QSL("data")).toElement().text();
skin.m_rawData = QByteArray::fromBase64(skin.m_rawData.toLocal8Bit());
// Obtain style name.
styles = skin_node.namedItem(QSL("style")).toElement().text();
skin.m_stylesNames = styles.split(',', QString::SkipEmptyParts);
@ -136,20 +103,40 @@ Skin SkinFactory::skinInfo(const QString &skin_name, bool *ok) const {
// Obtain version.
skin.m_version = skin_node.attributes().namedItem(QSL("version")).toAttr().value();
// Obtain other information.
skin.m_baseName = QString(skin_name).replace(QDir::separator(), '/');
// Obtain base folder.
const QString base_folder = skin.m_baseName.split(QL1C('/'), QString::SkipEmptyParts).at(0);
// Here we use "/" instead of QDir::separator() because CSS2.1 url field
// accepts '/' as path elements separator.
//
// "##" is placeholder for the actual path to skin file. This is needed for using
// images within the QSS file.
// So if one uses "##/images/border.png" in QSS then it is
// replaced by fully absolute path and target file can
// be safely loaded.
// Obtain layout markup wrapper.
skin.m_layoutMarkupWrapper = skin_node.namedItem(QSL("markup_wrapper")).toElement().text();
skin.m_layoutMarkupWrapper = QByteArray::fromBase64(skin.m_layoutMarkupWrapper.toLocal8Bit());
skin.m_layoutMarkupWrapper = skin.m_layoutMarkupWrapper.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + base_folder);
// Obtain layout markup.
skin.m_layoutMarkup = skin_node.namedItem(QSL("markup")).toElement().text();
skin.m_layoutMarkup = QByteArray::fromBase64(skin.m_layoutMarkup.toLocal8Bit());
skin.m_layoutMarkup = skin.m_layoutMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + base_folder);
// Obtain enclosure hyperlink wrapper.
skin.m_enclosureMarkup = skin_node.namedItem(QSL("markup_enclosure")).toElement().text();
skin.m_enclosureMarkup = QByteArray::fromBase64(skin.m_enclosureMarkup.toLocal8Bit());
skin.m_enclosureMarkup = skin.m_enclosureMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + base_folder);
// Obtain other information.
skin.m_baseName = QString(skin_name).replace(QDir::separator(), '/');
// Obtain skin raw data.
skin.m_rawData = skin_node.namedItem(QSL("data")).toElement().text();
skin.m_rawData = QByteArray::fromBase64(skin.m_rawData.toLocal8Bit());
skin.m_rawData = skin.m_rawData.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + base_folder);
// Free resources.
skin_file.close();

View File

@ -71,7 +71,7 @@ class SkinFactory : public QObject {
private:
// Loads the skin from give skin_data.
bool loadSkinFromData(const Skin &skin);
void loadSkinFromData(const Skin &skin);
// Holds name of the current skin.
Skin m_currentSkin;