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 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <widget class="QTreeView" name="feedTreeView"/>
+ <widget class="QTreeView" name="feedTreeView">
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ </widget>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -44,6 +48,12 @@
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
+ <attribute name="verticalHeaderDefaultSectionSize">
+ <number>24</number>
+ </attribute>
+ <attribute name="verticalHeaderMinimumSectionSize">
+ <number>24</number>
+ </attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
@@ -123,6 +133,7 @@
<string>Feed</string>
</property>
<addaction name="actionNext_unread_news"/>
+ <addaction name="actionUpdate_this_feed"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuFeed"/>
@@ -151,6 +162,11 @@
<string>N</string>
</property>
</action>
+ <action name="actionUpdate_this_feed">
+ <property name="text">
+ <string>Update</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>