# # # patch "NEWS" # from [d819b897368299e9ec4a1df3e11676f3008e88e4] # to [9caf1a89fde91b5d1de941c74002ac5174361821] # # patch "notes/IDEAS" # from [63f90c51297f127744e4915d51eee4a83a1f1c90] # to [947bbd2f5b51c70ea9aec4ad71e2af83d2ba51a6] # # patch "src/model/InventoryModel.cpp" # from [df0040b8a0d5172ae7e5e18186d37e1fa1360d49] # to [caaee221cd516e21be7b927d8fa672fd1e7ab6c1] # # patch "src/model/InventoryModel.h" # from [5973c6741bd2c0bfac492c906a7d14538ac1d3b7] # to [5829fc37eba4c40c1a559109444aa541f7377669] # # patch "src/view/widgets/InventoryView.cpp" # from [3fbf7435d43d399508b7035e2da1f104c38712c9] # to [eec5f4cbdc8b5821a3fcf18bc2f99c25f9dcec61] # ============================================================ --- NEWS d819b897368299e9ec4a1df3e11676f3008e88e4 +++ NEWS 9caf1a89fde91b5d1de941c74002ac5174361821 @@ -1,7 +1,8 @@ xxxx-xx-xx (1.0rc3) xxxx-xx-xx (1.0rc3) - - internal: bind guitone's internal settings system late to the needed - QSettings backend; improve the creation of Mac OS X distributable - binaries and images + - new: drag'n'drop support in the workspace view to easily rename items + - internal: bind guitone's internal settings system late to the needed + QSettings backend; improve the creation of Mac OS X distributable + binaries and images 2010-04-05 (1.0rc2) - new: annotate files directly from the workspace or the changeset ============================================================ --- notes/IDEAS 63f90c51297f127744e4915d51eee4a83a1f1c90 +++ notes/IDEAS 947bbd2f5b51c70ea9aec4ad71e2af83d2ba51a6 @@ -19,7 +19,6 @@ the TODO file: based on the platform) * add unit tests for all the internals * make file-saving rollback'able if aborted / on error -* implement drag'n'drop and proper rename support (stubs) * make more use of typedefs to define more clearly what kind of parameters a certain method accepts. If everything is just labeled as QString this won't help the code readability a lot... ============================================================ --- src/model/InventoryModel.cpp df0040b8a0d5172ae7e5e18186d37e1fa1360d49 +++ src/model/InventoryModel.cpp caaee221cd516e21be7b927d8fa672fd1e7ab6c1 @@ -230,27 +230,107 @@ Qt::ItemFlags InventoryModel::flags(cons Qt::ItemFlags InventoryModel::flags(const QModelIndex & index) const { - if (!index.isValid()) return 0; + if (!index.isValid()) + return 0; QFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - ModelItem * item = static_cast(index.internalPointer()); - I(item); + if (index.column() == 0) + { + ModelItem * item = static_cast(index.internalPointer()); + I(item); - // no special flags for pseudo items - PseudoItem * psitem = dynamic_cast(item); - if (psitem) + InventoryItem * invitem = dynamic_cast(item); + if (invitem && invitem->isNewNode()) + { + if (invitem->getPath() != "") + { + flags |= Qt::ItemIsEditable; + flags |= Qt::ItemIsDragEnabled; + } + + if (invitem->isDirectory() && index.column() == 0) + { + flags |= Qt::ItemIsDropEnabled; + } + } + } + + return flags; +} + +QStringList InventoryModel::mimeTypes() const +{ + return QStringList() << "application/x-inventory-items"; +} + +QMimeData * InventoryModel::mimeData(const QModelIndexList & indexes) const +{ + QMimeData * mimeData = new QMimeData(); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + + foreach (QModelIndex index, indexes) { - return flags; + if (!index.isValid()) + continue; + + ModelItem * item = static_cast(index.internalPointer()); + I(item); + InventoryItem * invitem = dynamic_cast(item); + stream << invitem->getPath(); } - InventoryItem * invitem = dynamic_cast(item); - if (invitem && invitem->getPath() != "" && - invitem->isNewNode() && index.column() == 0) + mimeData->setData("application/x-inventory-items", encodedData); + return mimeData; +} + +bool InventoryModel::dropMimeData(const QMimeData * data, Qt::DropAction action, + int row, int column, const QModelIndex & parent) +{ + Q_UNUSED(row); + + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat("application/x-inventory-items")) + return false; + + if (column > 0) + return false; + + if (!parent.isValid()) + return false; + + ModelItem * item = static_cast(parent.internalPointer()); + I(item); + InventoryItem * invitem = qobject_cast(item); + if (!invitem) + return false; + + QString targetPath = invitem->getPath(); + if (!targetPath.isEmpty()) + targetPath.append("/"); + + QByteArray encodedData = data->data("application/x-inventory-items"); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + + while (!stream.atEnd()) { - flags |= Qt::ItemIsEditable; + QString oldPath, newPath; + stream >> oldPath; + + int pos = oldPath.lastIndexOf('/'); + QString filename = pos == -1 + ? oldPath + : oldPath.right(oldPath.length() - pos - 1); + newPath = targetPath + filename; + + renamePath(oldPath, newPath); } - return flags; + + return true; } // the root item needs to store the header for each field @@ -404,6 +484,15 @@ void InventoryModel::renamePath(const QS void InventoryModel::renamePath(const QString & oldPath, const QString & newPath) { + // some sanity (see http://savannah.nongnu.org/bugs/?29484) + if (oldPath == newPath || + newPath.indexOf(oldPath + "/") == 0) + { + W(QString("ignoring invalid rename from %1 to %2") + .arg(oldPath).arg(newPath)); + return; + } + QStringList args; args << "rename" << oldPath << newPath; ============================================================ --- src/model/InventoryModel.h 5973c6741bd2c0bfac492c906a7d14538ac1d3b7 +++ src/model/InventoryModel.h 5829fc37eba4c40c1a559109444aa541f7377669 @@ -23,6 +23,7 @@ #include #include +#include struct NodeInsertion { NodeInsertion(ModelItem * p, int s, int e) @@ -42,6 +43,9 @@ public: QVariant data(const QModelIndex &, int) const; bool setData(const QModelIndex &, const QVariant &, int); Qt::ItemFlags flags(const QModelIndex &) const; + QStringList mimeTypes() const; + QMimeData * mimeData(const QModelIndexList &) const; + bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &); QVariant headerData(int, Qt::Orientation, int) const; QModelIndex index(int, int, const QModelIndex &) const; QModelIndex parent(const QModelIndex &) const; ============================================================ --- src/view/widgets/InventoryView.cpp 3fbf7435d43d399508b7035e2da1f104c38712c9 +++ src/view/widgets/InventoryView.cpp eec5f4cbdc8b5821a3fcf18bc2f99c25f9dcec61 @@ -33,6 +33,7 @@ InventoryView::InventoryView(QWidget * p setItemDelegate(&invViewDelegate); setSelectionMode(QAbstractItemView::ExtendedSelection); setDragEnabled(true); + setAcceptDrops(true); setDropIndicatorShown(true); setSortingEnabled(true); sortByColumn(0, Qt::AscendingOrder);