Implemented #266.

This commit is contained in:
Martin Rotter 2020-12-10 11:28:05 +01:00
parent dd7eab318c
commit ac8fdf6fae
10 changed files with 607 additions and 348 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<skin version="0.04">
<skin version="0.05">
<author>
<name>Martin Rotter</name>
<email>rotter.martinos@gmail.com</email>
@ -7,5 +7,6 @@
<palette>
<color key="1">#7ae2ff</color>
<color key="2">#f08f84</color>
<color key="3">#77dd77</color>
</palette>
</skin>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<skin version="0.23">
<skin version="0.24">
<author>
<name>Martin Rotter</name>
<email>rotter.martinos@gmail.com</email>
@ -7,5 +7,6 @@
<palette>
<color key="1">#4861f0</color>
<color key="2">#d93636</color>
<color key="3">#77dd77</color>
</palette>
</skin>

View File

@ -0,0 +1,132 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "core/messagesforfiltersmodel.h"
#include "core/messagefilter.h"
#include "definitions/definitions.h"
#include "exceptions/filteringexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/skinfactory.h"
MessagesForFiltersModel::MessagesForFiltersModel(QObject* parent) : QAbstractTableModel(parent) {
m_headerData << tr("Read") << tr("Important") << tr("Title")
<< tr("URL") << tr("Author") << tr("Created on");
}
void MessagesForFiltersModel::setMessages(const QList<Message>& messages) {
m_filteringDecisions.clear();
m_messages = messages;
emit layoutAboutToBeChanged();
emit layoutChanged();
}
int MessagesForFiltersModel::rowCount(const QModelIndex& parent) const {
Q_UNUSED(parent)
return m_messages.size();
}
int MessagesForFiltersModel::columnCount(const QModelIndex& parent) const {
Q_UNUSED(parent)
return m_headerData.size();
}
QVariant MessagesForFiltersModel::data(const QModelIndex& index, int role) const {
auto msg = messageForRow(index.row());
switch (role) {
case Qt::ItemDataRole::BackgroundRole: {
if (m_filteringDecisions.contains(index.row())) {
switch (m_filteringDecisions.value(index.row())) {
case MessageObject::FilteringAction::Accept:
return qApp->skins()->currentSkin().m_colorPalette[Skin::PaletteColors::Allright];
case MessageObject::FilteringAction::Ignore:
return qApp->skins()->currentSkin().m_colorPalette[Skin::PaletteColors::Error];
}
}
break;
}
case Qt::ItemDataRole::DisplayRole: {
switch (index.column()) {
case MFM_MODEL_ISREAD:
return msg.m_isRead;
case MFM_MODEL_ISIMPORTANT:
return msg.m_isImportant;
case MFM_MODEL_TITLE:
return msg.m_title;
case MFM_MODEL_URL:
return msg.m_url;
case MFM_MODEL_AUTHOR:
return msg.m_author;
case MFM_MODEL_CREATED:
return msg.m_created;
}
break;
}
}
return QVariant();
}
QVariant MessagesForFiltersModel::headerData(int section, Qt::Orientation orientation, int role) const {
Q_UNUSED(orientation)
switch (role) {
case Qt::ItemDataRole::DisplayRole:
if (section >=0 && section < m_headerData.size()) {
return m_headerData.at(section);
}
break;
}
return QVariant();
}
Qt::ItemFlags MessagesForFiltersModel::flags(const QModelIndex& index) const {
Q_UNUSED(index)
return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable;
}
int MessagesForFiltersModel::messagesCount() const {
return m_messages.size();
}
void MessagesForFiltersModel::testFilter(MessageFilter* filter, QJSEngine* engine, MessageObject* msg_proxy) {
m_filteringDecisions.clear();
for (int i = 0; i < m_messages.size(); i++) {
Message* msg = messageForRow(i);
msg_proxy->setMessage(msg);
try {
MessageObject::FilteringAction decision = filter->filterMessage(engine);
m_filteringDecisions.insert(i, decision);
}
catch (const FilteringException& ex) {
throw ex;
}
}
emit layoutAboutToBeChanged();
emit layoutChanged();
}
Message* MessagesForFiltersModel::messageForRow(int row) {
return &m_messages[row];
}
Message MessagesForFiltersModel::messageForRow(int row) const {
return m_messages[row];
}

View File

