Drag and drop file into QTreeWidget inside of QDialog - c++

I've been searching online for days and I cant find anything to help out with my specific problem. I'm trying to set up this dialog to accept files to be dropped into the QTreeWidget, named filesTreeWidget, but everything I've been searching online doesn't seem to make a difference. I'm pretty new to QT and C++ as well, so I'm sure that doesn't help.
Thanks for any help
Header
class FileIQ : public QDialog
{
Q_OBJECT
protected:
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
}
Cpp
FileIQ::FileIQ(QWidget *parent, DR::EnginePtr engine)
: QDialog(parent)
, ui(new Ui::FileIQ)
, engine_(engine)
{
ui->filesTreeWidget->setAcceptDrops(true);
ui->filesTreeWidget->setDropIndicatorShown(true);
setAcceptDrops(true);
}
void FileIQ::dropEvent(QDropEvent *event)
{
foreach(const QUrl &url, event->mimeData()->urls()) {
QString filename = url.toLocalFile();
qDebug() << "Dropped file:" << filename;
QTreeWidgetItem *item = new QTreeWidgetItem(ui->filesTreeWidget);
item->setText(0, filename);
}
}
void FileIQ::dragEnterEvent(QDragEnterEvent *event)
{
event->accept();
}
void FileIQ::dragMoveEvent(QDragMoveEvent * event)
{
event->accept();
}
void FileIQ::dragLeaveEvent(QDragLeaveEvent * event)
{
event->accept();
}

First, the right thing is to implement drag and drop within QTreeWidget, not inside QDialog. To do this we must create a class that inherits from QTreeWidget and we must implement the following protected methods:
bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,
const QMimeData *data, Qt::DropAction action)
Handles the data supplied by a drag and drop operation that ended with
the given action in the index in the given parent item.
The default implementation returns true if the drop was successfully
handled by decoding the mime data and inserting it into the model;
otherwise it returns false.
QStringList QTreeWidget::mimeTypes() const
Returns a list of MIME types that can be used to describe a list of
treewidget items.
Qt::DropActions QTreeWidget::supportedDropActions() const
Returns the drop actions supported by this view.
From the above we implemented this class:
#ifndef TREEWIDGET_H
#define TREEWIDGET_H
#include <QDropEvent>
#include <QTreeWidget>
#include <QMimeData>
#include <QFileInfo>
class FilesTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
FilesTreeWidget(QWidget *parent= Q_NULLPTR):
QTreeWidget(parent)
{
setAcceptDrops(true);
setDropIndicatorShown(true);
setColumnCount(2);
}
protected:
bool dropMimeData(QTreeWidgetItem *parent, int /*index*/, const QMimeData *data, Qt::DropAction /*action*/)
{
for(const QUrl url: data->urls()) {
const QFileInfo info( url.toLocalFile());
if(info.isFile()){
QTreeWidgetItem *item;
if (parent){
item = new QTreeWidgetItem(parent);
parent->setExpanded(true);
}
else
item = new QTreeWidgetItem(this);
item->setText(0, info.fileName());
item->setText(1, info.filePath());
}
}
return true;
}
QStringList mimeTypes () const
{
return QStringList()<<"text/uri-list";
}
Qt::DropActions supportedDropActions () const
{
return Qt::CopyAction;
}
};
#endif // TREEWIDGET_H
The complete example can be found in the following link. If you already have a QTreeWidget assigned by Qt Designer the simplest solution is to promote the Qt Designer QTreeWidget to use the new class.
Output:

Related

QDialog Help [?] Button does not trigger whatsthis event

I have created following dialog using QT designer form class
#ifndef DLG_GAMMA_H
#define DLG_GAMMA_H
#include <QDialog>
namespace Ui {
class Dlg_Gamma;
}
class Dlg_Gamma : public QDialog
{
Q_OBJECT
public:
explicit Dlg_Gamma(QWidget *parent = nullptr);
~Dlg_Gamma() override;
private slots:
void on_horizontalSlider_valueChanged(int value);
void on_saveButton_clicked();
void on_discardButton_clicked();
void on_resetButton_clicked();
signals:
void savechanges(QString filter);
void discardchanges();
void reset();
private:
Ui::Dlg_Gamma *ui;
bool eventFilter(QObject *target, QEvent *event) override;
void closeEvent(QCloseEvent *dlg) override;
bool close_X;
};
#endif // DLG_GAMMA_H
.cpp
bool Dlg_Gamma::eventFilter(QObject *target, QEvent *event)
{
qDebug() << event->type();
}
However, clicking on help button, does not trigger any event.
Has anybody faced this issue before ?
Does anybody know solution ?
bool MyDialog::event(QEvent *e)
{
// reimplement event processing
if(e->type()==QEvent::WhatsThisClicked)
{
QWhatsThisClickedEvent ce = static_cast<QWhatsThisClickedEvent>(e);
....
return true;
}
return QDialog::event(e);
}
This is the event catcher.
To use event filter you need to install it:
installEventFilter(this) in the constructor of the Dialog.
You need to install eventFilter on your 'help button' when using eventFilter.
You need to insert kind of code below in the constructor of the 'Dlg_Gamma'
ui->helpButton->installEventFilter(this)
For more information, Please refer to the information below.
https://doc.qt.io/qt-5/eventsandfilters.html

Qt Drag and Drop works in window. Can i make it so i can only drop into a Qlabel and not the entire window?

