QTranslator checking - qt

How to check which file with translation was loaded ? (Current loaded translation)
I load translation in main.c and I would like to check in MainWindow Class which translation was loaded.

I don't think you can do it, using Qt's methods.
The best way of doing it would be to write a wrapper around QTranslator and store all loaded translation files in it (you can load more than one translation file at a time).
Much worse, but easier way is to use a fake translation. Something like this:
const QString check = tr("lang");
if (check == "en") {
// it's english
} else if (check == "fr") {
// it's french
}
...

According to Internationalization with Qt, you anyway get the system locale to load the appropriate translation file. Just check the value of the locale string:
#include <QLocale>
QString locale = QLocale::system().name();
For example, for English, it is "en", for German - "de".

Related

QSoundEffect does not reload source

In my program it is possible to select a sound for an action. the sound is changeable, which means the .wav file gets replaced by another file.
This may cause the problem. When i replace the file and set the source of the QSoundEffect the sound does not change.
At the moment i am having a source like this:
//variable in .h
QUrl sound = "file:///"+soundDirectory+"sound.wav";
QUrl newSound = "file:///"+soundDirectory+"newSound.wav"; ;
QSoundEffect soundeffect;
//called in setSound() in .cpp
soundEffect.setSource(sound);
the sound loads without problem and i can play that sound.
i can change that sound with this code
// changing the sound in changeSound()
soundEffect.setSource(newSound);
this also works fine. the new sound is loaded and i can play it.
But it is also possible to change the sound files in the directory:
//changeSoundFile()
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), sound.toLocalFile());
This also works and replaces the sound file in its directory with another.
If I call setSound() after changing the file. It seems like the file does not get reload. and the sound is not changed. This is also the problem if changed the sound in between (call setSound on startup, then changeSound, then changeSoundFile and the setSound again)
Am I overlooking something?
It's not mentioned in the official docs, but you can find the implementation on GitHub:
void QSoundEffect::setSource(const QUrl &url) {
if (d->source() == url)
return;
d->setSource(url);
emit sourceChanged();
}
The file does not get reloaded because the URL is the same. The implementation holds an internal cache with the data that has been loaded before, so when you play the file, nothing change.
The API does not provide a way of forcing the reset of the data source. You have two alternatives:
Re-creating the QSoundEffect instance each time you modify the file.
Changing the file name:
// Create a temporal file
const auto uuid = QUuid::createUuid();
const auto new_filename = uuid.toString() + ".wav";
// Copy the file
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), new_filename);
sound = QUrl(new_filename);
// Use it
soundEffect.setSource(sound);

Pre-compile QML files under Qt Quick Controls

I am importing 2 QML files that come with Qt Controls - ScrollBar.qml and Button.qml in my project. I pre-compile all .qml files that I wrote to reduce application launch time. Is there a way to pre-compile these 2 QML files that come as part of the package?
I tried to remove these files from the qml/QtQuick/Controls/ path and placed them in the same folder as my .qml files but it still failed to load. When I reference ScrollBar in my code, it always tries to load ScrollBar.qml from qml/QtQuick/Controls/ path.
Does any one know if it is possible to pre-compile these QMLs at all? If yes, has any one successfully done it?
Appreciate any help. Thank you.
I'm assuming that you're referring to the Qt Quick Compiler as pre-compiling. The simplest way would just be to build the entire Qt Quick Controls module with the Qt Quick Compiler.
If you need to have it within your project, you could try adding an import that contains the Qt Quick Controls import. QQmlEngine::addImportPath() says:
The newly added path will be first in the importPathList().
That statement seems to imply that order matters, and the code confirms it:
QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local);
// Search local import paths for a matching version
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin);
for (const QString &qmldirPath : qmlDirPaths) {
QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
if (!absoluteFilePath.isEmpty()) {
QString url;
const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1);
if (absolutePath.at(0) == Colon)
url = QLatin1String("qrc://") + absolutePath.mid(1);
else
url = QUrl::fromLocalFile(absolutePath.toString()).toString();
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
cache->versionMajor = vmaj;
cache->versionMinor = vmin;
cache->qmldirFilePath = absoluteFilePath;
cache->qmldirPathUrl = url;
cache->next = cacheHead;
database->qmldirCache.insert(uri, cache);
*outQmldirFilePath = absoluteFilePath;
*outQmldirPathUrl = url;
return true;
}
}
Your project structure might look something like this:
myproject/
qml/
main.qml
QtQuick/
Controls/
Button.qml
ScrollBar.qml
qmldir
In main.cpp you'd set the path to the qml directory (note that the path will be different depending on whether you're doing an in-source build or a shadow build of your project, so you may want to use a resource file to simplify things):
engine.addImportPath("path/to/qml");
Note that the controls import other types. For example, Button uses the Settings singleton, which comes from the QtQuick.Controls.Private import, so you'd need to copy that into the qml directory, too. Settings loads a certain style for the button (ButtonStyle), which could be any of the styles in this folder, depending on which style is in use.
In short, you need to copy all of the potential dependencies of the QML files you're using.

