This commit is contained in:
Martin Rotter 2014-10-28 17:45:37 +01:00
parent bc2aa7f777
commit a539c9aacd
5 changed files with 126 additions and 7 deletions

View File

@ -9,6 +9,7 @@ Fixed:
Added: Added:
<ul> <ul>
<li>Items in feed list (categories and feeds) now can be re-arranged via drag-drop functionality (issue report #91).</li>
<li>Tray icon now displays blue number of unread messages if any of those messages is newly downloaded from online feed (enhancement #87).</li> <li>Tray icon now displays blue number of unread messages if any of those messages is newly downloaded from online feed (enhancement #87).</li>
<li>Fixed issue request #95: items are now permanently hidden (not deleted from database) when "deleted" from recycle bin.</li> <li>Fixed issue request #95: items are now permanently hidden (not deleted from database) when "deleted" from recycle bin.</li>
<li>Issue request #95: moreover custom incremental ability to update database schema was added to keep RSS Guard 2.0.0.4+ fully compatible with previous releases. Incremental algorithm supports both database backends.</li> <li>Issue request #95: moreover custom incremental ability to update database schema was added to keep RSS Guard 2.0.0.4+ fully compatible with previous releases. Incremental algorithm supports both database backends.</li>

View File

@ -25,12 +25,14 @@
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "miscellaneous/databasefactory.h" #include "miscellaneous/databasefactory.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "gui/messagebox.h"
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <QSqlRecord> #include <QSqlRecord>
#include <QPair> #include <QPair>
#include <QStack> #include <QStack>
#include <QMimeData>
#include <algorithm> #include <algorithm>
@ -66,6 +68,117 @@ FeedsModel::~FeedsModel() {
delete m_rootItem; delete m_rootItem;
} }
QMimeData *FeedsModel::mimeData(const QModelIndexList &indexes) const {
QMimeData *mime_data = new QMimeData();
QByteArray encoded_data;
QDataStream stream(&encoded_data, QIODevice::WriteOnly);
foreach (const QModelIndex &index, indexes) {
if (index.column() != 0) {
continue;
}
FeedsModelRootItem *item_for_index = itemForIndex(index);
if (item_for_index->kind() != FeedsModelRootItem::RootItem) {
stream << (quintptr) item_for_index;
}
}
mime_data->setData(MIME_TYPE_ITEM_POINTER, encoded_data);
return mime_data;
}
QStringList FeedsModel::mimeTypes() const {
return QStringList() << MIME_TYPE_ITEM_POINTER;
}
bool FeedsModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
Q_UNUSED(row)
Q_UNUSED(column)
if (action == Qt::IgnoreAction) {
return true;
}
else if (action != Qt::MoveAction) {
return false;
}
QByteArray dragged_items_data = data->data(MIME_TYPE_ITEM_POINTER);
if (dragged_items_data.isEmpty()) {
return false;
}
else {
QDataStream stream(&dragged_items_data, QIODevice::ReadOnly);
while (!stream.atEnd()) {
quintptr pointer_to_item;
stream >> pointer_to_item;
// We have item we want to drag, we also determine the target item.
FeedsModelRootItem *dragged_item = (FeedsModelRootItem*) pointer_to_item;
FeedsModelRootItem *target_item = itemForIndex(parent);
if (dragged_item == target_item || dragged_item->parent() == target_item) {
qDebug("Dragged item is equal to target item or its parent is equal to target item. Cancelling drag-drop action.");
return false;
}
if (dragged_item->kind() == FeedsModelRootItem::Feed) {
qDebug("Drag-drop action for feed '%s' detected, editing the feed.", qPrintable(dragged_item->title()));
FeedsModelFeed *actual_feed = static_cast<FeedsModelFeed*>(dragged_item);
FeedsModelFeed *feed_new = new FeedsModelFeed(*actual_feed);
feed_new->setParent(target_item);
editFeed(actual_feed, feed_new);
}
else if (dragged_item->kind() == FeedsModelRootItem::Category) {
qDebug("Drag-drop action for category '%s' detected, editing the feed.", qPrintable(dragged_item->title()));
FeedsModelCategory *actual_category = static_cast<FeedsModelCategory*>(dragged_item);
FeedsModelCategory *category_new = new FeedsModelCategory(*actual_category);
category_new->clearChildren();
category_new->setParent(target_item);
editCategory(actual_category, category_new);
}
}
return true;
}
}
Qt::DropActions FeedsModel::supportedDropActions() const {
return Qt::MoveAction;
}
Qt::ItemFlags FeedsModel::flags(const QModelIndex &index) const {
Qt::ItemFlags base_flags = QAbstractItemModel::flags(index);
FeedsModelRootItem *item_for_index = itemForIndex(index);
switch (item_for_index->kind()) {
case FeedsModelRootItem::RecycleBin:
return base_flags;
case FeedsModelRootItem::Category:
return base_flags | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
case FeedsModelRootItem::Feed:
return base_flags | Qt::ItemIsDragEnabled;
case FeedsModelRootItem::RootItem:
default:
return base_flags | Qt::ItemIsDropEnabled;
}
// TODO: Pokračovat tady: http://qt-project.org/doc/qt-4.8/model-view-programming.html#using-drag-and-drop-with-item-views
// neumožnit drag ani drop nad odpadkovým košem
}
QVariant FeedsModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant FeedsModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation != Qt::Horizontal) { if (orientation != Qt::Horizontal) {
return QVariant(); return QVariant();
@ -210,8 +323,7 @@ bool FeedsModel::addCategory(FeedsModelCategory *category, FeedsModelRootItem *p
} }
bool FeedsModel::editCategory(FeedsModelCategory *original_category, FeedsModelCategory *new_category) { bool FeedsModel::editCategory(FeedsModelCategory *original_category, FeedsModelCategory *new_category) {
QSqlDatabase database = qApp->database()->connection(objectName(), QSqlDatabase database = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings);
DatabaseFactory::FromSettings);
QSqlQuery query_update_category(database); QSqlQuery query_update_category(database);
FeedsModelRootItem *original_parent = original_category->parent(); FeedsModelRootItem *original_parent = original_category->parent();
FeedsModelRootItem *new_parent = new_category->parent(); FeedsModelRootItem *new_parent = new_category->parent();
@ -313,8 +425,7 @@ bool FeedsModel::addFeed(FeedsModelFeed *feed, FeedsModelRootItem *parent) {
} }
bool FeedsModel::editFeed(FeedsModelFeed *original_feed, FeedsModelFeed *new_feed) { bool FeedsModel::editFeed(FeedsModelFeed *original_feed, FeedsModelFeed *new_feed) {
QSqlDatabase database = qApp->database()->connection(objectName(), QSqlDatabase database = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings);
DatabaseFactory::FromSettings);
QSqlQuery query_update_feed(database); QSqlQuery query_update_feed(database);
FeedsModelRootItem *original_parent = original_feed->parent(); FeedsModelRootItem *original_parent = original_feed->parent();
FeedsModelRootItem *new_parent = new_feed->parent(); FeedsModelRootItem *new_parent = new_feed->parent();

View File

@ -51,6 +51,11 @@ class FeedsModel : public QAbstractItemModel {
return itemForIndex(index)->data(index.column(), role); return itemForIndex(index)->data(index.column(), role);
} }
QMimeData *mimeData(const QModelIndexList &indexes) const;
QStringList mimeTypes() const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
Qt::DropActions supportedDropActions() const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &child) const; QModelIndex parent(const QModelIndex &child) const;

