Qt Quick does not translate components loaded via Loader - qt

Situation:
Writing a Qt Quick application for embedded Linux system, want to use Qt translation mechnanism. Application shall select language on command coming in via RS232, currently hardcoded to "de" on a system set up for english language. Application loads various masks on command from RS232.
Problem:
Qt Quick translates only the main page (main.qml), but not the pages loaded via the Qt Loader (DEMO.ui.qml). Texts from main.qml are displayed in german, texts from DEMO.ui.qml are displayed untranslated.
I've added a "XX" prefix to all english translations (qml.en.ts), that also does not appear on the screen. So neither english nor german translations are loaded for pages loaded via the Qt Loader.
Clean build after lupdate, lrelease does not help. rm -rf build-$appname-*, build does not help.
Code:
application.cpp:
xlat=new QTranslator();
if (xlat->load(QLocale("de"), "qml", ".", ":/qml/i18n/", ".qm")) {
qDebug()<<"load translator ok";
bool ok=installTranslator(xlat);
//...
} // else error message
// ...
viewer->setSource(QUrl("qrc:/qml/main.qml"));
viewer->showFullScreen();
// ...
main.qml:
import QtQuick 2.0
Rectangle {
Text {
id: loadingMsg
text: qsTr("Loading ...")
// ...
}
Loader {
// ...
source: ""
function loadMask(aMaskId) {
// ...
setSource(gui.urlForMask(aMaskId));
}
}
// ...
}
components/SimpleButton.qml:
import QtQuick 2.0
// ...
Rectangle {
Text {
id: label
text: ""
// ...
}
property alias text: label.text
}
masks/DEMO.ui.qml:
import QtQuick 2.0
import "../components"
//...
SimpleButton {
//...
text: qsTr("Vent.")
}
//...
qml.de.ts:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<!-- ... -->
<context>
<name>DEMO</name>
<!-- ... --->
<message>
<source>Vent.</source>
<translation>Belüften</translation>
</message>
</context>
<context>
<name>main</name>
<message>
<source>Loading ...</source>
<translation>Lade ...</translation>
</message>
<!-- ... -->
</context>

Renaming DEMO.ui.qml to DEMO.qml did the trick. I guess that the Linguist tools (lupdate, lrelease) and the Qt runtime environment have different ideas of how to convert a filename to a context name.

Related

Set application to remember theme: dark vs light

There is this QML setup to remember application theme:
import QtQuick.Controls 2.0 as QQC2
QQC2.ApplicationWindow {
id: standaloneWindow // ID is required to be able to get properties
Material.theme: Material.Dark // Can be either Dark or Light
Component.onCompleted: {
// On launch, read theme from settings file
standaloneWindow.Material.theme = appSettings.materialTheme
}
Component.onDestruction:{
// On close, write theme to settings file
appSettings.materialTheme = standaloneWindow.Material.theme
}
Settings {
id: appSettings
category: "Theme"
property int materialTheme // Store theme as "int" type in settings file
}
}
Problem
At the very first launch (for example when settings file is deleted), the theme cannot be started with Dark. At the very first launch, the app always starts with Light theme, no matter what!
Cause
When there is no settings file, the appSettings.materialTheme becomes 0 which is default for int type. Consequently, 0 is equivalent to Material.Dark enum. That's why application always starts at dark mode when there is no settings file.
Question
How can I make the application start with light mode, even when there is no settings file?
Tried so far
I tried to use alias rather than int, but standaloneWindow doesn't have a property to bind to Material.theme:
Settings {
// ...
property alias materialTheme: standaloneWindow.???
}
Any suggestion?
As commented by #Mitch , problem got resolved by:
Settings {
id: appSettings
category: "Theme"
// Set dark theme to be default for the very first launch (when settings file is NOT available)
property int materialTheme: Material.Dark
}

How do I split my QML code into multiple files?

