[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();
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/