Impementation of QListView with MouseDoubleClick Event - qt

I am intended to implement an QListView, which will be showing a frame when I will double press my mousebutton on each delegate. With my very basic programming skill I cann't do it. Here below is my code:
void MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->listView->viewport() && event->type() == QEvent::MouseButtonDblClick)
{
int row = getListViewRow();
qDebug() << "Double Clicked on Row: " << row << endl;
mFrame->setGeometry(700,500,150,150);
mFrame->show(); }}
Inside my constructor I also have added this below line:
qApp->installEventFilter(this);
So please correct me to achieve the goal. Thanks.

The solution is quite simple: If you install an event-filter, you need to install it on the object whos events you want to filter:
ui->listView->viewport()->installEventFilter(this);

Related

Can't catch TapAndHoldGesture

I grabGesture()ed one of my buttons:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
in the constructor, and declared:
bool event(QEvent *event);
in protected slots, and implemented it like this:
bool MyClass::event(QEvent *event)
{
if (event->type() == QEvent::Gesture){
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
}
return true;
}
cout << "not a gesture event" << endl;
return QWidget::event(event);
}
and I keep getting "not a gesture event" printed to screen however I press (normal press / long press / ... )
What I'm trying to do is a long key press (from the keyboard)
It's said in the Qt Documentation:
A gesture could be a particular movement of a mouse, a touch screen
action, or a series of events from some other source. The nature of
the input, the interpretation of the gesture and the action taken are
the choice of the developer.
So I suppose also a keyboard can trigger QGesture events.
If the class handling the grap (MyClass) event is not the class where the gesture is detected on (QPushButton assuming buttons[0] is a QPushButton), then you need and event filter:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
buttons[0]->installEventFilter( myClass ); // myClass being a MyClass instance
Now, myClass object will be forwarded all events from buttons[0], this is done using QObject::eventFilter virtual function:
bool MyClass::eventFilter(QObject *obj, QEvent *event)
{
if ( event->type() == QEvent::Gesture && obj == buttons[0] )
{
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
return true;
}
}
// standard event processing
return Parent::eventFilter(obj, event); // Parent being MyClass parent type, maybe QDialog or QWidget
}

QPlainTextEdit double click event

I need to capture the double click event on a QPlainTextEdit that is inside a QDockWidget.
In my actual code I have installed an event filter in the QDockWidget, to handle resize operations, and in the QPlainTextEdit, to handle the double click events:
// Resize eventfilter
this->installEventFilter(this);
ui->myPlainTextEdit->installEventFilter(this);
But, although it works for the QDockWidget I am unable to catch the double click event for the QPlainTextEdit:
bool MyDockWidget::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::Resize && obj == this) {
QResizeEvent *resizeEvent = static_cast<QResizeEvent*>(event);
qDebug("Dock Resized (New Size) - Width: %d Height: %d",
resizeEvent->size().width(),
resizeEvent->size().height());
} else if (obj == ui->myPlainTextEdit && event->type() == QMouseEvent::MouseButtonDblClick) {
qDebug() << "Double click";
}
return QWidget::eventFilter(obj, event);
}
With this code the message "Double click" is never shown. Any idea what is wrong with the code?
QTextEdit inherits a QScrollView and when you double click on the viewport of the QTextEdit, the viewport receives the double click event. You can cross check your current code by double clicking on the edges of the text edit. It will capture the event.
To solve this, add the event filter to the view port in addition to the current event filters you have installed as shown below:
ui->myPlainTextEdit->viewport()->installEventFilter(this);
Next, capture the event using this if statement:
if ((obj == ui->myPlainTextEdit||obj==ui->myPlainTextEdit->viewport()) &&
event->type() == QEvent::MouseButtonDblClick)
{
qDebug() << "Double click"<<obj->objectName();
}
You can capture the click position using QMouseEvent:
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
qDebug()<<QString("Click location: (%1,%2)").arg(mouseEvent->x()).arg(mouseEvent->y());

Dragging from an inherited QTableView

