From 112191b027cf991614f6c186d3b2105072675c41 Mon Sep 17 00:00:00 2001 From: Juraj Oravec Date: Mon, 4 Apr 2022 23:04:36 +0200 Subject: [PATCH] QML: Add extension settings tutorial Signed-off-by: Juraj Oravec --- qml/README.md | 1 + qml/articles/8.Extension_settings.md | 84 ++++++++++++++++++ qml/extensions/qml_tutorial_8/main.qml | 74 +++++++++++++++ .../qml_tutorial_8/metadata.desktop | 11 +++ qml/images/tutorial8/settings_window.png | Bin 0 -> 15287 bytes 5 files changed, 170 insertions(+) create mode 100644 qml/articles/8.Extension_settings.md create mode 100644 qml/extensions/qml_tutorial_8/main.qml create mode 100644 qml/extensions/qml_tutorial_8/metadata.desktop create mode 100644 qml/images/tutorial8/settings_window.png diff --git a/qml/README.md b/qml/README.md index 92071b6..fcb6f53 100644 --- a/qml/README.md +++ b/qml/README.md @@ -7,3 +7,4 @@ 5. [Using notifications](articles/5.Using_notifications.md) - [Extension](extensions/qml_tutorial_5/) 6. [Using clipboard](articles/6.Using_clipboard.md) - [Extension](extensions/qml_tutorial_6/) 7. [Adding a sidebar](articles/7.Adding_a_sidebar.md) - [Extension](extensions/qml_tutorial_7/) +8. [Extension settings](articles/8.Extension_settings.md) - [Extension](extensions/qml_tutorial_8/) diff --git a/qml/articles/8.Extension_settings.md b/qml/articles/8.Extension_settings.md new file mode 100644 index 0000000..2050ff2 --- /dev/null +++ b/qml/articles/8.Extension_settings.md @@ -0,0 +1,84 @@ +# Falkon QML Tutorial - 8. Extension settings + +Hello, in this chapter I will show you how to create a settings dialog. + +These settings are stored as `ini` files in the +`profile/extensions/some_extension/settings.ini` and thus are suitable +only for small data storage like global user settings. + +## Use Settings + +At first set the settings option `X-Falkon-Settings=true` in the desktop +file to tell Falkon the settings for the extension are available. + +```ini +[Desktop Entry] +Name=Tutorial8 QML +Comment=Example QML extension with settings +Icon= +Type=Service +X-Falkon-Type=Extension/Qml + +X-Falkon-Author=Juraj Oravec +X-Falkon-Email=jurajoravec@mailo.com +X-Falkon-Version=1.0.0 +X-Falkon-Settings=true +``` + +```qml +Falkon.Settings { + id: settings + name: 'Tutorial8_settings' +} + +settingsWindow: Rectangle { + id: window + width: 256 + height: 200 +} +``` + +In this example Falkon settings API can be accessed through `settings` +object. The available API can be found at +[documentation](http://falkon.sgorava.xyz/docs/class_qml_settings.html) +or +[code](https://github.com/KDE/falkon/blob/master/src/lib/plugins/qml/api/settings/qmlsettings.h) + +## Troubleshooting +If you try to use the Qt style settings syntax +`settings.value('key', 'default')` you will receive an error message +like this one: +> "Could not convert argument 0 at" + "@file://falkon/plugins/qml_tutorial_8/main.qml:13" +"Passing incompatible arguments to C++ functions from JavaScript is dangerous and deprecated." +"This will throw a JavaScript TypeError in future releases of Qt!" +Unable to get value: key not defined + +Thus use a proper Falkon settings syntax eg. +```qml +settings.value({ + key: 'password' + defaultValue: '1234567890' +}) +``` + +## Limitations +I am aware of these potential limitation. +- I was unable to find a way to close a settings window from QML script +- Try to avoid saving variable of type `bool` with settings. The results +might not be as expected. + +## Example +The example will create a button which will be placed into the toolbar +and though settings optionaly adds icon to the statusbar. The settings +for the statusbar icon will change after browser restart. + +The setting window contains an image and a checkbox. + +This example is partialy ripped of from Falkon example extension. + +![Window with sidebar and view menu](../images/tutorial8/settings_window.png) + +### Code +The code for this example can be found at +[extensions/qml_tutorial_8](../extensions/qml_tutorial_8) diff --git a/qml/extensions/qml_tutorial_8/main.qml b/qml/extensions/qml_tutorial_8/main.qml new file mode 100644 index 0000000..821aaf3 --- /dev/null +++ b/qml/extensions/qml_tutorial_8/main.qml @@ -0,0 +1,74 @@ +import org.kde.falkon 1.0 as Falkon +import QtQuick.Controls 2.3 +import QtQuick 2.3 + +Falkon.PluginInterface { + + Falkon.Settings { + id: settings + name: 'Tutorial8_settings' + } + + init: function(state, settingsPath) { + console.log(i18n('"Tutorial8" plugin loaded')) + } + + testPlugin: function() { + return true + } + + unload: function() { + console.log(i18n('"Tutorial8" plugin unloaded')) + } + + Falkon.BrowserAction { + name: 'QML Tutorial 8' + identity: 'qml-tutorial-8-id' + title: i18n('Qml Tutorial 8') + toolTip: i18n('My little button') + icon: 'falkon' + location: Falkon.BrowserAction.NavigationToolBar | (settings.value({key: 'statusbar', defaultValue: 1}) == 1 ? Falkon.BrowserAction.StatusBar : 0) + popup: Rectangle { + width: 100; + height: 100; + } + } + + settingsWindow: Rectangle { + id: window + width: 256 + height: 200 + Image { + id: image + source: 'qrc:/icons/other/about.svg' + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + } + CheckBox { + id: checkStatusbar + checked: settings.value({key: 'statusbar', defaultValue: 1}) == 1 + text: 'Show in statusbar' + anchors.top: image.bottom + } + Button { + id: button + text: i18n('Save') + width: 256 + height: 50 + anchors.top: checkStatusbar.bottom + onClicked: function() { + var res = settings.setValue({ + key: 'statusbar', + value: checkStatusbar.checked ? 1 : 0 + }) + var sync = settings.sync() + if (res && sync) { + button.text = i18n('Saved!') + } else { + button.text = i18n('Error occurred, try again!') + } + } + } + } +} diff --git a/qml/extensions/qml_tutorial_8/metadata.desktop b/qml/extensions/qml_tutorial_8/metadata.desktop new file mode 100644 index 0000000..40f7861 --- /dev/null +++ b/qml/extensions/qml_tutorial_8/metadata.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Tutorial8 QML +Comment=Example QML extension with settings +Icon= +Type=Service +X-Falkon-Type=Extension/Qml + +X-Falkon-Author=Juraj Oravec +X-Falkon-Email=jurajoravec@mailo.com +X-Falkon-Version=1.0.0 +X-Falkon-Settings=true diff --git a/qml/images/tutorial8/settings_window.png b/qml/images/tutorial8/settings_window.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb10d3be20d23acc585e6daa20b3a306871f3e5 GIT binary patch literal 15287 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 literal 0 HcmV?d00001