QT drag and drop - Creating a temporary QLabel using qobject_cast - qt

I'm trying to give a custom class that inherits from QLabel to be draggable. Towards that end, I'm trying to create a temporary copy of the class at the current mouse position using the following code inside of the class' mousePressEvent:
QLabel *child = qobject_cast{QLabel*}(this->childAt(event->pos()));
NOTE: this line has carrots instead of brackets, but stack overflow interprets it and takes it out
if (!child)
return;
The child is never created, and I can't figure out why. Any ideas?

If your code is within your QLabel-derived class, childAt() is not the right function. That would return a child widget contained within your label. It doesn't sound like that is what you are trying to do, but correct me if I am misunderstanding.
The object you want to copy is this, but "copy" can have many meanings in c++, and I am not sure exactly you are trying to do. You will probably have to implement it yourself, perhaps with a method called clone() that creates a new instance of your class and populates the values you need to reproduce.
I suspect, though, that there is a better way to implement the drag and drop functionality you are looking for without a copy.

Related

How to replace all cursor appearances within a QML program?

I'm working on a game that uses QML for its UI.
I would like to replace all cursors appearances with cursor-images that are more fitting to the game style (e.g. pointing skeleton hand instead of the normal Qt::ArrowCursor).
Calling QGuiApplication::setOverrideCursor() seams not to be a practical solution as I can not "overwrite" each MouseArea to call may replaceCursor() magic-global-function. For example the change column with cursor within a TableView is currently impossible for me to manipulate.
To me the most practical solution would be to replace the appearance of all cursors but leaf Qt with the tasks to correctly choose the cursor style.
Thanks for any help!
You can still use QGuiApplication::setOverrideCursor() to decorate your mouse areas. It works like a stack, you can set and then restore cursors, so you begin with setting an initial cursor from main.cpp, and then you use an "overloaded" MouseArea which sets its cursor using setOverrideCursor() as well, instead of using the QML functionality.
For example:
onContainsMouseChanged: {
if (containsMouse) Sys.setOverrideCursor(yourCursortype)
else Sys.restoreOverrideCursor()
}
Of course, that means you will have to create an auxiliary object that will call those functions from C++, and expose it to QML so it can be called from there.

How to enable both internal reordering and external dropping in a Qt widget?

I have created a widget which inherits QListWidget.
My goal is for it to accept files dropped into it from an external file manager, and for the user to be able to reorder the elements in the widget. I can achieve both, but not at the same time.
If I just set
myWidget->setDragDropMode(QListView::InternalMove);
myWidget->setDragEnabled(true);
I can reorder the items within the widget, but I can't drop external items into it.
If I reimplement the dragMoveEvent, dragEnterEvent and dropEvent events, all of them just having acceptProposedAction(); and some debug messages inside them, I can drop external files into my widget, but I can no longer rearrange the items.
Is there a way to have the above two at the same time, or do I have to manage the items myself in the reimplemented functions? If so, how can I know if a dropped item is internal or external, and how can I know from which position it was taken and into which position in the list it was dropped into?
If I parse the mimeData which I got from the event, I can see whether it as a file or a text, and I get "qabstractitemmodeldatalist" if it was an internal item, but it still doesn't give me its position.
I can check event->pos() to know in pixels where the drop has been made, and event->source() to learn about what was dropped there, but is this really best practice, to start calculating pixel values and adding objects "manually"?
The solution was very simple: I just had to call the functions of the parent class at the end of each function I've overridden.
void myWidget::dropEvent(QDropEvent *event)
{
do_stuff_with_received_data(event);
QListWidget::dropEvent(event);
}

How to retrieve text from within QGraphicsView?

I'm attempting to retrieve certain text from a QT based window (on Windows). The text is contained in a QGraphicsView (actually, a class that inherits QGraphicsView).
I'm able to intercept it with a series of hooks due a specific call hierarchy in the application, though this is not a very desirable solution.
While the particular text item is likely to be custom, it would be of great help to just enumerate all the items in a QGraphicsView - if possible with class names.
Any pointers on how to go about this will be appreciated.
Note:
I've been having problems with the items() function of QGraphicsView, it seems to be impossible to iterate over either with QListIterator or with items().at().

How to subclass a widget to add more elements to it?

I'm trying to make a subclass of QTableView that has an embedded QLineEdit at the top for filtering the results as-you-type. I need my table to have the same API as a normal QTableView, so I want to subclass it rather than subclassing QWidget and adding a QLineEdit and QTableView to it.
I thought I could just re-implement paintEvent(QPaintEvent*), alter the QPaintEvent's rect() to start a bit lower (the height of a QLineEdit, so it draws under it) and then pass it thru to QTableView::paintEvent(), but the QPaintEvent argument only dictates what region needs to be repainted, not the region where the widget should be painted.
Anything you do in this regard is going to be hacky and result in just as much work (probably more work) as manually mapping all of the signals and slots to a child widget. You'll need to do a lot more than just change the paint events, you'd also have to adjust all of the mouse events, adjust any update rectangles, etc.
Alternatively you could just take the QTableView class from the Qt source and modify it directly (though that will probably break the LGPL and require you to publish your source if you don't have a commercial license.) But the easiest clean method is going to be implementing a container widget with the QTableView as a child.
I would try overriding the paintEvent, changing the widget::pos to be abit lower than it is and call QTableView::paintEvent()
I have to agree with Daniel: I don't think this is the right approach. You will likely want to create a custom widget with a line edit for performing the filtering. Otherwise, you will be entering into the challenging world of Qt hacking.
If you really need to provide access to the QTableView interface then simply add a public get method that returns a reference to the table.
This is somewhat similar to how Qt provides a QTabWidget class that inherits QWidget but has a private QTabBar that it uses internally. One significant difference is that it provides a protected tabBar() accessor rather than a public one.

How do I tell Qt to always show an editor in a QTableView?

I've got a QTableView for which I want to display the last column always in edit mode. (It's a QComboBox where the user should be able to always change the value.)
I think I've seen the solution in the Qt documentation, but I can't find it anymore. Is there a simple way of doing it?
I think I could archive this effect by using openPersistentEditor() for every cell, but I'm looking for a better way. (Like specifying it only one time for the whole column.)
One way to get the automatic editing behaviour is to call the view's setEditTriggers() function with the QAbstractItemView::AllEditTriggers value.
To display the contents of a given column in a certain way, take a look at QAbstractItemView::setItemDelegateForColumn(). This will let you specify a custom delegate just for those items that need it. However, it won't automatically create an editor widget for each of them (there could in principle be thousands of them), but you could use the delegate to render each item in a way that makes it look like an editor widget.
There are two possibilities:
Using setIndexWidget, but Trolltech writes:
This function should only be used to
display static content within the
visible area corresponding to an item
of data. If you want to display custom
dynamic content or implement a custom
editor widget, subclass QItemDelegate
instead.
(And it breaks the Model/View pattern…)
Or using a delegate's paint method. But here you have to implement everything like enabled/disabled elements yourself.
The QAbstractItemModel::flags virtual function is called to test if an item is editable (see Qt::ItemIsEditable). Take a look at Making the Model Editable in the Model/View Programming documentation.
I can't see an easy way to do this, but you might be able to manage by using a delegate. I honestly don't know exactly how it would work, but you should be able to get something working if you try hard enough. If you get a proper delegate, you should be able to set it on a whole view, one cell of a view, or just a column or row.

Resources