QObject::tr() not translating language properly

QLocale systemLocale;
LOG_ERROR() << "SYSTEM LANGUAGE:" << systemLocale.languageToString(systemLocale.language());
LOG_ERROR() << QObject::tr("Welcome");
The second line prints the correct language, when I change the language from the phone settings, however, "Welcome" doesn't get translated to the current system language. What could be the issue with this?
The translation is probably not loaded. Here's how you can load a file:
QTranslator translator;
QString locale_string = QLocale().name();
QString filename = QString("my_app_%1").arg(locale_string);
if (translator.load(filename, "app/native/qm")) {
app.installTranslator(&translator);
}
This would try to load translations from app/native/qm/my_app_fr.qm on a french device, for example.
Note that by default, you'll have to restart the application after changing the device language. You can use a LocaleHandler to update the translation when the phone language changes. Listen to onSystemLanguageChanged() signal, remove the old translator, then load the new one (same code as above).

New in 4.7.4: QDir::homePath() gives out empty string

QString path = QDir::homePath(); // <-- "path" is always ""
Is this a new bug in 4.7.4? use to work well in 4.7.3
I’m on OSX Lion (4.7.3 worked on Lion well).
The “Clear System Environment” probably cleared the HOME environment variable too.
Basically, QDir::homePath() returns QFile::decodeName(QByteArray(::getenv("HOME"))) almost unchecked. And that's an empty string, if there is no HOME variable.
Hmmm It seems the problem is resolved if I don’t use the “Clear System Environment”. I unchecked it, then re-built and it worked fine. could it be the “SHELL” definitions? I can’t think of anything other than that that’s remotely related to this. I guess something caused Qt to have QT_NO_FSFILEENGINE defined and thus to return an empty string:
// from Qt source file: QDir.cpp
QString QDirPrivate()
{
#ifdef QT_NO_FSFILEENGINE
return QString();
#else
return cleanPath(QFSFileEngine::homePath());
#endif
}

How to get Qt icon (QIcon) given a file extension

I am developing an application that needs to display icons associated with different file types.
Eg for .doc extensions, i need it to be able to display the Microsoft Word icon.
QUESTION:
How can I somehow get a QIcon from the system using QT sdk
Thanks.
Use the QtGui.QFileIconProvider class.
Since Qt5, use QMimeDatabase for that:
QMimeDatabase mime_database;
QIcon icon_for_filename(const QString &filename)
{
QIcon icon;
QList<QMimeType> mime_types = mime_database.mimeTypesForFileName(filename);
for (int i=0; i < mime_types.count() && icon.isNull(); i++)
icon = QIcon::fromTheme(mime_types[i].iconName());
if (icon.isNull())
return QApplication::style()->standardIcon(QStyle::SP_FileIcon);
else
return icon;
}
If you don't have special requirement, QMimeDatabase is a better choice for your need. I recommend you try #nitro2005's answer. You can still do this work by your hand by using QFileIconProvider.
If you want to do this work by your hand but you can't use QMimeDatabase for some reason, there is a solution works for Linux/X11. You can use QFileInfo(const QString &file) to get the file's suffix / extension (It's not necessary about the QString you passed to the QFileInfo constructor is a exist path or not), and then get the MIME type form that suffix, at last you can get the QIcon by using QIcon::fromTheme and it's done.
For example, the following code will check if file's suffix is ".bin", if is, the give it a icon from the system theme with "application-x-executable" MIME type. In fact it's just maintaining a MIME database by your self.
QString fileName("example.bin");
QFileInfo fi(fileName);
if (fi.suffix().compare(QString("bin")) == 0) {
item->setIcon(QIcon::fromTheme("application-x-executable",
provider.icon(QFileIconProvider::File)));
}
To get the MIME type string reference for your "MIME database", please checkout the freedesktop icon naming spec.

Resources