diff --git a/CMakeLists.txt b/CMakeLists.txt index aad1d82bf..c99512ae7 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,6 +381,7 @@ set(APP_SOURCES src/core/parsingfactory.cpp src/core/feeddownloader.cpp src/core/feedsimportexportmodel.cpp + src/core/feedsmodelrecyclebin.cpp # NETWORK-WEB sources. src/network-web/basenetworkaccessmanager.cpp @@ -457,6 +458,7 @@ set(APP_HEADERS src/core/feedsproxymodel.h src/core/feeddownloader.h src/core/feedsimportexportmodel.h + src/core/feedsmodelrecyclebin.h # NETWORK-WEB headers. src/network-web/webpage.h diff --git a/resources/graphics/icons/mini-kfaenza/folder-recycle-bin.png b/resources/graphics/icons/mini-kfaenza/folder-recycle-bin.png new file mode 100644 index 000000000..3bf56a1d3 Binary files /dev/null and b/resources/graphics/icons/mini-kfaenza/folder-recycle-bin.png differ diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index 85d12de9e..b4d399e15 100755 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -20,6 +20,7 @@ #include "definitions/definitions.h" #include "core/feedsmodelcategory.h" #include "core/feedsmodelfeed.h" +#include "core/feedsmodelrecyclebin.h" #include "core/feedsimportexportmodel.h" #include "miscellaneous/textfactory.h" #include "miscellaneous/databasefactory.h" @@ -690,6 +691,8 @@ void FeedsModel::loadFromDatabase() { // All data are now obtained, lets create the hierarchy. assembleCategories(categories); assembleFeeds(feeds); + + m_rootItem->appendChild(new FeedsModelRecycleBin()); } QList FeedsModel::feedsForIndex(const QModelIndex &index) { diff --git a/src/core/feedsmodelrecyclebin.cpp b/src/core/feedsmodelrecyclebin.cpp new file mode 100644 index 000000000..c29219664 --- /dev/null +++ b/src/core/feedsmodelrecyclebin.cpp @@ -0,0 +1,87 @@ +#include "core/feedsmodelrecyclebin.h" + +#include "miscellaneous/application.h" +#include "miscellaneous/iconfactory.h" + + +FeedsModelRecycleBin::FeedsModelRecycleBin(FeedsModelRootItem *parent) : FeedsModelRootItem(parent) { + m_kind = FeedsModelRootItem::RecycleBin; + m_icon = qApp->icons()->fromTheme("folder-recycle-bin"); + m_id = ID_RECYCLE_BIN; + m_title = tr("Recycle bin"); + m_description = tr("Recycle bin contains all deleted messages from all feeds."); + m_creationDate = QDateTime::currentDateTime(); +} + +FeedsModelRecycleBin::~FeedsModelRecycleBin() { +} + + +int FeedsModelRecycleBin::childCount() const { + return 0; +} + +void FeedsModelRecycleBin::appendChild(FeedsModelRootItem *child) { + Q_UNUSED(child) +} + +int FeedsModelRecycleBin::countOfUnreadMessages() const { + return 0; +} + +int FeedsModelRecycleBin::countOfAllMessages() const { + return 0; +} + + +QVariant FeedsModelRecycleBin::data(int column, int role) const { + switch (role) { + case Qt::DisplayRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_title; + } + else if (column == FDS_MODEL_COUNTS_INDEX) { + return qApp->settings()->value(APP_CFG_FEEDS, + "count_format", + "(%unread)").toString() + .replace("%unread", QString::number(countOfUnreadMessages())) + .replace("%all", QString::number(countOfAllMessages())); + } + else { + return QVariant(); + } + + case Qt::EditRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_title; + } + else if (column == FDS_MODEL_COUNTS_INDEX) { + return countOfUnreadMessages(); + } + else { + return QVariant(); + } + + case Qt::FontRole: + return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont; + + case Qt::DecorationRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_icon; + } + else { + return QVariant(); + } + + case Qt::TextAlignmentRole: + if (column == FDS_MODEL_COUNTS_INDEX) { + return Qt::AlignCenter; + } + else { + return QVariant(); + } + + default: + return QVariant(); + } +} diff --git a/src/core/feedsmodelrecyclebin.h b/src/core/feedsmodelrecyclebin.h new file mode 100644 index 000000000..c3e624d32 --- /dev/null +++ b/src/core/feedsmodelrecyclebin.h @@ -0,0 +1,23 @@ +#ifndef FEEDSMODELRECYCLEBIN_H +#define FEEDSMODELRECYCLEBIN_H + +#include "core/feedsmodelrootitem.h" + +#include + + +class FeedsModelRecycleBin : public FeedsModelRootItem { + Q_DECLARE_TR_FUNCTIONS(FeedsModelRecycleBin) + + public: + explicit FeedsModelRecycleBin(FeedsModelRootItem *parent = NULL); + virtual ~FeedsModelRecycleBin(); + + int childCount() const; + void appendChild(FeedsModelRootItem *child); + int countOfUnreadMessages() const; + int countOfAllMessages() const; + QVariant data(int column, int role) const; +}; + +#endif // FEEDSMODELRECYCLEBIN_H diff --git a/src/core/feedsmodelrootitem.cpp b/src/core/feedsmodelrootitem.cpp index 6189e2922..71bd81a74 100755 --- a/src/core/feedsmodelrootitem.cpp +++ b/src/core/feedsmodelrootitem.cpp @@ -38,7 +38,6 @@ FeedsModelRootItem::FeedsModelRootItem(FeedsModelRootItem *parent_item) FeedsModelRootItem::~FeedsModelRootItem() { qDebug("Destroying FeedsModelRootItem instance."); - qDeleteAll(m_childItems); } diff --git a/src/core/feedsmodelrootitem.h b/src/core/feedsmodelrootitem.h index 266b8b04f..65614fd84 100755 --- a/src/core/feedsmodelrootitem.h +++ b/src/core/feedsmodelrootitem.h @@ -31,9 +31,10 @@ class FeedsModelRootItem { public: // Describes the kind of the item. enum Kind { - RootItem = 1001, - Feed = 1002, - Category = 1003 + RootItem = 1001, + RecycleBin = 1002, + Feed = 1003, + Category = 1004 }; // Constructors and destructors. diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index 5507083e6..6882517f0 100755 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -31,7 +31,7 @@ MessagesModel::MessagesModel(QObject *parent) : QSqlTableModel(parent, qApp->database()->connection("MessagesModel", - DatabaseFactory::FromSettings)) { + DatabaseFactory::FromSettings)) { setObjectName("MessagesModel"); setupFonts(); setupIcons(); @@ -70,13 +70,18 @@ void MessagesModel::setupFonts() { void MessagesModel::loadMessages(const QList feed_ids) { m_currentFeeds = feed_ids; - QString assembled_ids = textualFeeds().join(", "); + if (feed_ids.size() == 1 && feed_ids[0] == ID_RECYCLE_BIN) { + setFilter("is_deleted = 1"); + } + else { + QString assembled_ids = textualFeeds().join(", "); + + setFilter(QString("feed IN (%1) AND is_deleted = 0").arg(assembled_ids)); + qDebug("Loading messages from feeds: %s.", qPrintable(assembled_ids)); + } - setFilter(QString("feed IN (%1) AND is_deleted = 0").arg(assembled_ids)); select(); fetchAll(); - - qDebug("Loading messages from feeds: %s.", qPrintable(assembled_ids)); } void MessagesModel::filterMessages(MessagesModel::DisplayFilter filter) { diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in index 9f8bb6492..b0b5b19f0 100755 --- a/src/definitions/definitions.h.in +++ b/src/definitions/definitions.h.in @@ -47,6 +47,7 @@ #define MAX_ZOOM_FACTOR 10.0 #define ICON_SIZE_SETTINGS 16 #define NO_PARENT_CATEGORY -1 +#define ID_RECYCLE_BIN -2 #define TRAY_ICON_BUBBLE_TIMEOUT 20000 #define KEY_MESSAGES_VIEW "messages_view_column_" #define CLOSE_LOCK_TIMEOUT 3000 diff --git a/src/gui/feedsview.cpp b/src/gui/feedsview.cpp index d4afae555..f86fc8dc5 100755 --- a/src/gui/feedsview.cpp +++ b/src/gui/feedsview.cpp @@ -347,8 +347,8 @@ void FeedsView::deleteSelectedItem() { } if (MessageBox::show(qApp->mainForm(), QMessageBox::Question, tr("Deleting feed or category"), - tr("You are about to delete selected feed or category."), tr("Do you really want to delete selected item?"), - QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) { + tr("You are about to delete selected feed or category."), tr("Do you really want to delete selected item?"), + QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) { // User changed his mind. qApp->closeLock()->unlock(); return; @@ -545,6 +545,16 @@ void FeedsView::selectionChanged(const QItemSelection &selected, m_selectedFeeds << feed->id(); } + if (m_selectedFeeds.isEmpty() && selectionModel()->selectedIndexes().size() > 0) { + QModelIndex selected_index = selectionModel()->selectedIndexes().at(0); + QModelIndex mapped_index = model()->mapToSource(selected_index); + FeedsModelRootItem *item = sourceModel()->itemForIndex(mapped_index); + + if (item->kind() == FeedsModelRootItem::RecycleBin) { + m_selectedFeeds.append(ID_RECYCLE_BIN); + } + } + emit feedsSelected(m_selectedFeeds); } @@ -557,14 +567,24 @@ void FeedsView::keyPressEvent(QKeyEvent *event) { } void FeedsView::contextMenuEvent(QContextMenuEvent *event) { - if (indexAt(event->pos()).isValid()) { - // Display context menu for categories. - if (m_contextMenuCategoriesFeeds == NULL) { - // Context menu is not initialized, initialize. - initializeContextMenuCategoriesFeeds(); - } + QModelIndex clicked_index = indexAt(event->pos()); - m_contextMenuCategoriesFeeds->exec(event->globalPos()); + if (clicked_index.isValid()) { + QModelIndex mapped_index = model()->mapToSource(clicked_index); + FeedsModelRootItem *clicked_item = sourceModel()->itemForIndex(mapped_index); + + if (clicked_item->kind() == FeedsModelRootItem::Category || clicked_item->kind() == FeedsModelRootItem::Feed) { + // Display context menu for categories. + if (m_contextMenuCategoriesFeeds == NULL) { + // Context menu is not initialized, initialize. + initializeContextMenuCategoriesFeeds(); + } + + m_contextMenuCategoriesFeeds->exec(event->globalPos()); + } + else if (clicked_item->kind() == FeedsModelRootItem::RecycleBin) { + // TODO: Display context menu for recycle bin. + } } else { // Display menu for empty space.