Using Qt to create an application that accepts a file drop. I have an area on my UI that I want to drop the file into, using a Qlabel. I have the function of dragging and dropping the file into the UI working, however I can drop it anywhere on the window, and not just into the Qlabel area.
I thought using
ui->label_drag->setAcceptDrops(true);
would work, however this just removed the functionality all together. What is the best way of handling this? if possible at all.
Thanks
The best way to do this is to override the QLabel class. In the dragEnterEvent be sure to call acceptProposedAction to process the move and leave events. If you don't do that, only the dragEnter event will fire.
Sample code follows. To use this in your project, add the source to your project and then right click on the label on the form and promote the item to QLabelDragDrop.
#ifndef QLABELDRAGDROP_H
#define QLABELDRAGDROP_H
#include <QLabel>
class QLabelDragDrop : public QLabel
{
Q_OBJECT
public:
explicit QLabelDragDrop(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
signals:
public slots:
};
#endif // QLABELDRAGDROP_H
#include "qlabeldragdrop.h"
#include <QDebug>
#include <QDragEnterEvent>
#include <QDropEvent>
QLabelDragDrop::QLabelDragDrop(QWidget *parent) : QLabel(parent)
{
setAcceptDrops(true);
setMouseTracking(true);
}
void QLabelDragDrop::dragEnterEvent(QDragEnterEvent *event)
{
qDebug() << "dragEnterEvent";
event->acceptProposedAction();
}
void QLabelDragDrop::dragLeaveEvent(QDragLeaveEvent *event)
{
qDebug() << "dragLeaveEvent";
releaseMouse();
}
void QLabelDragDrop::dragMoveEvent(QDragMoveEvent *event)
{
qDebug() << "dragMoveEvent";
}
void QLabelDragDrop::dropEvent(QDropEvent *event)
{
qDebug() << "dropEvent";
}

QListWidget-derived: drop event not firing

A widget derived from QListWidget is the only widget on a window. Function "setAcceptDrops(true);" is used in its constructor, and "event->accept();" is called in its "dragEnterEvent". However, its "dropEvent" could not be triggered. Please check the whole source code (created using Qt 5.12.0) at
github.com/jianz-github/dropevent.
I have asked a question at Qt Drop event not firing. This situation is supposed to be the same, but it is not. Weird.
Thanks in advance for any help.
In this case, the solution is to overwrite the dragMoveEvent() method as well.
listbox.h
#ifndef LISTBOX_H
#define LISTBOX_H
#include <QListWidget>
#include <QDropEvent>
#include <QDragEnterEvent>
class ListBox : public QListWidget
{
public:
ListBox(QWidget *parent = nullptr);
protected:
void dropEvent(QDropEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
};
#endif // LISTBOX_H
listbox.cpp
#include "listbox.h"
#include <QDebug>
ListBox::ListBox(QWidget *parent) : QListWidget (parent)
{
setAcceptDrops(true);
}
void ListBox::dropEvent(QDropEvent *event)
{
qDebug() << "dropEvent"<<event;
}
void ListBox::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void ListBox::dragMoveEvent(QDragMoveEvent *event)
{
event->acceptProposedAction();
}

Qt - Drag and Drop File into ListView

I am trying to write a simple program (nothing special) which has a QListView and some Buttons.
My question is:
How do I specifically tell the QListView to accept Drag and Drop from the filesystem?
I currently have
setAcceptDrops(true)
Which is OK, but the drag and drop works on the whole (Main)Window. I just want it to work when the file is dragged into the QListView.
Why doesn't this work?:
ui->listView->setAcceptDrops(true);
The whole code:
#include "player.h"
#include "ui_player.h"
#include <QListView>
Player::Player(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Player)
{
ui->setupUi(this);
setAcceptDrops(true);
//This doesnt work:
//ui->listView->setAcceptDrops(true);
}
Player::~Player()
{
delete ui;
}
void Player::dropEvent(QDropEvent *ev)
{
QList<QUrl> urls = ev -> mimeData() -> urls();
foreach(QUrl url, urls)
{
qDebug() << url.toString();
}
ev->acceptProposedAction();
}
void Player::dragEnterEvent(QDragEnterEvent *ev)
{
ev->acceptProposedAction();
}
You should override these event functions for QListView, not QMainWindow. When you do ui->listView->setAcceptDrops(true);, QListView is now the widget that reacts to the drop events, by calling its virtual dropEvent and dragEnterEvent functions.
Make your own class that inherits QListView and define dropEvent and dragEnterEvent in there:
class MyListView
{
public:
MyListView(QWidget *parent); // implement
protected:
void dropEvent(QDropEvent *ev) override; // implement
void dragEnterEvent(QDragEnterEvent *ev) override; // implement
};
You might also want to override dragMoveEvent as the reference says.

Call the base class implementation

I was able to simulate the Right-Click event by subclassing the QTableWidget:
header file:
#ifndef QRIGHCLICKTABLE_H
#define QRIGHCLICKTABLE_H
#include <QTableWidget>
#include <QMouseEvent>
class QRightClickTable : public QTableWidget
{
Q_OBJECT
public:
explicit QRightClickTable(QWidget *parent = 0);
private slots:
void mousePressEvent(QMouseEvent *e);
signals:
void rightClicked();
public slots:
};
#endif // QRIGHCLICKTABLE_H
cpp file
QRightClickTable::QRightClickTable(QWidget *parent) :
QPushButton(parent)
{
}
void QRightClickTable::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::RightButton)
emit rightClicked();
}
QRightClickTable *button = new QRightClickTable(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));
void MainWindow::onRightClicked()
{
qDebug() << "User right clicked me";
}
Now, right-click works correctly, but there are other problems with QTableWidget: all other mouse events, such as the left click to select a cell, no longer work.
Can you help me? I know I need to call the base class implementation in my override of mousePressEvent, you could show me how with a little piece of code?
Change your event handler like this :
void QRightClickTable::mousePressEvent(QMouseEvent *e) {
if(e->button()==Qt::RightButton) {
emit rightClicked();
} else {
QTableWidget::mousePressEvent(e);
}
}