Qt World Summit: Register Today!

QAction, QToolButton, QToolBar & drag n drop

  • Hey

    I'm trying to learn how I can implement a drag and drop on QToolBar... so far its quite interesting journey.

    In essence what I understand so far is that QToolBar, holds QWidgets which points to QActions(widget->defaultAction());

    (below code kinds jumps between eventFilter and dragEnterEvent/dropEvent)

    So I have installed event filter(Qtoolbar one) on all my QWidgets inside QToolBar via a loop findChild<QWidget*>();

    If I perform drag&drop operation on a QAction/QToolButton I'm doing something like : >

    bool icToolBar::eventFilter(QObject *watched, QEvent *event) {
        if (event->type() == QEvent::Enter) {
            qDebug() << watched;
            if (!mPressed)mLastAction = static_cast<QToolButton *>(watched)->defaultAction(); // make sure I did not already press on some button/action.
        if (event->type() == QEvent::Leave) {
            if (mLastAction && mPressed) {
                qDebug() << "I had last action thini so i must be dragging?";
            if (!mPressed) {
                mLastAction = nullptr; // clear the last action entered
        if (event->type() == QEvent::MouseButtonPress) {
            mInitialPos = static_cast<QMouseEvent *>(event)->pos(); // I need it to determine drag trigger
            mButton = static_cast<QMouseEvent *>(event)->button(); // need to know which button for later reference
            mPressed = true; 
        if (event->type() == QEvent::MouseMove) {
            if (mPressed && mLastAction != nullptr) { // ensuring that I pressed on a button and that i have it stored. 
                if ((static_cast<QMouseEvent *>(event)->pos() - mInitialPos).manhattanLength() >= QApplication::startDragDistance()) {
        if (event->type() == QEvent::MouseButtonRelease) {
            mPressed = false;
            mLastAction = nullptr;
            mButton = Qt::NoButton;
        return QObject::eventFilter(watched, event);
    void icToolBar::performDragOp() {
        icInternalMime *mimeData = new icInternalMime(); // my custom mime
        mimeData->setMimeType(mType); // setting mime type
        mimeData->setActionBtn(mLastAction); // setting button I captured early
        QDrag *drag = new QDrag(this); // standard drag 
        switch (mButton) {
            case (Qt::LeftButton): { // deciding which drag type I want to have - no idea if thats the right way tho.
            case (Qt::RightButton): {
    //// no idea if that stuff needs to be here, debug decide.
        mPressed = false; 
        mLastAction = nullptr;
        mButton = Qt::NoButton;
    //I presume after drag.exec() finishes this code runs next... How can I then clear the action that I pressed on. It remaing in a "press state" 
    void icToolBar::dropEvent(QDropEvent *event) {
        qDebug() << "im being dropped?"; // yay ? 
        const icInternalMime *mim = dynamic_cast<const icInternalMime *>(event->mimeData());
        QAction *act = mim->getActionBtn(); // retrieve action
        act->installEventFilter(this); // this dont work - and this is the issue. The newly added action, does not have event filter properly installed. So I cant drag it again... 
        addAction(act); // so this properly adds the action back to the toolbar - BUT, will the early configured signal connect() still work? 
        /// In future use insertAction() in order to specify exact position according to hover/drop/position cursor.

    Now here i have 3 issues.

    1. Once Action gets dropped and re-added. Its event filter is incorrect. I need to re-install event filter on it again. How can I do this ? I can always loop over all children again but that feels "wrong".
    2. If drop action is refused. The original button I pressed on to drag remain pressed. How can I reset its state?
      3 . More question than issue. But if I execute the drag/drop this way. Do I need to re-configure connection() on action trigger? I'm hoping that it will still point to the right "command" ?

    TIA :- )

  • Bump bump bump help :- )

Log in to reply