How to forward signals to the last-clicked QGraphicsScene - qt

I have a few QGraphicsScene subclasses "CustomScene" all deriving from a common interface that contains the virtual functions cut(), copy(), paste(), and delete(). QGraphicsScene is the superclass, which is inherited by CustomSceneInterface, which is inherited by CustomScene. Each of the CustomScenes are shown in separate QGraphicsViews in the main window. I also have QActions for cut, copy, paste, and delete.
I'm having trouble figuring out how to send the QAction signals to whichever CustomScene was clicked on last (or whichever has "focus").
How can I do this?

I realized I can just send the QAction signals to slots that check which QGraphicsView has focus and then call its scene's appropriate method. I'll need to call
QWidget::setFocusPolicy(Qt::ClickFocus)
on the QGraphicsViews to get this to work properly. If someone can think of a better solution, please let me know.
EDIT:
With Qt5 and being able to use lambda expressions as slots, I can now employ a pretty spiffy approach. First, I make a function lastClickedScene(), which returns whichever scene was last clicked on. Then I do connect(actionCut, &QAction::triggered, [=]{lastClickedScene->cut();}).

Related

Can I pass "this" to a Q_Slot?

I have an application with many windows (QWidgets).
I didn't save a list of open windows, though, so everytime I want to close a window, I have to retrieve it.
Particularly, each of these windows is called here SubWindow.
Every SubWindow class contains a layout with a MultiEditor *sEditors, which has a menu with an action that closes the current window.
Every SubWindow is created within the MainWindow.
I have two plans.
1) destroying the SubWindow from within itself, by adding in the SubWindow constructor
connect(sEditors, SIGNAL(closeWindow()),
this, closeWindow()));
or
2) destroying the SubWindow from within the MainWindow class, by adding in the SubWindow constructor
connect(sEditors, SIGNAL(closeWindow()),
main, SLOT(closeWindow(this)));
About 1), I don't understand how I can close and destroy a QWidget from within itself (delete this; didn't seem to work, but I can try again).
About 2) my SLOT(closeWindow(this)) doesn't seem to be triggered, so I am wondering if I can pass "this" as an argument.
Ad 1) You can use QObject::deleteLater(). This will destroy the object in the next event loop cycle, and is specifically create for situations like this
Ad 2) You cannot pass actual arguments as parameters in signal-slot connections.
You can however find out who has emitted the signal by using the sender() function in the slot. In your case, that would be the sEditors object.
Other options:
3) You can use a QSignalMapper to map signals from your editors to the Subwindows.
4) (Using Qt5 / C++11) You can use a lambda connection in your Subwindows:
connect(sEditors, SIGNAL(closeWindow()), [this] () {this->closeWindow();});
Can I pass this to a Qt slot?
A slot is a non-static method, so it already has access to this. The this you refer to is the third argument to QObject::connect. In Qt 4 syntax, you're free to omit the third argument - it defaults to this. In Qt 5 syntax, you must be explicit about it, though.
I don't understand how I can close and destroy a QWidget from within itself
To delete any QObject from within itself, use QObject::deleteLater(). Recall that a QWidget is-a QObject in terms of LSP.
my SLOT(closeWindow(this)) doesn't seem to be triggered
There's no such slot (give us a link to its documentation: you can't), and your slot signature is also invalid because the only things within the parentheses in the slot signature can be types, and this is not a type: SLOT(slotName(TYPE_LIST_HERE)), e.g. SLOT(mySlot(int,QString)).
To close a widget, use its close() slot:
connect(sEditors, SIGNAL(closeWindow()), this, SLOT(close());
Yet, by using Qt 4 connect syntax, you're leaving coding mistakes to be detected at runtime - and then if you don't pay attention to the debug output at runtime, you'll miss it. It's thus much better to use the new (Qt 5) connect syntax, and let the compiler detect errors for you:
connect(sEditors, &MultiEditor::closeWindow, this, &QWidget::close);
Alas, there's no need to tightly couple the object that sends closeWindow to SubWindow - at least not within the SubWindow::SubWindow(). Instead, you can connect at the place where you create the editor.
To delete a widget when it gets closed, simply set the Qt::WA_DeleteOnClose attribute on it and let Qt do it for you. No need to explicitly call deleteLater etc.
You might factor all of it into a factory method:
template <class T> T* SubWindow::makeEditor() {
auto sub = new T{this};
sub->setAttribute(Qt::WA_DeleteOnClose);
connect(sEditor, &MultiEditor::closeWindow, sub, &QWidget::close);
return sub;
}
MainWindow::MainWindow(/*...*/) : /*...*/ {
makeEditor<EditorType1>();
makeEditor<EditorType2>();
/*...*/
}

How to connect multiple QShortcuts to one slot in Qt? And find out inside the slot which shortcut emitted it?

Is it possible to pass parameters?
Something like this:
shortcut_key_one, channelSLot(int)
shortcut_key_two, channelSLot(int)
shortcut_key_three, channelSLot(int)
If it doesn't matter what the shortcut was, assign the shortcuts to a QAction using QAction::setShortcuts.
font_increase_action_ = new QAction(tr("&Increase font sizes"), this);
font_increase_action_->setShortcuts(QList<QKeySequence>()
<< Qt::CTRL + Qt::Key_BracketRight
<< Qt::CTRL + Qt::Key_Greater);
connect(font_increase_action_, SIGNAL(triggered()), SLOT(IncreaseFontSizes()));
If you really need to know which shortcut was pressed, you could assign each one to a separate QAction and then use the QSignalMapper.
Well, to do exactly what you're asking, you could keep track of all of your QShortcut objects and then use the sender() function inside of your slot to determine which QShortcut caused the slot to be triggered.
However, it sounds like you seriously want to consider using and overriding QWidget::keyPressEvent() instead if at all possible. It would be a lot easier to ask the QKeyEvent object which key was pressed than to do all this crazy QShortcut mess.

Qt QGraphicsScene::drawItems subsitute?

For QGraphicsScene::drawItems the reference says:
Reimplement this function to provide custom painting of all items for the scene; gaining complete control over how each item is drawn.
But this function is marked as obsolete.
Is there any new equivalent method?
QGraphicsView::paintEvent() now calls
d->scene->d_func()->drawItems()
which means the method is part of class QGraphicsScenePrivate which you cannot override afaik.
If you need to change the way your items are drawn, first try to think of another way (i.e. a solution which does not require stepping into the drawItems() method). If you can't find any solution like that, your only chance is reactivating the pre-4.6-behaviour by setting
QGraphicsView::setOptimizationFlag( QGraphicsView::IndirectPainting )

Qt Get signal-slot connection information from a widget

I have a feeling this isn't possible with the current API, but I have to ask. Is it possible to query a particular QObject's signal or slot name (from the metaObject) and retrieve all the QObjects and their slot or signals names that are connected to it?
I'm doing this because, in effect, I have a large number of layouts that contain an identical arrangement of widgets, for each layout there an object and each of the layout's widgets control the various properties of it. I want to keep one layout, and connect it's widgets' signal/slots to all the other objects in the same pattern, but in order to do this I need to 'record' all the signal-slot data.
Is it possible?
There is an interesting file in Qt - %Qtdir%/src/corelib/kernel/qobject_p.h, it contains class QObjectPrivate, used by Qt internally.
Use
static QObjectPrivate *get(QObject *o) function to get QObjectPrivate member for your widgets, and try to call its interesting members like
QObjectList receiverList(const char *signal) const; or QObjectList senderList() const;. File is totally undocumented, but it seems to contain exactly what you need...

Single function that handle multiple QObjects

Hi I have a problem, in my program I have several QLabel and QTextbrowser, at times, I want each of them to display something, but I want to do this through another function called NewMessage. So NewMessage will receive message from QLabel or QTextbrowser, and process them, then display it. But the problem is I don't want to have overloading function for QLabel and QTextBrowser, I want only 1 NewMessage function that can handle message pass in by either QLabel or QTextBrowser(the objects have to pass themselves in as well), how should I do that? Does it has to do with something called casting? Thank you !
I'm not sure I fully understand what you want to achieve. May be you could start by reading Qt documentation about QObject and qobject_cast :
http://doc.qt.io/qt-5/qobject.html#qobject_cast

Resources