mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-02 09:34:58 -05:00
Support moving groups with drag and drop.
This commit is contained in:
parent
9e0a6ad2d8
commit
d3fbb291bd
@ -17,8 +17,11 @@
|
|||||||
|
|
||||||
#include "GroupModel.h"
|
#include "GroupModel.h"
|
||||||
|
|
||||||
|
#include <QtCore/QMimeData>
|
||||||
|
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
|
#include "core/Tools.h"
|
||||||
|
|
||||||
GroupModel::GroupModel(Database* db, QObject* parent)
|
GroupModel::GroupModel(Database* db, QObject* parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
@ -148,6 +151,103 @@ Group* GroupModel::groupFromIndex(const QModelIndex& index) const
|
|||||||
return static_cast<Group*>(index.internalPointer());
|
return static_cast<Group*>(index.internalPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::DropActions GroupModel::supportedDropActions() const
|
||||||
|
{
|
||||||
|
return Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags GroupModel::flags(const QModelIndex& modelIndex) const
|
||||||
|
{
|
||||||
|
if (!modelIndex.isValid()) {
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
}
|
||||||
|
else if (modelIndex == index(0, 0)) {
|
||||||
|
return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDropEnabled;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
||||||
|
int row, int column, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(column);
|
||||||
|
|
||||||
|
if (!data || (action != Qt::MoveAction) || !parent.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the format is supported
|
||||||
|
QStringList types = mimeTypes();
|
||||||
|
Q_ASSERT(!types.isEmpty());
|
||||||
|
QString format = types.at(0);
|
||||||
|
if (!data->hasFormat(format)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row > rowCount(parent)) {
|
||||||
|
row = rowCount(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode and insert
|
||||||
|
QByteArray encoded = data->data(format);
|
||||||
|
QDataStream stream(&encoded, QIODevice::ReadOnly);
|
||||||
|
Uuid dbUuid;
|
||||||
|
Uuid groupUuid;
|
||||||
|
stream >> dbUuid >> groupUuid;
|
||||||
|
|
||||||
|
Database* db = Database::databaseByUuid(dbUuid);
|
||||||
|
if (!db) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Group* dragGroup = db->resolveGroup(groupUuid);
|
||||||
|
if (!dragGroup || !Tools::hasChild(db, dragGroup) || dragGroup == db->rootGroup()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Group* parentGroup = groupFromIndex(parent);
|
||||||
|
|
||||||
|
if (dragGroup == parentGroup || Tools::hasChild(dragGroup, parentGroup)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentGroup == dragGroup->parent() && row > parentGroup->children().indexOf(dragGroup)) {
|
||||||
|
row--;
|
||||||
|
}
|
||||||
|
|
||||||
|
dragGroup->setParent(parentGroup, row);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList GroupModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
QStringList types;
|
||||||
|
types << QLatin1String("application/x-keepassx-group");
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* GroupModel::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_root->database()->uuid() << groupFromIndex(indexes[i])->uuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
data->setData(mimeTypes().first(), encoded);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void GroupModel::groupDataChanged(Group* group)
|
void GroupModel::groupDataChanged(Group* group)
|
||||||
{
|
{
|
||||||
QModelIndex ix = index(group);
|
QModelIndex ix = index(group);
|
||||||
@ -196,7 +296,9 @@ void GroupModel::groupAboutToMove(Group* group, Group* toGroup, int pos)
|
|||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
beginMoveRows(oldParentIndex, oldPos, oldPos, newParentIndex, pos);
|
bool moveResult = beginMoveRows(oldParentIndex, oldPos, oldPos, newParentIndex, pos);
|
||||||
|
Q_UNUSED(moveResult);
|
||||||
|
Q_ASSERT(moveResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupModel::groupMoved()
|
void GroupModel::groupMoved()
|
||||||
|
@ -38,6 +38,12 @@ public:
|
|||||||
QModelIndex parent(const QModelIndex& index) const;
|
QModelIndex parent(const QModelIndex& index) 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;
|
||||||
|
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
|
||||||
|
const QModelIndex& parent);
|
||||||
|
QStringList mimeTypes() const;
|
||||||
|
QMimeData* mimeData(const QModelIndexList& indexes) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex parent(Group* group) const;
|
QModelIndex parent(Group* group) const;
|
||||||
|
@ -40,6 +40,10 @@ GroupView::GroupView(Database* db, QWidget* parent)
|
|||||||
// invoke later so the EntryView is connected
|
// invoke later so the EntryView is connected
|
||||||
QMetaObject::invokeMethod(this, "emitGroupChanged", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(this, "emitGroupChanged", Qt::QueuedConnection,
|
||||||
Q_ARG(QModelIndex, m_model->index(0, 0)));
|
Q_ARG(QModelIndex, m_model->index(0, 0)));
|
||||||
|
|
||||||
|
setDragEnabled(true);
|
||||||
|
viewport()->setAcceptDrops(true);
|
||||||
|
setDropIndicatorShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* GroupView::currentGroup()
|
Group* GroupView::currentGroup()
|
||||||
|
@ -91,7 +91,7 @@ void TestGroupModel::test()
|
|||||||
QSignalSpy spyMoved(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
QSignalSpy spyMoved(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
|
||||||
Group* group2 = new Group();
|
Group* group2 = new Group();
|
||||||
group1->setObjectName("group2");
|
group2->setObjectName("group2");
|
||||||
group2->setName("group2");
|
group2->setName("group2");
|
||||||
group2->setParent(groupRoot);
|
group2->setParent(groupRoot);
|
||||||
QModelIndex index2 = model->index(1, 0, indexRoot);
|
QModelIndex index2 = model->index(1, 0, indexRoot);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user