@ -0,0 +1,44 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef MESSAGESFORFILTERSMODEL_H
#define MESSAGESFORFILTERSMODEL_H
#include <QAbstractTableModel>
#include "core/messageobject.h"
#include <QJSEngine>
class MessageFilter;
class MessagesForFiltersModel : public QAbstractTableModel {
Q_OBJECT
public:
explicit MessagesForFiltersModel(QObject* parent = nullptr);
virtual int rowCount(const QModelIndex& parent) const;
virtual int columnCount(const QModelIndex& parent) const;
virtual QVariant data(const QModelIndex& index, int role) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
public:
int messagesCount() const;
void testFilter(MessageFilter* filter, QJSEngine* engine, MessageObject* msg_proxy);
Message messageForRow(int row) const;
Message* messageForRow(int row);
public slots:
void setMessages(const QList<Message>& messages);
private:
QList<QString> m_headerData{};
QList<Message> m_messages{};
// Key is integer position of the message within the list of messages.
QMap<int, MessageObject::FilteringAction> m_filteringDecisions{};
};
#endif // MESSAGESFORFILTERSMODEL_H

View File

@ -218,6 +218,14 @@
#define FDS_MODEL_TITLE_INDEX 0
#define FDS_MODEL_COUNTS_INDEX 1
// Indexes of columns for message filter manager models.
#define MFM_MODEL_ISREAD 0
#define MFM_MODEL_ISIMPORTANT 1
#define MFM_MODEL_TITLE 2
#define MFM_MODEL_URL 3
#define MFM_MODEL_AUTHOR 4
#define MFM_MODEL_CREATED 5
#if defined(Q_OS_LINUX)
#define OS_ID "Linux"
#elif defined(Q_OS_OSX)

View File

