Experience modes support added
This commit is contained in:
parent
44ea99a2e7
commit
effb5a137f
@ -43,3 +43,25 @@ QStringList StyleController::allStyles() const
|
|||||||
// qDebug() << "styles:" << dir.entryList();
|
// qDebug() << "styles:" << dir.entryList();
|
||||||
return dir.entryList(QDir::Dirs);
|
return dir.entryList(QDir::Dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString StyleController::currentExperience() const
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
return settings.value("experience", "Default").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyleController::setCurrentExperience(const QString ¤tExperience)
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
if (settings.value("experience").toString() != currentExperience) {
|
||||||
|
settings.setValue("experience", currentExperience);
|
||||||
|
emit currentExperienceChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList StyleController::allExperiences() const
|
||||||
|
{
|
||||||
|
QDir dir(":/ui/experiences");
|
||||||
|
qDebug() << "experiences:" << dir.entryList();
|
||||||
|
return QStringList() << "Default" << dir.entryList();
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,9 @@ class StyleController : public QObject
|
|||||||
Q_PROPERTY(QString currentStyle READ currentStyle WRITE setCurrentStyle NOTIFY currentStyleChanged)
|
Q_PROPERTY(QString currentStyle READ currentStyle WRITE setCurrentStyle NOTIFY currentStyleChanged)
|
||||||
Q_PROPERTY(QStringList allStyles READ allStyles CONSTANT)
|
Q_PROPERTY(QStringList allStyles READ allStyles CONSTANT)
|
||||||
|
|
||||||
|
Q_PROPERTY(QString currentExperience READ currentExperience WRITE setCurrentExperience NOTIFY currentExperienceChanged)
|
||||||
|
Q_PROPERTY(QStringList allExperiences READ allExperiences CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StyleController(QObject *parent = nullptr);
|
explicit StyleController(QObject *parent = nullptr);
|
||||||
|
|
||||||
@ -17,8 +20,14 @@ public:
|
|||||||
|
|
||||||
QStringList allStyles() const;
|
QStringList allStyles() const;
|
||||||
|
|
||||||
|
QString currentExperience() const;
|
||||||
|
void setCurrentExperience(const QString ¤tExperience);
|
||||||
|
|
||||||
|
QStringList allExperiences() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentStyleChanged();
|
void currentStyleChanged();
|
||||||
|
void currentExperienceChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,34 @@ Page {
|
|||||||
property bool swipeViewReady: false
|
property bool swipeViewReady: false
|
||||||
property bool tabsReady: false
|
property bool tabsReady: false
|
||||||
|
|
||||||
|
// FIXME: All this can go away when we require Controls 2.3 (Qt 5.10) or greater as TabBar got a major rework there.
|
||||||
|
// Ideally we'd just list the 3 items and set visible to false if the server version isn't good enough but TabBar
|
||||||
|
// has troubles dealing with that. For now, let's manually fill it and use a timer to initialize the currentIndex.
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Fill SwipeView (The 2 static views things and scenes will already be there).
|
||||||
|
if (engine.jsonRpcClient.ensureServerVersion(1.6)) {
|
||||||
|
swipeView.insertItem(0, favoritesViewComponent.createObject(swipeView))
|
||||||
|
}
|
||||||
|
var experienceView = null;
|
||||||
|
if (styleController.currentExperience != "Default") {
|
||||||
|
experienceView = experienceViewComponent.createObject(swipeView, {source: "experiences/" + styleController.currentExperience + "/Main.qml" });
|
||||||
|
swipeView.insertItem(0, experienceView)
|
||||||
|
}
|
||||||
|
root.swipeViewReady = true;
|
||||||
|
|
||||||
|
|
||||||
|
var pi = 0;
|
||||||
|
if (experienceView) {
|
||||||
|
tabEntryComponent.createObject(tabBar, {text: experienceView.title, iconSource: experienceView.icon, pageIndex: pi++})
|
||||||
|
}
|
||||||
|
if (engine.jsonRpcClient.ensureServerVersion(1.6)) {
|
||||||
|
tabEntryComponent.createObject(tabBar, {text: qsTr("Favorites"), iconSource: "../images/starred.svg", pageIndex: pi++})
|
||||||
|
}
|
||||||
|
tabEntryComponent.createObject(tabBar, {text: qsTr("Things"), iconSource: "../images/share.svg", pageIndex: pi++})
|
||||||
|
tabEntryComponent.createObject(tabBar, {text: qsTr("Scenes"), iconSource: "../images/slideshow.svg", pageIndex: pi++})
|
||||||
|
root.tabsReady = true
|
||||||
|
}
|
||||||
|
|
||||||
readonly property bool viewReady: swipeViewReady && tabsReady
|
readonly property bool viewReady: swipeViewReady && tabsReady
|
||||||
onViewReadyChanged: {
|
onViewReadyChanged: {
|
||||||
if (tabSettings.currentMainViewIndex > swipeView.count) {
|
if (tabSettings.currentMainViewIndex > swipeView.count) {
|
||||||
@ -90,13 +118,6 @@ Page {
|
|||||||
anchors.rightMargin: anchors.leftMargin
|
anchors.rightMargin: anchors.leftMargin
|
||||||
currentIndex: root.currentViewIndex
|
currentIndex: root.currentViewIndex
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (engine.jsonRpcClient.ensureServerVersion(1.6)) {
|
|
||||||
swipeView.insertItem(0, favoritesViewComponent.createObject(swipeView))
|
|
||||||
}
|
|
||||||
swipeView.insertItem(0, experienceViewComponent.createObject(swipeView))
|
|
||||||
root.swipeViewReady = true;
|
|
||||||
}
|
|
||||||
onCurrentIndexChanged: {
|
onCurrentIndexChanged: {
|
||||||
root.currentViewIndex = currentIndex
|
root.currentViewIndex = currentIndex
|
||||||
}
|
}
|
||||||
@ -106,8 +127,9 @@ Page {
|
|||||||
Loader {
|
Loader {
|
||||||
width: swipeView.width
|
width: swipeView.width
|
||||||
height: swipeView.height
|
height: swipeView.height
|
||||||
source: "experiences/garagegates/Main.qml"
|
|
||||||
clip: true
|
clip: true
|
||||||
|
readonly property string title: item ? item.title : ""
|
||||||
|
readonly property string icon: item ? item.icon : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,21 +239,6 @@ Page {
|
|||||||
((systemProductType === "ios" && Screen.height === 375) ? -10 : -20) :
|
((systemProductType === "ios" && Screen.height === 375) ? -10 : -20) :
|
||||||
(systemProductType === "ios" && Screen.height === 812) ? 14 : 0)
|
(systemProductType === "ios" && Screen.height === 812) ? 14 : 0)
|
||||||
|
|
||||||
|
|
||||||
// FIXME: All this can go away when we require Controls 2.3 (Qt 5.10) or greater as TabBar got a major rework there.
|
|
||||||
// Ideally we'd just list the 3 items and set visible to false if the server version isn't good enough but TabBar
|
|
||||||
// has troubles dealing with that. For now, let's manually fill it and use a timer to initialize the currentIndex.
|
|
||||||
Component.onCompleted: {
|
|
||||||
var pi = 0;
|
|
||||||
tabEntryComponent.createObject(tabBar, {text: qsTr("UX"), iconSource: "../images/starred.svg", pageIndex: pi++})
|
|
||||||
if (engine.jsonRpcClient.ensureServerVersion(1.6)) {
|
|
||||||
tabEntryComponent.createObject(tabBar, {text: qsTr("Favorites"), iconSource: "../images/starred.svg", pageIndex: pi++})
|
|
||||||
}
|
|
||||||
tabEntryComponent.createObject(tabBar, {text: qsTr("Things"), iconSource: "../images/share.svg", pageIndex: pi++})
|
|
||||||
tabEntryComponent.createObject(tabBar, {text: qsTr("Scenes"), iconSource: "../images/slideshow.svg", pageIndex: pi++})
|
|
||||||
root.tabsReady = true
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: tabEntryComponent
|
id: tabEntryComponent
|
||||||
MainPageTabButton {
|
MainPageTabButton {
|
||||||
|
|||||||
@ -46,6 +46,23 @@ Page {
|
|||||||
onClicked: pageStack.push(appLogComponent)
|
onClicked: pageStack.push(appLogComponent)
|
||||||
enabled: AppLogController.enabled
|
enabled: AppLogController.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Experience mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
currentIndex: model.indexOf(styleController.currentExperience)
|
||||||
|
model: styleController.allExperiences
|
||||||
|
onActivated: {
|
||||||
|
styleController.currentExperience = model[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import Nymea 1.0
|
|||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: root
|
id: root
|
||||||
spacing: (parent.width - app.iconSize*2*children.length) / children.length
|
spacing: (parent.width - app.iconSize*2*children.length) / (children.length - 1)
|
||||||
// implicitWidth: app.iconSize * 2 * children.length + spacing * (children.length - 1)
|
// implicitWidth: app.iconSize * 2 * children.length + spacing * (children.length - 1)
|
||||||
implicitWidth: childrenRect.width
|
implicitWidth: childrenRect.width
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,9 @@ import "qrc:/ui/components"
|
|||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: root
|
||||||
|
readonly property string title: qsTr("Garage gates")
|
||||||
|
readonly property string icon: Qt.resolvedUrl("qrc:/ui/images/shutter/shutter-050.svg")
|
||||||
|
|
||||||
DevicesProxy {
|
DevicesProxy {
|
||||||
id: garagesFilterModel
|
id: garagesFilterModel
|
||||||
@ -12,6 +15,15 @@ Item {
|
|||||||
shownInterfaces: ["garagegate"]
|
shownInterfaces: ["garagegate"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmptyViewPlaceholder {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - app.margins * 2
|
||||||
|
text: qsTr("There are no garage gates set up yet.")
|
||||||
|
imageSource: "qrc:/ui/images/shutter/shutter-050.svg"
|
||||||
|
buttonText: qsTr("Set up now")
|
||||||
|
visible: garagesFilterModel.count === 0
|
||||||
|
}
|
||||||
|
|
||||||
SwipeView {
|
SwipeView {
|
||||||
id: swipeView
|
id: swipeView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -32,35 +44,54 @@ Item {
|
|||||||
readonly property StateType intermediatePositionStateType: device.deviceClass.stateTypes.findByName("intermediatePosition")
|
readonly property StateType intermediatePositionStateType: device.deviceClass.stateTypes.findByName("intermediatePosition")
|
||||||
readonly property State intermediatePositionState: intermediatePositionStateType ? device.states.getState(intermediatePositionStateType.id) : null
|
readonly property State intermediatePositionState: intermediatePositionStateType ? device.states.getState(intermediatePositionStateType.id) : null
|
||||||
|
|
||||||
ColumnLayout {
|
GridLayout {
|
||||||
|
id: layout
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: app.margins
|
anchors.margins: app.margins
|
||||||
|
columns: app.landscape ? 2 : 1
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
id: label
|
||||||
text: garageGateView.device.name
|
text: garageGateView.device.name
|
||||||
font.pixelSize: app.largeFont
|
font.pixelSize: app.largeFont
|
||||||
Layout.fillWidth: true
|
Layout.preferredWidth: layout.width
|
||||||
|
Layout.columnSpan: parent.columns
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorIcon {
|
Item {
|
||||||
name: "qrc:/ui/images/shutter/shutter-" + currentImage + ".svg"
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: width
|
Layout.minimumWidth: app.landscape ? layout.width / 2 : layout.width
|
||||||
|
|
||||||
property string currentImage: garageGateView.openState.value === "closed" ? "100" :
|
|
||||||
garageGateView.openState.value === "open" && garageGateView.intermediatePositionState.value === false ? "000" : "050"
|
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
height: Math.min(parent.height, parent.width)
|
||||||
|
width: height
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "qrc:/ui/images/shutter/shutter-" + currentImage + ".svg"
|
||||||
|
property string currentImage: garageGateView.openState.value === "closed" ? "100" :
|
||||||
|
garageGateView.openState.value === "open" && garageGateView.intermediatePositionState.value === false ? "000" : "050"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShutterControls {
|
Item {
|
||||||
id: controls
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.preferredHeight: controls.implicitHeight
|
||||||
device: garageGateView.device
|
Layout.minimumWidth: app.landscape ? layout.width / 2 : layout.width
|
||||||
|
|
||||||
|
ShutterControls {
|
||||||
|
id: controls
|
||||||
|
device: garageGateView.device
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageIndicator {
|
||||||
|
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter }
|
||||||
|
count: garagesFilterModel.count
|
||||||
|
currentIndex: swipeView.currentIndex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user