SlideShare ist ein Scribd-Unternehmen logo
1 von 38
Practical QML
Burkhard Stubert
Chief Engineer, Embedded Use
www.embeddeduse.com
Contents

 Key Navigation
 Dynamic Language Change
 Themes
Key Navigation in Cars

Navigation clusters for controlling
in-vehicle infotainment systems
Key Navigation in Harvesters

Driver terminals for
Harvesters and tractors
Active Focus
 QML item needs active focus to receive key

events
 Only single item has active focus
 Property Item.activeFocus (read-only)
 True if item has active focus
 Function Item.forceActiveFocus()
 Forces item to have active focus
 Property Item.focus
 Requests active focus when set to true
Focus Scopes
 Component FocusScope
 Controls which child item gets active focus
 Needed for introducing new components with key
handling
 When FocusScope receives active focus:
 Last item to request focus gains active focus
 When last item is FocusScope, active focus is
forwarded to FocusScope
Who gains active focus?
FocusScope A
FocusScope B1
Rectangle C1

Rectangle C2

focus: true

FocusScope B2

focus: true

Rectangle D1

Rectangle D1
focus: true
Recap: KeyNavigation
Attached Property
Tab
Backtab

FlagButton {
id: france
KeyNavigation.backtab: spain
KeyNavigation.tab: italy
Crossing FocusScopes with
KeyNavigation
focus: true
focus: true

 Enclose flag rows with FocusScope as preliminary

for FlagRow component
 What happens when crossing to other flag row?
Crossing FocusScopes with
KeyNavigation (2)

 KeyNavigation stops when crossing to other

FocusScope
 Reason: FocusScope changes focus instead of
activeFocus
Crossing Focus Scopes
with KeyNavigation (3)
 Solution:

FlagButton {
id: italy
KeyNavigation.backtab: france
KeyNavigation.tab: uk
Keys.onTabPressed: uk.forceActiveFocus()
 KeyNavigation not suited for components
 Reason: top item of component always a FocusScope
 KeyNavigation forces monolithic code
Introducing a Generic
Cursor Component
 Forces guiding the solution
 Write code for state machine, visual items, key and
mouse handling only once
 Use only one way to move active focus:
forceActiveFocus()
 Tab and backtab chains must take component
structures into account
Moving Active Focus in Item
Hierarchy
FlagRow.row0

FlagRow.row1

FlagButton.france

FlagButton.italy

FlagButton.uk

Cursor.france

Cursor.italy

Cursor.italy

Tab

Tab

 KeyNavigation structure needs four properties:

tabUp/tabDown and backtabUp/backtabDow
Introducing New Attached
Property KeyNav
 KeyNav
 tabUp : Item
 backtabUp: Item

tabDown: Item
backtabDown: Item

 Attached properties ≈ multipe inheritance
 Save us from declaring four properties in each QML
component
 Example use in middle FlagButton
FlagButton {
id: flag1
KeyNav.backtabUp: flag0.KeyNav.backtabDown
KeyNav.tabUp: flag2.KeyNav.tabDown
}
Handling the Return Key in
Cursor
signal released()
Keys.onPressed: {
if (event.key === Qt.Key_Return) {
root.state = “pressed”
event.accepted = true
}
}
Keys.onReleased: {
if (event.key === Qt.Key_Return) {
root.state = “focused”
root.released()
event.accepted = true
}
}

Make key and mouse
handling look the same for
clients

Also add “pressed” State to
states property
Move out of if-clause to
stop default key handling of
ListView (Up and Down)

Forward in Cursor instance
of FlagButton:
onReleased: root.release()
Key Navigation in ListViews
 Forces guiding the solution
 ListView item has no way to find out previous and
next item
• Cannot use forceActiveFocus()

 Changing currentIndex changes focus
• Reimplement doTab() and doBacktab() for Cursor

 Special cases for moving the active focus into the
ListView with Tab and Backtab
• Implement doTab() and doBacktab() for ListView
Key Navigation in ListViews
(2)
 Extract doTab() and doBacktab() from Cursor

into ButtonCursor and ListViewItemCursor

Cursor

ButtonCursor

ListViewItemCursor

doTab() and doBacktab()
use forceActiveFocus()
to move active focus

doTab() and doBacktab()
change currentIndex to
move active focus
Key Navigation in ListViews
(3)
 Every ListView inherits from BaseListView

 BaseListView provides tabbing and backtabbing

into list view
In BaseListView:
function doTab() {
root.positionViewAtIndex(0,
ListView.Beginning)
root.currentIndex = 0
root.forceActiveFocus()
}

Ensure that first item will
be visible
Request focus for first item

Forces active focus on
ListView, which passes it to
first item
Adding Mouse Handling to
Cursor Components
MouseArea {
anchors.fill: parent
onPressed: {
root.doMousePress()
root.state = “pressed”
mouse.accepted = true
}
onReleased: {
if (root.activeFocus) {
root.state = “focused”
root.released()
}
mouse.accepted = true
}
}

Active focus on item
pressed, no dereferencing
of tab chain needed
Mouse press different for
buttons and list view items

Do not execute “release”
when item lost
focus, e.g., when error
dialog opened
Adding Mouse Handling to
Cursor Components (2)
In ButtonCursor:
function doMousePress() {
root.forceActiveFocus()
}
index provided by delegate
in ListView

In ListViewItemCursor:
function doMousePress() {
delegateRoot.ListView.view.currentIndex = index
delegateRoot.ListView.view.forceActiveFocus()
}
For the case when the flag
row has active focus and
the user clicks in list view.
Avoids multiple cursors.
Contents

 Key Navigation
 Dynamic Language Change
 Themes
Dynamic Language Change
Dynamic Language Change
for QWidgets
 QCoreApplication::installTranslator() sends

LanguageChange event to application object
 QApplication::event() posts LanguageChange
event to every top-level widget (QWidget*)
 QWidget::event() calls changeEvent() on the
widget and sends LanguageChange event to all
its children
 changeEvent() is called on every widget in the widget
tree rooted at a top-level widget
Problems in QML
 Not a single QWidget in QML applications
 Not even QQuickView derives from QWidget
 QApplication not used in QML applications
 Note: QApplication derives from QGuiApplication

Need to rebuild LanguageChange
infrastructure in QML
Dynamic Language Change
in QML
 TranslationManager emits signal

languageChanged()
 Qt/C++ classes (e.g., list models) connect signal
with their retranslate() slot
 Every qsTr() call in QML must be reevaluated
when signal emitted
Changing the Language
 TranslationManager::setLanguage(language)
 Load translation file for language in QTranslator
 Remove old translator from application
 Install new translator in application
 emit languageChanged(language)

 Call setLanguage() before main view of

application is created
 Call setLanguage() when user changes
language
Retranslating Qt/C++
Models
 Equivalent to reimplementing changeEvent()

and calling retranslateUi()
 In constructor of model class:
connect(TranslationManager::instance(),
SIGNAL(languageChanged(QString)),
this,
SLOT(retranslate(QString)));
Retranslating Qt/C++
Models (2)
void BiggestCitiesModel::retranslate(const QString &language)
{
emit titleChange();
CityDatabase::instance()->retranslate(language);
emit dataChanged(index(0), index(m_cities.count() - 1));
}
Notify QML ListView that
all its items have changed
and need reloading
Notify QML code that
title property has
changed
QML calls title(), which
returns tr(rawTitle())

Delegate retranslation, as
model is “view” on
database
Retranslating Qt/C++
Models (3)
const char *CityDatabase::m_strings[][2] = {
{ QT_TR_NOOP(“Munich”), QT_TR_NOOP(“Bavaria”) }, …
void CityDatabase::retranslate(const QString &language) {
if (m_currentLanguage != language) {
for (int i = 0; i < m_cities.count(); ++i) {
m_cities[i]->setName(tr(m_strings[i][0]));
…
}
m_currentLanguage = language;
}
Reset visible members
}

Guard against multiple
“views” (e.g., German
cities, British cities)
requesting retranslation
to same language

(e.g., city name, state)
with new translation of
raw string
Reevaluating qsTr on
Language Change
Text {
text: qsTr(“City:”) + g_tr.languageChanged
…
}

 Use Property Binding:
 Whenever g_tr.languageChanged changes, text must
be reevaluated:
 qsTr() is called and returns translation for new
language
Reevaluating qsTr on
Language Change (2)
In TranslationManager:
Q_PROPERTY(QString languageChanged
READ emptyString
NOTIFY languageChanged)

QString emptyString() const {
return “”;
}
Empty string can be appended
to translated string without
changing anything

Emitting this signal forces QML
to call emptyString(), the READ
method of languageChanged
property
Reevaluating qsTr on
Language Change (3)
On instance of QQuickView:
view->rootContext()->setContextProperty(
“g_tr”, TranslationManager::instance());

Makes pointer to
TranslationManager globally
available in QML under name g_tr
Contents

 Key Navigation
 Dynamic Language Change
 Themes
Dynamic Theme Change
Theming QML Code
Rectangle {
color: index % 2 === 0 ?
“#1E90FF” :
“#00BFFF”

Row {
Text {
text: city.name
color: “#191970”

Unthemed

Rectangle {
color: index % 2 === 0 ?
g_theme.listViewItem.
backgroundColor :
g_theme.listViewItem.
backgroundColorAlt
Row {
Text {
text: city.name
color: g_theme.listViewItem.
textColor

Themed
Implementing the Themes
QtObject {
property QtObject listViewItem : QtObject {
property color backgroundColor: “#1E90FF”
property color backgroundColorAlt: “#00BFFF”
property color textColor: “#191970”
}

QtObject {
property QtObject listViewItem : QtObject {
property color backgroundColor: “#A5A5A5”
property color backgroundColorAlt: “#818181”
property color textColor: “#1E1E1E”
}
Changing Themes
In top-level QML item (main.qml)

Global variable accessible from
everywhere in QML

property alias g_theme: loader.item
Loader { id: loader }
Set theme on start-up
Component.onCompleted: {
loader.source = Qt.resolveUrl(“BlueTheme.qml”)
}
QQuickView forwards signal
Connections {
themeChanged(QString theme)
target: g_viewer
onThemeChanged: {
loader.source = Qt.resolvedUrl(theme + “Theme.qml”)
}
}
The End

Thank you!

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Best Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part IBest Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part I
 
Qt Application Programming with C++ - Part 2
Qt Application Programming with C++ - Part 2Qt Application Programming with C++ - Part 2
Qt Application Programming with C++ - Part 2
 
Qt Qml
Qt QmlQt Qml
Qt Qml
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
 
QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong?
 
Qt and QML performance tips & tricks for Qt 4.7
Qt and QML performance tips & tricks for Qt 4.7Qt and QML performance tips & tricks for Qt 4.7
Qt and QML performance tips & tricks for Qt 4.7
 
Introduction to QML
Introduction to QMLIntroduction to QML
Introduction to QML
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
 
Qt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickQt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt Quick
 
02 - Basics of Qt
02 - Basics of Qt02 - Basics of Qt
02 - Basics of Qt
 
Best Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IVBest Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IV
 
Best Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIBest Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part II
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
 
Qt Application Programming with C++ - Part 1
Qt Application Programming with C++ - Part 1Qt Application Programming with C++ - Part 1
Qt Application Programming with C++ - Part 1
 
UI Programming with Qt-Quick and QML
UI Programming with Qt-Quick and QMLUI Programming with Qt-Quick and QML
UI Programming with Qt-Quick and QML
 
Best Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIBest Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part III
 
Kotlin for Android Development
Kotlin for Android DevelopmentKotlin for Android Development
Kotlin for Android Development
 
Qt Workshop
Qt WorkshopQt Workshop
Qt Workshop
 
QVariant, QObject — Qt's not just for GUI development
QVariant, QObject — Qt's not just for GUI developmentQVariant, QObject — Qt's not just for GUI development
QVariant, QObject — Qt's not just for GUI development
 
Qt 5 - C++ and Widgets
Qt 5 - C++ and WidgetsQt 5 - C++ and Widgets
Qt 5 - C++ and Widgets
 

Ähnlich wie Practical QML - Key Navigation, Dynamic Language and Theme Change

Practicalfileofvb workshop
Practicalfileofvb workshopPracticalfileofvb workshop
Practicalfileofvb workshop
dhi her
 

Ähnlich wie Practical QML - Key Navigation, Dynamic Language and Theme Change (20)

From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
06 win forms
06 win forms06 win forms
06 win forms
 
4.7.14&amp;17.7.14&amp;23.6.15&amp;10.9.15
4.7.14&amp;17.7.14&amp;23.6.15&amp;10.9.154.7.14&amp;17.7.14&amp;23.6.15&amp;10.9.15
4.7.14&amp;17.7.14&amp;23.6.15&amp;10.9.15
 
Practicalfileofvb workshop
Practicalfileofvb workshopPracticalfileofvb workshop
Practicalfileofvb workshop
 
Flex 4 tips
Flex 4 tipsFlex 4 tips
Flex 4 tips
 
engineeringdsgtnotesofunitfivesnists.ppt
engineeringdsgtnotesofunitfivesnists.pptengineeringdsgtnotesofunitfivesnists.ppt
engineeringdsgtnotesofunitfivesnists.ppt
 
IT104 Week 4 - Module/Function
IT104 Week 4 - Module/FunctionIT104 Week 4 - Module/Function
IT104 Week 4 - Module/Function
 
intro_gui
intro_guiintro_gui
intro_gui
 
Visualbasic tutorial
Visualbasic tutorialVisualbasic tutorial
Visualbasic tutorial
 
Csphtp1 12
Csphtp1 12Csphtp1 12
Csphtp1 12
 
WPF Controls
WPF ControlsWPF Controls
WPF Controls
 
Controls events
Controls eventsControls events
Controls events
 
Treinamento Qt básico - aula III
Treinamento Qt básico - aula IIITreinamento Qt básico - aula III
Treinamento Qt básico - aula III
 
Android 3
Android 3Android 3
Android 3
 
Flutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdfFlutter State Management Using GetX.pdf
Flutter State Management Using GetX.pdf
 
MEngine Advanced
MEngine AdvancedMEngine Advanced
MEngine Advanced
 
Lab #2: Introduction to Javascript
Lab #2: Introduction to JavascriptLab #2: Introduction to Javascript
Lab #2: Introduction to Javascript
 
MVVM with Kotlin: Making iOS and Android apps as similar as possible
MVVM with Kotlin: Making iOS and Android apps as similar as possibleMVVM with Kotlin: Making iOS and Android apps as similar as possible
MVVM with Kotlin: Making iOS and Android apps as similar as possible
 
JavaScript
JavaScriptJavaScript
JavaScript
 

Mehr von Burkhard Stubert

Using Qt under LGPLv3
Using Qt under LGPLv3Using Qt under LGPLv3
Using Qt under LGPLv3
Burkhard Stubert
 
Landmaschinen-HMIs für 2016 (in German)
Landmaschinen-HMIs für 2016 (in German)Landmaschinen-HMIs für 2016 (in German)
Landmaschinen-HMIs für 2016 (in German)
Burkhard Stubert
 
Developing Driver Terminal for Forage Harvester with QML and Qt
Developing Driver Terminal for Forage Harvester with QML and QtDeveloping Driver Terminal for Forage Harvester with QML and Qt
Developing Driver Terminal for Forage Harvester with QML and Qt
Burkhard Stubert
 

Mehr von Burkhard Stubert (7)

Webinar: Building Embedded Applications from QtCreator with Docker
Webinar: Building Embedded Applications from QtCreator with DockerWebinar: Building Embedded Applications from QtCreator with Docker
Webinar: Building Embedded Applications from QtCreator with Docker
 
A Deep Dive into QtCanBus
A Deep Dive into QtCanBusA Deep Dive into QtCanBus
A Deep Dive into QtCanBus
 
Using Qt under LGPLv3
Using Qt under LGPLv3Using Qt under LGPLv3
Using Qt under LGPLv3
 
Qt World Summit 2017: Qt vs. Web - Total Cost of Ownership
Qt World Summit 2017: Qt vs. Web - Total Cost of OwnershipQt World Summit 2017: Qt vs. Web - Total Cost of Ownership
Qt World Summit 2017: Qt vs. Web - Total Cost of Ownership
 
Burkhard Stubert: Project Portfolio and Expertise
Burkhard Stubert: Project Portfolio and ExpertiseBurkhard Stubert: Project Portfolio and Expertise
Burkhard Stubert: Project Portfolio and Expertise
 
Landmaschinen-HMIs für 2016 (in German)
Landmaschinen-HMIs für 2016 (in German)Landmaschinen-HMIs für 2016 (in German)
Landmaschinen-HMIs für 2016 (in German)
 
Developing Driver Terminal for Forage Harvester with QML and Qt
Developing Driver Terminal for Forage Harvester with QML and QtDeveloping Driver Terminal for Forage Harvester with QML and Qt
Developing Driver Terminal for Forage Harvester with QML and Qt
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Kürzlich hochgeladen (20)

Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 

Practical QML - Key Navigation, Dynamic Language and Theme Change

  • 1. Practical QML Burkhard Stubert Chief Engineer, Embedded Use www.embeddeduse.com
  • 2. Contents  Key Navigation  Dynamic Language Change  Themes
  • 3. Key Navigation in Cars Navigation clusters for controlling in-vehicle infotainment systems
  • 4. Key Navigation in Harvesters Driver terminals for Harvesters and tractors
  • 5. Active Focus  QML item needs active focus to receive key events  Only single item has active focus  Property Item.activeFocus (read-only)  True if item has active focus  Function Item.forceActiveFocus()  Forces item to have active focus  Property Item.focus  Requests active focus when set to true
  • 6. Focus Scopes  Component FocusScope  Controls which child item gets active focus  Needed for introducing new components with key handling  When FocusScope receives active focus:  Last item to request focus gains active focus  When last item is FocusScope, active focus is forwarded to FocusScope
  • 7. Who gains active focus? FocusScope A FocusScope B1 Rectangle C1 Rectangle C2 focus: true FocusScope B2 focus: true Rectangle D1 Rectangle D1 focus: true
  • 8. Recap: KeyNavigation Attached Property Tab Backtab FlagButton { id: france KeyNavigation.backtab: spain KeyNavigation.tab: italy
  • 9. Crossing FocusScopes with KeyNavigation focus: true focus: true  Enclose flag rows with FocusScope as preliminary for FlagRow component  What happens when crossing to other flag row?
  • 10. Crossing FocusScopes with KeyNavigation (2)  KeyNavigation stops when crossing to other FocusScope  Reason: FocusScope changes focus instead of activeFocus
  • 11. Crossing Focus Scopes with KeyNavigation (3)  Solution: FlagButton { id: italy KeyNavigation.backtab: france KeyNavigation.tab: uk Keys.onTabPressed: uk.forceActiveFocus()  KeyNavigation not suited for components  Reason: top item of component always a FocusScope  KeyNavigation forces monolithic code
  • 12. Introducing a Generic Cursor Component  Forces guiding the solution  Write code for state machine, visual items, key and mouse handling only once  Use only one way to move active focus: forceActiveFocus()  Tab and backtab chains must take component structures into account
  • 13. Moving Active Focus in Item Hierarchy FlagRow.row0 FlagRow.row1 FlagButton.france FlagButton.italy FlagButton.uk Cursor.france Cursor.italy Cursor.italy Tab Tab  KeyNavigation structure needs four properties: tabUp/tabDown and backtabUp/backtabDow
  • 14. Introducing New Attached Property KeyNav  KeyNav  tabUp : Item  backtabUp: Item tabDown: Item backtabDown: Item  Attached properties ≈ multipe inheritance  Save us from declaring four properties in each QML component  Example use in middle FlagButton FlagButton { id: flag1 KeyNav.backtabUp: flag0.KeyNav.backtabDown KeyNav.tabUp: flag2.KeyNav.tabDown }
  • 15. Handling the Return Key in Cursor signal released() Keys.onPressed: { if (event.key === Qt.Key_Return) { root.state = “pressed” event.accepted = true } } Keys.onReleased: { if (event.key === Qt.Key_Return) { root.state = “focused” root.released() event.accepted = true } } Make key and mouse handling look the same for clients Also add “pressed” State to states property Move out of if-clause to stop default key handling of ListView (Up and Down) Forward in Cursor instance of FlagButton: onReleased: root.release()
  • 16. Key Navigation in ListViews  Forces guiding the solution  ListView item has no way to find out previous and next item • Cannot use forceActiveFocus()  Changing currentIndex changes focus • Reimplement doTab() and doBacktab() for Cursor  Special cases for moving the active focus into the ListView with Tab and Backtab • Implement doTab() and doBacktab() for ListView
  • 17. Key Navigation in ListViews (2)  Extract doTab() and doBacktab() from Cursor into ButtonCursor and ListViewItemCursor Cursor ButtonCursor ListViewItemCursor doTab() and doBacktab() use forceActiveFocus() to move active focus doTab() and doBacktab() change currentIndex to move active focus
  • 18. Key Navigation in ListViews (3)  Every ListView inherits from BaseListView  BaseListView provides tabbing and backtabbing into list view In BaseListView: function doTab() { root.positionViewAtIndex(0, ListView.Beginning) root.currentIndex = 0 root.forceActiveFocus() } Ensure that first item will be visible Request focus for first item Forces active focus on ListView, which passes it to first item
  • 19. Adding Mouse Handling to Cursor Components MouseArea { anchors.fill: parent onPressed: { root.doMousePress() root.state = “pressed” mouse.accepted = true } onReleased: { if (root.activeFocus) { root.state = “focused” root.released() } mouse.accepted = true } } Active focus on item pressed, no dereferencing of tab chain needed Mouse press different for buttons and list view items Do not execute “release” when item lost focus, e.g., when error dialog opened
  • 20. Adding Mouse Handling to Cursor Components (2) In ButtonCursor: function doMousePress() { root.forceActiveFocus() } index provided by delegate in ListView In ListViewItemCursor: function doMousePress() { delegateRoot.ListView.view.currentIndex = index delegateRoot.ListView.view.forceActiveFocus() } For the case when the flag row has active focus and the user clicks in list view. Avoids multiple cursors.
  • 21. Contents  Key Navigation  Dynamic Language Change  Themes
  • 23. Dynamic Language Change for QWidgets  QCoreApplication::installTranslator() sends LanguageChange event to application object  QApplication::event() posts LanguageChange event to every top-level widget (QWidget*)  QWidget::event() calls changeEvent() on the widget and sends LanguageChange event to all its children  changeEvent() is called on every widget in the widget tree rooted at a top-level widget
  • 24. Problems in QML  Not a single QWidget in QML applications  Not even QQuickView derives from QWidget  QApplication not used in QML applications  Note: QApplication derives from QGuiApplication Need to rebuild LanguageChange infrastructure in QML
  • 25. Dynamic Language Change in QML  TranslationManager emits signal languageChanged()  Qt/C++ classes (e.g., list models) connect signal with their retranslate() slot  Every qsTr() call in QML must be reevaluated when signal emitted
  • 26. Changing the Language  TranslationManager::setLanguage(language)  Load translation file for language in QTranslator  Remove old translator from application  Install new translator in application  emit languageChanged(language)  Call setLanguage() before main view of application is created  Call setLanguage() when user changes language
  • 27. Retranslating Qt/C++ Models  Equivalent to reimplementing changeEvent() and calling retranslateUi()  In constructor of model class: connect(TranslationManager::instance(), SIGNAL(languageChanged(QString)), this, SLOT(retranslate(QString)));
  • 28. Retranslating Qt/C++ Models (2) void BiggestCitiesModel::retranslate(const QString &language) { emit titleChange(); CityDatabase::instance()->retranslate(language); emit dataChanged(index(0), index(m_cities.count() - 1)); } Notify QML ListView that all its items have changed and need reloading Notify QML code that title property has changed QML calls title(), which returns tr(rawTitle()) Delegate retranslation, as model is “view” on database
  • 29. Retranslating Qt/C++ Models (3) const char *CityDatabase::m_strings[][2] = { { QT_TR_NOOP(“Munich”), QT_TR_NOOP(“Bavaria”) }, … void CityDatabase::retranslate(const QString &language) { if (m_currentLanguage != language) { for (int i = 0; i < m_cities.count(); ++i) { m_cities[i]->setName(tr(m_strings[i][0])); … } m_currentLanguage = language; } Reset visible members } Guard against multiple “views” (e.g., German cities, British cities) requesting retranslation to same language (e.g., city name, state) with new translation of raw string
  • 30. Reevaluating qsTr on Language Change Text { text: qsTr(“City:”) + g_tr.languageChanged … }  Use Property Binding:  Whenever g_tr.languageChanged changes, text must be reevaluated:  qsTr() is called and returns translation for new language
  • 31. Reevaluating qsTr on Language Change (2) In TranslationManager: Q_PROPERTY(QString languageChanged READ emptyString NOTIFY languageChanged) QString emptyString() const { return “”; } Empty string can be appended to translated string without changing anything Emitting this signal forces QML to call emptyString(), the READ method of languageChanged property
  • 32. Reevaluating qsTr on Language Change (3) On instance of QQuickView: view->rootContext()->setContextProperty( “g_tr”, TranslationManager::instance()); Makes pointer to TranslationManager globally available in QML under name g_tr
  • 33. Contents  Key Navigation  Dynamic Language Change  Themes
  • 35. Theming QML Code Rectangle { color: index % 2 === 0 ? “#1E90FF” : “#00BFFF” Row { Text { text: city.name color: “#191970” Unthemed Rectangle { color: index % 2 === 0 ? g_theme.listViewItem. backgroundColor : g_theme.listViewItem. backgroundColorAlt Row { Text { text: city.name color: g_theme.listViewItem. textColor Themed
  • 36. Implementing the Themes QtObject { property QtObject listViewItem : QtObject { property color backgroundColor: “#1E90FF” property color backgroundColorAlt: “#00BFFF” property color textColor: “#191970” } QtObject { property QtObject listViewItem : QtObject { property color backgroundColor: “#A5A5A5” property color backgroundColorAlt: “#818181” property color textColor: “#1E1E1E” }
  • 37. Changing Themes In top-level QML item (main.qml) Global variable accessible from everywhere in QML property alias g_theme: loader.item Loader { id: loader } Set theme on start-up Component.onCompleted: { loader.source = Qt.resolveUrl(“BlueTheme.qml”) } QQuickView forwards signal Connections { themeChanged(QString theme) target: g_viewer onThemeChanged: { loader.source = Qt.resolvedUrl(theme + “Theme.qml”) } }