@ -1,12 +1,13 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include <QDateTime>
#include <QJSEngine>
#include <QProcess>
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "gui/dialogs/formmessagefiltersmanager.h"
#include "core/messagefilter.h"
#include "core/messagesforfiltersmodel.h"
#include "exceptions/filteringexception.h"
#include "gui/guiutilities.h"
#include "gui/messagebox.h"
@ -19,9 +20,15 @@
FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const QList<ServiceRoot*>& accounts, QWidget* parent)
: QDialog(parent), m_feedsModel(new AccountCheckSortedModel(this)), m_rootItem(new RootItem()),
m_accounts(accounts), m_reader(reader), m_loadingFilter(false) {
m_accounts(accounts), m_reader(reader), m_loadingFilter(false), m_msgModel(new MessagesForFiltersModel(this)) {
m_ui.setupUi(this);
std::sort(m_accounts.begin(), m_accounts.end(), [](const ServiceRoot* lhs, const ServiceRoot* rhs) {
return lhs->title().compare(rhs->title(), Qt::CaseSensitivity::CaseInsensitive) < 0;
});
m_ui.m_treeExistingMessages->setModel(m_msgModel);
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("view-list-details")));
m_ui.m_treeFeeds->setIndentation(FEEDS_VIEW_INDENTATION);
@ -32,9 +39,17 @@ FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const Q
m_ui.m_btnRemoveSelected->setIcon(qApp->icons()->fromTheme(QSL("list-remove")));
m_ui.m_btnBeautify->setIcon(qApp->icons()->fromTheme(QSL("format-justify-fill")));
m_ui.m_btnTest->setIcon(qApp->icons()->fromTheme(QSL("media-playback-start")));
m_ui.m_btnRunOnMessages->setIcon(qApp->icons()->fromTheme(QSL("media-playback-start")));
m_ui.m_btnDetailedHelp->setIcon(qApp->icons()->fromTheme(QSL("help-contents")));
m_ui.m_txtScript->setFont(QFontDatabase::systemFont(QFontDatabase::SystemFont::FixedFont));
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_ISREAD, QHeaderView::ResizeMode::ResizeToContents);
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_ISIMPORTANT, QHeaderView::ResizeMode::ResizeToContents);
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_AUTHOR, QHeaderView::ResizeMode::ResizeToContents);
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_CREATED, QHeaderView::ResizeMode::ResizeToContents);
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_TITLE, QHeaderView::ResizeMode::Interactive);
m_ui.m_treeExistingMessages->header()->setSectionResizeMode(MFM_MODEL_URL, QHeaderView::ResizeMode::Interactive);
connect(m_ui.m_btnDetailedHelp, &QPushButton::clicked, this, []() {
qApp->web()->openUrlInExternalBrowser(MSG_FILTERING_HELP);
});
@ -55,6 +70,8 @@ FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const Q
connect(m_ui.m_btnUncheckAll, &QPushButton::clicked, m_feedsModel->sourceModel(), &AccountCheckModel::uncheckAllItems);
connect(m_feedsModel->sourceModel(), &AccountCheckModel::checkStateChanged,
this, &FormMessageFiltersManager::onFeedChecked);
connect(m_ui.m_treeFeeds->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &FormMessageFiltersManager::displayMessagesOfFeed);
initializeTestingMessage();
loadFilters();
@ -104,7 +121,7 @@ void FormMessageFiltersManager::addNewFilter() {
try {
auto* fltr = m_reader->addMessageFilter(
tr("New message filter"),
QSL("function filterMessage() { return 1; }"));
QSL("function filterMessage() { return MessageObject.Accept; }"));
auto* it = new QListWidgetItem(fltr->name(), m_ui.m_listFilters);
it->setData(Qt::ItemDataRole::UserRole, QVariant::fromValue<MessageFilter*>(fltr));
@ -145,6 +162,8 @@ void FormMessageFiltersManager::loadFilter() {
}
void FormMessageFiltersManager::testFilter() {
m_ui.m_txtErrors->clear();
// Perform per-message filtering.
QJSEngine filter_engine;
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
@ -155,10 +174,24 @@ void FormMessageFiltersManager::testFilter() {
: NO_PARENT_CATEGORY,
{});
auto* fltr = selectedFilter();
Message msg = testingMessage();
MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj);
// Test real messages.
try {
m_msgModel->testFilter(fltr, &filter_engine, &msg_obj);
}
catch (const FilteringException& ex) {
m_ui.m_txtErrors->setTextColor(Qt::GlobalColor::red);
m_ui.m_txtErrors->insertPlainText(tr("EXISTING messages filtering error: '%1'.\n").arg(ex.message()));
// See output.
m_ui.m_twMessages->setCurrentIndex(2);
}
// Test sample message.
Message msg = testingMessage();
msg_obj.setMessage(&msg);
try {
@ -182,19 +215,37 @@ void FormMessageFiltersManager::testFilter() {
QString::number(msg.m_created.toMSecsSinceEpoch()),
msg.m_contents);
m_ui.m_txtErrors->setPlainText(answer);
m_ui.m_txtErrors->insertPlainText(answer);
}
catch (const FilteringException& ex) {
m_ui.m_txtErrors->setTextColor(Qt::GlobalColor::red);
m_ui.m_txtErrors->setPlainText(tr("JavaScript-based filter contains errors: '%1'.").arg(ex.message()));
}
m_ui.m_txtErrors->insertPlainText(tr("SAMPLE message filtering error: '%1'.\n").arg(ex.message()));
// See output.
m_ui.m_tcMessage->setCurrentIndex(1);
// See output.
m_ui.m_twMessages->setCurrentIndex(2);
}
}
void FormMessageFiltersManager::displayMessagesOfFeed() {
auto* item = m_feedsModel->sourceModel()->itemForIndex(m_feedsModel->mapToSource(m_ui.m_treeFeeds->currentIndex()));
if (item != nullptr) {
m_msgModel->setMessages(item->undeletedMessages());
}
else {
m_msgModel->setMessages({});
}
}
void FormMessageFiltersManager::loadAccount(ServiceRoot* account) {
m_feedsModel->setRootItem(account, false, true);
if (account != nullptr) {
m_msgModel->setMessages(account->undeletedMessages());
}
else {
m_msgModel->setMessages({});
}
}
void FormMessageFiltersManager::loadFilterFeedAssignments(MessageFilter* filter, ServiceRoot* account) {
@ -233,6 +284,7 @@ void FormMessageFiltersManager::onFeedChecked(RootItem* item, Qt::CheckState sta
return;
}
// Update feed/filter assignemnts.
switch (state) {
case Qt::CheckState::Checked:
m_reader->assignMessageFilterToFeed(feed, selectedFilter());
@ -272,7 +324,7 @@ void FormMessageFiltersManager::showFilter(MessageFilter* filter) {
}
// See message.
m_ui.m_tcMessage->setCurrentIndex(0);
m_ui.m_twMessages->setCurrentIndex(0);
m_loadingFilter = false;
}
@ -298,7 +350,7 @@ void FormMessageFiltersManager::beautifyScript() {
proc_clang_format.setProgram(QSL("clang-format"));
#endif
if (!proc_clang_format.open()) {
if (!proc_clang_format.open() || proc_clang_format.error() == QProcess::ProcessError::FailedToStart) {
MessageBox::show(this, QMessageBox::Icon::Critical,
tr("Cannot find 'clang-format'"),
tr("Script was not beautified, because 'clang-format' tool was not found."));

View File

@ -12,6 +12,7 @@
class AccountCheckSortedModel;
class MessageFilter;
class FeedReader;
class MessagesForFiltersModel;
class FormMessageFiltersManager : public QDialog {
Q_OBJECT
@ -30,6 +31,7 @@ class FormMessageFiltersManager : public QDialog {
void loadFilter();
void loadFilters();
void testFilter();
void displayMessagesOfFeed();
// Load feeds/categories tree.
void loadAccount(ServiceRoot* account);
@ -56,6 +58,7 @@ class FormMessageFiltersManager : public QDialog {
QList<ServiceRoot*> m_accounts;
FeedReader* m_reader;
bool m_loadingFilter;
MessagesForFiltersModel* m_msgModel;
};
#endif // FORMMESSAGEFILTERSMANAGER_H

View File

@ -6,386 +6,407 @@
<rect>
<x>0</x>
<y>0</y>
<width>845</width>
<height>644</height>
<width>1229</width>
<height>546</height>
</rect>
</property>
<property name="windowTitle">
<string>Message filters</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QPushButton" name="m_btnRemoveSelected">
<property name="text">
<string>Remove selected</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="m_btnAddNew">
<property name="text">
<string>Add new</string>
</property>
</widget>
</item>
<item row="1" column="0">
<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 row="0" column="0" colspan="3">
<widget class="QListWidget" name="m_listFilters">
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Account</string>
</property>
<property name="buddy">
<cstring>m_cmbAccounts</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="m_cmbAccounts"/>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QTreeView" name="m_treeFeeds">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>1</number>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QWidget" name="gridLayoutWidget">
<layout class="QGridLayout" name="gridLayout_2" rowstretch="1,2" columnstretch="2,3">
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<widget class="QPushButton" name="m_btnCheckAll">
<property name="text">
<string>&amp;Check all</string>
</property>
</widget>
</item>
<item>
<item row="2" column="2">
<spacer name="horizontalSpacer_5">
<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 row="1" column="0" colspan="3">
<widget class="QTreeView" name="m_treeFeeds">
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="m_btnUncheckAll">
<property name="text">
<string>&amp;Uncheck all</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<item row="0" column="0" colspan="3">
<widget class="QComboBox" name="m_cmbAccounts"/>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QPushButton" name="m_btnRemoveSelected">
<property name="text">
<string>Remove selected</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="m_btnAddNew">
<property name="text">
<string>&amp;New filter</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QListWidget" name="m_listFilters">
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbDetails">
<property name="title">
<string>Message filter details</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtTitle</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_txtTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="placeholderText">
<string>Title of message filter</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>JavaScript code</string>
</property>
<property name="buddy">
<cstring>m_txtScript</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPlainTextEdit" name="m_txtScript">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="placeholderText">
<string>Your JavaScript-based message filtering logic</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="m_btnTest">
<property name="text">
<string>&amp;Test</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnRunOnMessages">
<property name="text">
<string>Process checked feeds</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnBeautify">
<property name="text">
<string>&amp;Beautify</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnDetailedHelp">
<property name="text">
<string>Detailed &amp;help</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbDetails">
<property name="title">
<string>Message filter details</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Title</string>
</widget>
<widget class="QTabWidget" name="m_twMessages">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="m_tabExistingMessages">
<attribute name="title">
<string>Existing messages</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="buddy">
<cstring>m_txtTitle</cstring>
<property name="topMargin">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="m_txtTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="placeholderText">
<string>Title of message filter</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>JavaScript code</string>
<property name="rightMargin">
<number>0</number>
</property>
<property name="buddy">
<cstring>m_txtScript</cstring>
<property name="bottomMargin">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPlainTextEdit" name="m_txtScript">
<property name="placeholderText">
<string>Your JavaScript-based message filtering logic</string>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="m_tcMessage">
<property name="currentIndex">
<widget class="QTreeView" name="m_treeExistingMessages">
<property name="indentation">
<number>0</number>
</property>
<widget class="QWidget" name="m_tabSample">
<attribute name="title">
<string>Sample message</string>
</attribute>
<layout class="QFormLayout" name="formLayout_2">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="m_cbSampleRead">
<property name="text">
<string>Read</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="m_cbSampleImportant">
<property name="text">
<string>Important</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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 row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtSampleTitle</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_txtSampleTitle"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtSampleUrl</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="m_txtSampleUrl"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Author</string>
</property>
<property name="buddy">
<cstring>m_txtSampleAuthor</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="m_txtSampleAuthor"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Created on</string>
</property>
<property name="buddy">
<cstring>m_txtSampleCreatedOn</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="m_txtSampleCreatedOn"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Contents</string>
</property>
<property name="buddy">
<cstring>m_txtSampleContents</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPlainTextEdit" name="m_txtSampleContents"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="m_tabScriptOutput">
<attribute name="title">
<string>Script output</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QTextEdit" name="m_txtErrors">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="m_btnTest">
</widget>
<widget class="QWidget" name="m_tabSampleMessage">
<attribute name="title">
<string>Sample message</string>
</attribute>
<layout class="QFormLayout" name="formLayout_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 row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>&amp;Test!</string>
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtSampleTitle</cstring>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnBeautify">
<item row="1" column="1">
<widget class="QLineEdit" name="m_txtSampleTitle"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Beautify!</string>
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtSampleUrl</cstring>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_btnDetailedHelp">
<item row="2" column="1">
<widget class="QLineEdit" name="m_txtSampleUrl"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Detailed &amp;help</string>
<string>Author</string>
</property>
<property name="buddy">
<cstring>m_txtSampleAuthor</cstring>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="3" column="1">
<widget class="QLineEdit" name="m_txtSampleAuthor"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Created on</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="buddy">
<cstring>m_txtSampleCreatedOn</cstring>
</property>
</spacer>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="m_txtSampleCreatedOn"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Contents</string>
</property>
<property name="buddy">
<cstring>m_txtSampleContents</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPlainTextEdit" name="m_txtSampleContents"/>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="m_cbSampleRead">
<property name="text">
<string>Read</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="m_cbSampleImportant">
<property name="text">
<string>Important</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="m_tabOutput">
<attribute name="title">
<string>Script output</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="QTextEdit" name="m_txtErrors">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item row="2" column="1">
<item>
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -411,17 +432,11 @@
<tabstop>m_txtTitle</tabstop>
<tabstop>m_txtScript</tabstop>
<tabstop>m_btnTest</tabstop>
<tabstop>m_btnRunOnMessages</tabstop>
<tabstop>m_btnBeautify</tabstop>
<tabstop>m_btnDetailedHelp</tabstop>
<tabstop>m_tcMessage</tabstop>
<tabstop>m_cbSampleRead</tabstop>
<tabstop>m_cbSampleImportant</tabstop>
<tabstop>m_txtSampleTitle</tabstop>
<tabstop>m_txtSampleUrl</tabstop>
<tabstop>m_txtSampleAuthor</tabstop>
<tabstop>m_txtSampleCreatedOn</tabstop>
<tabstop>m_txtSampleContents</tabstop>
<tabstop>m_txtErrors</tabstop>
<tabstop>m_twMessages</tabstop>
<tabstop>m_treeExistingMessages</tabstop>
</tabstops>
<resources/>
<connections>

View File

@ -38,6 +38,7 @@ HEADERS += core/feeddownloader.h \
core/message.h \
core/messagefilter.h \
core/messageobject.h \
core/messagesforfiltersmodel.h \
core/messagesmodel.h \
core/messagesmodelcache.h \
core/messagesmodelsqllayer.h \
@ -195,6 +196,7 @@ SOURCES += core/feeddownloader.cpp \
core/message.cpp \
core/messagefilter.cpp \
core/messageobject.cpp \
core/messagesforfiltersmodel.cpp \
core/messagesmodel.cpp \
core/messagesmodelcache.cpp \
core/messagesmodelsqllayer.cpp \

View File

@ -13,7 +13,8 @@
struct RSSGUARD_DLLSPEC Skin {
enum class PaletteColors {
Highlight = 1,
Error = 2
Error = 2,
Allright = 3
};
QString m_baseName;