Subclassing QTreeWidgetItem for Drag & Drop?
Greetings all,
Regular lurker, first time posting. I want to be able to allow drops only on certain items in a QTreeWidget. Is it possible to subclass QTreeWidgetItem to allow it to be a "drop target" for a drag & drop operation? The code below shows the approach I tried, but it doesn't work correctly: only the first MyTreeWidgetItem I add to the tree control accepts drops! The fact that this only 'sort of' works makes me suspect I'm bumping into a side effect of some of Qt's C++ magic. Is it possible to subclass QTreeWidgetItem to accept drops? Alternatively, if there is another way to achieve the goal of fine-grained control of which items can be "dropped on", I'd be happy to learn about that.
Thanks!
Paul Kerchen
Platform/environment: Qt 4.3.3, MSVC 7.1, Windows XP
Code:
{
Q_OBJECT
public:
signals:
void itemDropped
( MyTreeWidgetItem
* item,
QWidget* source
);
protected:
};
MyTreeWidgetItem::MyTreeWidgetItem( TreeWidget* parent )
{
setAcceptDrops(true);
}
void MyTreeWidgetItem::
{
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
}
void MyTreeWidgetItem::
{
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
}
void MyTreeWidgetItem::
{
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
emit itemDropped(this, event->source());
}
Re: Subclassing QTreeWidgetItem for Drag & Drop?
Well, I found another way to do what I need to do without having to subclass QTreeWidgetItem:
Subclass QTreeWidget and reimplement dragEnterEvent() and dragMoveEvent() so that they check to see if the item that the event occurred over is an item that can accept the drop. For example:
Code:
void MyTreeWidget::
{
if ( itemAcceptsEvent(event,item) )
event->setDropAction(Qt::CopyAction);
else
event->setDropAction(Qt::IgnoreAction);
event->accept();
}
A few important points:
- Call accept() and not acceptProposedAction() if you're overriding the proposed action.
- IgnoreAction must be one of the possible actions specified by the drag source when the drag was initiated. Otherwise, it defaults to CopyAction.
Hopefully this saves someone a little time!
Re: Subclassing QTreeWidgetItem for Drag & Drop?
If you can read my code this QListWidget can drag drop multile items as icon.. and text
from attribute hotels sauna bar, ecc..
Code:
{
Q_OBJECT
//
public:
IconScroller
( bool enable
= false ,
QWidget* parent
= 0 ){
enableout = enable;
setAcceptDrops(true);
setDropIndicatorShown(false);
if (enable) {
setDragEnabled(true);
}
///////setIconSize ( QSize(80,80));
}
{
if (enableout) {
if (!child) {
return;
}
/* IcoLine = hotel attribut icon mit beschreibung in 6 sprachen und
int kategorie int id + pixmap 30x30 */
IcoLine Io = child->data(Qt::UserRole).value<IcoLine>();
QPixmap dragicon
= Io.
pix().
scaledToWidth(Io.
pix().
width() * 3);
/* zoom it */ /* TabIcone liste von IcoLine */
TabIcone dd;
dd.all_lines.append(Io);
QList<QListWidgetItem *> tutti = selectedItems();
for (int i=0; i<tutti.size(); i++) {
IcoLine Iter = pane->data(Qt::UserRole).value<IcoLine>();
dd.all_lines.append(Iter);
}
QString stream
= SaveTabelicon
(dd
);
/* QDataStream zu toBase64 fuer sql*/ mimeData->setData("application/x-atticonhotel",stream.toUtf8());
drag->setMimeData(mimeData);
drag->setPixmap(dragicon);
///////drag->setHotSpot(event->pos() - ????? ); //////
/* make pixmap large and setHotSpot not need */
if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) {
qDebug() << "### drag move it " << Io.id();
}
}
}
{
///////qDebug() << "### dropEvent";
if (event->mimeData()->hasFormat("application/x-atticonhotel")) {
QByteArray itemData
= event
->mimeData
()->data
("application/x-atticonhotel");
//////////qDebug() << "### dropEvent entra siiiiiiiiiiii ";
TabIcone liste = OpenTabelicon(daten);
emit AppendList(liste);
event->accept();
} else {
event->ignore();
}
}
{
qDebug() << "### dragEnterEvent ";
if (event->mimeData()->hasFormat("application/x-atticonhotel")) {
qDebug() << "### dragEnterEvent si ";
event->acceptProposedAction();
} else {
event->ignore();
}
}
{
qDebug() << "### dragMoveEvent ";
if (event->mimeData()->hasFormat("application/x-atticonhotel")) {
qDebug() << "### dragMoveEvent si ";
event->acceptProposedAction();
} else {
event->ignore();
}
}
bool enableout;
signals:
void AppendList(TabIcone);
public slots:
};
Re: Subclassing QTreeWidgetItem for Drag & Drop?
It is not required to reimplement any events to handle drops. You need to do three things. First make sure your item returns a ItemIsDropEnabled flag among its QListWidgetItem::flags(). Then you will possibly need to reimplement QListWidget::dropMimeData() to handle a drop. You'll probably want to reimplement QListWidget::mimeData() as well, to be able to start drags properly.