View File

@ -75,6 +75,8 @@
#define FEEDS_VIEW_INDENTATION 10 #define FEEDS_VIEW_INDENTATION 10
#define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7" #define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7"
#define MIME_TYPE_ITEM_POINTER "rssguard/itempointer"
#define BACKUP_NAME_SETTINGS "config" #define BACKUP_NAME_SETTINGS "config"
#define BACKUP_SUFFIX_SETTINGS ".ini.backup" #define BACKUP_SUFFIX_SETTINGS ".ini.backup"
#define BACKUP_NAME_DATABASE "database" #define BACKUP_NAME_DATABASE "database"

View File

@ -603,9 +603,9 @@ void FeedsView::setupAppearance() {
setEditTriggers(QAbstractItemView::NoEditTriggers); setEditTriggers(QAbstractItemView::NoEditTriggers);
setIndentation(FEEDS_VIEW_INDENTATION); setIndentation(FEEDS_VIEW_INDENTATION);
setAcceptDrops(false); setAcceptDrops(false);
setDragEnabled(false); setDragEnabled(true);
setDropIndicatorShown(false); setDropIndicatorShown(true);
setDragDropMode(QAbstractItemView::NoDragDrop); setDragDropMode(QAbstractItemView::InternalMove);
setAllColumnsShowFocus(false); setAllColumnsShowFocus(false);
setRootIsDecorated(false); setRootIsDecorated(false);
setSelectionMode(QAbstractItemView::SingleSelection); setSelectionMode(QAbstractItemView::SingleSelection);