PDA

View Full Version : Is it possible to drag an item of a QComboBox?



jjcarles
31st March 2010, 10:03
Hi.

Previously I put this message in the forum for newbies, but no such luck. So I have decided to change it to this forum. Sorry for the inconvenience.

I'm trying to create a class that allows me to drag & drop items from a QComboBox.



class IndicatorComboBox : public QComboBox
{
Q_OBJECT

protected:
QPoint m_dragStartPosition;

void mousePressEvent(QMouseEvent *pEvent);
void mouseMoveEvent(QMouseEvent *pEvent);

public:
IndicatorComboBox(QWidget *parent = 0);

signals:

public slots:

}




IndicatorComboBox::IndicatorComboBox(QWidget *parent) : QComboBox(parent)
{
}

void IndicatorComboBox::mousePressEvent(QMouseEvent *pEvent)
{
if (pEvent->button() == Qt::LeftButton) {
m_dragStartPosition = pEvent->pos();
}

QComboBox::mousePressEvent(pEvent);
}

void IndicatorComboBox::mouseMoveEvent(QMouseEvent *pEvent)
{
if (!(pEvent->buttons() & Qt::LeftButton)) {
return;
}

if (currentIndex() < 0) {
return;
}

if ((pEvent->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) {
return;
}

QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;

mimeData->setText(currentText());
drag->setMimeData(mimeData);

//drag->start();
Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction);
}



My problem is that if there is the line "QComboBox::mousePressEvent(pEvent); " I can't drag the items. And, if I remove the line, the combobox will not open (but the drag works fine).

Thanks in advance.

jjcarles
1st April 2010, 14:18
Hello again.

I changed the code to check if events are implemented correctly.



#include "indicatorwidget.h"

#include <iostream>

IndicatorComboBox::IndicatorComboBox(QWidget *parent) : QComboBox(parent)
{
setAcceptDrops(true);
}

void IndicatorComboBox::mousePressEvent(QMouseEvent *pEvent)
{
std::cout << "mousePressEvent" << std::endl;

if (pEvent->button() == Qt::LeftButton) {
m_dragStartPosition = pEvent->pos();
}

QComboBox::mousePressEvent(pEvent);
}

void IndicatorComboBox::mouseMoveEvent(QMouseEvent *pEvent)
{
std::cout << "mouseMoveEvent" << std::endl;

if (pEvent->buttons() & Qt::LeftButton) {
int distance = (pEvent->pos() - m_dragStartPosition).manhattanLength();
if (distance >= QApplication::startDragDistance()) {
startDrag();
}
}

QComboBox::mouseMoveEvent(pEvent);
}

void IndicatorComboBox::startDrag()
{
QString item = currentText();

std::cout << "startDrag" << std::endl;

if (!item.isEmpty()) {
QMimeData *mimeData = new QMimeData;
mimeData->setText(item);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
}
}

void IndicatorComboBox::dragEnterEvent(QDragEnterEvent *pEvent)
{
IndicatorComboBox *source = qobject_cast<IndicatorComboBox *>(pEvent->source());

std::cout << "dragEnterEvent\n" << std::endl;

if (source && source != this) {
pEvent->setDropAction(Qt::CopyAction);
pEvent->accept();
}
}

void IndicatorComboBox::dragMoveEvent(QDragMoveEvent *pEvent)
{

IndicatorComboBox *source = qobject_cast<IndicatorComboBox *>(pEvent->source());

std::cout << "dragEnterEvent" << std::endl;

if (source && source != this) {
pEvent->setDropAction(Qt::CopyAction);
pEvent->accept();
}
}

IndicatorWidget::IndicatorWidget(QWidget *parent) : QWidget(parent)
{
m_horizontalLayout = new QHBoxLayout;
m_indicatorLabel = new QLabel(this);
m_indicatorComboBox = new IndicatorComboBox(this);

m_indicatorLabel->setAlignment(Qt::AlignCenter);

m_horizontalLayout->addWidget(m_indicatorLabel);
m_horizontalLayout->addWidget(m_indicatorComboBox);

m_indicatorLabel->setText(tr("Indicador:"));
m_indicatorComboBox->insertItems(0, QStringList() << tr("RSI") << tr("Volumen"));

setLayout(m_horizontalLayout);

adjustSize();
}





#ifndef _INDICATORWIDGET_H_
#define _INDICATORWIDGET_H_

#include <QtGui>

class IndicatorComboBox : public QComboBox
{
Q_OBJECT

protected:
QPoint m_dragStartPosition;

void mousePressEvent(QMouseEvent *pEvent);
void mouseMoveEvent(QMouseEvent *pEvent);
void dragEnterEvent(QDragEnterEvent *pEvent);
void dragMoveEvent(QDragMoveEvent *pEvent);

void startDrag(void);

public:
IndicatorComboBox(QWidget *parent = 0);

signals:

public slots:

};

class IndicatorWidget : public QWidget
{
Q_OBJECT

protected:
QHBoxLayout *m_horizontalLayout;
QLabel *m_indicatorLabel;
IndicatorComboBox *m_indicatorComboBox;

public:
IndicatorWidget(QWidget *parent = 0);

signals:

public slots:

};

#endif /* _INDICATORWIDGET_H_ */


My surprise has been that events mouseMoveEvent (), dragEnterEvent () and dragMoveEvent () not run if you run the event QComboBox: mousePressEvent (line 18). If I delete line 18, all events are executed but the combobox will not open. Any ideas?

Thanks In advance.

jjcarles
8th April 2010, 19:42
Hello again.

I'm still trying to solve my problem with drag & drop of QComboBox. Can this be done or am I wasting time?

Thanks in advance.

norobro
9th April 2010, 00:07
From the Qt docs: here (http://doc.trolltech.com/4.6/model-view-dnd.html)
The standard views automatically support internal drag and drop, where items are moved around to change the order in which they are displayed. By default, drag and drop is not enabled for these views . . . .
So, if you just want to drag items around in the popup of your combo box all you need is the following statement:
m_indicatorComboBox->view()->setDragDropMode(QAbstractItemView::DragDrop);
If you want to drag to another standard view you only need a few additional lines of code as explained in the Qt doc linked above.