mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-26 09:21:21 -05:00
Support moving entries with drag and drop.
This commit is contained in:
parent
79b6ff99e4
commit
74ac6c27d7
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include "EntryModel.h"
|
#include "EntryModel.h"
|
||||||
|
|
||||||
|
#include <QtCore/QMimeData>
|
||||||
|
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ EntryModel::EntryModel(QObject* parent)
|
|||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
, m_group(0)
|
, m_group(0)
|
||||||
{
|
{
|
||||||
|
setSupportedDragActions(Qt::MoveAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* EntryModel::entryFromIndex(const QModelIndex& index) const
|
Entry* EntryModel::entryFromIndex(const QModelIndex& index) const
|
||||||
@ -106,6 +109,49 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::DropActions EntryModel::supportedDropActions() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags EntryModel::flags(const QModelIndex& modelIndex) const
|
||||||
|
{
|
||||||
|
if (!modelIndex.isValid()) {
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDragEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntryModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
QStringList types;
|
||||||
|
types << QLatin1String("application/x-keepassx-entry");
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const
|
||||||
|
{
|
||||||
|
if (indexes.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* data = new QMimeData();
|
||||||
|
QByteArray encoded;
|
||||||
|
QDataStream stream(&encoded, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
for (int i = 0; i < indexes.size(); i++) {
|
||||||
|
if (!indexes[i].isValid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stream << m_group->database()->uuid() << entryFromIndex(indexes[i])->uuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
data->setData(mimeTypes().first(), encoded);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void EntryModel::entryAboutToAdd(Entry* entry)
|
void EntryModel::entryAboutToAdd(Entry* entry)
|
||||||
{
|
{
|
||||||
Q_UNUSED(entry);
|
Q_UNUSED(entry);
|
||||||
|
@ -35,6 +35,10 @@ public:
|
|||||||
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
Qt::DropActions supportedDropActions() const;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& modelIndex) const;
|
||||||
|
QStringList mimeTypes() const;
|
||||||
|
QMimeData* mimeData(const QModelIndexList& indexes) const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setGroup(Group* group);
|
void setGroup(Group* group);
|
||||||
|
@ -27,6 +27,7 @@ EntryView::EntryView(QWidget* parent)
|
|||||||
|
|
||||||
setUniformRowHeights(true);
|
setUniformRowHeights(true);
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
|
setDragEnabled(true);
|
||||||
|
|
||||||
connect(this, SIGNAL(activated(const QModelIndex&)), SLOT(emitEntryActivated(const QModelIndex&)));
|
connect(this, SIGNAL(activated(const QModelIndex&)), SLOT(emitEntryActivated(const QModelIndex&)));
|
||||||
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(entrySelectionChanged()));
|
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(entrySelectionChanged()));
|
||||||
|
@ -180,9 +180,10 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
|||||||
|
|
||||||
// check if the format is supported
|
// check if the format is supported
|
||||||
QStringList types = mimeTypes();
|
QStringList types = mimeTypes();
|
||||||
Q_ASSERT(!types.isEmpty());
|
Q_ASSERT(types.size() == 2);
|
||||||
QString format = types.at(0);
|
bool isGroup = data->hasFormat(types.at(0));
|
||||||
if (!data->hasFormat(format)) {
|
bool isEntry = data->hasFormat(types.at(1));
|
||||||
|
if (!isGroup && !isEntry) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,23 +192,25 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decode and insert
|
// decode and insert
|
||||||
QByteArray encoded = data->data(format);
|
QByteArray encoded = data->data(isGroup ? types.at(0) : types.at(1));
|
||||||
QDataStream stream(&encoded, QIODevice::ReadOnly);
|
QDataStream stream(&encoded, QIODevice::ReadOnly);
|
||||||
Uuid dbUuid;
|
Uuid dbUuid;
|
||||||
Uuid groupUuid;
|
Uuid itemUuid;
|
||||||
stream >> dbUuid >> groupUuid;
|
stream >> dbUuid >> itemUuid;
|
||||||
|
|
||||||
Database* db = Database::databaseByUuid(dbUuid);
|
Database* db = Database::databaseByUuid(dbUuid);
|
||||||
if (!db) {
|
if (!db) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Group* dragGroup = db->resolveGroup(groupUuid);
|
|
||||||
|
Group* parentGroup = groupFromIndex(parent);
|
||||||
|
|
||||||
|
if (isGroup) {
|
||||||
|
Group* dragGroup = db->resolveGroup(itemUuid);
|
||||||
if (!dragGroup || !Tools::hasChild(db, dragGroup) || dragGroup == db->rootGroup()) {
|
if (!dragGroup || !Tools::hasChild(db, dragGroup) || dragGroup == db->rootGroup()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* parentGroup = groupFromIndex(parent);
|
|
||||||
|
|
||||||
if (dragGroup == parentGroup || Tools::hasChild(dragGroup, parentGroup)) {
|
if (dragGroup == parentGroup || Tools::hasChild(dragGroup, parentGroup)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -217,13 +220,24 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dragGroup->setParent(parentGroup, row);
|
dragGroup->setParent(parentGroup, row);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Entry* dragEntry = db->resolveEntry(itemUuid);
|
||||||
|
if (!dragEntry || !Tools::hasChild(db, dragEntry) || row != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dragEntry->setGroup(parentGroup);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GroupModel::mimeTypes() const
|
QStringList GroupModel::mimeTypes() const
|
||||||
{
|
{
|
||||||
QStringList types;
|
QStringList types;
|
||||||
types << QLatin1String("application/x-keepassx-group");
|
types << "application/x-keepassx-group";
|
||||||
|
types << "application/x-keepassx-entry";
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "GroupView.h"
|
#include "GroupView.h"
|
||||||
|
|
||||||
#include <QtCore/QMetaObject>
|
#include <QtCore/QMetaObject>
|
||||||
|
#include <QtGui/QDragMoveEvent>
|
||||||
|
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
@ -46,6 +47,17 @@ GroupView::GroupView(Database* db, QWidget* parent)
|
|||||||
setDropIndicatorShown(true);
|
setDropIndicatorShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupView::dragMoveEvent(QDragMoveEvent* event)
|
||||||
|
{
|
||||||
|
QTreeView::dragMoveEvent(event);
|
||||||
|
|
||||||
|
// entries may only be dropped on groups
|
||||||
|
if (event->isAccepted() && event->mimeData()->hasFormat("application/x-keepassx-entry")
|
||||||
|
&& (dropIndicatorPosition() == AboveItem || dropIndicatorPosition() == BelowItem)) {
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Group* GroupView::currentGroup()
|
Group* GroupView::currentGroup()
|
||||||
{
|
{
|
||||||
return m_model->groupFromIndex(currentIndex());
|
return m_model->groupFromIndex(currentIndex());
|
||||||
|
@ -41,6 +41,9 @@ private Q_SLOTS:
|
|||||||
void emitGroupChanged(const QModelIndex& index);
|
void emitGroupChanged(const QModelIndex& index);
|
||||||
void emitGroupChanged();
|
void emitGroupChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragMoveEvent(QDragMoveEvent* event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recInitExpanded(Group* group);
|
void recInitExpanded(Group* group);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user