PDA

View Full Version : Draggable QActions in Qt



vajindarladdad
13th August 2009, 08:55
Hi All Experts ,
I am developing an application in which i want a QMenu in which the actions are draggable.
Is there any standard Flag that can be set to the QMenu or QAction .

I have developed a Custom QMenu, in which i have implemented the drag and drop Events.
But the problem is that .. the action is getting added to the end , this happens only when the beforeAction is 0.



class CustomMenu : public QMenu
{
Q_OBJECT

public:
CustomMenu(QWidget *parent = 0);
bool addActionBool;
bool check;
QAction *beforeAction;
QAction *afterAction;
QAction *action;
QPoint startPos;
int i;
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);

private:
void performDrag();
};





CustomMenu::CustomMenu(QWidget *parent):QMenu(parent)
{
setAcceptDrops(true);
//action = new QAction(this);
}

void CustomMenu::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
startPos = event->pos();
action = this->activeAction(); // getting the current active action
}
QMenu::mousePressEvent(event);
}

void CustomMenu::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
int distance = (event->pos() - startPos).manhattanLength();
if (distance >= QApplication::startDragDistance())
{
performDrag();
}
}
QMenu::mouseMoveEvent(event);
}

void CustomMenu::performDrag()
{
check = action->isChecked();
if (action) {
QMimeData *mimeData = new QMimeData;
mimeData->setText(action->text());

QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
/*delete action;*/removeAction(action);
}
}

void CustomMenu::dragEnterEvent(QDragEnterEvent *event)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}

void CustomMenu::dragMoveEvent(QDragMoveEvent *event)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}

void CustomMenu::dropEvent(QDropEvent *event)
{
QAction *newAction = new QAction(event->mimeData()->text(),this);
newAction->setCheckable(true);
newAction->setChecked(check);
beforeAction = actionAt(QCursor::pos());
insertAction(beforeAction,newAction); //It appends action if before is 0 or before is not a valid action for this widget. beforeAction is 0 here.
event->setDropAction(Qt::MoveAction);
event->accept();
}



where i am going wrong ??

wysota
13th August 2009, 09:19
Why ar you creating a new action in the drop event instead of reusing the original one? Are you sure beforeAction points to a valid action (can you retrieve its name) after using actionAt? To me it would seem more appropriate to use the position from the drop event and not from QCursor::pos().

vajindarladdad
14th August 2009, 08:50
Hello Sir,
beforeAction always comes out to be 0.
Not able to access it.
How to get the action which has the mouse focus ? I have used actionAt , but its not working.
I am struck here & I will reuse the original action instead of newAction.

wysota
14th August 2009, 09:30
Hello Sir,
beforeAction always comes out to be 0.
Not able to access it.
Probably because of misuse of QCursor::pos()


How to get the action which has the mouse focus ? I have used actionAt , but its not working.
The way you did it was incorrect. Don't use QCursor::pos() which is unreliable and returns the position in screen coordinates, not widget coordinates.

vajindarladdad
14th August 2009, 09:37
Sir ,
Please give me a hint to access the QAction based on the mouse position.
is there any other function to access it.

wysota
14th August 2009, 10:42
Probably QDropEvent::pos() and QMenu::actionAt() but I think I have already said that...

vajindarladdad
14th August 2009, 11:15
Thanks a million ,