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

Christof Warlich cwarlich at gmx.de
Wed Dec 30 06:27:48 CET 2009


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



More information about the Qt-interest-old mailing list