Коммит e283b8bb создал по автору Alexey Andreev's avatar Alexey Andreev
Просмотр файлов

[UseCases] Introduce forms and view use cases. #6

Additional examples for the related Silica Use Cases project
владелец d756a7b9
......@@ -13,8 +13,12 @@
* Developer, 2020
* Alexander Kazantcev
* Developer, 2022
* Dmitriy Lapshin
* Developer, 2020 - 2023
* Evgeniy Taishev
* Developer, 2022
* Kirill Chuvilin
* Developer, 2020 - 2021
* Petr Mironychev
* Developer, 2020 - 2022
* Sidorova Anastasiya
......
/****************************************************************************
**
** Copyright (C) 2023 Open Mobile Platform LLC.
** Contact: https://community.omprussia.ru/open-source
**
** This file is part of the Silica Use Cases project.
**
** $QT_BEGIN_LICENSE:BSD$
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Open Mobile Platform LLC copyright holder nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPEN MOBILE PLATFORM LLC OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import Sailfish.Silica 1.0
Label {
id: root
objectName: "runningText"
readonly property var animationModes: {
"WithoutReverseAnimation": 0,
"ReverseAnimation": 1,
"CyclicMovement": 2
}
property int animationMode: animationModes.WithoutReverseAnimation
property alias pauseDuration: textAnimation.pauseDuration
property alias velocity: textAnimation.velocity
SequentialAnimation on x {
id: textAnimation
objectName: "textAnimation"
property int xTo: animationMode === animationModes.CyclicMovement
? - root.contentWidth
: parent.width - root.contentWidth
property int velocity: 25 * Theme.pixelRatio
property int pauseDuration: 1100
loops: Animation.Infinite
running: root.contentWidth > parent.width
PauseAnimation {
duration: animationMode === animationModes.CyclicMovement
? 0
: textAnimation.pauseDuration
}
SmoothedAnimation {
to: textAnimation.xTo
velocity: textAnimation.velocity
maximumEasingTime: animationMode === animationModes.CyclicMovement
? 100
: -1
}
PauseAnimation {
duration: animationMode === animationModes.CyclicMovement
? 0
: textAnimation.pauseDuration
}
SmoothedAnimation {
to: animationMode === animationModes.CyclicMovement
? parent.width
: 0
velocity: textAnimation.velocity
duration: animationMode === animationModes.ReverseAnimation
? -1
: 0
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 Open Mobile Platform LLC.
** Contact: https://community.omprussia.ru/open-source
**
** This file is part of the Silica Use Cases project.
**
** $QT_BEGIN_LICENSE:BSD$
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Open Mobile Platform LLC copyright holder nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPEN MOBILE PLATFORM LLC OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import Sailfish.Silica 1.0
Column {
id: root
property alias model: repeater.model
property bool exclusive: true
property string selectedRole: "selected"
property string valueRole: "value"
property string nameRole: "name"
property string iconRole: "icon"
property string descriptionRole: "description"
signal selectedValuesChanged()
function selectedValues() {
var selectedValues = new Array(children.length - 1);
if (exclusive) {
if (repeater.selectedIndex >= 0)
selectedValues[repeater.selectedIndex] = children[repeater.selectedIndex].value;
} else {
for (var iChild = 0; iChild < selectedValues.length; ++iChild) {
var child = children[iChild];
if (child.checked)
selectedValues[iChild] = child.value;
}
}
return selectedValues;
}
width: parent ? parent.width : Screen.width
Repeater {
id: repeater
property int selectedIndex: -1
onModelChanged: selectedIndex = -1
delegate: switchDelegate
}
Component {
id: switchDelegate
IconTextSwitch {
id: switchItem
readonly property var m: model.modelData || model
readonly property var value: m[root.valueRole] === undefined ? m : m[root.valueRole]
onClicked: {
if (checked) {
if (root.exclusive)
return;
checked = false;
repeater.selectedIndex = -1;
} else {
checked = true;
repeater.selectedIndex = model.index;
}
root.selectedValuesChanged();
}
Component.onCompleted: {
if (m[root.selectedRole])
repeater.selectedIndex = model.index;
}
text: m[root.nameRole] === undefined ? value : m[root.nameRole]
description: m[root.descriptionRole] || ""
icon.source: m[root.iconRole] || ""
automaticCheck: false
Binding {
id: targetStateWatcher
when: root.exclusive
target: switchItem
property: "checked"
value: model.index === repeater.selectedIndex
}
}
}
}
/*******************************************************************************
**
** Copyright (C) 2020 - 2023 Open Mobile Platform LLC.
** This file is part of the Showcase of the Aurora OS UI components project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer
** in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../components/"
Page {
id: root
property alias title: pageHeader.title
property alias description: pageHeader.description
property bool exclusive: true
allowedOrientations: Orientation.All
showNavigationIndicator: flickable.contentY < pageHeader.height / 2
SilicaFlickable {
id: flickable
anchors.fill: parent
contentHeight: layout.height
Column {
id: layout
width: parent.width
PageHeader { id: pageHeader }
SectionHeader { text: qsTr("Int Value") }
SwitchGroup {
id: intValueGroup
exclusive: root.exclusive
model: ListModel {
ListElement { value: -1; description: qsTr("It's negative") }
ListElement { value: 0; name: qsTr("Zero"); selected: true }
ListElement { value: 1; icon: "image://theme/icon-m-about" }
}
onSelectedValuesChanged: console.log("Int values:", selectedValues())
}
SectionHeader { text: qsTr("String Value") }
SwitchGroup {
id: stringValueGroup
exclusive: root.exclusive
model: [
{ value: "First", description: qsTr("It's the first one") },
{ value: "Second", name: qsTr("2nd") },
{ value: "Third", icon: "image://theme/icon-m-accept" },
"Forth"
]
onSelectedValuesChanged: console.log("String values:", selectedValues())
}
SectionHeader { text: qsTr("Variable Value") }
SwitchGroup {
id: variableValueGroup
exclusive: root.exclusive
model: [
{ value: true, name: qsTr("True") },
5,
{ value: "Some text", name: qsTr("Some text") },
{ value: new Date(), name: (new Date()).toLocaleDateString(), description: qsTr("Values could be quite variable") }
]
onSelectedValuesChanged: console.log("Variable values:", selectedValues())
}
}
VerticalScrollDecorator { }
PullDownMenu {
quickSelect: true
MenuItem {
text: root.exclusive
? qsTr("Turn multiple selection on")
: qsTr("Turn multiple selection off")
onClicked: root.exclusive = !root.exclusive
}
}
}
}
/*******************************************************************************
**
** Copyright (C) 2020 - 2023 Open Mobile Platform LLC.
** This file is part of the Showcase of the Aurora OS UI components project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer
** in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../components/"
Page {
id: root
objectName: "listViewWithRunningLinePage"
property alias title: pageHeader.title
property alias description: pageHeader.description
allowedOrientations: Orientation.All
PageHeader {
id: pageHeader
objectName: "pageHeader"
}
SilicaListView {
id: listView
objectName: "listViewWithRunningLine"
anchors {
fill: parent
topMargin: pageHeader.height
}
model: ListModel {
objectName: "model"
ListElement {
delegateText: qsTr("This is short string.")
lineAnimationMode: 0
}
ListElement {
delegateText: qsTr("This line runs without reverse animation. Let's make it long enough to animate")
lineAnimationMode: 0
}
ListElement {
delegateText: qsTr("This line runs with reverse animation. Let's make it long enough to animate")
lineAnimationMode: 1
}
ListElement {
delegateText: qsTr("This line runs with cyclic movement. Let's make it long enough to animate")
lineAnimationMode: 2
}
}
delegate: ListItem {
objectName: "listViewDelegate"
Rectangle {
objectName: "objectToPlaceText"
width: listView.width * 0.75
height: runningText.font.pixelSize * 2
color: "transparent"
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
border {
color: palette.primaryColor
width: 2 * Theme.pixelRatio
}
clip: true
RunningText {
id: runningText
objectName: "runningText"
width: parent.width
height: parent.height
text: delegateText
verticalAlignment: Text.AlignVCenter
animationMode: lineAnimationMode
}
}
}
VerticalScrollDecorator { objectName: "scroll" }
}
}
......@@ -203,6 +203,24 @@ Page {
subtitle: qsTr("Show how application display with cutout")
section: qsTr("Example")
}
ListElement {
page: "DeclarativeRadioButtonsPage.qml"
title: qsTr("Forms: Declarative Radio Buttons")
subtitle: qsTr("Using QML only")
section: qsTr("Example")
}
ListElement {
page: "RadioButtonsModelPage.qml"
title: qsTr("Forms: Radio Buttons with Model")
subtitle: qsTr("Controlled by C++ model")
section: qsTr("Example")
}
ListElement {
page: "ListViewWithRunningLine.qml"
title: qsTr("Views: ListView with running line")
subtitle: qsTr("ListView delegate contents running line")
section: qsTr("Example")
}
}
SilicaListView {
......
/*******************************************************************************
**
** Copyright (C) 2020 - 2023 Open Mobile Platform LLC.
** This file is part of the Showcase of the Aurora OS UI components project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer
** in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/
import QtQuick 2.0
import Sailfish.Silica 1.0
import ru.auroraos.Silica.UseCases 1.0
Page {
id: root
property string title
property string description
allowedOrientations: Orientation.All
showNavigationIndicator: view.contentY < view.headerItem.height / 2
SelectGroupModel { id: selectGroupModel }
SilicaListView {
id: view
model: selectGroupModel
spacing: Theme.paddingMedium
anchors.fill: parent
header: PageHeader { title: root.title; description: root.description }
delegate: IconTextSwitch {
id: switchItem
checked: model.selected
automaticCheck: false
text: model.name
description: model.description
icon.source: model.icon
onClicked: model.selected = !model.selected
}
ViewPlaceholder {
enabled: view.count == 0
text: qsTr("No items")
hintText: qsTr("Use pulley menu to append some")
}
PullDownMenu {
quickSelect: true
MenuItem {
text: selectGroupModel.exclusive
? qsTr("Turn multiple selection on")
: qsTr("Turn multiple selection off")
onClicked: selectGroupModel.exclusive = !selectGroupModel.exclusive
}
MenuItem {
text: qsTr("Append item")
onClicked: pageStack.push(newItemDialog)
}
}
}
Component {
id: newItemDialog
Dialog {
canAccept: newItemDialogTypeSelector.value !== "number"
|| !newItemDialogNumberValueInput.errorHighlight
onAccepted: {
var value
switch (newItemDialogTypeSelector.value) {
case "text":
value = newItemDialogTextValueInput.text
break
case "number":
value = Number(newItemDialogTextValueInput.text)
break
case "date":
value = newItemDialogDateValuePicker.date
break
}
// You can only append a single value if no other parameters are specified.
// In other cases, you need to define an object with optional fields:
// selected, value, name, description and icon.
if (newItemDialogNameInput.text
|| newItemDialogDescriptionInput.text
|| newItemDialogIconSelector.value
|| newItemDialogSelectedSwitch.checked) {
value = { value: value }
if (newItemDialogNameInput.text)
value.name = newItemDialogNameInput.text
if (newItemDialogDescriptionInput.text)
value.description = newItemDialogDescriptionInput.text
if (newItemDialogIconSelector.value)
value.icon = "image://theme/" + newItemDialogIconSelector.value
if (newItemDialogSelectedSwitch.checked)
value.selected = true
}
selectGroupModel.append(value)
}
SilicaFlickable {
contentHeight: newItemDialogLayout.height
anchors.fill: parent
Column {
id: newItemDialogLayout
width: parent.width
DialogHeader { acceptText: qsTr("Append") }
ComboBox {
id: newItemDialogTypeSelector
label: qsTr("Value type")
value: ["text", "number", "date"][currentIndex]
menu: ContextMenu {
MenuItem { text: qsTr("Text") }
MenuItem { text: qsTr("Number") }
MenuItem { text: qsTr("Date") }
}
onValueChanged: {
switch (value) {
case "text":
newItemDialogTextValueInput.forceActiveFocus()
break
case "number":
newItemDialogNumberValueInput.forceActiveFocus()
break
case "date":
newItemDialogDateValuePicker.forceActiveFocus()
break
}
}
}
TextArea {
id: newItemDialogTextValueInput
label: qsTr("Value")
placeholderText: qsTr("Input text value")
visible: newItemDialogTypeSelector.value === "text"
width: parent.width
}
TextField {
id: newItemDialogNumberValueInput
label: qsTr("Value")
placeholderText: qsTr("Input number value")
visible: newItemDialogTypeSelector.value === "number"
width: parent.width
inputMethodHints: Qt.ImhFormattedNumbersOnly
validator: DoubleValidator { }
EnterKey.enabled: !errorHighlight
EnterKey.iconSource: "image://theme/icon-m-enter-next"
EnterKey.onClicked: newItemDialogNameInput.forceActiveFocus()
}
DatePicker {
id: newItemDialogDateValuePicker
visible: newItemDialogTypeSelector.value === "date"
monthYearVisible: true
}
TextSwitch {
id: newItemDialogSelectedSwitch
text: qsTr("Insert the item as selected")
checked: false
}
TextField {
id: newItemDialogNameInput
label: qsTr("Name")
placeholderText: qsTr("Input name or skip")
text: newItemDialogTypeSelector.value === "date"
? newItemDialogDateValuePicker.date.toLocaleDateString()
: ""
width: parent.width
EnterKey.iconSource: "image://theme/icon-m-enter-next"
EnterKey.onClicked: newItemDialogDescriptionInput.forceActiveFocus()
}
TextArea {
id: newItemDialogDescriptionInput
label: qsTr("Description")
placeholderText: qsTr("Input description or skip")
width: parent.width
}
ComboBox {
id: newItemDialogIconSelector
label: qsTr("Icon")
menu: ContextMenu {
MenuItem { text: "" }
MenuItem { text: "icon-m-about" }
MenuItem { text: "icon-m-accept" }
MenuItem { text: "icon-m-accessory-speaker" }
MenuItem { text: "icon-m-acknowledge" }
MenuItem { text: "icon-m-add" }
MenuItem { text: "icon-m-alarm" }
}
}
}
}
}
}
}
......@@ -44,8 +44,10 @@ PKGCONFIG += \
SOURCES += \
src/main.cpp \
src/selectgroupmodel.cpp
HEADERS += \
src/selectgroupmodel.h
DISTFILES += \
rpm/ru.auroraos.UIComponentGallery.spec \
......
......@@ -38,12 +38,16 @@
#include <auroraapp.h>
#include <QtQuick>
#include "selectgroupmodel.h"
int main(int argc, char *argv[])
{
QScopedPointer<QGuiApplication> application(Aurora::Application::application(argc, argv));
application->setOrganizationName(QStringLiteral("ru.auroraos"));
application->setApplicationName(QStringLiteral("UIComponentGallery"));
qmlRegisterType<SelectGroupModel>("ru.auroraos.Silica.UseCases", 1, 0, "SelectGroupModel");
QScopedPointer<QQuickView> view(Aurora::Application::createView());
view->setSource(Aurora::Application::pathTo(QStringLiteral("qml/UIComponentGallery.qml")));
view->show();
......
/*******************************************************************************
**
** Copyright (C) 2020 - 2023 Open Mobile Platform LLC.
** This file is part of the Showcase of the Aurora OS UI components project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer
** in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/
#include "selectgroupmodel.h"
#include <QVariant>
#include <QJsonValue>
#include <QJsonObject>
#include <QDebug>
const auto s_selectedRoleName = QByteArrayLiteral("selected");
const auto s_valueRoleName = QByteArrayLiteral("value");
const auto s_nameRoleName = QByteArrayLiteral("name");
const auto s_descriptionRoleName = QByteArrayLiteral("description");
const auto s_iconRoleName = QByteArrayLiteral("icon");
SelectGroupModel::SelectGroupModel(QObject *parent) : QAbstractListModel(parent),
_exclusive(true)
{ }
int SelectGroupModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return _items.count();
}
QHash<int, QByteArray> SelectGroupModel::roleNames() const
{
return {
{ SelectedRole, s_selectedRoleName },
{ ValueRole, s_valueRoleName },
{ NameRole, s_nameRoleName },
{ DescriptionRole, s_descriptionRoleName },
{ IconRole, s_iconRoleName }
};
}
QVariant SelectGroupModel::data(const QModelIndex &index, int role) const
{
auto iItem = index.row();
if (iItem < 0 || iItem >= _items.count())
return QVariant();
switch (role) {
case SelectedRole:
return _selectedItems.contains(iItem);
case ValueRole:
return _items[iItem].value().toVariant();
case NameRole:
return _items[iItem].name();
case DescriptionRole:
return _items[iItem].description();
case IconRole:
return _items[iItem].icon();
default:
return QVariant();
}
}
bool SelectGroupModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
auto iItem = index.row();
if (iItem < 0 || iItem >= _items.count())
return false;
switch (role) {
case SelectedRole:
return updateSelected(iItem, value.toBool());
case ValueRole:
if (!_items[iItem].setValue(value.toJsonValue()))
return true;
break;
case NameRole:
if (!_items[iItem].setName(value.toString()))
return true;
break;
case DescriptionRole:
if (!_items[iItem].setDescription(value.toString()))
return true;
break;
case IconRole:
if (!_items[iItem].setIcon(value.toString()))
return true;
break;
default:
return false;
}
emit dataChanged(index, index, { role });
return true;
}
Qt::ItemFlags SelectGroupModel::flags(const QModelIndex &index) const
{
return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
}
bool SelectGroupModel::exclusive() const
{
return _exclusive;
}
void SelectGroupModel::setExclusive(bool exclusive)
{
if (_exclusive == exclusive)
return;
_exclusive = exclusive;
if (_exclusive && _selectedItems.count() > 1) {
while (_selectedItems.count() > 1) {
auto iSelectedItem = *_selectedItems.begin();
_selectedItems.remove(iSelectedItem);
auto modelIndex = QAbstractItemModel::createIndex(iSelectedItem, 0);
emit dataChanged(modelIndex, modelIndex, { SelectedRole });
}
emit selectedValuesChanged();
}
emit exclusiveChanged();
}
QJsonArray SelectGroupModel::selectedValues() const
{
QJsonArray selectedValues;
for (int iItem = 0; iItem < _items.count(); ++iItem) {
if (_selectedItems.contains(iItem))
selectedValues.append(_items[iItem].value());
else
selectedValues.append(QJsonValue(QJsonValue::Undefined));
}
return selectedValues;
}
int SelectGroupModel::selectedCount() const
{
return _selectedItems.count();
}
void SelectGroupModel::clear()
{
beginResetModel();
_items.clear();
endResetModel();
}
void SelectGroupModel::append(const QJsonValue &value)
{
beginInsertRows(QModelIndex(), _items.count(), _items.count());
auto item = Item(value);
_items.append(item);
if (item.selected())
updateSelected(_items.count() - 1, true);
endInsertRows();
}
bool SelectGroupModel::updateSelected(int iItem, bool selected)
{
if (iItem < 0 || iItem >= _items.count())
return false;
if (selected) {
if (_selectedItems.contains(iItem))
return true;
if (_exclusive){
auto oldSelectedItems = _selectedItems;
_selectedItems.clear();
for (auto oldSelectedItem : oldSelectedItems) {
auto modelIndex = QAbstractItemModel::createIndex(oldSelectedItem, 0);
emit dataChanged(modelIndex, modelIndex, { SelectedRole });
}
}
_selectedItems.insert(iItem);
} else {
if (!_selectedItems.contains(iItem))
return true;
if (_exclusive && _selectedItems.count() <= 1)
return true;
_selectedItems.remove(iItem);
}
auto modelIndex = QAbstractItemModel::createIndex(iItem, 0);
emit dataChanged(modelIndex, modelIndex, { SelectedRole });
emit selectedValuesChanged();
return true;
}
SelectGroupModel::Item::Item(const QJsonValue &value)
{
if (value.isObject()) {
auto object = value.toObject();
_selected = object.value(s_selectedRoleName).toBool();
_value = object.value(s_valueRoleName);
_name = object.value(s_nameRoleName).toString();
_description = object.value(s_descriptionRoleName).toString();
_icon = object.value(s_iconRoleName).toString();
} else {
_selected = false;
_value = value;
}
}
bool SelectGroupModel::Item::selected() const
{
return _selected;
}
const QJsonValue& SelectGroupModel::Item:: value() const
{
return _value;
}
bool SelectGroupModel::Item::setValue(const QJsonValue &value)
{
if (_value == value)
return false;
_value = value;
return true;
}
QString SelectGroupModel::Item::name() const
{
return _name.isEmpty() ? _value.toVariant().toString() : _name;
}
bool SelectGroupModel::Item::setName(const QString &name)
{
if (_name == name)
return false;
_name = name;
return true;
}
QString SelectGroupModel::Item::description() const
{
return _description;
}
bool SelectGroupModel::Item::setDescription(const QString &description)
{
if (_description == description)
return false;
_description = description;
return true;
}
QUrl SelectGroupModel::Item::icon() const
{
return _icon;
}
bool SelectGroupModel::Item::setIcon(const QUrl &icon)
{
if (_icon == icon)
return false;
_icon = icon;
return true;
}
/*******************************************************************************
**
** Copyright (C) 2020 - 2023 Open Mobile Platform LLC.
** This file is part of the Showcase of the Aurora OS UI components project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer
** in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/
#ifndef SELECTGROUPMODEL_H
#define SELECTGROUPMODEL_H
#include <QAbstractListModel>
#include <QUrl>
#include <QSet>
#include <QJsonArray>
class SelectGroupModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool exclusive READ exclusive WRITE setExclusive NOTIFY exclusiveChanged)
Q_PROPERTY(QJsonArray selectedValues READ selectedValues NOTIFY selectedValuesChanged)
Q_PROPERTY(int selectedCount READ selectedCount NOTIFY selectedValuesChanged)
public:
enum Role
{
SelectedRole = Qt::UserRole + 1,
ValueRole,
NameRole,
DescriptionRole,
IconRole
};
explicit SelectGroupModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool exclusive() const;
void setExclusive(bool exclusive);
QJsonArray selectedValues() const;
int selectedCount() const;
public slots:
void clear();
void append(const QJsonValue &item);
signals:
void exclusiveChanged();
void selectedValuesChanged();
private:
class Item {
public:
explicit Item(const QJsonValue &_value);
bool selected() const;
const QJsonValue& value() const;
bool setValue(const QJsonValue &value);
QString name() const;
bool setName(const QString &name);
QString description() const;
bool setDescription(const QString &description);
QUrl icon() const;
bool setIcon(const QUrl &icon);
private:
bool _selected;
QJsonValue _value;
QString _name;
QString _description;
QUrl _icon;
};
bool _exclusive;
QList<Item> _items;
QSet<int> _selectedItems;
bool updateSelected(int iItem, bool selected);
};
#endif // SELECTGROUPMODEL_H
......@@ -693,6 +693,69 @@
<translation>Показать пример страницы</translation>
</message>
</context>
<context>
<name>DeclarativeRadioButtonsPage</name>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="64"/>
<source>Int Value</source>
<translation>Значение Int</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="71"/>
<source>It&apos;s negative</source>
<translation>Отрицательное</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="72"/>
<source>Zero</source>
<translation>Ноль</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="79"/>
<source>String Value</source>
<translation>Строка</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="86"/>
<source>It&apos;s the first one</source>
<translation>Первый</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="87"/>
<source>2nd</source>
<translation>Второй</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="95"/>
<source>Variable Value</source>
<translation>Переменное значение</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="102"/>
<source>True</source>
<translation>Истина</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="104"/>
<source>Some text</source>
<translation>Немного текста</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="105"/>
<source>Values could be quite variable</source>
<translation>Значения могут быть переменными</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="119"/>
<source>Turn multiple selection on</source>
<translation>Включить множественный выбор</translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="120"/>
<source>Turn multiple selection off</source>
<translation>Выключить множественный выбор</translation>
</message>
</context>
<context>
<name>DefaultCoverPage</name>
<message>
......@@ -2161,6 +2224,29 @@
<translation></translation>
</message>
</context>
<context>
<name>ListViewWithRunningLine</name>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="68"/>
<source>This is short string.</source>
<translation>Это короткая строка.</translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="73"/>
<source>This line runs without reverse animation. Let&apos;s make it long enough to animate</source>
<translation>Эта строка выполняется без обратной анимации. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="78"/>
<source>This line runs with reverse animation. Let&apos;s make it long enough to animate</source>
<translation>Эта строка работает с обратной анимацией. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="83"/>
<source>This line runs with cyclic movement. Let&apos;s make it long enough to animate</source>
<translation>Эта строка проходит с циклическим движением. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
</context>
<context>
<name>MainPage</name>
<message>
......@@ -2448,6 +2534,9 @@
<message>
<location filename="../qml/pages/MainPage.qml" line="198"/>
<location filename="../qml/pages/MainPage.qml" line="204"/>
<location filename="../qml/pages/MainPage.qml" line="210"/>
<location filename="../qml/pages/MainPage.qml" line="216"/>
<location filename="../qml/pages/MainPage.qml" line="222"/>
<source>Example</source>
<translation>Пример</translation>
</message>
......@@ -2461,8 +2550,38 @@
<source>Show how application display with cutout</source>
<translation>Показать, как отображается приложение с вырезом эркана</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="208"/>
<source>Forms: Declarative Radio Buttons</source>
<translation>Формы: декларативные переключатели</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="209"/>
<source>Using QML only</source>
<translation>Использование только QML</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="214"/>
<source>Forms: Radio Buttons with Model</source>
<translation>Формы: радиокнопки с моделью</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="215"/>
<source>Controlled by C++ model</source>
<translation>Управляется моделью C++</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="220"/>
<source>Views: ListView with running line</source>
<translation>ListView с бегущей строкой</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="221"/>
<source>ListView delegate contents running line</source>
<translation>Делегат ListView содержит бегущую строку</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="232"/>
<source>UI Component Gallery</source>
<translation>Галерея компонентов UI</translation>
</message>
......@@ -2962,6 +3081,105 @@
<translation>Круг прогресса</translation>
</message>
</context>
<context>
<name>RadioButtonsModelPage</name>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="74"/>
<source>No items</source>
<translation>Нет элементов</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="75"/>
<source>Use pulley menu to append some</source>
<translation>Воспользуйтесь меню, чтобы добавить</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="83"/>
<source>Turn multiple selection on</source>
<translation>Включить множественный выбор</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="84"/>
<source>Turn multiple selection off</source>
<translation>Выключить множественный выбор</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="90"/>
<source>Append item</source>
<translation>Добавить элемент</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="146"/>
<source>Append</source>
<translation>Добавить</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="151"/>
<source>Value type</source>
<translation>Тип значения</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="154"/>
<source>Text</source>
<translation>Текст</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="155"/>
<source>Number</source>
<translation>Числа</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="156"/>
<source>Date</source>
<translation>Дата</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="177"/>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="186"/>
<source>Value</source>
<translation>Значение</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="178"/>
<source>Input text value</source>
<translation>Значение ввода текста</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="187"/>
<source>Input number value</source>
<translation>Значение ввода числа</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="209"/>
<source>Insert the item as selected</source>
<translation>Добавьте выбранный элемент</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="216"/>
<source>Name</source>
<translation>Название</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="217"/>
<source>Input name or skip</source>
<translation>Введите название или пропустите</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="230"/>
<source>Description</source>
<translation>Описание</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="231"/>
<source>Input description or skip</source>
<translation>Введите описание или пропустите</translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="238"/>
<source>Icon</source>
<translation>Значок</translation>
</message>
</context>
<context>
<name>SearchPage</name>
<message>
......
......@@ -693,6 +693,69 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DeclarativeRadioButtonsPage</name>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="64"/>
<source>Int Value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="71"/>
<source>It&apos;s negative</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="72"/>
<source>Zero</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="79"/>
<source>String Value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="86"/>
<source>It&apos;s the first one</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="87"/>
<source>2nd</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="95"/>
<source>Variable Value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="102"/>
<source>True</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="104"/>
<source>Some text</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="105"/>
<source>Values could be quite variable</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="119"/>
<source>Turn multiple selection on</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/DeclarativeRadioButtonsPage.qml" line="120"/>
<source>Turn multiple selection off</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultCoverPage</name>
<message>
......@@ -2161,6 +2224,29 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ListViewWithRunningLine</name>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="68"/>
<source>This is short string.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="73"/>
<source>This line runs without reverse animation. Let&apos;s make it long enough to animate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="78"/>
<source>This line runs with reverse animation. Let&apos;s make it long enough to animate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/ListViewWithRunningLine.qml" line="83"/>
<source>This line runs with cyclic movement. Let&apos;s make it long enough to animate</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainPage</name>
<message>
......@@ -2448,6 +2534,9 @@
<message>
<location filename="../qml/pages/MainPage.qml" line="198"/>
<location filename="../qml/pages/MainPage.qml" line="204"/>
<location filename="../qml/pages/MainPage.qml" line="210"/>
<location filename="../qml/pages/MainPage.qml" line="216"/>
<location filename="../qml/pages/MainPage.qml" line="222"/>
<source>Example</source>
<translation type="unfinished"></translation>
</message>
......@@ -2461,8 +2550,38 @@
<source>Show how application display with cutout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="208"/>
<source>Forms: Declarative Radio Buttons</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="209"/>
<source>Using QML only</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="214"/>
<source>Forms: Radio Buttons with Model</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="215"/>
<source>Controlled by C++ model</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="220"/>
<source>Views: ListView with running line</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="221"/>
<source>ListView delegate contents running line</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="232"/>
<source>UI Component Gallery</source>
<translation>UI Component Gallery</translation>
</message>
......@@ -2962,6 +3081,105 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RadioButtonsModelPage</name>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="74"/>
<source>No items</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="75"/>
<source>Use pulley menu to append some</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="83"/>
<source>Turn multiple selection on</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="84"/>
<source>Turn multiple selection off</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="90"/>
<source>Append item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="146"/>
<source>Append</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="151"/>
<source>Value type</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="154"/>
<source>Text</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="155"/>
<source>Number</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="156"/>
<source>Date</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="177"/>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="186"/>
<source>Value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="178"/>
<source>Input text value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="187"/>
<source>Input number value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="209"/>
<source>Insert the item as selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="216"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="217"/>
<source>Input name or skip</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="230"/>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="231"/>
<source>Input description or skip</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qml/pages/RadioButtonsModelPage.qml" line="238"/>
<source>Icon</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SearchPage</name>
<message>
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать