Ability to edit/delete tags.

This commit is contained in:
Martin Rotter 2020-10-07 20:22:50 +02:00
parent 205c32735f
commit 1e1b3f5255
11 changed files with 145 additions and 8 deletions

View File

@ -46,6 +46,7 @@
<file>./graphics/Faenza/actions/64/system-search.png</file>
<file>./graphics/Faenza/actions/64/system-upgrade.png</file>
<file>./graphics/Faenza/actions/64/tab-new.png</file>
<file>./graphics/Faenza/actions/64/tag-new.png</file>
<file>./graphics/Faenza/actions/64/up.png</file>
<file>./graphics/Faenza/actions/64/view-fullscreen.png</file>
<file>./graphics/Faenza/actions/64/view-list-details.png</file>
@ -114,6 +115,9 @@
<file>./graphics/Numix/22/actions/system-search.svg</file>
<file>./graphics/Numix/22/actions/system-upgrade.svg</file>
<file>./graphics/Numix/22/actions/tab-new.svg</file>
<file>./graphics/Numix/22/actions/tag-folder.svg</file>
<file>./graphics/Numix/22/actions/tag-new.svg</file>
<file>./graphics/Numix/22/actions/tag-properties.svg</file>
<file>./graphics/Numix/22/actions/up.svg</file>
<file>./graphics/Numix/22/actions/view-fullscreen.svg</file>
<file>./graphics/Numix/22/actions/view-list-details.svg</file>

View File

@ -7,7 +7,7 @@
#include "miscellaneous/iconfactory.h"
#include "services/abstract/label.h"
FormAddEditLabel::FormAddEditLabel(QWidget* parent) : QDialog(parent) {
FormAddEditLabel::FormAddEditLabel(QWidget* parent) : QDialog(parent), m_editableLabel(nullptr) {
m_ui.setupUi(this);
m_ui.m_txtName->lineEdit()->setPlaceholderText(tr("Name for your label"));
@ -26,11 +26,10 @@ FormAddEditLabel::FormAddEditLabel(QWidget* parent) : QDialog(parent) {
}
Label* FormAddEditLabel::execForAdd() {
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("tag-properties")), tr("Create new label"));
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("tag-new")), tr("Create new label"));
m_ui.m_btnColor->setRandomColor();
auto exit_code = exec();
auto xxx = m_ui.m_btnColor->color().name();
if (exit_code == QDialog::DialogCode::Accepted) {
return new Label(m_ui.m_txtName->lineEdit()->text(), m_ui.m_btnColor->color());
@ -39,3 +38,23 @@ Label* FormAddEditLabel::execForAdd() {
return nullptr;
}
}
bool FormAddEditLabel::execForEdit(Label* lbl) {
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("tag-properties")), tr("Edit label '%1'").arg(lbl->title()));
m_editableLabel = lbl;
m_ui.m_btnColor->setColor(lbl->color());
m_ui.m_txtName->lineEdit()->setText(lbl->title());
auto exit_code = exec();
if (exit_code == QDialog::DialogCode::Accepted) {
// TODO: Place server-side changes perhaps to here?
m_editableLabel->setColor(m_ui.m_btnColor->color());
m_editableLabel->setTitle(m_ui.m_txtName->lineEdit()->text());
return true;
}
else {
return false;
}
}

View File

@ -21,9 +21,11 @@ class FormAddEditLabel : public QDialog {
public slots:
Label* execForAdd();
bool execForEdit(Label* lbl);
private:
Ui::FormAddEditLabel m_ui;
Label* m_editableLabel;
};
#endif // FORMADDEDITLABEL_H

View File

