[qet] [4325] Element collection : improve drag and drop behavior |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qet Archives
]
Revision: 4325
Author: blacksun
Date: 2016-01-16 15:25:20 +0100 (Sat, 16 Jan 2016)
Log Message:
-----------
Element collection : improve drag and drop behavior
Modified Paths:
--------------
trunk/sources/ElementsCollection/elementcollectionitem.cpp
trunk/sources/ElementsCollection/elementcollectionitem.h
trunk/sources/ElementsCollection/elementlocation.cpp
trunk/sources/ElementsCollection/elementlocation.h
trunk/sources/ElementsCollection/elementscollectionmodel.cpp
trunk/sources/ElementsCollection/elementscollectionwidget.cpp
trunk/sources/ElementsCollection/fileelementcollectionitem.cpp
trunk/sources/ElementsCollection/fileelementcollectionitem.h
trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp
trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.h
Modified: trunk/sources/ElementsCollection/elementcollectionitem.cpp
===================================================================
--- trunk/sources/ElementsCollection/elementcollectionitem.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementcollectionitem.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -63,6 +63,13 @@
return true;
}
+/**
+ * @brief ElementCollectionItem::insertChild
+ * Insert item at position row in the child item list
+ * @param row
+ * @param item
+ * @return true if item was inserted, if item is already a chil of this item, return false
+ */
bool ElementCollectionItem::insertChild(int row, ElementCollectionItem *item)
{
if (m_child_items.contains(item)) return false;
@@ -96,6 +103,78 @@
}
/**
+ * @brief ElementCollectionItem::lastItemForPath
+ * Return the last existing item in this ElementCollectionItem hierarchy according to the given path.
+ * Next_item is the first non existing item in this hierarchy according to the given path.
+ * @param path : The path to find last item. The path must be in form : path/otherPath/.../.../myElement.elmt.
+ * @param newt_item : The first item that not exist in this hierarchy
+ * @return : The last item that exist in this hierarchy, or nullptr can't find (an error was occurred, or path already exist)
+ */
+ElementCollectionItem *ElementCollectionItem::lastItemForPath(const QString &path, QString &newt_item)
+{
+ QStringList str_list = path.split("/");
+ if (str_list.isEmpty()) return nullptr;
+
+ ElementCollectionItem *return_eci = this;
+ foreach (QString str, str_list)
+ {
+ ElementCollectionItem *eci = return_eci->childWithCollectionName(str);
+ if (!eci)
+ {
+ newt_item = str;
+ return return_eci;
+ }
+ else
+ return_eci = eci;
+ }
+
+ return nullptr;
+}
+
+/**
+ * @brief ElementCollectionItem::rowForInsertItem
+ * Return the row for insert a new child item to this item with name @collection_name.
+ * If row can't be found (collection_name is null, or already exist) return -1;
+ * @param collection_name
+ * @return
+ */
+int ElementCollectionItem::rowForInsertItem(const QString &collection_name)
+{
+ if (collection_name.isEmpty()) return -1;
+
+ QList <ElementCollectionItem *> child;
+ //The item to insert is an element we search from element child
+ if (collection_name.endsWith(".elmt"))
+ {
+ child = elementsChild();
+ //There isn't element, we insert at last position
+ if (child.isEmpty())
+ return childCount();
+ }
+ //The item is a directory, we search from directory child
+ else
+ {
+ child = directoriesChild();
+ //There isn't directory, we insert at first position
+ if(child.isEmpty())
+ return 0;
+ }
+
+ foreach (ElementCollectionItem *eci, child)
+ if (eci->collectionName() > collection_name)
+ return indexOfChild(eci);
+
+ return childCount();
+}
+
+/**
+ * @brief ElementCollectionItem::insertNewItem
+ * By defualt do nothing, implement this method in subclass
+ * to handle the insertion of a new item with name collection_name
+ */
+void ElementCollectionItem::insertNewItem(const QString &collection_name) {Q_UNUSED (collection_name);}
+
+/**
* @brief ElementCollectionItem::childCount
* @return the number of childs of this item
*/
@@ -131,15 +210,15 @@
return new QMimeData();
}
-bool ElementCollectionItem::canDropMimeData(const QMimeData *data, Qt::DropAction action, int column) const
+bool ElementCollectionItem::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column) const
{
- Q_UNUSED(data); Q_UNUSED(action); Q_UNUSED(column);
+ Q_UNUSED(data); Q_UNUSED(action); Q_UNUSED(row); Q_UNUSED(column);
return false;
}
-bool ElementCollectionItem::dropMimeData(const QMimeData *data, Qt::DropAction action, int column)
+bool ElementCollectionItem::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column)
{
- Q_UNUSED(data); Q_UNUSED(action); Q_UNUSED(column);
+ Q_UNUSED(data); Q_UNUSED(action); Q_UNUSED(row); Q_UNUSED(column);
return false;
}
Modified: trunk/sources/ElementsCollection/elementcollectionitem.h
===================================================================
--- trunk/sources/ElementsCollection/elementcollectionitem.h 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementcollectionitem.h 2016-01-16 14:25:20 UTC (rev 4325)
@@ -19,6 +19,7 @@
#define ELEMENTCOLLECTIONITEM_H
#include <QVariant>
+#include "elementlocation.h"
class QMimeData;
class ElementCollectionItem;
@@ -44,12 +45,15 @@
bool insertChild (int row, ElementCollectionItem *item);
ElementCollectionItem *child(int row);
ElementCollectionItem *childWithCollectionName(QString name) const;
+ ElementCollectionItem *lastItemForPath(const QString &path, QString &newt_item);
+ int rowForInsertItem(const QString &collection_name);
+ virtual void insertNewItem(const QString &collection_name);
int childCount() const;
int columnCount() const;
virtual QVariant data(int column, int role);
virtual QMimeData *mimeData();
- virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int column) const;
- virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int column);
+ virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column) const;
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column);
virtual Qt::ItemFlags flags();
ElementCollectionItem *parent();
int row() const;
Modified: trunk/sources/ElementsCollection/elementlocation.cpp
===================================================================
--- trunk/sources/ElementsCollection/elementlocation.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementlocation.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -27,8 +27,7 @@
* @brief ElementLocation::ElementLocation
* @param path : path of item in file system
*/
-ElementLocation::ElementLocation(QString path):
- m_project(nullptr)
+ElementLocation::ElementLocation(QString path)
{
if (!path.isEmpty())
setPath(path);
@@ -47,6 +46,19 @@
setPath(path);
}
+/**
+ * @brief ElementLocation::ElementLocation
+ * Constructor, build an ElementLocation from a QMimeData, the mime data format
+ * must be "application/x-qet-element-uri" or "application/x-qet-category-uri".
+ * This location can be null even if format is valid.
+ * @param data
+ */
+ElementLocation::ElementLocation(const QMimeData *data)
+{
+ if (data->hasFormat("application/x-qet-element-uri") || data->hasFormat("application/x-qet-category-uri"))
+ setPath(data->text());
+}
+
ElementLocation::~ElementLocation()
{}
@@ -194,9 +206,10 @@
*/
bool ElementLocation::isNull() const
{
- if (!m_file_system_path.isEmpty()) return false;
- else if (!m_collection_path.isEmpty()) return false;
- else return true;
+ if (isFileSystem() || isProject())
+ return false;
+ else
+ return true;
}
/**
@@ -224,6 +237,29 @@
}
/**
+ * @brief ElementLocation::isFileSystem
+ * @return True if this location represent a file system item.
+ */
+bool ElementLocation::isFileSystem() const
+{
+ if (m_project) return false;
+ if (m_file_system_path.isEmpty()) return false;
+ return true;
+}
+
+/**
+ * @brief ElementLocation::isProject
+ * @return True if this location represent an item from a project.
+ */
+bool ElementLocation::isProject() const
+{
+ if (m_project && !m_collection_path.isEmpty())
+ return true;
+ else
+ return false;
+}
+
+/**
* @brief ElementLocation::collectionPath
* @return the colletion relative to the collection
*/
Modified: trunk/sources/ElementsCollection/elementlocation.h
===================================================================
--- trunk/sources/ElementsCollection/elementlocation.h 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementlocation.h 2016-01-16 14:25:20 UTC (rev 4325)
@@ -24,6 +24,7 @@
#include <QIcon>
class QETProject;
+class QMimeData;
/**
* @brief The ElementLocation class
@@ -36,6 +37,7 @@
public:
ElementLocation(QString path = QString());
ElementLocation(QString path, QETProject *project);
+ ElementLocation(const QMimeData *data);
~ElementLocation();
bool setPath(QString path);
@@ -44,6 +46,7 @@
bool isElement() const;
bool isDirectory() const;
bool isFileSystem() const;
+ bool isProject() const;
QString collectionPath(bool protocol = true) const;
QString fileSystemPath() const;
@@ -59,7 +62,7 @@
private:
QString m_collection_path;
QString m_file_system_path;
- QETProject *m_project;
+ QETProject *m_project = nullptr;
QDomElement m_xml;
QUuid m_uuid;
QIcon m_icon;
Modified: trunk/sources/ElementsCollection/elementscollectionmodel.cpp
===================================================================
--- trunk/sources/ElementsCollection/elementscollectionmodel.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementscollectionmodel.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -193,32 +193,32 @@
bool ElementsCollectionModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
{
- if (!parent.isValid())
- return false;
+ if (!(QAbstractItemModel::canDropMimeData(data, action, row, column, parent) && parent.isValid())) return false;
- if (!hasIndex(row, column, parent)) return false;
+ ElementCollectionItem *eci = static_cast <ElementCollectionItem *>(parent.internalPointer());
+ if (!eci) return false;
- QModelIndex item = index(row, column, parent);
-
- if (item.isValid())
- return static_cast<ElementCollectionItem*>(item.internalPointer())->canDropMimeData(data, action, column);
- else
- return false;
-
+ return eci->canDropMimeData(data, action, row, column);
}
bool ElementsCollectionModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
if (!parent.isValid()) return false;
- if (!hasIndex(row, column, parent)) return false;
+ ElementLocation location(data);
+ if (location.isNull()) return false;
- QModelIndex item = index(row, column, parent);
+ ElementCollectionItem *eci = static_cast<ElementCollectionItem*> (parent.internalPointer());
+ if (!eci) return false;
+ if (eci->isElement()) eci = eci->parent();
- if (item.isValid())
- return static_cast<ElementCollectionItem*>(item.internalPointer())->dropMimeData(data, action, column);
- else
- return false;
+ int i = eci->rowForInsertItem(location.fileName());
+ if (i < 0) return false;
+
+ beginInsertRows(parent, i, i);
+ bool rb = eci->dropMimeData(data, action, row, column);
+ endInsertRows();
+ return rb;
}
QStringList ElementsCollectionModel::mimeTypes() const
@@ -342,14 +342,13 @@
if (!xpeci) return;
QString collection_name;
- XmlProjectElementCollectionItem *parent_xpeci = xpeci->lastItemForPath(path, collection_name);
- if (parent_xpeci)
- {
- int new_row = parent_xpeci->rowForInsertItem(collection_name);
- if (new_row <= -1) return;
- QModelIndex parent_index = createIndex(parent_xpeci->row(), 0, parent_xpeci);
- beginInsertRows(parent_index, new_row, new_row);
- parent_xpeci->insertNewItem(collection_name);
- endInsertRows();
- }
+ ElementCollectionItem *eci = xpeci->lastItemForPath(path, collection_name);
+ if (!eci) return;
+
+ int new_row = eci->rowForInsertItem(collection_name);
+ if (new_row <= -1) return;
+ QModelIndex parent_index = createIndex(eci->row(), 0, eci);
+ beginInsertRows(parent_index, new_row, new_row);
+ eci->insertNewItem(collection_name);
+ endInsertRows();
}
Modified: trunk/sources/ElementsCollection/elementscollectionwidget.cpp
===================================================================
--- trunk/sources/ElementsCollection/elementscollectionwidget.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/elementscollectionwidget.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -115,6 +115,9 @@
m_tree_view->setIconSize(QSize(50, 50));
m_tree_view->setDragDropMode(QAbstractItemView::DragDrop);
m_tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_tree_view->setAutoExpandDelay(500);
+ m_tree_view->setAnimated(true);
+ m_tree_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_main_vlayout->addWidget(m_tree_view);
//Setup the progress bar
Modified: trunk/sources/ElementsCollection/fileelementcollectionitem.cpp
===================================================================
--- trunk/sources/ElementsCollection/fileelementcollectionitem.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/fileelementcollectionitem.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -122,6 +122,16 @@
}
/**
+ * @brief FileElementCollectionItem::collectionName
+ * @return The collection name of this item
+ */
+QString FileElementCollectionItem::collectionName() const
+{
+ if (isCollectionRoot()) return QString();
+ else return m_path;
+}
+
+/**
* @brief FileElementCollectionItem::data
* @param column
* @param role
@@ -195,9 +205,9 @@
* @param column
* @return True if the data can be dropped
*/
-bool FileElementCollectionItem::canDropMimeData(const QMimeData *data, Qt::DropAction action, int column) const
+bool FileElementCollectionItem::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column) const
{
- Q_UNUSED(action); Q_UNUSED(column);
+ Q_UNUSED(action); Q_UNUSED(row); Q_UNUSED(column);
if (isCommonCollection()) return false;
if (data->hasFormat("application/x-qet-element-uri") || data->hasFormat("application/x-qet-category-uri"))
@@ -213,9 +223,9 @@
* @param column
* @return Handle the drop of a data
*/
-bool FileElementCollectionItem::dropMimeData(const QMimeData *data, Qt::DropAction action, int column)
+bool FileElementCollectionItem::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column)
{
- Q_UNUSED(action); Q_UNUSED(column);
+ Q_UNUSED(action); Q_UNUSED(row); Q_UNUSED(column);
if (isCommonCollection()) return false;
FileElementCollectionItem *feci = this;
@@ -381,6 +391,15 @@
return false;
}
+void FileElementCollectionItem::insertNewItem(const QString &collection_name)
+{
+ if (collection_name.isEmpty()) return;
+
+ FileElementCollectionItem *feci = new FileElementCollectionItem(this);
+ feci->setPathName(collection_name);
+ insertChild(rowForInsertItem(collection_name), feci);
+}
+
/**
* @brief FileElementCollectionItem::setPathName
* Set the name of this item in the file system path.
@@ -434,7 +453,9 @@
bool FileElementCollectionItem::handleElementDrop(const QMimeData *data)
{
ElementLocation location(data->text());
- return QFile::copy(location.fileSystemPath(), fileSystemPath() + "/" + location.fileSystemPath().split("/").last());
+ bool rb = QFile::copy(location.fileSystemPath(), fileSystemPath() + "/" + location.fileSystemPath().split("/").last());
+ if (rb) insertNewItem(location.fileName());
+ return rb;
}
/**
@@ -449,7 +470,11 @@
QDir origin_dir(location.fileSystemPath());
if (origin_dir.exists())
- return createSubDir(origin_dir, QDir(fileSystemPath()));
+ {
+ bool rb = createSubDir(origin_dir, QDir(fileSystemPath()));
+ if(rb) insertNewItem(location.fileName());
+ return rb;
+ }
else
return false;
}
Modified: trunk/sources/ElementsCollection/fileelementcollectionitem.h
===================================================================
--- trunk/sources/ElementsCollection/fileelementcollectionitem.h 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/fileelementcollectionitem.h 2016-01-16 14:25:20 UTC (rev 4325)
@@ -42,11 +42,12 @@
QString dirPath() const;
QString collectionPath() const;
+ QString collectionName() const;
virtual QVariant data(int column, int role);
virtual QMimeData *mimeData();
- virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int column) const;
- virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int column);
+ virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column) const;
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column);
virtual Qt::ItemFlags flags();
virtual bool isDir() const;
@@ -58,6 +59,7 @@
virtual bool canRemoveContent();
virtual bool removeContent();
+ virtual void insertNewItem(const QString &collection_name);
private:
void setPathName(QString path_name);
Modified: trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp
===================================================================
--- trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp 2016-01-16 14:25:20 UTC (rev 4325)
@@ -254,71 +254,6 @@
}
/**
- * @brief XmlProjectElementCollectionItem::lastItemForPath
- * Return the last existing item in this XmlProjectElementCollectionItem hierarchy according to the given path.
- * Next_item is the first non existing item in this hierarchy according to the given path.
- * @param path : The path to find last item. The path must be in form : path/otherPath/myElement.elmt.
- * @param next_item : The first item that not exist in this hierarchy
- * @return : The last item that exist in this hierarchy, or nullptr can't find (an error was occurred, or path already exist)
- */
-XmlProjectElementCollectionItem *XmlProjectElementCollectionItem::lastItemForPath(const QString &path, QString &next_item)
-{
- QStringList str_list = path.split("/");
- if (str_list.isEmpty()) return nullptr;
-
- XmlProjectElementCollectionItem *xpeci = this;
- foreach (QString str, str_list)
- {
- ElementCollectionItem *eci = xpeci->childWithCollectionName(str);
- if (!eci)
- {
- next_item = str;
- return xpeci;
- }
- else
- xpeci = static_cast<XmlProjectElementCollectionItem *>(eci);
- }
-
- return nullptr;
-}
-
-/**
- * @brief XmlProjectElementCollectionItem::rowForInsertItem
- * Return the row for insert a new child item to this item with name @collection_name.
- * If row can't be found (collection_name is null, or already exist) return -1;
- * @param path
- * @return
- */
-int XmlProjectElementCollectionItem::rowForInsertItem(const QString &collection_name)
-{
- if (collection_name.isEmpty()) return -1;
-
- QList <ElementCollectionItem *> child;
- //The item to insert is an element we search from element child
- if (collection_name.endsWith(".elmt"))
- {
- child = elementsChild();
- //There isn't element, we insert at last position
- if (child.isEmpty())
- return childCount();
- }
- //The item is a directory, we search from directory child
- else
- {
- child = directoriesChild();
- //There isn't directory, we insert at first position
- if(child.isEmpty())
- return 0;
- }
-
- foreach (ElementCollectionItem *eci, child)
- if (eci->collectionName() > collection_name)
- return indexOfChild(eci);
-
- return childCount();
-}
-
-/**
* @brief XmlProjectElementCollectionItem::insertNewItem
* When this XmlProjectElementCollectionItem is already created, we must to use this method for insert a new item.
* Befor use this, see rowForInsertItem and lastItemForPath
Modified: trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.h
===================================================================
--- trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.h 2016-01-14 19:32:58 UTC (rev 4324)
+++ trunk/sources/ElementsCollection/xmlprojectelementcollectionitem.h 2016-01-16 14:25:20 UTC (rev 4325)
@@ -54,12 +54,8 @@
QString collectionPath() const;
QString embeddedPath() const;
virtual QString collectionName() const;
-
- XmlProjectElementCollectionItem *lastItemForPath(const QString &path, QString &next_item);
- int rowForInsertItem(const QString &collection_name);
void insertNewItem(const QString &collection_name);
-
private:
void populate();