Unsolved 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 usinginsertFromMimeData
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 onQWidgetTextController
, 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#1313Following this example, I got a solution.
I have a QAction added in the QMainWindow, with a shortcut being QKeySequence::Paste and connected to apaste
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()