@ -29,7 +29,8 @@
FeedsView::FeedsView(QWidget* parent)
: QTreeView(parent), m_contextMenuService(nullptr), m_contextMenuBin(nullptr), m_contextMenuCategories(nullptr),
m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr), m_contextMenuOtherItems(nullptr) {
m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr), m_contextMenuOtherItems(nullptr),
m_contextMenuLabel(nullptr) {
setObjectName(QSL("FeedsView"));
// Allocate models.
@ -656,6 +657,28 @@ QMenu* FeedsView::initializeContextMenuOtherItem(RootItem* clicked_item) {
return m_contextMenuOtherItems;
}
QMenu* FeedsView::initializeContextMenuLabel(RootItem* clicked_item) {
if (m_contextMenuLabel == nullptr) {
m_contextMenuLabel = new QMenu(tr("Context menu for label"), this);
}
else {
m_contextMenuLabel->clear();
}
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
if (!specific_actions.isEmpty()) {
m_contextMenuLabel->addSeparator();
m_contextMenuLabel->addActions(specific_actions);
}
else {
m_contextMenuLabel->addAction(qApp->mainForm()->m_ui->m_actionEditSelectedItem);
m_contextMenuLabel->addAction(qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
}
return m_contextMenuLabel;
}
void FeedsView::setupAppearance() {
// Setup column resize strategies.
header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch);
@ -722,6 +745,9 @@ void FeedsView::contextMenuEvent(QContextMenuEvent* event) {
else if (clicked_item->kind() == RootItem::Kind::ServiceRoot) {
initializeContextMenuService(clicked_item)->exec(event->globalPos());
}
else if (clicked_item->kind() == RootItem::Kind::Label) {
initializeContextMenuLabel(clicked_item)->exec(event->globalPos());
}
else {
initializeContextMenuOtherItem(clicked_item)->exec(event->globalPos());
}

View File

@ -110,6 +110,7 @@ class RSSGUARD_DLLSPEC FeedsView : public QTreeView {
QMenu* initializeContextMenuImportant(RootItem* clicked_item);
QMenu* initializeContextMenuEmptySpace();
QMenu* initializeContextMenuOtherItem(RootItem* clicked_item);
QMenu* initializeContextMenuLabel(RootItem* clicked_item);
void setupAppearance();
void saveExpandStates(RootItem* item);
@ -121,6 +122,7 @@ class RSSGUARD_DLLSPEC FeedsView : public QTreeView {
QMenu* m_contextMenuImportant;
QMenu* m_contextMenuEmptySpace;
QMenu* m_contextMenuOtherItems;
QMenu* m_contextMenuLabel;
FeedsModel* m_sourceModel;
FeedsProxyModel* m_proxyModel;
};

View File

@ -54,6 +54,42 @@ QList<Label*> DatabaseQueries::getLabels(const QSqlDatabase& db, int account_id)
return labels;
}
bool DatabaseQueries::updateLabel(const QSqlDatabase& db, Label* label) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("UPDATE Labels SET name = :name, color = :color "
"WHERE id = :id AND account_id = :account_id;");
q.bindValue(QSL(":name"), label->title());
q.bindValue(QSL(":color"), label->color().name());
q.bindValue(QSL(":id"), label->id());
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
return q.exec();
}
bool DatabaseQueries::deleteLabel(const QSqlDatabase& db, Label* label) {
// NOTE: All dependecies are done via SQL foreign cascaded keys, so no
// extra removals are needed.
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("DELETE FROM Labels WHERE id = :id AND account_id = :account_id;");
q.bindValue(QSL(":id"), label->id());
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
if (q.exec()) {
q.prepare("DELETE FROM LabelsInMessages WHERE label = :custom_id AND account_id = :account_id;");
q.bindValue(QSL(":custom_id"), label->customId());
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
return q.exec();
}
else {
return false;
}
}
bool DatabaseQueries::createLabel(const QSqlDatabase& db, Label* label, int account_id) {
QSqlQuery q(db);
@ -70,7 +106,10 @@ bool DatabaseQueries::createLabel(const QSqlDatabase& db, Label* label, int acco
label->setId(q.lastInsertId().toInt());
}
return res;
// Fixup missing custom IDs.
q.prepare("UPDATE Labels SET custom_id = id WHERE custom_id IS NULL OR custom_id = '';");
return q.exec() && res;
}
bool DatabaseQueries::markImportantMessagesReadUnread(const QSqlDatabase& db, int account_id, RootItem::ReadStatus read) {

View File

@ -20,6 +20,8 @@ class DatabaseQueries {
// Label operators.
static QList<Label*> getLabels(const QSqlDatabase& db, int account_id);
static bool updateLabel(const QSqlDatabase& db, Label* label);
static bool deleteLabel(const QSqlDatabase& db, Label* label);
static bool createLabel(const QSqlDatabase& db, Label* label, int account_id);
// Message operators.

View File

@ -2,6 +2,12 @@
#include "services/abstract/label.h"
#include "gui/dialogs/formaddeditlabel.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasefactory.h"
#include "miscellaneous/databasequeries.h"
#include "services/abstract/serviceroot.h"
#include <QPainter>
#include <QPainterPath>
@ -23,6 +29,39 @@ void Label::setColor(const QColor& color) {
m_color = color;
}
bool Label::canBeEdited() const {
return true;
}
bool Label::editViaGui() {
FormAddEditLabel form(qApp->mainFormWidget());
if (form.execForEdit(this)) {
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
return DatabaseQueries::updateLabel(db, this);
}
else {
return false;
}
}
bool Label::canBeDeleted() const {
return true;
}
bool Label::deleteViaGui() {
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
if (DatabaseQueries::deleteLabel(db, this)) {
getParentServiceRoot()->requestItemRemoval(this);
return true;
}
else {
return false;
}
}
QIcon Label::generateIcon(const QColor& color) {
QPixmap pxm(64, 64);

View File

@ -17,6 +17,10 @@ class Label : public RootItem {
QColor color() const;
void setColor(const QColor& color);
virtual bool canBeEdited() const;
virtual bool editViaGui();
virtual bool canBeDeleted() const;
virtual bool deleteViaGui();
static QIcon generateIcon(const QColor& color);
private:

View File

@ -12,7 +12,7 @@
LabelsNode::LabelsNode(const QList<Label*>& labels, RootItem* parent_item) : RootItem(parent_item), m_actLabelNew(nullptr) {
setKind(RootItem::Kind::Labels);
setId(ID_LABELS);
setIcon(qApp->icons()->fromTheme(QSL("mail-mark-important")));
setIcon(qApp->icons()->fromTheme(QSL("tag-folder")));
setTitle(tr("Labels"));
setDescription(tr("You can see all your labels (tags) here."));
setCreationDate(QDateTime::currentDateTime());
@ -25,7 +25,7 @@ LabelsNode::LabelsNode(const QList<Label*>& labels, RootItem* parent_item) : Roo
QList<QAction*> LabelsNode::contextMenuFeedsList() {
if (m_actLabelNew == nullptr) {
// Initialize it all.
m_actLabelNew = new QAction(qApp->icons()->fromTheme("tag-new"), tr("New label"), this);
m_actLabelNew = new QAction(qApp->icons()->fromTheme(QSL("tag-new")), tr("New label"), this);
connect(m_actLabelNew, &QAction::triggered, this, &LabelsNode::createLabel);
}

View File

@ -506,7 +506,7 @@ bool ServiceRoot::loadMessagesForItem(RootItem* item, MessagesModel* model) {
// Show messages with particular label.
model->setFilter(QString("Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1 AND "
"(SELECT COUNT(*) FROM LabelsInMessages WHERE account_id = %1 AND message = Messages.custom_id AND label = %2) > 0")
.arg(QString::number(accountId()), QString::number(item->id())));
.arg(QString::number(accountId()), item->customId()));
}
else if (item->kind() == RootItem::Kind::Labels) {
// Show messages with any label.