using getOpenFileName in a handler - qt

I have implemented the getOPenFileName in a handler in qt (in a when_pushbutton_clicked more specifically). How can I save the produced string in a QString in main rather than inside the handler?

You can use a signal connection to save in a QString variable the path of your file name.
const QString fileName = QFileDialog::getOpenFileName(0, tr("Select the file"), getLastDirectory(), "Txt Files (*.txt)");
if (fileName.isEmpty()) {
// No file was selected
return;
}
// then emit the signal
emit fileWasSelected(fileName);
In your main function you cant handle the event in the main class by a simple connection:
QObject::connect(yourClass, &YourClass::fileWasSelected, [&](const QString& filename) {
// Now, do what you want with your path
}):
Another way, its to save the file in a private variable, and set up a getter:
class MyClass {
....
public:
inline QString path() const { return _path; }
private:
QString _path;
}
And then access to the variable from the main.

Related

How to wait for Async lamda function to finish before returning value in a QT Web Assembly

so I wrote a programm for my thesis in Qt and now i am supposed to turn it into a working web assembly, which wasnt a real problem except for the filedownload part. I rewrote my filedownload method from:
QString costumfile::read(QString filename){
QString fileName = QFileDialog::getOpenFileName(nullptr, filename, "", "Text Files (*.txt )");
QFile file(filename);
qDebug()<<filename<<"filename";
if(!file.open(QFile::ReadOnly |
QFile::Text))
{
qDebug() << " Could not open the file for reading";
return "";
}
QTextStream in(&file);
QString myText = in.readAll();
//qDebug() << myText;
file.close();
return myText;
}
To this:
QString costumfile::read(QString filename)
{
QMessageBox msgBox;
QString textUser="Open" + filename;
msgBox.setText(textUser);
msgBox.exec();
QString text="hallo";
qDebug()<<filename;
auto fileContentReady = [&](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
msgBox.setText("Error");
msgBox.exec();
} else {
text=fileContent;
qDebug()<<text<<"texstis";
return fileContent;
}
return fileContent;
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
and the problem is that the return doesnt wait for the lambda function because its asynch...
I then tried using eventloops which works fine in the Destop applikation but isnt supported in the webassembly Applikation.
So does someone have a good idea how to wait for the fileContentReady Function?
As far as I know, Qt for WebAssembly currently does not support waiting using event loops (at least Qt 6.2 does not). See Qt wiki:
"Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object."
https://wiki.qt.io/Qt_for_WebAssembly
So you would have to modify your method to handle the asynchronous call. What I mean is that whatever you want to do with the file, you can write directly into the fileContentReady lambda you have. If this is a generic function, you can let the caller register a done callback to execute when the file is ready. Something like:
QString costumfile::read(QString filename,
const std::function<void(const QString&)>& done)
{
...
auto fileContentReady = [=](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
// Report error
} else {
text=fileContent;
qDebug()<<text<<"texstis";
done(text);
}
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
// When calling costumfile::read
read(filename, [=] (const QString& text) {
// Do something with `text`
});
Also, about the usage of QMessageBox exec(). This can also cause problems as it internally creates a nested event loop which is not yet supported in Qt for WebAssembly. Instead use the show() method.
auto msgBox = new QMessageBox();
msgBox->setText(textUser);
connect(msgBox, &QMessageBox::finished, &QMessageBox::deleteLater);
msgBox->show();

How to load QTranslator from database?

There is no way to load QTranslator from my own way.
I want to exclude .ts files from architecture of my app. I just want to load my languages from databse, whitch will be update from anywhere. And i don't want to load any files(.ts). Does exists the way somthing like this:
QTranslator::load(QStringList)??? QStringList is a language pairs.
The QTranslator::translate method is virtual - which means you can simply create your own translator that extends QTranslator and override this (and one other) method:
class MyTranslator : public QTranslator
{
public:
MyTranslator(QStringList data, QObject* parent) :
QTranslator(parent)
{
// ...
}
bool isEmpty() const override {
return false; //or use your own logic to determine if data contains translations
}
QString translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1) const override {
// Use the data to somehow find your translation
}
};
I understand your goal. Why don't you get the data from your database, save it as temporary file, load via QTranslator (regular way), then delete the temporary file?
Another option is maybe the overload for:
bool QTranslator::load(const uchar *data, int len, const QString
&directory = QString())
(from: http://doc.qt.io/qt-5/qtranslator.html#load-2 ), which would allow you to load from your own structure without temp file.

Qt tr() translation with static members and namespaces

I'm working on translation our Qt GUI project.
*.ts file is generated successfully.
I filled *.ts file with translations using Qt Linguist.
But at runtime, translation with namespaces and static members does not work.
Other translations (when tr() method calls in class, that are inherited from QObject) works ok.
I have the following code (translation does not work):
Example with namespaces:
// example with namespaces
// declaration in header
namespace Error
{
namespace RadionetworkInput
{
QString alreadyInUse = QT_TR_NOOP("already in use");
char requestFailed[] = QT_TR_NOOP("request failed");
}
}
Usage in cpp:
// usage in cpp code0
QString error0 = Error::RadionetworkInput::alreadyInUse;
QString error1 = tr(Error::RadionetworkInput::requestFailed);
Example with static members:
// example with static members
// declaration in header
namespace Error
{
class RadionetworkInput
{
public:
static const QString alreadyInUse;
static const char requestFailed[];
}
QString Error::RadionetworkInput::alreadyInUse = QT_TR_NOOP("already in use");
char Error::RadionetworkInput::requestFailed[] = QT_TR_NOOP("request failed");
}
Usage in cpp code
// usage in cpp code
QString error0 = Error::RadionetworkInput::alreadyInUse;
QString error1 = tr(Error::RadionetworkInput::requestFailed);
Example, with working translation:
class ViewNetwork : public QObject
{
Q_OBJECT
public:
explicit ViewNetwork(QString name = tr("New Radionetwork"));
};
Usage in code:
ViewNetwork::ViewNetwork(QString name)
{
QString dummy = name;
}
Using QObject::tr() instead QT_TR_NOOP() macro does not help.
Problem is your understanding how it works. With static members variables they are initialized before main function starts.
This means two thing:
they are initialized before QApplication object is created and before yuo load translation files! (I'm surprised that this didn't lead to a crash)
value is calculated only once (not updated if translation changes)!
What you should do? Just change static variable to functions:
// example with namespaces
// declaration in header
namespace Error
{
namespace RadionetworkInput
{
QString alreadyInUse() { return QT_TR_NOOP("already in use"); }
QString requestFailed() { return QT_TR_NOOP("request failed"); }
}
}
and
// example with static members
// declaration in header
namespace Error
{
class RadionetworkInput
{
public:
static QString alreadyInUse();
static QString requestFailed();
}
QString Error::RadionetworkInput::alreadyInUse() { return QT_TR_NOOP("already in use"); }
QString Error::RadionetworkInput::requestFailed() { return QT_TR_NOOP("request failed"); }
}
Returning translation as char[] is pointless, co I've corrected that also (I don't know why you did it).

How to read widgets from the .ui file in qt5?

I am trying to get the list of widgets from a .ui files.
So here is a bit of code:
QUiLoader loader;
QFile file(fname);
file.open(QFile::ReadOnly);
QWidget *myWidget = loader.load(&file, this);
file.close();
QStringList avlb_wd = loader.availableWidgets();
QMessageBox msg;
foreach (const QString &str, avlb_wd)
{
msg.setText(str);
msg.exec();
}
But as I can see, availableWidgets() gives me all the widgets, not the ones that are in .ui file.
How can I achieve it?
Thanks forward.
Make a subclass of QUiLoader, and reimplement createWidget, createLayout and createAction (there's also createActionGroup, but it's not really supported any more, unless you manually edit the ui file).
These functions are called every time a new widget, layout or action is created by the ui loader. So just call the base-class implementation to get the created object, and then you can gather whatever information you like, before returning it.
UPDATE:
So the basic QUiLoader subclass would look like this (add other overloads as required):
class UiLoader : public QUiLoader
{
Q_OBJECT
public:
UiLoader(QObject *parent = 0) : QUiLoader(parent) { }
virtual QWidget* createWidget(const QString &className,
QWidget *parent = 0, const QString &name = QString())
{
QWidget* widget = QUiLoader::createWidget(className, parent, name);
// do stuff with className, name, widget, etc
return widget;
}
};

Qt 4.8 - QFileIconProvider, Getting icon for non-existent file (based on extension)

I'm currently trying to get the icon based on a file extension, but it seems like QFileIconProvider will only return an icon if it can actually read an existing file. Is there any way I can get a QIcon based off of a file extension? One alternative would be to write a temporary file with the desired extension, but that is very inefficient so I'm looking for a way around.
Any help would be appreciated!
Here's my solution for Windows:
iconprovider.h:
class IconProvider
{
public:
static IconProvider * instance();
static QIcon fileIcon(const QString &filename);
static QIcon dirIcon();
private:
IconProvider() {}
private:
static IconProvider *self;
QPixmapCache iconCache;
QFileIconProvider iconProvider;
};
iconprovider.cpp:
IconProvider *IconProvider::self = 0;
IconProvider *IconProvider::instance()
{
if(!self)
self = new IconProvider();
return self;
}
QIcon IconProvider::fileIcon(const QString &filename)
{
QFileInfo fileInfo(filename);
QPixmap pixmap;
#ifdef Q_OS_WIN32
if (fileInfo.suffix().isEmpty() || fileInfo.suffix() == "exe" && fileInfo.exists())
{
return instance()->iconProvider.icon(fileInfo);
}
if (!instance()->iconCache.find(fileInfo.suffix(), &pixmap))
{
// Support for nonexistent file type icons, will reimplement it as custom icon provider later
/* We don't use the variable, but by storing it statically, we
* ensure CoInitialize is only called once. */
static HRESULT comInit = CoInitialize(NULL);
Q_UNUSED(comInit);
SHFILEINFO shFileInfo;
unsigned long val = 0;
val = SHGetFileInfo((const wchar_t *)("foo." + fileInfo.suffix()).utf16(), 0, &shFileInfo,
sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
if (val && shFileInfo.hIcon)
{
pixmap = QPixmap::fromWinHICON(shFileInfo.hIcon);
if (!pixmap.isNull())
{
instance()->iconCache.insert(fileInfo.suffix(), pixmap);
}
DestroyIcon(shFileInfo.hIcon);
}
else
{
// TODO: Return default icon if nothing else found
}
}
#else
// Default icon for Linux and Mac OS X for now
return instance()->iconProvider.icon(fileInfo);
#endif
return QIcon(pixmap);
}
QIcon IconProvider::dirIcon()
{
return instance()->iconProvider.icon(QFileIconProvider::Folder);
}

Resources