Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to catch a paste action from a widget other than Text container



  • Hello,
    I'm working on an application which displays a void area at start. I would like to catch a "paste" event to insert in this case a QPixmap in the area when the data are an image.
    I didn't find any way for that.
    What I see is that only Text containers can manage paste event, and if needed using insertFromMimeData to manage the pasted data.
    Is it really the only way to paste data ?



  • Hi,

    I am interested to learn and help as well. From your case, it would seems like you would like to put an image into the void space.
    Once dropped, the space will be filled with the chosen photo.

    I came across an example that may be the solution. Here is the link: https://evileg.com/en/post/240/

    I cut short the code and utilise the widget.cpp only. Its not clean but this is it. If it works, credit goes to Evgenij (evileg)

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QPalette>
    #include <QDragEnterEvent>
    #include <QMimeData>
    #include <QDropEvent>
    #include <QScrollArea>
    #include <QLabel>
    #include <QListView>
    #include <QGridLayout>
    #include <QStandardItemModel>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
    
        // Drag event method
        virtual void dragEnterEvent(QDragEnterEvent* event) override;
        // Method for drop an object with data
        virtual void dropEvent(QDropEvent *event) override;
    
    private slots:
        // Slot for processing clicks on list items
        void onImagesListViewClicked(const QModelIndex& index);
    
    private:
        QScrollArea*        m_scrollArea;       // Image scrolling area
        QLabel*             m_imageLabel;       // Label for displaying pictures
        QListView*          m_imagesListView;   // List with images
        QGridLayout*        m_gridLayout;       // Grid for the interface
        QStandardItemModel* m_imagesModel;      // Data Model with Images
    };
    
    #endif // WIDGET_H
    
    

    widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    
    #include <QStandardItem>
    #include "imagedelegate.h"
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent)
    {
        setAcceptDrops(true);       // Allow drop events for data objects
        setMinimumWidth(640);
        setMinimumHeight(480);
    
        /// Configure the interface
        m_gridLayout = new QGridLayout(this);
        m_scrollArea = new QScrollArea(this);
        m_scrollArea->setBackgroundRole(QPalette::Dark);
        m_imageLabel = new QLabel(this);
        m_scrollArea->setWidget(m_imageLabel);
        m_gridLayout->addWidget(m_scrollArea, 0, 0);
    }
    
    Widget::~Widget()
    {
    
    }
    
    void Widget::dragEnterEvent(QDragEnterEvent *event)
    {
        // You must necessarily accept the data transfer event in the application window area
        event->accept();
    }
    
    void Widget::dropEvent(QDropEvent *event)
    {
        // When we drop the file into the application area, we take the path to the file from the MIME data
        QString filePath = event->mimeData()->urls()[0].toLocalFile();
        // Create an image
        QPixmap pixmap(filePath);
        // We place it in the scrolling area through QLabel
        m_imageLabel->setPixmap(pixmap);
        m_imageLabel->resize(pixmap.size());
    
        // Adding an item to the list
        m_imagesModel->appendRow(new QStandardItem(QIcon(pixmap), filePath));
    }
    
    void Widget::onImagesListViewClicked(const QModelIndex &index)
    {
        // When we click on an element in the list, we take the path to the file
        QPixmap pixmap(m_imagesModel->data(index).toString());
        // And install the file in the main view area
        m_imageLabel->setPixmap(pixmap);
        m_imageLabel->resize(pixmap.size());
    }
    
    


  • You can look into the qt source file about how text containers handle a paste action:
    https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qwidgettextcontrol.cpp.html#1313



  • @Faruq Thanks for this. I will probably use it. But this does answer to the question which focus is on paste action, not drag-drop.
    @Bonnie I don't find documentation on QWidgetTextController, but this is interesting. I see that a keyPressEvent is caught to deal with the Paste action. I will try that.



  • @YvesB
    QWidgetTextController is an internal (private) controller class for almost all qt text containers.
    It doesn't have any documentation because we are not supposed to use it.



  • @Bonnie said in How to catch a paste action from a widget other than Text container:

    You can look into the qt source file about how text containers handle a paste action:
    https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qwidgettextcontrol.cpp.html#1313

    Following this example, I got a solution.
    I have a QAction added in the QMainWindow, with a shortcut being QKeySequence::Paste and connected to a paste function. I have edited this function to detect the context of the paste action. Some extracts of my program in Python:

            self.actionPaste = QAction(
                    QIcon.fromTheme('edit-paste',
                            QIcon(rsrcPath + '/editpaste.png')),
                    self.tr("&Paste"), self, priority=QAction.LowPriority,
                    shortcut=QKeySequence.Paste,
                    enabled=((len(QApplication.clipboard().text()) != 0) or QApplication.clipboard().mimeData().hasImage()))
            tb.addAction(self.actionPaste)
    

    and

        def paste(self):
            #   send the command to the active section
            widget = self.focusWidget()
            if widget.metaObject().className() == "CTextEdit":
                widget.paste()
            if widget.metaObject().className() == "ChapterTab":
                widget.edit.pasteDrawing()
    

Log in to reply