From 809e0c41cd60f7aa716da6a54e1b04c4fa0292f5 Mon Sep 17 00:00:00 2001 From: Leonardo Robol Date: Thu, 27 Oct 2011 16:24:22 +0200 Subject: [PATCH] Added possibility to remove feeds and categories. --- include/feedmodel.h | 10 ++++++++ include/mainwindow.h | 8 ++++++ include/rssparser.h | 5 ++++ larss/feedmodel.cpp | 57 +++++++++++++++++++++++++++++++++++++++++ larss/feedpoller.cpp | 6 ++--- larss/mainwindow.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++-- larss/rssparser.cpp | 19 ++++++++++++++ ui/mainwindow.ui | 18 ++++++++++++- 8 files changed, 188 insertions(+), 6 deletions(-) diff --git a/include/feedmodel.h b/include/feedmodel.h index 039970b..ae37145 100644 --- a/include/feedmodel.h +++ b/include/feedmodel.h @@ -48,6 +48,16 @@ public: bool addFeed (QString name, QString url, FeedNode* categoryNode); /** + * @brief Remove rows from the treeview + */ + bool removeElements (int row, int count, const QModelIndex &parent = QModelIndex()); + + /** + * @brief Remove a single row from the treeview. + */ + bool removeElement (int row, const QModelIndex &parent = QModelIndex()); + + /** * @brief Select data from the database. */ void select(); diff --git a/include/mainwindow.h b/include/mainwindow.h index 283f191..ab44d93 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -36,6 +36,14 @@ private slots: void on_actionNext_unread_news_triggered(); + void on_actionUpdate_this_feed_triggered(); + + void on_feedTreeView_customContextMenuRequested(const QPoint &pos); + + void removeSelectedFeed (); + + void removeSelectedCategory (); + public slots: /** * @brief Callback for the start of an update of a feed. diff --git a/include/rssparser.h b/include/rssparser.h index 53cca45..e9ba405 100644 --- a/include/rssparser.h +++ b/include/rssparser.h @@ -78,6 +78,11 @@ namespace Larss { int getNextUnread (const QModelIndex& index); /** + * @brief Delete all news that are from the given feed. + */ + void removeNewsForFeed (const QModelIndex& index); + + /** * @brief Database where all the news will be loaded and saved. */ QSqlDatabase db; diff --git a/larss/feedmodel.cpp b/larss/feedmodel.cpp index e79b57b..143e196 100644 --- a/larss/feedmodel.cpp +++ b/larss/feedmodel.cpp @@ -109,6 +109,63 @@ FeedModel::setData(const QModelIndex &index, const QVariant &value, int role) } bool +FeedModel::removeElements(int row, int count, const QModelIndex &parent) +{ + for(int i = 0; i < count; i++) + { + if (!removeElement(row, parent)) + return false; + } + return true; +} + +bool +FeedModel::removeElement(int row, const QModelIndex &parent) +{ + if (parent.isValid()) + { + // This means that this is a feed. + QModelIndex index = parent.child(row, 0); + FeedNode *node = itemFromIndex(index); + + QSqlQuery query(db); + query.prepare ("DELETE FROM feeds WHERE id=:feed;"); + query.bindValue("feed", node->id()); + + if (!query.exec()) + { + qDebug() << "Error removing a row"; + return false; + } + else + QStandardItemModel::removeRow(row, parent); + } + else + { + // This means that this is a feed. + QModelIndex index = this->index(row, 0, parent); + FeedNode *node = itemFromIndex(index); + QSqlQuery query(db); + query.prepare ("DELETE FROM categories WHERE id=:category"); + query.bindValue("category", node->id()); + + if (!query.exec()) + { + qDebug() << "Error removing a row"; + return false; + } + else + { + QStandardItemModel::removeRow(row, parent); + } + } + + return true; +} + + + +bool FeedModel::addCategory(QString name) { // First push the data in the database. diff --git a/larss/feedpoller.cpp b/larss/feedpoller.cpp index d8f479d..be46756 100644 --- a/larss/feedpoller.cpp +++ b/larss/feedpoller.cpp @@ -197,11 +197,11 @@ FeedPoller::networkManagerReplyFinished(QNetworkReply *reply) } } - // Commit the changes. - parser->db.commit(); - if (!parser->submitAll()) qDebug() << "Error submitting new data"; + + // Commit the changes. + parser->db.commit(); } else qDebug () << "Error parsing the document"; diff --git a/larss/mainwindow.cpp b/larss/mainwindow.cpp index cbbfe59..53a968b 100644 --- a/larss/mainwindow.cpp +++ b/larss/mainwindow.cpp @@ -31,7 +31,8 @@ MainWindow::MainWindow(QWidget *parent) : ui->feedTreeView->setModel(feedModel); ui->feedTreeView->setItemDelegate (new UnReadCountItemDelegate(feedModel, rssParser)); - // Load the RSSParser, hiding the unnecessary columns + // Load the RSSParser, hiding the unnecessary columns and applying + // some custom style :) ui->newsTableView->setModel(rssParser); ui->newsTableView->setColumnHidden(0, true); // ID ui->newsTableView->setColumnHidden(1, true); // Feed ID @@ -41,6 +42,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->newsTableView->setColumnHidden(7, true); // Read state ui->newsTableView->horizontalHeader()->setResizeMode(2, QHeaderView::Stretch); ui->newsTableView->horizontalHeader()->setResizeMode(6, QHeaderView::ResizeToContents); + ui->newsTableView->setAlternatingRowColors(true); // Show nothing for now. rssParser->setFilter("1 = 0"); @@ -50,7 +52,8 @@ MainWindow::MainWindow(QWidget *parent) : SLOT(loadingFeedStart(QString))); poller->start(); - // Install event filter to handle particular events. + // Install event filter to handle particular events, such as mouseclicks that + // triggers original article loading. ui->webViewTitleLabel->installEventFilter(this); loadedNews = ""; @@ -201,3 +204,67 @@ void Larss::MainWindow::on_actionNext_unread_news_triggered() loadFeed (ui->newsTableView->selectionModel()->currentIndex()); } } + +void Larss::MainWindow::on_actionUpdate_this_feed_triggered() +{ + QModelIndex index = ui->feedTreeView->selectionModel()->currentIndex(); + if (index.isValid()) + { + poller->queueWork(index); + } +} + +void Larss::MainWindow::on_feedTreeView_customContextMenuRequested(const QPoint &pos) +{ + QModelIndex index = ui->feedTreeView->indexAt(pos); + if (index.isValid()) + { + // Check if this is a category or not. + FeedNode *node = feedModel->itemFromIndex(index); + + QMenu popupMenu (this); + + if (node->type() == FeedNode::Feed) + { + popupMenu.addAction(tr("Update"), this, SLOT(on_actionUpdate_this_feed_triggered())); + popupMenu.addAction(tr("Remove"), this, + SLOT(removeSelectedFeed())); + } + else if (node->type() == FeedNode::Category) + { + popupMenu.addAction(tr("Remove"), this, + SLOT(removeSelectedCategory())); + } + + popupMenu.exec(ui->feedTreeView->mapToGlobal(pos)); + } +} + +void Larss::MainWindow::removeSelectedFeed() +{ + QModelIndex index = ui->feedTreeView->currentIndex(); + + // We need to remove all the feeds from that category + rssParser->removeNewsForFeed(index); + + // And then remove the feed itself. + feedModel->removeElement(index.row(), index.parent()); +} + +void Larss::MainWindow::removeSelectedCategory() +{ + // Check that the category is empty before removing it + QModelIndex index = ui->feedTreeView->currentIndex(); + if (feedModel->rowCount(index) > 0) + { + QMessageBox messageBox; + messageBox.setText("Impossible to remove category"); + messageBox.setInformativeText("Please remove feeds in this category before trying to remove it."); + + messageBox.exec (); + } + else + { + feedModel->removeElement(index.row()); + } +} diff --git a/larss/rssparser.cpp b/larss/rssparser.cpp index be2e6b5..62c0b66 100644 --- a/larss/rssparser.cpp +++ b/larss/rssparser.cpp @@ -183,3 +183,22 @@ Larss::RssParser::getNextUnread(const QModelIndex& starting) return -1; } + +void +Larss::RssParser::removeNewsForFeed(const QModelIndex& index) +{ + if (!index.isValid()) + return; + FeedNode *node = model->itemFromIndex(index); + + if (node->type() == FeedNode::Feed) + { + int id = node->id(); + QSqlQuery query(db); + query.prepare("DELETE FROM news WHERE feed=:feed"); + query.bindValue("feed", id); + + if (!query.exec()) + qDebug() << "Error deleting news from feed " << node->name(); + } +} diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 286a875..5c4de59 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -20,7 +20,11 @@ Qt::Horizontal - + + + Qt::CustomContextMenu + + Qt::Vertical @@ -44,6 +48,12 @@ false + + 24 + + + 24 + false @@ -123,6 +133,7 @@ Feed + @@ -151,6 +162,11 @@ N + + + Update + + -- 2.1.4