Add support for the keypad interface in media devices
This commit is contained in:
parent
b5a0fcd650
commit
a2f1fa93b2
@ -407,14 +407,8 @@ void NymeaConnection::updateActiveBearers()
|
||||
qDebug() << "Inactive network config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName();
|
||||
}
|
||||
|
||||
// Retrying with a new config manager:
|
||||
QNetworkConfigurationManager *newMan = new QNetworkConfigurationManager(this);
|
||||
qDebug() << "Trying with new config manager:";
|
||||
configs = newMan->allConfigurations();
|
||||
foreach (const QNetworkConfiguration &config, configs) {
|
||||
qDebug() << "Config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName() << config.state();
|
||||
}
|
||||
newMan->deleteLater();
|
||||
qWarning() << "Updating network manager";
|
||||
m_networkConfigManager->updateConfigurations();
|
||||
}
|
||||
|
||||
if (m_availableBearerTypes != availableBearerTypes) {
|
||||
|
||||
@ -474,7 +474,7 @@ BrowserItem *DeviceManager::browserItem(const QUuid &deviceId, const QString &it
|
||||
|
||||
void DeviceManager::browseDeviceResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Browsing response:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
|
||||
// qDebug() << "Browsing response:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
|
||||
int id = params.value("id").toInt();
|
||||
if (!m_browsingRequests.contains(id)) {
|
||||
qWarning() << "Received a browsing reply for an id we don't know.";
|
||||
|
||||
@ -208,5 +208,6 @@
|
||||
<file>ui/images/browser/BrowserIconApplication.svg</file>
|
||||
<file>ui/images/browser/BrowserIconDocument.svg</file>
|
||||
<file>ui/images/browser/BrowserIconPackage.svg</file>
|
||||
<file>ui/images/home.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -191,5 +191,7 @@
|
||||
<file>ui/components/BrowserContextMenu.qml</file>
|
||||
<file>ui/magic/SelectBrowserItemActionPage.qml</file>
|
||||
<file>ui/delegates/BrowserItemDelegate.qml</file>
|
||||
<file>ui/components/NavigationPad.qml</file>
|
||||
<file>ui/components/KeypadButton.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -10,7 +10,7 @@ ApplicationWindow {
|
||||
font.capitalization: Font.MixedCase
|
||||
font.family: "Ubuntu"
|
||||
|
||||
Material.background: "black"
|
||||
Material.background: "#151515"
|
||||
|
||||
// The core system name.
|
||||
property string systemName: "nymea"
|
||||
|
||||
@ -25,7 +25,7 @@ T.Button {
|
||||
|
||||
contentItem: Text {
|
||||
text: control.text
|
||||
color: app.backgroundColor
|
||||
color: control.Material.backgroundColor
|
||||
font.bold: control.font.bold
|
||||
font.capitalization: Font.AllUppercase
|
||||
font.family: control.font.family
|
||||
|
||||
32
nymea-app/ui/components/KeypadButton.qml
Normal file
32
nymea-app/ui/components/KeypadButton.qml
Normal file
@ -0,0 +1,32 @@
|
||||
import QtQuick 2.5
|
||||
import Nymea 1.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias imageSource: icon.name
|
||||
|
||||
property color activeColor: app.accentColor
|
||||
|
||||
function activate() {
|
||||
t.start();
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
id: icon
|
||||
anchors.fill: parent
|
||||
color: active ? root.activeColor : keyColor
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
|
||||
property bool active: t.running
|
||||
|
||||
Timer {
|
||||
id: t;
|
||||
interval: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
255
nymea-app/ui/components/NavigationPad.qml
Normal file
255
nymea-app/ui/components/NavigationPad.qml
Normal file
@ -0,0 +1,255 @@
|
||||
import QtQuick 2.5
|
||||
import Nymea 1.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property Device device: null
|
||||
|
||||
readonly property bool isExtended: device && device.deviceClass.interfaces.indexOf("extendednavigationpad") >= 0
|
||||
|
||||
readonly property ActionType navigateActionType: device ? device.deviceClass.actionTypes.findByName("navigate") : null
|
||||
|
||||
Pane {
|
||||
id: pane
|
||||
Material.elevation: 2
|
||||
width: Math.min(root.width, root.height)
|
||||
height: Math.min(root.width, root.height)
|
||||
anchors.centerIn: parent
|
||||
|
||||
padding: 0
|
||||
|
||||
contentItem: Item {
|
||||
|
||||
Pane {
|
||||
anchors.centerIn: parent
|
||||
Material.elevation: 2
|
||||
rotation: 45
|
||||
width: Math.sqrt(Math.pow(parent.width / 2, 2) + Math.pow(parent.height / 2, 2))
|
||||
height: width
|
||||
}
|
||||
|
||||
KeypadButton {
|
||||
id: backButton
|
||||
anchors { left: parent.left; top: parent.top; margins: parent.width * .1 }
|
||||
height: app.iconSize
|
||||
width: app.iconSize
|
||||
imageSource: "../images/back.svg"
|
||||
Item { id: backButtonArea; anchors.centerIn: parent; width: pane.width / 4; height: width; rotation: 45; }
|
||||
}
|
||||
KeypadButton {
|
||||
id: menuButton
|
||||
anchors { right: parent.right; top: parent.top; margins: parent.width * .1 }
|
||||
height: app.iconSize
|
||||
width: app.iconSize
|
||||
visible: root.device.deviceClass.interfaces.indexOf("extendednavigationpad") >= 0
|
||||
imageSource: "../images/navigation-menu.svg"
|
||||
Item { id: menuButtonArea; anchors.centerIn: parent; width: pane.width / 4; height: width; rotation: 45 }
|
||||
}
|
||||
KeypadButton {
|
||||
id: homeButton
|
||||
anchors { left: parent.left; bottom: parent.bottom; margins: parent.width * .1 }
|
||||
height: app.iconSize
|
||||
width: app.iconSize
|
||||
imageSource: "../images/home.svg"
|
||||
visible: root.device.deviceClass.interfaces.indexOf("extendednavigationpad") >= 0
|
||||
Item { id: homeButtonArea; anchors.centerIn: parent; width: pane.width / 4; height: width; rotation: 45 }
|
||||
}
|
||||
KeypadButton {
|
||||
id: infoButton
|
||||
anchors { right: parent.right; bottom: parent.bottom; margins: parent.width * .1 }
|
||||
height: app.iconSize
|
||||
width: app.iconSize
|
||||
imageSource: "../images/info.svg"
|
||||
visible: root.device.deviceClass.interfaces.indexOf("extendednavigationpad") >= 0
|
||||
Item { id: infoButtonArea; anchors.centerIn: parent; width: pane.width / 4; height: width; rotation: 45 }
|
||||
}
|
||||
Rectangle {
|
||||
id: enterButton
|
||||
anchors.centerIn: parent
|
||||
height: app.iconSize
|
||||
width: app.iconSize
|
||||
radius: width / 2
|
||||
border.color: t.running ? app.accentColor : "#808080"
|
||||
Behavior on border.color { ColorAnimation { duration: 200 } }
|
||||
Timer { id: t; interval: 400 }
|
||||
border.width: 3
|
||||
color: "transparent"
|
||||
function activate() { t.start() }
|
||||
}
|
||||
|
||||
Item { id: enterButtonArea; anchors.centerIn: parent; width: pane.width / 4; height: width; rotation: 0 }
|
||||
Item { id: leftButtonArea; anchors { left: parent.left; verticalCenter: parent.verticalCenter; } width: pane.width / 4; height: width; rotation: 0 }
|
||||
Item { id: rightButtonArea; anchors { right: parent.right; verticalCenter: parent.verticalCenter; } width: pane.width / 4; height: width; rotation: 0 }
|
||||
Item { id: upButtonArea; anchors { top: parent.top; horizontalCenter: parent.horizontalCenter; } width: pane.width / 4; height: width; rotation: 0 }
|
||||
Item { id: downButtonArea; anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; } width: pane.width / 4; height: width; rotation: 0 }
|
||||
|
||||
Repeater {
|
||||
id: directionsRepeater
|
||||
model: 4
|
||||
|
||||
Column {
|
||||
height: parent.height * .8
|
||||
width: app.iconSize
|
||||
anchors.centerIn: parent
|
||||
rotation: index * 90
|
||||
|
||||
function activate() {
|
||||
if (!delayTimer.running) {
|
||||
delayTimer.idx = 2;
|
||||
delayTimer.start();
|
||||
} else {
|
||||
delayTimer.onceMore = true;
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: delayTimer;
|
||||
triggeredOnStart: true
|
||||
interval: 150
|
||||
repeat: true
|
||||
property int idx: 2
|
||||
property bool onceMore: false
|
||||
onTriggered: {
|
||||
print("activating", idx)
|
||||
childRepeater.itemAt(idx--).activate()
|
||||
if (idx < 0) {
|
||||
if (onceMore) {
|
||||
idx = 2;
|
||||
onceMore = false;
|
||||
} else {
|
||||
delayTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Repeater {
|
||||
id: childRepeater
|
||||
model: 3
|
||||
KeypadButton {
|
||||
height: app.iconSize
|
||||
width: height
|
||||
imageSource: "../images/up.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
|
||||
property int startX
|
||||
property int startY
|
||||
|
||||
property string lockedDirection: "none"
|
||||
readonly property int steps: 20
|
||||
readonly property int stepSize: height / steps
|
||||
|
||||
property int horizontalSteps: 0
|
||||
property int verticalSteps: 0
|
||||
|
||||
onPressed: {
|
||||
startX = mouseX
|
||||
startY = mouseY
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
var horizontalDiff = mouseX - startX
|
||||
var verticalDiff = mouseY - startY
|
||||
|
||||
if (lockedDirection == "none") {
|
||||
if (Math.abs(horizontalDiff) > stepSize) {
|
||||
lockedDirection = "horizontal"
|
||||
trigger(horizontalDiff > 0 ? "right" : "left")
|
||||
directionsRepeater.itemAt(horizontalDiff > 0 ? 1 : 2).activate()
|
||||
} else if (Math.abs(verticalDiff) > stepSize) {
|
||||
lockedDirection = "vertical"
|
||||
trigger(verticalDiff > 0 ? "down" : "up")
|
||||
directionsRepeater.itemAt(verticalDiff > 0 ? 2 : 0).activate()
|
||||
}
|
||||
}
|
||||
|
||||
horizontalSteps = horizontalDiff / stepSize
|
||||
verticalSteps = verticalDiff / stepSize
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (lockedDirection === "none") {
|
||||
if (checkButton(backButtonArea)) {
|
||||
trigger("back");
|
||||
backButton.activate();
|
||||
} else if (checkButton(leftButtonArea)) {
|
||||
trigger("left");
|
||||
directionsRepeater.itemAt(3).activate()
|
||||
} else if (checkButton(rightButtonArea)) {
|
||||
trigger("right");
|
||||
directionsRepeater.itemAt(1).activate()
|
||||
} else if (checkButton(upButtonArea)) {
|
||||
trigger("up");
|
||||
directionsRepeater.itemAt(0).activate()
|
||||
} else if (checkButton(downButtonArea)) {
|
||||
trigger("down");
|
||||
directionsRepeater.itemAt(2).activate()
|
||||
} else if (checkButton(enterButtonArea)) {
|
||||
trigger("enter");
|
||||
enterButton.activate();
|
||||
} else if (checkButton(menuButtonArea)) {
|
||||
trigger("menu");
|
||||
menuButton.activate();
|
||||
} else if (checkButton(homeButtonArea)) {
|
||||
trigger("home");
|
||||
homeButton.activate();
|
||||
} else if (checkButton(infoButtonArea)) {
|
||||
trigger("info");
|
||||
infoButton.activate();
|
||||
}
|
||||
}
|
||||
|
||||
lockedDirection = "none"
|
||||
}
|
||||
|
||||
function checkButton(button) {
|
||||
var coords = mouseArea.mapToItem(button, mouseX, mouseY)
|
||||
if (coords.x > 0 && coords.x < button.width && coords.y > 0 && coords.y < button.height) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function trigger(direction) {
|
||||
var params = []
|
||||
var param = {}
|
||||
param["paramTypeId"] = root.navigateActionType.paramTypes.findByName("to").id;
|
||||
param["value"] = direction;
|
||||
params.push(param);
|
||||
engine.deviceManager.executeAction(root.device.id, root.navigateActionType.id, params)
|
||||
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: repeatTimer
|
||||
running: mouseArea.lockedDirection !== "none"
|
||||
interval: 1000
|
||||
repeat: true
|
||||
onRunningChanged: interval = 1000
|
||||
onTriggered: {
|
||||
if (mouseArea.lockedDirection === "horizontal") {
|
||||
mouseArea.trigger(mouseArea.horizontalSteps > 0 ? "right" : "left")
|
||||
directionsRepeater.itemAt(mouseArea.horizontalSteps > 0 ? 1 : 3).activate()
|
||||
} else if (mouseArea.lockedDirection === "vertical") {
|
||||
mouseArea.trigger(mouseArea.verticalSteps > 0 ? "down" : "up")
|
||||
directionsRepeater.itemAt(mouseArea.verticalSteps > 0 ? 2 : 0).activate()
|
||||
}
|
||||
interval = Math.max(50, 1000 - Math.abs(mouseArea.lockedDirection === "horizontal" ? mouseArea.horizontalSteps : mouseArea.verticalSteps) * 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ SwipeDelegate {
|
||||
property bool prominentSubText: true
|
||||
|
||||
property string iconName
|
||||
property string fallbackIcon
|
||||
property string thumbnail
|
||||
property int iconSize: app.iconSize
|
||||
property color iconColor: app.accentColor
|
||||
property alias iconKeyColor: icon.keyColor
|
||||
@ -41,21 +41,24 @@ SwipeDelegate {
|
||||
Item {
|
||||
Layout.preferredHeight: root.iconSize
|
||||
Layout.preferredWidth: height
|
||||
visible: root.iconName || root.fallbackIcon
|
||||
visible: root.iconName.length > 0 || root.thumbnail.length > 0
|
||||
|
||||
ColorIcon {
|
||||
id: icon
|
||||
anchors.fill: parent
|
||||
name: root.iconName
|
||||
color: root.iconColor
|
||||
visible: root.iconName
|
||||
visible: root.iconName && thumbnailImage.status !== Image.Ready
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
Image {
|
||||
id: thumbnailImage
|
||||
anchors.fill: parent
|
||||
name: root.fallbackIcon
|
||||
color: root.iconColor
|
||||
visible: root.fallbackIcon && (!root.iconName || icon.status === Image.Error)
|
||||
source: root.thumbnail
|
||||
visible: root.thumbnail.length > 0
|
||||
fillMode: Image.PreserveAspectFit
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
|
||||
@ -12,8 +12,8 @@ NymeaListItemDelegate {
|
||||
progressive: model.browsable
|
||||
subText: model.description
|
||||
prominentSubText: false
|
||||
iconName: model.thumbnail
|
||||
fallbackIcon: "../images/browser/" + model.icon + ".svg"
|
||||
iconName: "../images/browser/" + model.icon + ".svg"
|
||||
thumbnail: model.thumbnail
|
||||
enabled: model.browsable || model.executable
|
||||
secondaryIconName: model.actionTypeIds.length > 0 ? "../images/navigation-menu.svg" : ""
|
||||
secondaryIconClickable: true
|
||||
|
||||
@ -43,7 +43,7 @@ DeviceListPageBase {
|
||||
readonly property StateType playerTypeStateType: deviceClass.stateTypes.findByName("playerType")
|
||||
readonly property State playerTypeState: playerTypeStateType ? device.states.getState(playerTypeStateType.id) : null
|
||||
|
||||
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||
bottomPadding: index === root.devicesProxy.count - 1 ? topPadding : 0
|
||||
contentItem: Pane {
|
||||
id: contentItem
|
||||
Material.elevation: 2
|
||||
@ -96,7 +96,7 @@ DeviceListPageBase {
|
||||
qsTr("No playback")
|
||||
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
// font.pixelSize: app.largeFont
|
||||
// font.pixelSize: app.largeFont
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
@ -193,10 +193,8 @@ DeviceListPageBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,15 +14,7 @@ DevicePageBase {
|
||||
showBrowserButton: false
|
||||
|
||||
onBackPressed: {
|
||||
if (swipeView.currentIndex > 0) {
|
||||
if (internalPageStack.depth > 1) {
|
||||
internalPageStack.pop();
|
||||
} else {
|
||||
swipeView.currentIndex = 0;
|
||||
}
|
||||
} else {
|
||||
pageStack.pop();
|
||||
}
|
||||
swipeView.currentItem.backPressed()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
@ -83,9 +75,22 @@ DevicePageBase {
|
||||
SwipeView {
|
||||
id: swipeView
|
||||
anchors.fill: parent
|
||||
interactive: root.deviceClass.browsable
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.deviceClass.browsable) {
|
||||
browserComponent.createObject(swipeView)
|
||||
}
|
||||
|
||||
if (root.deviceClass.interfaces.indexOf("navigationpad") >= 0) {
|
||||
navigationComponent.createObject(swipeView)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
function backPressed() {
|
||||
pageStack.pop();
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: contentColumn
|
||||
anchors.fill: parent
|
||||
@ -139,8 +144,21 @@ DevicePageBase {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: browserComponent
|
||||
|
||||
Item {
|
||||
|
||||
function backPressed() {
|
||||
if (internalPageStack.depth > 1) {
|
||||
internalPageStack.pop();
|
||||
} else {
|
||||
swipeView.currentIndex--
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: internalPageStack
|
||||
anchors.fill: parent
|
||||
@ -150,7 +168,6 @@ DevicePageBase {
|
||||
id: internalBrowserPage
|
||||
ListView {
|
||||
id: listView
|
||||
anchors.fill: parent
|
||||
model: browserItems
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
@ -163,7 +180,7 @@ DevicePageBase {
|
||||
}
|
||||
|
||||
delegate: BrowserItemDelegate {
|
||||
fallbackIcon: "../images/browser/" + (model.mediaIcon && model.mediaIcon !== "MediaBrowserIconNone" ? model.mediaIcon : model.icon) + ".svg"
|
||||
iconName: "../images/browser/" + (model.mediaIcon && model.mediaIcon !== "MediaBrowserIconNone" ? model.mediaIcon : model.icon) + ".svg"
|
||||
busy: d.pendingItemId === model.id
|
||||
device: root.device
|
||||
|
||||
@ -188,10 +205,34 @@ DevicePageBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: navigationComponent
|
||||
Item {
|
||||
function backPressed() {
|
||||
swipeView.currentIndex--;
|
||||
}
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: app.margins
|
||||
|
||||
NavigationPad {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
device: root.device
|
||||
}
|
||||
|
||||
MediaControls {
|
||||
Layout.fillWidth: true
|
||||
device: root.device
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,10 +287,10 @@ DevicePageBase {
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 2
|
||||
visible: root.deviceClass.browsable
|
||||
visible: swipeView.count > 1
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
width: parent.width / 2
|
||||
width: parent.width / swipeView.count
|
||||
color: app.accentColor
|
||||
x: swipeView.currentIndex * width
|
||||
Behavior on x { NumberAnimation { duration: 150 } }
|
||||
@ -259,14 +300,14 @@ DevicePageBase {
|
||||
RowLayout {
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: root.deviceClass.browsable && swipeView.currentIndex > 0 ? parent.width / 4 : 0
|
||||
Layout.preferredWidth: swipeView.count > 1 && swipeView.currentIndex > 0 ? parent.width / 4 : 0
|
||||
Behavior on Layout.preferredWidth { NumberAnimation {} }
|
||||
HeaderButton {
|
||||
anchors.centerIn: parent
|
||||
imageSource: "../images/back.svg"
|
||||
opacity: root.deviceClass.browsable && swipeView.currentIndex == 1 ? 1 : 0
|
||||
opacity: swipeView.count > 1 && swipeView.currentIndex > 0 ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
onClicked: swipeView.currentIndex = 0
|
||||
onClicked: swipeView.currentIndex--
|
||||
}
|
||||
}
|
||||
Item {
|
||||
@ -329,13 +370,13 @@ DevicePageBase {
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: root.deviceClass.browsable && swipeView.currentIndex == 0 ? parent.width / 4 : 0
|
||||
Layout.preferredWidth: swipeView.count > 1 && swipeView.currentIndex < swipeView.count - 1 ? parent.width / 4 : 0
|
||||
Behavior on Layout.preferredWidth { NumberAnimation {} }
|
||||
HeaderButton {
|
||||
anchors.centerIn: parent
|
||||
imageSource: "../images/next.svg"
|
||||
onClicked: swipeView.currentIndex = 1
|
||||
opacity: root.deviceClass.browsable && swipeView.currentIndex == 0 ? 1 : 0
|
||||
onClicked: swipeView.currentIndex++
|
||||
opacity: swipeView.count > 1 && swipeView.currentIndex < swipeView.count - 1 ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
}
|
||||
}
|
||||
|
||||
177
nymea-app/ui/images/home.svg
Normal file
177
nymea-app/ui/images/home.svg
Normal file
@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg4874"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel r"
|
||||
viewBox="0 0 96 96.000001"
|
||||
sodipodi:docname="home.svg">
|
||||
<defs
|
||||
id="defs4876" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.5967995"
|
||||
inkscape:cx="-22.603439"
|
||||
inkscape:cy="10.133975"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4780"
|
||||
showgrid="true"
|
||||
showborder="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5451"
|
||||
empspacing="8" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="8,-8.0000001"
|
||||
id="guide4063" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="4,-8.0000001"
|
||||
id="guide4065" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,88.000001"
|
||||
id="guide4067" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,92.000001"
|
||||
id="guide4069" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="104,4"
|
||||
id="guide4071" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,8.0000001"
|
||||
id="guide4073" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="88,-8.0000001"
|
||||
id="guide4077" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,84.000001"
|
||||
id="guide4074" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="12,-8.0000001"
|
||||
id="guide4076" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="84,-8.0000001"
|
||||
id="guide4080" />
|
||||
<sodipodi:guide
|
||||
position="-8,48"
|
||||
orientation="0,1"
|
||||
id="guide4172" />
|
||||
<sodipodi:guide
|
||||
position="92,-8.0000001"
|
||||
orientation="1,0"
|
||||
id="guide4760" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4879">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(67.857146,-78.50504)">
|
||||
<g
|
||||
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||
id="g4845"
|
||||
style="display:inline">
|
||||
<g
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="next01.png"
|
||||
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||
id="g4778"
|
||||
inkscape:label="Layer 1">
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||
id="g4780"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||
id="rect4782"
|
||||
width="96.037987"
|
||||
height="96"
|
||||
x="-438.00244"
|
||||
y="345.36221"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4667"
|
||||
d="m 405.98979,361.35146 12.00475,0 0,12.01076 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:48;marker:none;enable-background:accumulate"
|
||||
inkscape:transform-center-x="-26.000146"
|
||||
inkscape:transform-center-y="-19.865735" />
|
||||
<path
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||
d="m 15.988281,39 0,49 L 68,88 l 4e-6,-4.000006 -48,0 0,-45.999998 z m 60.011723,-1.000004 0,49.999998 4.011715,6e-6 -0.01171,-50.000004 z"
|
||||
transform="matrix(0,-1,-1.0003957,0,438.00245,441.36222)"
|
||||
id="path4658"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccc" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 389.38086,349.93164 -2.79492,2.86133 41.55078,40.57031 -41.55078,40.56836 2.79492,2.86133 44.48242,-43.43164 -44.48242,-43.42969 z"
|
||||
id="path4158"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4165"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 384.74345,393.36217 c 0.2538,-1.01585 0.5239,-2.36509 0.80985,-4.04761 0.28572,-1.68252 0.42858,-3.61904 0.42858,-5.80952 0,-1.96822 -0.28571,-3.60317 -0.85748,-4.90475 -0.5399,-1.30156 -1.318,-2.33332 -2.33429,-3.09522 -0.98451,-0.79367 -2.17546,-1.34919 -3.57285,-1.66667 -1.39737,-0.31762 -2.93765,-0.47618 -4.62083,-0.47618 l -24.62884,0 1.9e-4,20 z"
|
||||
sodipodi:nodetypes="ccsccssccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@ -26,6 +26,12 @@ Page {
|
||||
anchors.fill: parent
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: listView.model.busy
|
||||
visible: running
|
||||
}
|
||||
|
||||
delegate: BrowserItemDelegate {
|
||||
width: parent.width
|
||||
device: root.device
|
||||
|
||||
Reference in New Issue
Block a user