I have just started playing with QML and have a view where I have a bunch of components as follows:
Window {
....
property Component dateTumbler: ControlView {
// Definition follows
}
property Component timeTumbler: ControlView {
// More definition follows
}
// More controls
}
This makes the main QML file very long and cumbersome to edit and maintain. I tried to separate this into different files as follows:
// DateTumblerView.qml
component: DateTumblerView { // Not sure how to inherit here..
// Definition here
}
I'm trying to use it like this:
property component dateTumbler: DateTumblerView {}
However, this never works and the DateTumblerView is never found. I am not sure if I am doing this correctly.
[EDIT]
ControlView is defined as follows:
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtMultimedia 5.5
Rectangle {
id: view
property bool darkBackground: false
Text {
id: textSingleton
}
SoundEffect {
id: playCalSound
source: "qrc:/sound/test.wav"
}
}
[END EDIT]
What is the proper way to split QML code into multiple files?
Your DateTumblerView.qml file should look like this:
ControlView {
// More definition follows
}
And you would use it like this:
property Component dateTumbler: DateTumblerView {}
Or:
Component {
id: dateTumbler
DateTumblerView {}
}
Or if you wanted to use it directly:
DateTumblerView {}
It's pretty much the same as when your code was just in one file. Anytime you do <Type> {}, you're inheriting that type and can set or add new properties, functions, and subcomponents. The difference is that it is in a separate file, has a specific name (the name of the file), and you can reuse that code as many times as you want.
For more details, see Defining Custom QML Types for Re-use.

Change icon depending on language in Qt

Is there a standard mechanism for setting language-depending icons in Qt.
If not, would this work and would it be safe:
MyWidget->setIcon(QPixmap(dir.currentPath() + tr("/images/icon_en.png") ));
//icon_en should be translated according to corresponding image names
There is no standard mechanism for setting icon depending on the locale in Qt. Nevertheless, writing your own mechanism is very plain.
IMO, using tr in your code is redundant. This way is much more flexible:
// Get current system locale:
const QString LOCALE = QLocale::system().name(); // For example, result is "en_US"
// Extract language code from the previously obtained locale:
const QString LANG = LOCALE.split('_').at(0); // Result is "en"
// Path to our icons:
const QString PATH = QString(QApplication::applicationDirPath() + "/images");
// Build the path to the icon file:
const QString ICON = QString("%1/icon_%2.png").arg(PATH, LANG);
// Check if the icon for the current locale exists:
if (QFile::exists(ICON)) {
// Set this icon for our window:
setWindowIcon(QPixmap(ICON));
}
else {
// Otherwise fallback to the default icon:
setWindowIcon(QPixmap(PATH + "/icon_default.png"));
}
Generally, the technique you posted is correct. Just few remarks on your code:
Note that QDir::currentPath() does not return the executable directory; it returns the current working directory. Use QApplication::applicationDirPath() instead.
You may also want to use Qt Resource System instead of storing images along with your executable.
You can load an icon from a ressource file.
Then you can specify an alias for specific languages in the ressource file:
<qresource>
<file>cut.jpg</file>
</qresource>
<qresource lang="fr">
<file alias="cur.jpg">cut_fr.jpg</file>
<qresource>
This way when the app is turned to french automatically the alias icon is selected.

Dot symbol in "type" field of property definition operator

I am using Qt 5.2 and QtQuick 2.2.
In my project I have several modules that are placed in separated directories. My problem is that I can't use dot-separator in typename while defining properties.
For example:
MyRect.qml
import QtQuick 2.2
Rectangle {
id: root
property color rectColor: "white"
color: root.rectColor
}
MyRectInRect.qml
import QtQuick 2.2
import "./" as MyModule
Rectangle {
id: root
property MyModule.MyRect innerRect: MyModule.MyRect { }
// ^ error: Unexpected token `.'; Unexpected token `identifier'
}
I have searched for something that could explain this behavior in the manual, but looks like there is nothing about it there. I guess that dot symbol is not allowed to be used in "type" field of property definition. But is there any way to explicitly define, what component from which module should be used as a type? Cause there may be need of declaring properties with same typenames, but from different modules.
This is a known issue: QTBUG-10822

Problem with embedding QML into resource Qt application

I have some problem with embedding my QML component into resource of my application.
I have some gui.qml
import QtQuick 1.0
Rectangle {
width: 480
height: 525
color: "#ffff00"
}
My dirs
\main.cpp
\gui.qml
I tried run it:
view = new QDeclarativeView(m_GUI);
view->setSource(QUrl("qrc:/gui.qml"));
But i catch:
qrc:/gui.qml: File not found
What's wrong?
Thank all )
I solved it.
In resource i have "Prefix" for the root path.
view->setSource(QUrl("qrc:/MyPrefix/gui.qml"));

Resources