In addition to comments regarding design and reading file names from GUI thread before creating the other one and passing handles as arguments, I understand that may be some scenarios where you need to invoke GUI dialogs from other threads.
One solution can be to emit a signal from your thread and capture in the GUI's. The drawback of this approach is that it may be difficult to get a result (the name of a file in your case).
A similar solution is to use a Qt::BlockingQueuedConnection
to invoke a method of an object living in the GUI thread while blocking the other thread until the method returns.
Next example illustrates this using a helper object:
class FileDialogCaller : public QObject {
Q_OBJECT
public:
FileDialogCaller(QObject* parent = 0) : QObject(parent) {
// The helper object will live in the GUI thread
moveToThread(qApp->thread());
}
// Add the rest of parameters as needed
QString getSaveFileName(QWidget* parent, const QString& caption, const QString& dir,
const QString& filter) {
QString fileName;
if (QThread::currentThread() != qApp->thread()) { // no GUI thread
QMetaObject::invokeMethod(this, "getSaveFileName_", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, fileName),
Q_ARG(QWidget*, parent),
Q_ARG(QString, caption),
Q_ARG(QString, dir),
Q_ARG(QString, filter));
} else { // in GUI thread, direct call
fileName = getSaveFileName_(parent, caption, dir, filter);
}
return fileName;
}
private:
Q_INVOKABLE
QString getSaveFileName_(QWidget* parent, const QString& caption, const QString& dir,
const QString& filter) {
return QFileDialog::getSaveFileName(parent, caption, dir, filter);
}
};
To use it just:
QString fileName = FileDialogCaller().getSaveFileName(nullptr, "Save", "", "Any (*.*)");