I have in my app a table view called "partsview" which is descended from a QTableView, this is on the main form. The relevant header code looks like:
class partsiew : public QTableView
{
Q_OBJECT
public:
explicit partsview(QWidget *parent = 0);
public:
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
};
I have also added the following into the constructor of "partsview":
this->setSelectionMode(QAbstractItemView::ExtendedSelection);
this->setDragEnabled(true);
this->setAcceptDrops(true);
this->setDropIndicatorShown(true);
though the last two are probably not needed.
When dragging, I can pick up a row and drag it to a target - a QTreeView - and I get the appropriate cursor and even a dropMimeData event is fired on the treeview.
However, the row and column values in the dropMimeData() method are always -1 and the two methods in the "partsview" are not called.
I'm guessing that the first error may have something to do with the second. Have I declared the mimeType() and mimeData() methods correctly for them to be called during a drag operation.
I have been following this page in the documentation QT4.6 - Using Model/View Classes
Here is the link for the most recent documentation on it:
http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views
I recently worked on some code for doing an internal move of cells on a single table, but while I was researching it, I found some other useful links.
http://qt-project.org/forums/viewthread/14197
I used the code in the above link and translated it to use QTableView instead of QTableWidget:
void MyTableView::dropEvent(QDropEvent *event)
{
// TODO: switch to using EyeTrackerModel::dropMimeData instead
QPoint old_coordinates = QPoint(-1,-1);
int dropAction = event->dropAction();
if(currentIndex().isValid()) //Check if user is not accessing empty cell
{
old_coordinates = QPoint( currentIndex().row(), currentIndex().column() );
}
QTableView::dropEvent(event);
qDebug() << "Detected drop event...";
event->acceptProposedAction();
if( this->indexAt(event->pos()).isValid() && old_coordinates != QPoint(-1, -1))
{
qDebug() << "Drop Event Accepted.";
qDebug() << "Source: " << old_coordinates.x() << old_coordinates.y()
<< "Destination: " << this->indexAt(event->pos()).row()
<< this->indexAt(event->pos()).column()
<< "Type: " << dropAction;
emit itemDropped( old_coordinates.x(), old_coordinates.y(),
this->indexAt(event->pos()).row(),
this->indexAt(event->pos()).column(),
dropAction);
}
// resize rows and columns right after a move!
this->doAdjustSize();
}
Even though the following answer is for Python, it still helped me when checking for what I could be missing.
QT: internal drag and drop of rows in QTableView, that changes order of rows in QTableModel
Here are some code snippets from my recent project related to drag and drop. I think you have most of them already, but I included them below for completeness.
QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
// if(index.isValid())
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
// else
// return Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QAbstractTableView(QWidget *parent) :
QTableView(parent)
{
setAcceptDrops(true);
setDefaultDropAction(Qt::MoveAction);
}
Hope that helps.

Handle mouse events in QListView

I've Dialog that shows folders (in treeView) and files (in listView) respectively. In listView doubleClick signal is handled by a slot that Qt created while I used Designer with aproppriate slot to be implemented. The problem is that I'm not able to handle RIGHT MOUSE click. Is there a solution?
P.S.
I've googled for a while to solve this problem, it seems that inheriting QListView and overriding solve the problem. But in my case I've already populated Qt's standart QListView using Designer.
In this case you can use event filter:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->listView->viewport() && event->type() == QEvent::MouseButtonDblClick)
{
QMouseEvent *ev = static_cast<QMouseEvent *>(event);
if (ev->buttons() & Qt::RightButton)
{
qDebug()<< "double clicked" << ev->pos();
qDebug()<< ui->listView->indexAt(ev->pos()).data();
}
}
return QObject::eventFilter(obj, event);
}
To use eventFilter you should also:
protected:
bool eventFilter(QObject *obj, QEvent *event);//in header
and
qApp->installEventFilter(this);//in constructor
Possible addition to your problem. If you want do different things when user clicks left or right mouse buttons you should handle lest and right clicks in filter, without doubleClick signal (because it emits signal in both cases) and your code can be something like:
QMouseEvent *ev = static_cast<QMouseEvent *>(event);
if (ev->buttons() & Qt::RightButton)
{
qDebug()<< "RightButton double clicked";
//do something
}
if (ev->buttons() & Qt::LeftButton)
{
qDebug()<< "LeftButton double clicked";
//do something
}
In my case, I started trying to catch mouse events when a user right-clicked on a line in the QListView, but they never came through. However, all I really wanted to do was popup a context menu, and it turns out the contextMenuEvent did get through! So I didn't have to subclass QListView, just added a contextMenuEvent() to my widget that contained the QListView.
This was Qt3, so your mileage will most definitely differ.

Qt : QWheelEvent does not refer to a value

I'm trying to create a Ctrl + Mousewheel macro to zoom in and out of an image view in my application.
Currently I am trying to use the current code:
new QShortcut(QKeySequence(Qt::CTRL + QWidget::wheelEvent(QWheelEvent *event)), this, SLOT(zoom()));
However I get the error QWheelEvent does not refer to a value. I have all the necessary includes in my header file so I do not understand why I'm getting the error.
Is it illegal to bind the widget event in conjunction within a QKeySequence? If so, how should I handle the event?
You can't use QKeySequence in this way. You should reimplement wheelEvent or use next event filter (it is example how to zoom in/out in textEdit, you can use this code for your special case):
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(obj == ui->plainTextEdit && event->type() == QEvent::Wheel )
{
QWheelEvent *wheel = static_cast<QWheelEvent*>(event);
if( wheel->modifiers() == Qt::ControlModifier )
if(wheel->delta() > 0)
ui->plainTextEdit->zoomIn(2);
else
ui->plainTextEdit->zoomOut(2);
}
return QObject::eventFilter(obj, event);
}
Main idea: catch wheel event and check is Ctrl modifier is pressed.
To use eventFilter you should also:
protected:
bool eventFilter(QObject *obj, QEvent *event);//in header
and
qApp->installEventFilter(this);//in constructor
Note: I showed example with event filter because it is not require subclassing, it is not better or something else, reimplement wheelEvent with similar code and you will get absolutely same result.

Resources