CFileDialog as child of QWidget - qt

Yes, I know, one should not mix different platforms, but I am working on a Qt application and now we have a new requirement: a standard Windows Open File Dialog should be used in place of a QFileDialog.
So I would like to create a CFileDialog that is a child of a QWidget. I have found a question related to the inverse problem: QWidget as a child of an existing MFC component but nothing about my specific issue.
My plan is to write a wrapper class
class FileStdWDialog : CFileDialog
with a constructor
FileDirStdWDialog(QWidget *parent, ...);
and map this to a call to the superclass constructor
CFileDialog(..., ..., ..., ..., ..., CWnd* pParentWnd, ...)
So, if I understand correctly, my problem boils down to mapping
a QWidget * to a CWnd *. Do you know if there is an easy way to do this?
Update
Thanks for the hints. Probably, getting the HWND for a QWidget and
converting this to CWnd * is the right solution. I will try this way.

You could call ::GetOpenFileName and ::GetSaveFileName. Those are the Win32 functions that CFileDialog wraps, I think. So you wouldn't need MFC.
By the way, starting with Windows Vista, it is recommended to use the Common Item Dialog, rather than the standard Open and Save dialogs.

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 forward signals to the last-clicked QGraphicsScene

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();}).

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...

Segmentation fault in Qt application framework

this generates a segmentation fault becuase of "QColor colorMap[9]";. If I remove colorMap the segmentation fault goes away. If I put it back. It comes back. If I do a clean all then build all, it goes away. If I increase its arraysize it comes back. On the other hand if I reduce it it doesnt come back. I tired adding this array to another project and
What could be happening. I am really curious to know. I have removed everything else in that class. This widget subclassed is used to promote a widget in a QMainWindow.
class LevelIndicator : public QWidget
{
public:
LevelIndicator(QWidget * parent);
void paintEvent(QPaintEvent * event );
float percent;
QColor colorMap[9];
int NUM_GRADS;
};
the error happens inside ui_mainwindow.h at one of these lines:
hpaFwdPwrLvl->setObjectName(QString::fromUtf8("hpaFwdPwrLvl"));
verticalLayout->addWidget(hpaFwdPwrLvl);
I know i am not providing much but I will give alink to the app. Im trying to see if anyone has a quick answer for this.
If I do a clean all then build all, it goes away.
This makes it sound as though your build system isn't recognizing a dependency and that a change to that class definition isn't triggering a rebuild of something that should be recompiled when the definition changes.
Make sure class LevelIndicator is defined in exactly one place (generally that would be a header file that gets included by whatever modules need to use a LevelIndicator object). Also make sure that any global/static instances of LevelIndicator objects are following the one definition rule.
Firstly it might not be QColor, that may simply be changing the memory layout enough that a buffer overrun somewhere else triggers a segfault - try a different size QColor ..[1] for example.
Can QColor be used as an array like this, does it have the correct default ctor?

Qt signals & inheritance question

I am relatively new to programming with Qt and had a question. Short version:
How do I inherit signals defined in superclasses?
I am trying to subclass someone else's nicely made QTWidgets to change some of the default behavior:
//Plot3D is a QWidget that defines a signal "rotationChanged"
class matLinePlot : public QObject, public Plot3D {
Q_OBJECT;
//etc...
public:
//etc...
//Catch Plot3D's signal "rotationChanged" and do some magic with it:
void initPlot(){
QObject::connect(this, SIGNAL(rotationChanged( double , double , double )),
this, SLOT(myRotationChanged(double, double, double)));
}
};
The problem is in the QObject::connect line. What I would like to do is connect the rotationChanged SIGNAL (from qwt3D_plot.h) to a local function/SLOT - "myRotationChanged". However whenever I do this, at run time I get:
Object::connect: No such signal matLinePlot::rotationChanged(double, double, double)
in C:...\matrixVisualization.h. Of course, I know that rotationChanged isn't in matrixVisualization.h - it's in qwt_plot3D.h, but I thought that since I inherit from Plot3D everything should be fine. But, now that I think about it, since SIGNAL and SLOT are macros, I assume MOC doesn't know/care about inheritance.
Which leads me to my question - since MOC and SIGNALS / SLOTS don't seem to know about inheritance etc: how can I subclass a widget defined somewhere else and get access to the widget's signals?
I have a lot of examples of how to use encapsulation to accomplish something like this, but I'm afraid I don't understand how to do this with inheritance.
Sorry if this is a ridiculous question - I feel like I'm missing something obvious.
I guess the problem is the multiple inheritance:
class matLinePlot : public QObject, public Plot3D
...
I assume that Plot3D is a subclass of QObject? In this case, you should do
class matLinePlot : public Plot3D
...
instead.
SIGNAL(x) and SLOT(x) are macros that generate string literals. At runtime, slots and signals are matched up using string compares of those generated literals.
(I would have added a comment to mdec's comment, but I don't have enough rep)
I believe that will work if the Plot3D::rotationChanged signal is public or protected. Are you sure the signal is not private?
Edit:
Although I could not find a specific reference, I'll have to conclude that signals are always public. At least a test I did here seemed to indicate that I could connect to a signal even if it was declared in the private section of a class.
I also verified that a signal declared in QObject could be connected using a subclass of QObject in the connect statement so signals are definitely inheritable. As I see in other answers and comments here, the issue must be elsewhere.
Incorrect -> see comments.
I'm using Qtopia at Uni and I believe I recall someone saying something about spacing in the SIGNAL and SLOT parameters for connect.
Try using
QObject::connect(this, SIGNAL(rotationChanged(double,double,double)),
this, SLOT(myRotationChanged(double,double,double)));
I know it doesn't seem intuitive, as C++ isn't sensitive to whitespace, however I believe it has something to do with some of the magic that Qtopia/QT uses when connecting signals and slots. This may only apply to Qtopia, or I may have heard wrong, but give it a try. Additionally are the signals public or protected and have you included the appropriate header files?

Resources