Не подтверждена Коммит d64d9725 создал по автору OMP Education's avatar OMP Education Зафиксировано автором Alexey Andreev
Просмотр файлов

[UseCases] Port logic from existing complex use cases project

владелец 7764e97b
Конвейер #31830 пройдено in 44 секунды
......@@ -28,6 +28,7 @@ The project has a standard standard of an application based on C++ and QML for A
describes the project structure for the qmake build system.
* **[icons](icons)** directory contains the application icons for different screen resolutions.
* **[qml](qml)** directory contains the QML source code and the UI resources.
* **[components](qml/components)** directory contains the custom QML components.
* **[cover](qml/cover)** directory contains the application cover implementations.
* **[icons](qml/icons)** directory contains the additional custom UI icons.
* **[pages](qml/pages)** directory contains the application pages.
......
......@@ -27,6 +27,7 @@
* Файл **[ru.auroraos.UiComponentGallery.pro](ru.auroraos.UiComponentGallery.pro)** описывает структуру проекта для системы сборки qmake.
* Каталог **[icons](icons)** содержит иконки приложения для поддерживаемых разрешений экрана.
* Каталог **[qml](qml)** содержит исходный код на QML и ресурсы интерфейса пользователя.
* Каталог **[components](qml/components)** содержит вспомогательные QML компоненты.
* Каталог **[cover](qml/cover)** содержит реализации обложек приложения.
* Каталог **[icons](qml/icons)** содержит дополнительные иконки интерфейса пользователя.
* Каталог **[pages](qml/pages)** содержит страницы приложения.
......
// SPDX-FileCopyrightText: 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
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
}
}
}
// SPDX-FileCopyrightText: 2020 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
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
}
}
}
}
// SPDX-FileCopyrightText: 2020 - 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
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
//% "Forms: Radio Buttons with Model"
title: qsTrId("ui-component-gallery-main-forms-declarative-radio-buttons")
//% "Using QML only"
description: qsTrId("ui-component-gallery-main-using-qml-only")
}
SectionHeader {
//% "Int Value"
text: qsTrId("ui-component-gallery-declarative-radio-buttons-int-value")
}
SwitchGroup {
id: intValueGroup
exclusive: root.exclusive
model: ListModel {
ListElement {
value: -1
//% "It's negative"
description: qsTrId("ui-component-gallery-declarative-radio-buttons-its-negative")
}
ListElement {
value: 0
//% "Zero"
name: qsTrId("ui-component-gallery-declarative-radio-buttons-zero")
selected: true
}
ListElement {
value: 1
icon: "image://theme/icon-m-about"
}
}
onSelectedValuesChanged: console.log("Int values:", selectedValues())
}
SectionHeader {
//% "String Value"
text: qsTrId("ui-component-gallery-declarative-radio-buttons-string-value")
}
SwitchGroup {
id: stringValueGroup
exclusive: root.exclusive
model: [{
"value": "First",
//% "It's the first one"
"description": qsTrId("ui-component-gallery-declarative-radio-buttons-its-the-first-one")
}, {
"value": "Second",
//% "2nd"
"name": qsTrId("ui-component-gallery-declarative-radio-buttons-2-nd")
}, {
"value": "Third",
"icon": "image://theme/icon-m-accept"
}, "Forth"]
onSelectedValuesChanged: console.log("String values:", selectedValues())
}
SectionHeader {
//% "Variable Value"
text: qsTrId("ui-component-gallery-declarative-radio-buttons-variable-value")
}
SwitchGroup {
id: variableValueGroup
exclusive: root.exclusive
model: [{
"value": true,
//% "True"
"name": qsTrId("ui-component-gallery-declarative-radio-buttons-true")
}, 5, {
"value": "Some text",
//% "Some text"
"name": qsTrId("ui-component-gallery-declarative-radio-buttons-some-text")
}, {
"value": new Date(),
"name": (new Date()).toLocaleDateString(),
//% "Values could be quite variable"
"description": qsTrId("ui-component-gallery-declarative-radio-buttons-values-could-be-quite-variable")
}]
onSelectedValuesChanged: console.log("Variable values:", selectedValues())
}
}
VerticalScrollDecorator {
}
PullDownMenu {
quickSelect: true
MenuItem {
text: root.exclusive ?
//% "Turn multiple selection on"
qsTrId("ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-on") :
//% "Turn multiple selection off"
qsTrId("ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-off")
onClicked: root.exclusive = !root.exclusive
}
}
}
}
// SPDX-FileCopyrightText: 2020 - 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
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"
//% "Views: ListView with running line"
title: qsTrId("ui-component-gallery-main-views-list-view-with-running-line")
}
SilicaListView {
id: listView
objectName: "listViewWithRunningLine"
anchors {
fill: parent
topMargin: pageHeader.height
}
model: ListModel {
objectName: "model"
ListElement {
//% "This is short string."
delegateText: qsTrId("ui-component-gallery-list-view-with-running-line-this-is-short-string")
lineAnimationMode: 0
}
ListElement {
//% "This line runs without reverse animation. Let's make it long enough to animate"
delegateText: qsTrId("ui-component-gallery-list-view-with-running-line-this-line-runs-without-reverse-animation-lets-make-it-long-enough-to-animate")
lineAnimationMode: 0
}
ListElement {
//% "This line runs with reverse animation. Let's make it long enough to animate"
delegateText: qsTrId("ui-component-gallery-list-view-with-running-line-this-line-runs-with-reverse-animation-lets-make-it-long-enough-to-animate")
lineAnimationMode: 1
}
ListElement {
//% "This line runs with cyclic movement. Let's make it long enough to animate"
delegateText: qsTrId("ui-component-gallery-list-view-with-running-line-this-line-runs-with-cyclic-movement-lets-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"
}
}
}
......@@ -248,6 +248,33 @@ Page {
//% "Example"
section: qsTrId("ui-component-gallery-main-example")
}
ListElement {
page: "DeclarativeRadioButtonsPage.qml"
//% "Forms: Declarative Radio Buttons"
title: qsTrId("ui-component-gallery-main-forms-declarative-radio-buttons")
//% "Using QML only"
subtitle: qsTrId("ui-component-gallery-main-using-qml-only")
//% "Example"
section: qsTrId("ui-component-gallery-main-example")
}
ListElement {
page: "RadioButtonsModelPage.qml"
//% "Forms: Radio Buttons with Model"
title: qsTrId("ui-component-gallery-main-forms-radio-buttons-with-model")
//% "Controlled by C++ model"
subtitle: qsTrId("ui-component-gallery-main-controlled-by-c-model")
//% "Example"
section: qsTrId("ui-component-gallery-main-example")
}
ListElement {
page: "ListViewWithRunningLine.qml"
//% "Views: ListView with running line"
title: qsTrId("ui-component-gallery-main-views-list-view-with-running-line")
//% "ListView delegate contents running line"
subtitle: qsTrId("ui-component-gallery-main-list-view-delegate-contents-running-line")
//% "Example"
section: qsTrId("ui-component-gallery-main-example")
}
}
SilicaListView {
......
// SPDX-FileCopyrightText: 2020 - 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
import QtQuick 2.0
import Sailfish.Silica 1.0
import ru.auroraos.Silica.UseCases 1.0
Page {
id: root
//% "Forms: Radio Buttons with Model"
property string title: qsTrId("ui-component-gallery-main-forms-radio-buttons-with-model")
//% "Controlled by C++ model"
property string description: qsTrId("ui-component-gallery-main-controlled-by-c-model")
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
//% "No items"
text: qsTrId("ui-component-gallery-radio-buttons-model-no-items")
//% "Use pulley menu to append some"
hintText: qsTrId("ui-component-gallery-radio-buttons-model-use-pulley-menu-to-append-some")
}
PullDownMenu {
quickSelect: true
MenuItem {
text: selectGroupModel.exclusive ?
//% "Turn multiple selection on"
qsTrId("ui-component-gallery-radio-buttons-model-turn-multiple-selection-on") :
//% "Turn multiple selection off"
qsTrId("ui-component-gallery-radio-buttons-model-turn-multiple-selection-off")
onClicked: selectGroupModel.exclusive = !selectGroupModel.exclusive
}
MenuItem {
//% "Append item"
text: qsTrId("ui-component-gallery-radio-buttons-model-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 {
//% "Append"
acceptText: qsTrId("ui-component-gallery-radio-buttons-model-append")
}
ComboBox {
id: newItemDialogTypeSelector
//% "Value type"
label: qsTrId("ui-component-gallery-radio-buttons-model-value-type")
value: ["text", "number", "date"][currentIndex]
menu: ContextMenu {
MenuItem {
//% "Text"
text: qsTrId("ui-component-gallery-radio-buttons-model-text")
}
MenuItem {
//% "Number"
text: qsTrId("ui-component-gallery-radio-buttons-model-number")
}
MenuItem {
//% "Date"
text: qsTrId("ui-component-gallery-radio-buttons-model-date")
}
}
onValueChanged: {
switch (value) {
case "text":
newItemDialogTextValueInput.forceActiveFocus();
break;
case "number":
newItemDialogNumberValueInput.forceActiveFocus();
break;
case "date":
newItemDialogDateValuePicker.forceActiveFocus();
break;
}
}
}
TextArea {
id: newItemDialogTextValueInput
//% "Value"
label: qsTrId("ui-component-gallery-radio-buttons-model-value")
//% "Input text value"
placeholderText: qsTrId("ui-component-gallery-radio-buttons-model-input-text-value")
visible: newItemDialogTypeSelector.value === "text"
width: parent.width
}
TextField {
id: newItemDialogNumberValueInput
//% "Value"
label: qsTrId("ui-component-gallery-radio-buttons-model-value")
//% "Input number value"
placeholderText: qsTrId("ui-component-gallery-radio-buttons-model-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
//% "Insert the item as selected"
text: qsTrId("ui-component-gallery-radio-buttons-model-insert-the-item-as-selected")
checked: false
}
TextField {
id: newItemDialogNameInput
//% "Name"
label: qsTrId("ui-component-gallery-radio-buttons-model-name")
//% "Input name or skip"
placeholderText: qsTrId("ui-component-gallery-radio-buttons-model-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
//% "Description"
label: qsTrId("ui-component-gallery-radio-buttons-model-description")
//% "Input description or skip"
placeholderText: qsTrId("ui-component-gallery-radio-buttons-model-input-description-or-skip")
width: parent.width
}
ComboBox {
id: newItemDialogIconSelector
//% "Icon"
label: qsTrId("ui-component-gallery-radio-buttons-model-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"
}
}
}
}
}
}
}
}
......@@ -10,8 +10,10 @@ PKGCONFIG += \
SOURCES += \
src/main.cpp \
src/selectgroupmodel.cpp \
HEADERS += \
src/selectgroupmodel.h \
DISTFILES += \
rpm/$${TARGET}.spec \
......
......@@ -4,12 +4,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();
......
// SPDX-FileCopyrightText: 2020 - 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#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;
}
// SPDX-FileCopyrightText: 2020 - 2023 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#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
......@@ -530,6 +530,54 @@
<source>Reset status bar</source>
<translation>Сбросить строку состояния</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-int-value">
<source>Int Value</source>
<translation>Значение Int</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-its-negative">
<source>It&apos;s negative</source>
<translation>Отрицательное</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-zero">
<source>Zero</source>
<translation>Ноль</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-string-value">
<source>String Value</source>
<translation>Строка</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-its-the-first-one">
<source>It&apos;s the first one</source>
<translation>Первый</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-2-nd">
<source>2nd</source>
<translation>Второй</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-variable-value">
<source>Variable Value</source>
<translation>Переменное значение</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-true">
<source>True</source>
<translation>Истина</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-some-text">
<source>Some text</source>
<translation>Немного текста</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-values-could-be-quite-variable">
<source>Values could be quite variable</source>
<translation>Значения могут быть переменными</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-on">
<source>Turn multiple selection on</source>
<translation>Включить множественный выбор</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-off">
<source>Turn multiple selection off</source>
<translation>Выключить множественный выбор</translation>
</message>
<message id="ui-component-gallery-dialog-dialogs">
<source>Dialogs</source>
<translation>Диалоги</translation>
......@@ -1658,6 +1706,22 @@
<source>mind-boggling</source>
<translation>ошеломляюще</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-is-short-string">
<source>This is short string.</source>
<translation>Это короткая строка.</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-without-reverse-animation-lets-make-it-long-enough-to-animate">
<source>This line runs without reverse animation. Let&apos;s make it long enough to animate</source>
<translation>Эта строка выполняется без обратной анимации. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-with-reverse-animation-lets-make-it-long-enough-to-animate">
<source>This line runs with reverse animation. Let&apos;s make it long enough to animate</source>
<translation>Эта строка работает с обратной анимацией. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-with-cyclic-movement-lets-make-it-long-enough-to-animate">
<source>This line runs with cyclic movement. Let&apos;s make it long enough to animate</source>
<translation>Эта строка проходит с циклическим движением. Давайте сделаем ее достаточно длинной, чтобы анимировать</translation>
</message>
<message id="ui-component-gallery-main-buttons">
<source>Buttons</source>
<translation>Кнопки</translation>
......@@ -1878,6 +1942,30 @@
<source>Show how application display with cutout</source>
<translation>Показать, как отображается приложение с вырезом эркана</translation>
</message>
<message id="ui-component-gallery-main-forms-declarative-radio-buttons">
<source>Forms: Radio Buttons with Model</source>
<translation>Формы: декларативные переключатели</translation>
</message>
<message id="ui-component-gallery-main-using-qml-only">
<source>Using QML only</source>
<translation>Использование только QML</translation>
</message>
<message id="ui-component-gallery-main-forms-radio-buttons-with-model">
<source>Forms: Radio Buttons with Model</source>
<translation>Формы: радиокнопки с моделью</translation>
</message>
<message id="ui-component-gallery-main-controlled-by-c-model">
<source>Controlled by C++ model</source>
<translation>Управляется моделью C++</translation>
</message>
<message id="ui-component-gallery-main-views-list-view-with-running-line">
<source>Views: ListView with running line</source>
<translation>ListView с бегущей строкой</translation>
</message>
<message id="ui-component-gallery-main-list-view-delegate-contents-running-line">
<source>ListView delegate contents running line</source>
<translation>Делегат ListView содержит бегущую строку</translation>
</message>
<message id="ui-component-gallery-main-ui-component-gallery">
<source>UI Component Gallery</source>
<translation>Галерея компонентов UI</translation>
......@@ -2202,6 +2290,82 @@
<source>Progress circle</source>
<translation>Круг прогресса</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-no-items">
<source>No items</source>
<translation>Нет элементов</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-use-pulley-menu-to-append-some">
<source>Use pulley menu to append some</source>
<translation>Воспользуйтесь меню, чтобы добавить</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-turn-multiple-selection-on">
<source>Turn multiple selection on</source>
<translation>Включить множественный выбор</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-turn-multiple-selection-off">
<source>Turn multiple selection off</source>
<translation>Выключить множественный выбор</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-append-item">
<source>Append item</source>
<translation>Добавить элемент</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-append">
<source>Append</source>
<translation>Добавить</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-value-type">
<source>Value type</source>
<translation>Тип значения</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-text">
<source>Text</source>
<translation>Текст</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-number">
<source>Number</source>
<translation>Числа</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-date">
<source>Date</source>
<translation>Дата</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-value">
<source>Value</source>
<translation>Значение</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-text-value">
<source>Input text value</source>
<translation>Значение ввода текста</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-number-value">
<source>Input number value</source>
<translation>Значение ввода числа</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-insert-the-item-as-selected">
<source>Insert the item as selected</source>
<translation>Добавьте выбранный элемент</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-name">
<source>Name</source>
<translation>Название</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-name-or-skip">
<source>Input name or skip</source>
<translation>Введите название или пропустите</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-description">
<source>Description</source>
<translation>Описание</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-description-or-skip">
<source>Input description or skip</source>
<translation>Введите описание или пропустите</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-icon">
<source>Icon</source>
<translation>Значок</translation>
</message>
<message id="ui-component-gallery-search-countries">
<source>Countries</source>
<translation>Страны</translation>
......@@ -3404,7 +3568,7 @@
</message>
<message id="ui-component-gallery-web-view-back-navigation">
<source>Back navigation </source>
<translation type="unfinished">Навигация назад </translation>
<translation>Навигация назад </translation>
</message>
<message id="ui-component-gallery-web-view-enabled">
<source>enabled.</source>
......@@ -3412,7 +3576,7 @@
</message>
<message id="ui-component-gallery-web-view-forward-navigation">
<source>Forward navigation </source>
<translation type="unfinished">Навигация вперед </translation>
<translation>Навигация вперед </translation>
</message>
<message id="ui-component-gallery-web-view-httpsauroraosru">
<source>https://auroraos.ru</source>
......
......@@ -530,6 +530,54 @@
<source>Reset status bar</source>
<translation>Reset status bar</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-int-value">
<source>Int Value</source>
<translation>Int Value</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-its-negative">
<source>It&apos;s negative</source>
<translation>It&apos;s negative</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-zero">
<source>Zero</source>
<translation>Zero</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-string-value">
<source>String Value</source>
<translation>String Value</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-its-the-first-one">
<source>It&apos;s the first one</source>
<translation>It&apos;s the first one</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-2-nd">
<source>2nd</source>
<translation>2nd</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-variable-value">
<source>Variable Value</source>
<translation>Variable Value</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-true">
<source>True</source>
<translation>True</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-some-text">
<source>Some text</source>
<translation>Some text</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-values-could-be-quite-variable">
<source>Values could be quite variable</source>
<translation>Values could be quite variable</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-on">
<source>Turn multiple selection on</source>
<translation>Turn multiple selection on</translation>
</message>
<message id="ui-component-gallery-declarative-radio-buttons-turn-multiple-selection-off">
<source>Turn multiple selection off</source>
<translation>Turn multiple selection off</translation>
</message>
<message id="ui-component-gallery-dialog-dialogs">
<source>Dialogs</source>
<translation>Dialogs</translation>
......@@ -1658,6 +1706,22 @@
<source>mind-boggling</source>
<translation>mind-boggling</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-is-short-string">
<source>This is short string.</source>
<translation>This is short string.</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-without-reverse-animation-lets-make-it-long-enough-to-animate">
<source>This line runs without reverse animation. Let&apos;s make it long enough to animate</source>
<translation>This line runs without reverse animation. Let&apos;s make it long enough to animate</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-with-reverse-animation-lets-make-it-long-enough-to-animate">
<source>This line runs with reverse animation. Let&apos;s make it long enough to animate</source>
<translation>This line runs with reverse animation. Let&apos;s make it long enough to animate</translation>
</message>
<message id="ui-component-gallery-list-view-with-running-line-this-line-runs-with-cyclic-movement-lets-make-it-long-enough-to-animate">
<source>This line runs with cyclic movement. Let&apos;s make it long enough to animate</source>
<translation>This line runs with cyclic movement. Let&apos;s make it long enough to animate</translation>
</message>
<message id="ui-component-gallery-main-buttons">
<source>Buttons</source>
<translation>Buttons</translation>
......@@ -1878,6 +1942,30 @@
<source>Show how application display with cutout</source>
<translation>Show how application display with cutout</translation>
</message>
<message id="ui-component-gallery-main-forms-declarative-radio-buttons">
<source>Forms: Radio Buttons with Model</source>
<translation>Forms: Radio Buttons with Model</translation>
</message>
<message id="ui-component-gallery-main-using-qml-only">
<source>Using QML only</source>
<translation>Using QML only</translation>
</message>
<message id="ui-component-gallery-main-forms-radio-buttons-with-model">
<source>Forms: Radio Buttons with Model</source>
<translation>Forms: Radio Buttons with Model</translation>
</message>
<message id="ui-component-gallery-main-controlled-by-c-model">
<source>Controlled by C++ model</source>
<translation>Controlled by C++ model</translation>
</message>
<message id="ui-component-gallery-main-views-list-view-with-running-line">
<source>Views: ListView with running line</source>
<translation>Views: ListView with running line</translation>
</message>
<message id="ui-component-gallery-main-list-view-delegate-contents-running-line">
<source>ListView delegate contents running line</source>
<translation>ListView delegate contents running line</translation>
</message>
<message id="ui-component-gallery-main-ui-component-gallery">
<source>UI Component Gallery</source>
<translation>UI Component Gallery</translation>
......@@ -2202,6 +2290,82 @@
<source>Progress circle</source>
<translation>Progress circle</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-no-items">
<source>No items</source>
<translation>No items</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-use-pulley-menu-to-append-some">
<source>Use pulley menu to append some</source>
<translation>Use pulley menu to append some</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-turn-multiple-selection-on">
<source>Turn multiple selection on</source>
<translation>Turn multiple selection on</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-turn-multiple-selection-off">
<source>Turn multiple selection off</source>
<translation>Turn multiple selection off</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-append-item">
<source>Append item</source>
<translation>Append item</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-append">
<source>Append</source>
<translation>Append</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-value-type">
<source>Value type</source>
<translation>Value type</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-text">
<source>Text</source>
<translation>Text</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-number">
<source>Number</source>
<translation>Number</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-date">
<source>Date</source>
<translation>Date</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-value">
<source>Value</source>
<translation>Value</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-text-value">
<source>Input text value</source>
<translation>Input text value</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-number-value">
<source>Input number value</source>
<translation>Input number value</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-insert-the-item-as-selected">
<source>Insert the item as selected</source>
<translation>Insert the item as selected</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-name">
<source>Name</source>
<translation>Name</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-name-or-skip">
<source>Input name or skip</source>
<translation>Input name or skip</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-description">
<source>Description</source>
<translation>Description</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-input-description-or-skip">
<source>Input description or skip</source>
<translation>Input description or skip</translation>
</message>
<message id="ui-component-gallery-radio-buttons-model-icon">
<source>Icon</source>
<translation>Icon</translation>
</message>
<message id="ui-component-gallery-search-countries">
<source>Countries</source>
<translation>Countries</translation>
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать