QStandardItem :: clone()未被调用进行拖放 [英] QStandardItem::clone() not being called for Drag and Drop

查看:262
本文介绍了QStandardItem :: clone()未被调用进行拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Qt应用程序,其中使用了QStandardItemModel派生类,还有一个QTreeView与之交互。我想启用拖放功能以在模型中复制和移动项目。为此,我已完成以下操作:

I have a Qt application where I am using a QStandardItemModel derived class, and a QTreeView to interact with it. I would like to enable drag and drop to copy and move items around the model. To enable this, I have done the following:


  • 在表示叶节点的QStandardItem子类中:setDragEnabled(true)并将clone()覆盖为

  • 在Folder节点中:setDropEnabled(true)

  • 在QTreeView中:setDragEnabled(true); setAcceptDrops(true); setDropIndicatorShown(true);

拖放的工作方式是尊重可以拖动的物品和可以接受的物品。但是,无论移动还是复制它都不会使用我的clone()函数创建新项目。它只会复制QStandardItem基类可用的设置和数据,丢失子类覆盖等。

Drag and Drop works to the extent that it honors which items can be dragged and which can accept drops. However, whether moving or copying it does not create new items using my clone() functions. It only copies the settings and data available to the QStandardItem base class, losing subclass overrides and such.

如何获取模型和视图以使用克隆( )功能,还是要解决这个问题?

How do I get the model and views to make use of my clone() functions, or work around this?

谢谢您的帮助。

推荐答案

我想我已经找到了解决该框架的方法,或多或少地完成了我所期望的框架。

I think I have found a work around that more or less does what I was expecting the Framework to do.

头文件:

class QextDragDropModel : public QStandardItemModel
{
public:
    /**
     * Uses the passed indexes, and encodes a list of QStandardItem pointers into
     * the mime data.
     */
    virtual QMimeData* mimeData(const QModelIndexList &indexes) const;

    /**
     * Decodes the mimedata, and uses the each QStandardItem::clone() implmentation
     * to place a copy at the requested position of the model.  If it is a move
     * operation Qt will remove the previous item.
     */
    virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
                              int row, int column, const QModelIndex &parent);

};

实现:

QMimeData* QextDragDropModel::mimeData(const QModelIndexList &indexes) const
{
    // Need to have the base function create the initial mimeData.
    // It apparently puts something in there that makes Qt call dropMimeData().
    QMimeData* mimeData = QStandardItemModel::mimeData(indexes);

    // The raw data that will be placed in the mimeData.
    QByteArray mimeBytes;

    // Scope the data stream.
    {
         QDataStream ds(&mimeBytes, QIODevice::WriteOnly);

         // The first item encoded will be the number of pointers to expect.
         ds << quint32(indexes.size());

         // Now for each index get a pointer to the standardItem, and write
         // itto the datastream.
         for (int i = 0; i < indexes.size(); i++)
         {
              QStandardItem* ptrItem = itemFromIndex(indexes[i]);
              ds.writeRawData((const char*)&ptrItem, sizeof(QStandardItem*));
         }
    }

    // Add the encoded standard item pointers into the mimeData.
    mimeData->setData("Qt/QStandardItemArray", mimeBytes);

    return mimeData;
}

bool QextDragDropModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
                                     int row, int column, const QModelIndex &parent)
{
    // Get the QStandardItem target of the drop.
    QStandardItem* target = itemFromIndex(parent);

    // If the target is valid, accepts drops and the mimedata has QStandardItem pointers
    // go ahead with decode and insertion.  (Checking drop enabled pobably already
    // done by the framework before calling this function.)
    if ( NULL != target && target->isDropEnabled() && data->hasFormat("Qt/QStandardItemArray") )
    {
         // Fetch the encoded bytes, create a data stream for decoding,
         // and variables to store the output.
         QByteArray indexListBytes = data->data("Qt/QStandardItemArray");
         QDataStream ds(&indexListBytes, QIODevice::ReadOnly);
         quint32 numItems = 0;

         // Get the number of items, allocate memory to store pointers to
         // them and read the pointer data into that memory.
         ds >> numItems;
         int byteLen = numItems*sizeof(QStandardItem*);
         QStandardItem** stdItems = (QStandardItem**)malloc(byteLen);
         ds.readRawData((char*)stdItems, byteLen);

         // Add items to the target at a specific child index if requested,
         // using thier clone() function to create the items.
         for (int i = 0; i < numItems; i++)
         {
             if ( 0 <= row )
                  target->insertRow(row, stdItems[i]->clone());
              else
                  target->appendRow(stdItems[i]->clone());
         }

         // Free memory allocated to store item pointers.
         free(stdItems);

         return true;
    }

    return false;
}

对于我的应用程序,我可能会添加一个具有以下功能的自定义项目类:接受或拒绝特定项目,使用模型查询,而不是简单地将其转储到接受滴的任何项目中,但是对于主要问题,这很好。

For my application, I'll probably add a custom item class with functionality to accept or reject specific items, with the model querying that instead of simply dumping into anything that accepts drops, but for the main question, this is good.

这篇关于QStandardItem :: clone()未被调用进行拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