[Qt-interest] How to get access to dropped element

Christof Warlich christof at warlich.name
Fri Jan 1 23:26:19 CET 2010


I got it solved by myself. Just for reference to anyone else who may 
come across the
same issue:  The info w.r.t. the dropped data is available in  
QAbstractItemModel::dropMimeData.
While this may not be so much a surprise, the QT documentation lacks a 
description
of the default MIME-type being used  
("application/x-qabstractitemmodeldatalist").

The following reimplementation of that function shows how get hold of 
the contained data:

   bool dropMimeData(const QMimeData *data, Qt::DropAction action, int 
row, int column, const QModelIndex &parent) {
       qDebug() << "TreeModel drop" << data->formats();
       QByteArray itemData = 
data->data("application/x-qabstractitemmodeldatalist");
       QDataStream stream(&itemData, QIODevice::ReadOnly);
       int r, c;
       QMap<int, QVariant> v;
       stream >> r >> c >> v;
       qDebug() << "Row and column:" << r << " " << c;
       for(QMap<int, QVariant>::iterator it = v.begin(); it != v.end(); 
it++) {
           qDebug() << "Name:" << "," << it.value();
       }
       return QAbstractItemModel::dropMimeData(data, action, row, 
column, parent);
   }

Christof Warlich schrieb:
> Hi,
>
> it seems I'm really stuck after reading the manual over and over again:
>
> The (compilable) example below shall allow to drag items from a 
> read-only list view to a read-write tree view. So far, insertion of 
> items into the tree through drag and drop works fine, but I'm only able 
> to insert default elements whenever a drop occurs, as I do not know how 
> to find out which of the elements from the list were dropped.
>
> The insertion into my custon TreeItem data structure is done in 
> insertRows() below. Is this the right way to do it? I do not see a way 
> to get any information w.r.t. the dropped item there, so I guess it 
> should be done somewhere else?
>
> Many thanks for any help,
>
> Christof
>
> #include <QtGui>
> #include <deque>
> // Readonly list data to choose from:
> const char *List[] = {"Willi", "Max", "Bert"};
> // The related read-only model:
> class ListModel: public QAbstractListModel {
>    public:
>      int rowCount(const QModelIndex &) const {
>          return sizeof(List)/sizeof(List[0]);
>      }
>      QVariant data(const QModelIndex &index, int role) const {
>          if (!index.isValid()) return QVariant();
>          if(role == Qt::DisplayRole) return QVariant(List[index.row()]);
>          else return QVariant();
>      }
>      Qt::ItemFlags flags(const QModelIndex &) const {
>          return (Qt::ItemIsEnabled | Qt::ItemIsSelectable |
>                  Qt::ItemIsDragEnabled);
>      }
> };
>
> // The destination tree data structure:
> struct TreeItem {
>      TreeItem(const char *name, TreeItem *parent = 0):
>         Name(name), Parent(parent) {}
>      std::deque<TreeItem *> Children;
>      int row() const {
>          if(Parent) {
>              std::deque<TreeItem *> &children = Parent->Children;
>              for(size_t i = 0; i < children.size(); i++) {
>                  if(this == children[i]) return i;
>              }
>          }
>          return 0;
>      }
>      const char *Name;
>      TreeItem *Parent;
> } Root("Tree"); // The tree's root item;
> // The related read / write model:
> class TreeModel: public QAbstractItemModel {
>    public:
>      TreeModel(QObject *parent = 0): QAbstractItemModel(parent) {}
>      int rowCount(const QModelIndex &parent) const {
>          TreeItem *parentItem;
>          if (!parent.isValid()) parentItem = &Root;
>          else parentItem = static_cast<TreeItem *>
>                            (parent.internalPointer());
>          return parentItem->Children.size();
>      }
>      int columnCount(const QModelIndex &) const {return 1;}
>      QModelIndex index(int row, int column,
>                        const QModelIndex &parent) const {
>          if (!hasIndex(row, column, parent)) return QModelIndex();
>          TreeItem *parentItem;
>          if (!parent.isValid()) parentItem = &Root;
>          else parentItem = static_cast<TreeItem *>
>                            (parent.internalPointer());
>          TreeItem *childItem = parentItem->Children[row];
>          if (childItem) return createIndex(row, column, childItem);
>          else return QModelIndex();
>      }
>      QModelIndex parent(const QModelIndex &child) const {
>          if (!child.isValid()) return QModelIndex();
>          TreeItem *childItem = static_cast<TreeItem *>
>                                (child.internalPointer());
>          TreeItem *parentItem = childItem->Parent;
>          if (parentItem == &Root) return QModelIndex();
>          return createIndex(parentItem->row(), 0, parentItem);
>      }
>      QVariant data(const QModelIndex &index, int role) const {
>          if (!index.isValid()) return QVariant();
>          TreeItem *treeItem = static_cast<TreeItem *>
>                               (index.internalPointer());
>          if (role == Qt::DisplayRole) return QVariant(treeItem->Name);
>          else return QVariant();
>      }
>      QVariant headerData(int, Qt::Orientation orientation,
>                          int role) const {
>          if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
>              return QVariant(Root.Name);
>          else return QVariant();
>      }
>      Qt::ItemFlags flags(const QModelIndex &) const {
>          return Qt::ItemIsDropEnabled | Qt::ItemIsEnabled |
>                 Qt::ItemIsSelectable;
>      }
>      bool insertRows(int position, int rows,
>                      const QModelIndex &parent = QModelIndex()) {
>          beginInsertRows(parent, position, position + rows - 1);
>          TreeItem *parentItem;
>          if (!parent.isValid()) parentItem = &Root;
>          else parentItem = static_cast<TreeItem *>
>                            (parent.internalPointer());
>          std::deque<TreeItem *> &list =  parentItem->Children;
>          for (int row = 0; row < rows; ++row) {
>              // How could I get the dragged item's name here?
>              list.insert(list.begin() + position,
>                          new TreeItem("DraggedName", parentItem));
>          }
>          endInsertRows();
>          return true;
>      }
>      // This one never gets called. How can I remove items from the tree?
>      bool removeRows(int position, int rows, const QModelIndex &parent) {
>          beginRemoveRows(parent, position, position + rows - 1);
>          TreeItem *parentItem;
>          if (!parent.isValid()) parentItem = &Root;
>          else parentItem = static_cast<TreeItem *>
>                            (parent.internalPointer());
>          std::deque<TreeItem *> &list =  parentItem->Children;
>          for (int row = 0; row < rows; ++row) {
>              std::deque<TreeItem *>::iterator
>                  it = list.begin() + position;
>              list.erase(it);
>              delete *it;
>          }
>          endRemoveRows();
>          return true;
>       }
> };
>
> // Putting it all together:
> int main(int argc, char *argv[]) {
>      QApplication app(argc, argv);
>      QSplitter *splitter = new QSplitter;
>
>      ListModel *listModel = new ListModel;
>      QListView *listView = new QListView(splitter);
>      listView->setDragEnabled(true);
>      listView->setModel(listModel);
>
>      TreeModel *treeModel = new TreeModel;
>      QTreeView *treeView = new QTreeView(splitter);
>      treeView->setAcceptDrops(true);
>      treeView->setModel(treeModel);
>
>      splitter->setWindowTitle("Drag items from list to tree.");
>      splitter->show();
>      return app.exec();
> }
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
>   




More information about the Qt-interest-old mailing list