Merge PR #159: Add a "noir" style

This commit is contained in:
Jenkins 2019-03-10 14:44:19 +01:00
commit d0a9d07a01
38 changed files with 1452 additions and 48 deletions

View File

@ -137,7 +137,7 @@ Connection *NymeaConnection::currentConnection() const
void NymeaConnection::sendData(const QByteArray &data)
{
if (connected()) {
qDebug() << "sending data:" << data;
// qDebug() << "sending data:" << data;
m_currentTransport->sendData(data);
} else {
qWarning() << "Connection: Not connected. Cannot send.";
@ -382,7 +382,7 @@ void NymeaConnection::updateActiveBearers()
QList<QNetworkConfiguration> configs = m_networkConfigManager->allConfigurations(QNetworkConfiguration::Active);
// qDebug() << "Network configuations:" << configs.count();
foreach (const QNetworkConfiguration &config, configs) {
qDebug() << "Candidate network config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName();
// qDebug() << "Candidate network config:" << config.name() << config.bearerTypeFamily() << config.bearerTypeName();
// NOTE: iOS doesn't correctly report bearer types. It'll be Unknown all the time. Let's hardcode it to WiFi for that...
#if defined(Q_OS_IOS)

View File

@ -101,6 +101,20 @@ void DevicesProxy::setFilterTagId(const QString &filterTag)
}
}
QString DevicesProxy::filterDeviceClassId() const
{
return m_filterDeviceClassId;
}
void DevicesProxy::setFilterDeviceClassId(const QString &filterDeviceClassId)
{
if (m_filterDeviceClassId != filterDeviceClassId) {
m_filterDeviceClassId = filterDeviceClassId;
emit filterDeviceClassIdChanged();
invalidateFilter();
}
}
QStringList DevicesProxy::shownInterfaces() const
{
return m_shownInterfaces;
@ -231,6 +245,11 @@ bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_pa
return false;
}
}
if (!m_filterDeviceClassId.isEmpty()) {
if (device->deviceClassId() != m_filterDeviceClassId) {
return false;
}
}
DeviceClass *deviceClass = m_engine->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId());
if (!m_shownInterfaces.isEmpty()) {
bool foundMatch = false;

View File

@ -38,6 +38,7 @@ class DevicesProxy : public QSortFilterProxyModel
Q_PROPERTY(Engine* engine READ engine WRITE setEngine NOTIFY engineChanged)
Q_PROPERTY(DevicesProxy *parentProxy READ parentProxy WRITE setParentProxy NOTIFY parentProxyChanged)
Q_PROPERTY(QString filterTagId READ filterTagId WRITE setFilterTagId NOTIFY filterTagIdChanged)
Q_PROPERTY(QString filterDeviceClassId READ filterDeviceClassId WRITE setFilterDeviceClassId NOTIFY filterDeviceClassIdChanged)
Q_PROPERTY(QStringList shownInterfaces READ shownInterfaces WRITE setShownInterfaces NOTIFY shownInterfacesChanged)
Q_PROPERTY(QStringList hiddenInterfaces READ hiddenInterfaces WRITE setHiddenInterfaces NOTIFY hiddenInterfacesChanged)
Q_PROPERTY(QString nameFilter READ nameFilter WRITE setNameFilter NOTIFY nameFilterChanged)
@ -62,6 +63,9 @@ public:
QString filterTagId() const;
void setFilterTagId(const QString &filterTag);
QString filterDeviceClassId() const;
void setFilterDeviceClassId(const QString &filterDeviceClassId);
QStringList shownInterfaces() const;
void setShownInterfaces(const QStringList &shownInterfaces);
@ -86,6 +90,7 @@ signals:
void engineChanged();
void parentProxyChanged();
void filterTagIdChanged();
void filterDeviceClassIdChanged();
void shownInterfacesChanged();
void hiddenInterfacesChanged();
void nameFilterChanged();
@ -100,6 +105,7 @@ private:
Engine *m_engine = nullptr;
DevicesProxy *m_parentProxy = nullptr;
QString m_filterTagId;
QString m_filterDeviceClassId;
QStringList m_shownInterfaces;
QStringList m_hiddenInterfaces;
QString m_nameFilter;

View File

@ -37,7 +37,7 @@ public:
StateTypeIdRole
};
explicit States(QObject *parent = 0);
explicit States(QObject *parent = nullptr);
QList<State *> states();

View File

@ -170,5 +170,6 @@
<file>ui/images/sensors/presence.svg</file>
<file>ui/images/powersocket.svg</file>
<file>ui/images/dial.svg</file>
<file>ui/images/ventilation.svg</file>
</qresource>
</RCC>

View File

@ -77,7 +77,7 @@ int main(int argc, char *argv[])
}
QFont applicationFont;
applicationFont.setFamily("Ubuntu");
// applicationFont.setFamily("Oswald");
applicationFont.setCapitalization(QFont::MixedCase);
applicationFont.setPixelSize(16);
applicationFont.setWeight(QFont::Normal);

View File

@ -164,5 +164,13 @@
<file>ui/thingconfiguration/EditThingsPage.qml</file>
<file>ui/thingconfiguration/ConfigureThingPage.qml</file>
<file>ui/connection/CertificateDialog.qml</file>
<file>ui/experiences/garagegates/Main.qml</file>
<file>ui/experiences/heating/Main.qml</file>
<file>ui/fonts/Oswald-Bold.ttf</file>
<file>ui/fonts/Oswald-ExtraLight.ttf</file>
<file>ui/fonts/Oswald-Light.ttf</file>
<file>ui/fonts/Oswald-Medium.ttf</file>
<file>ui/fonts/Oswald-Regular.ttf</file>
<file>ui/fonts/Oswald-SemiBold.ttf</file>
</qresource>
</RCC>

View File

@ -43,3 +43,25 @@ QStringList StyleController::allStyles() const
// qDebug() << "styles:" << dir.entryList();
return dir.entryList(QDir::Dirs);
}
QString StyleController::currentExperience() const
{
QSettings settings;
return settings.value("experience", "Default").toString();
}
void StyleController::setCurrentExperience(const QString &currentExperience)
{
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();
}

View File

@ -9,6 +9,9 @@ class StyleController : public QObject
Q_PROPERTY(QString currentStyle READ currentStyle WRITE setCurrentStyle NOTIFY currentStyleChanged)
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:
explicit StyleController(QObject *parent = nullptr);
@ -17,8 +20,14 @@ public:
QStringList allStyles() const;
QString currentExperience() const;
void setCurrentExperience(const QString &currentExperience);
QStringList allExperiences() const;
signals:
void currentStyleChanged();
void currentExperienceChanged();
};

View File

@ -3,10 +3,14 @@
<file>styles/light/ApplicationWindow.qml</file>
<file>styles/light/Page.qml</file>
<file>styles/light/logo.svg</file>
<file>styles/light/Button.qml</file>
<file>styles/dark/ApplicationWindow.qml</file>
<file>styles/dark/Page.qml</file>
<file>styles/dark/logo.svg</file>
<file>styles/dark/Button.qml</file>
<file>styles/light/Button.qml</file>
<file>styles/noir/ApplicationWindow.qml</file>
<file>styles/noir/Page.qml</file>
<file>styles/noir/logo.svg</file>
<file>styles/noir/Button.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,36 @@
import QtQuick 2.0
import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2
ApplicationWindow {
// The app style
Material.theme: Material.Dark
// Main background color
Material.background: "#50514f"
font.family: "Oswald"
// The header background color
property color primaryColor: Qt.darker("#50514f", 1.1)
// Header font color
property color headerForegroundColor: "#ebebeb"
// The font color
property color foregroundColor: "#ebebeb"
// The color of selected/highlighted things
property color accentColor: "#f45b69"
// colors for interfaces, e.g. icons
property var interfaceColors: {
"temperaturesensor": "#FF0000",
"humiditysensor": "#00BFFF",
"moisturesensor":"#0000FF",
"lightsensor": "#FFA500",
"conductivitysensor": "#008000",
"pressuresensor": "#808080"
}
}

View File

@ -0,0 +1,77 @@
import QtQuick 2.9
import QtQuick.Templates 2.2 as T
import QtQuick.Controls 2.2
import QtQuick.Controls.impl 2.2
import QtQuick.Controls.Material 2.2
import QtQuick.Controls.Material.impl 2.2
T.Button {
id: control
implicitWidth: Math.max(background ? background.implicitWidth : 0,
contentItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
contentItem.implicitHeight + topPadding + bottomPadding)
baselineOffset: contentItem.y + contentItem.baselineOffset
// external vertical padding is 6 (to increase touch area)
padding: 12
leftPadding: padding - 4
rightPadding: padding - 4
Material.elevation: flat ? control.down || control.hovered ? 2 : 0
: control.down ? 8 : 2
Material.background: flat ? "transparent" : undefined
contentItem: Text {
text: control.text
font: control.font
color: app.primaryColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
// TODO: Add a proper ripple/ink effect for mouse/touch input and focus state
background: Rectangle {
implicitWidth: 64
implicitHeight: 40
// external vertical padding is 6 (to increase touch area)
y: 6
width: parent.width
height: parent.height - 12
radius: height / 2
color: !control.enabled ? control.Material.buttonDisabledColor :
control.highlighted ? control.Material.highlightedButtonColor : control.Material.accentColor
PaddedRectangle {
y: parent.height - 4
width: parent.width
height: 4
radius: 2
topPadding: -2
clip: true
visible: control.checkable && (!control.highlighted || control.flat)
color: control.checked && control.enabled ? control.Material.accentColor : control.Material.secondaryTextColor
}
// The layer is disabled when the button color is transparent so you can do
// Material.background: "transparent" and get a proper flat button without needing
// to set Material.elevation as well
layer.enabled: control.enabled && control.Material.buttonColor.a > 0
layer.effect: ElevationEffect {
elevation: control.Material.elevation
}
Ripple {
clipRadius: 2
width: parent.width
height: parent.height
pressed: control.pressed
anchor: control
active: control.down || control.visualFocus || control.hovered
color: control.Material.rippleColor
}
}
}

View File

@ -0,0 +1,10 @@
import QtQuick 2.0
import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2
Page {
background: Rectangle {
color: Material.background
}
}

View File

@ -0,0 +1,603 @@
<?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="256"
height="256"
id="svg2"
version="1.1"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/micha/Develop/mea/mea/guh-logo-256x256.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs4">
<linearGradient
id="SVGID_1_"
gradientUnits="userSpaceOnUse"
x1="369.02579"
y1="171.88429"
x2="441.68719"
y2="262.58051">
<stop
offset="0.1296"
style="stop-color:#7CC099"
id="stop46" />
<stop
offset="0.3785"
style="stop-color:#6FB594"
id="stop48" />
<stop
offset="0.835"
style="stop-color:#4E9688"
id="stop50" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop52" />
</linearGradient>
<linearGradient
id="SVGID_2_"
gradientUnits="userSpaceOnUse"
x1="936.13898"
y1="154.45329"
x2="918.56207"
y2="154.45329"
gradientTransform="matrix(0.9669,0.2553,-0.2553,0.9669,-399.6603,-163.1002)">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop61" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop63" />
</linearGradient>
<linearGradient
id="SVGID_3_"
gradientUnits="userSpaceOnUse"
x1="451.01599"
y1="201.9489"
x2="442.73761"
y2="243.37801">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop72" />
<stop
offset="0.2568"
style="stop-color:#78BC98"
id="stop74" />
<stop
offset="0.5165"
style="stop-color:#6CB193"
id="stop76" />
<stop
offset="0.7767"
style="stop-color:#589F8C"
id="stop78" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop80" />
</linearGradient>
<linearGradient
id="SVGID_4_"
gradientUnits="userSpaceOnUse"
x1="457.62369"
y1="234.5722"
x2="457.47629"
y2="234.5722">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop87" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop89" />
</linearGradient>
<linearGradient
id="SVGID_5_"
gradientUnits="userSpaceOnUse"
x1="467.88159"
y1="223.4929"
x2="457.62369"
y2="223.4929">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop96" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop98" />
</linearGradient>
<linearGradient
id="SVGID_6_"
gradientUnits="userSpaceOnUse"
x1="457.47629"
y1="235.823"
x2="452.43719"
y2="235.823">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop105" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop107" />
</linearGradient>
<linearGradient
id="SVGID_7_"
gradientUnits="userSpaceOnUse"
x1="452.19159"
y1="227.27921"
x2="460.47461"
y2="227.27921">
<stop
offset="0"
style="stop-color:#6AA583"
id="stop112" />
<stop
offset="1"
style="stop-color:#4C9E96"
id="stop114" />
</linearGradient>
<linearGradient
id="SVGID_8_"
gradientUnits="userSpaceOnUse"
x1="473.17111"
y1="268.90411"
x2="455.23529"
y2="283.95389"
gradientTransform="matrix(0.9997,0.0227,-0.0227,0.9997,-36.4014,-7.9207)">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop119" />
<stop
offset="1"
style="stop-color:#57BAAE"
id="stop121" />
</linearGradient>
<linearGradient
id="SVGID_9_"
gradientUnits="userSpaceOnUse"
x1="447.13129"
y1="274.66199"
x2="470.95151"
y2="274.66199"
gradientTransform="matrix(0.9997,0.0227,-0.0227,0.9997,-36.4014,-7.9207)">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop126" />
<stop
offset="0.2327"
style="stop-color:#76BA97"
id="stop128" />
<stop
offset="0.5485"
style="stop-color:#65AB90"
id="stop130" />
<stop
offset="0.9106"
style="stop-color:#489186"
id="stop132" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop134" />
</linearGradient>
<linearGradient
id="SVGID_10_"
gradientUnits="userSpaceOnUse"
x1="415.2153"
y1="260.93829"
x2="422.0509"
y2="252.7919">
<stop
offset="0"
style="stop-color:#4C9E96"
id="stop141" />
<stop
offset="0.4859"
style="stop-color:#489790"
id="stop143" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop145" />
</linearGradient>
<linearGradient
id="SVGID_11_"
gradientUnits="userSpaceOnUse"
x1="425.60641"
y1="203.1666"
x2="393.7475"
y2="239.4308">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop152" />
<stop
offset="0.3183"
style="stop-color:#77BF9C"
id="stop154" />
<stop
offset="0.6757"
style="stop-color:#6ABDA3"
id="stop156" />
<stop
offset="1"
style="stop-color:#57BAAE"
id="stop158" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="83.152338"
inkscape:cy="132.37098"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="2880"
inkscape:window-height="1698"
inkscape:window-x="0"
inkscape:window-y="44"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid922" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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(-143.41788,-709.27353)">
<g
transform="matrix(1.4088177,0,0,1.4088177,-318.98436,501.41139)"
id="g41">
<g
id="g43">
<linearGradient
id="linearGradient3548"
gradientUnits="userSpaceOnUse"
x1="369.02579"
y1="171.88429"
x2="441.68719"
y2="262.58051">
<stop
offset="0.1296"
style="stop-color:#7CC099"
id="stop3550" />
<stop
offset="0.3785"
style="stop-color:#6FB594"
id="stop3552" />
<stop
offset="0.835"
style="stop-color:#4E9688"
id="stop3554" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop3556" />
</linearGradient>
<path
style="fill:url(#SVGID_1_)"
inkscape:connector-curvature="0"
d="m 433.7,212.6 c -5.9,-10.1 -19,-17.9 -27.5,-21 -8.5,-3.2 -18,-10.1 -18,-10.1 -7.5,-5 -9.7,-9 -13.7,-14 -1.2,2.6 -2.2,5.8 -3,9.6 1.8,3.1 8.7,13.4 28.1,21.5 1.7,0.7 6.9,2.8 7,2.9 l 6.5,2.6 -6.7,-1.9 c -0.2,-0.1 -5.5,-1.6 -7.3,-2.2 -17.3,-6.3 -25,-15.1 -28,-19.9 -0.8,4.9 -1.1,10.6 -0.7,16.5 5.2,4.7 14,11 26.9,15.4 0.9,0.3 3.6,1.3 3.6,1.3 l 3.4,1.2 -3.5,-0.5 c -0.1,0 -3,-0.4 -4,-0.6 -12.1,-2.9 -20.5,-8.4 -26.1,-13.3 0.5,4.3 1.4,8.6 2.8,13 0.3,1 0.7,2.1 1.1,3 4.4,2 9.6,3.9 15.4,5.2 1.1,0.2 4.3,1.1 4.3,1.1 l 3.8,1 -4,-0.2 c -0.1,0 -3.4,-0.2 -4.5,-0.4 -5.1,-0.7 -9.8,-2 -13.9,-3.6 6.6,13.7 18.8,21.4 35.2,27.5 18.7,7 19.4,25 19.4,25 0,0 5.1,-3.8 9.6,-18.4 5.1,-16.2 -0.3,-30.6 -6.2,-40.7 z"
id="path54" />
</g>
<g
id="g56">
<g
id="g58">
<linearGradient
id="linearGradient3561"
gradientUnits="userSpaceOnUse"
x1="936.13898"
y1="154.45329"
x2="918.56207"
y2="154.45329"
gradientTransform="matrix(0.9669,0.2553,-0.2553,0.9669,-399.6603,-163.1002)">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop3563" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop3565" />
</linearGradient>
<path
style="fill:url(#SVGID_2_)"
inkscape:connector-curvature="0"
d="m 458.6,233.8 c 4.9,-3.6 6.9,-7.8 8.5,-12.5 0.7,-2.1 1.3,-5 0.3,-8.1 -0.8,-2.5 -6.5,-6.2 -11.2,-4.7 -5.1,1.7 -6.1,8.1 -6.5,10.9 -0.6,4.3 0.4,10.9 2.8,17.6 -0.1,0 2.1,-0.2 6.1,-3.2 z"
id="path65" />
</g>
<g
id="g67">
<g
id="g69">
<linearGradient
id="linearGradient3570"
gradientUnits="userSpaceOnUse"
x1="451.01599"
y1="201.9489"
x2="442.73761"
y2="243.37801">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop3572" />
<stop
offset="0.2568"
style="stop-color:#78BC98"
id="stop3574" />
<stop
offset="0.5165"
style="stop-color:#6CB193"
id="stop3576" />
<stop
offset="0.7767"
style="stop-color:#589F8C"
id="stop3578" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop3580" />
</linearGradient>
<path
style="fill:url(#SVGID_3_)"
inkscape:connector-curvature="0"
d="m 449.7,219.4 c 0.4,-2.8 1.4,-9.2 6.5,-10.9 4.2,-1.4 9.3,1.5 10.8,3.9 -1.5,-3.9 -5.6,-6.6 -9,-8.3 -4.8,-2.5 -10.8,-2.9 -15.7,-1.7 -4.6,1.1 -7,3.6 -10.9,6.9 0.8,1.1 1.6,2.2 2.2,3.3 4.6,8 9,18.6 8.2,30.6 3,-5 9.7,-6.1 10.6,-6.2 -2.4,-6.6 -3.4,-13.3 -2.7,-17.6 z"
id="path82" />
</g>
<g
id="g84">
<linearGradient
id="linearGradient3584"
gradientUnits="userSpaceOnUse"
x1="457.62369"
y1="234.5722"
x2="457.47629"
y2="234.5722">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop3586" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop3588" />
</linearGradient>
<path
style="fill:url(#SVGID_4_)"
inkscape:connector-curvature="0"
d="m 457.6,234.5 c -0.1,0 -0.1,0.1 -0.1,0.1 0,0 0.1,0 0.1,-0.1 z"
id="path91" />
</g>
<g
id="g93">
<linearGradient
id="linearGradient3592"
gradientUnits="userSpaceOnUse"
x1="467.88159"
y1="223.4929"
x2="457.62369"
y2="223.4929">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop3594" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop3596" />
</linearGradient>
<path
style="fill:url(#SVGID_5_)"
inkscape:connector-curvature="0"
d="m 467.4,213.2 c -0.1,-0.2 -0.2,-0.5 -0.4,-0.8 0.7,1.7 0.8,3.7 0.1,5.9 -1.5,4.9 -1.8,7.1 -6.1,12.9 -1,1.3 -2.2,2.4 -3.4,3.2 0.3,-0.2 0.6,-0.4 1,-0.7 4.9,-3.6 6.9,-7.8 8.5,-12.5 0.7,-2 1.2,-4.9 0.3,-8 z"
id="path100" />
</g>
<g
id="g102">
<linearGradient
id="linearGradient3600"
gradientUnits="userSpaceOnUse"
x1="457.47629"
y1="235.823"
x2="452.43719"
y2="235.823">
<stop
offset="0"
style="stop-color:#DBE6E0"
id="stop3602" />
<stop
offset="1"
style="stop-color:#BCDED3"
id="stop3604" />
</linearGradient>
<path
style="fill:url(#SVGID_6_)"
inkscape:connector-curvature="0"
d="m 452.4,237 c 0,0 0,0 0,0 0,0 1.8,-0.2 5,-2.4 -2.5,1.7 -4.9,2.4 -4.9,2.4 0,0 0,0 -0.1,0 z"
id="path109" />
</g>
</g>
<linearGradient
id="linearGradient3607"
gradientUnits="userSpaceOnUse"
x1="452.19159"
y1="227.27921"
x2="460.47461"
y2="227.27921">
<stop
offset="0"
style="stop-color:#6AA583"
id="stop3609" />
<stop
offset="1"
style="stop-color:#4C9E96"
id="stop3611" />
</linearGradient>
<path
style="fill:url(#SVGID_7_)"
inkscape:connector-curvature="0"
d="m 458.2,217.6 c -1,-0.3 -2,0 -2.8,0.6 -0.2,0.3 -0.3,0.6 -0.4,0.9 -0.4,1.6 0.5,3.3 2.2,3.7 0.7,0.2 1.3,0.1 1.9,-0.1 -0.9,6.9 -5.9,12.4 -6.9,13.5 0.1,0.4 0.2,0.5 0.2,0.7 0.3,0 0.4,-0.1 0.9,-0.2 1.7,-1.9 6.7,-7.9 7,-15.5 0.5,-1.5 -0.5,-3.1 -2.1,-3.6 z"
id="path116" />
</g>
<linearGradient
id="linearGradient3614"
gradientUnits="userSpaceOnUse"
x1="473.17111"
y1="268.90411"
x2="455.23529"
y2="283.95389"
gradientTransform="matrix(0.9997,0.0227,-0.0227,0.9997,-36.4014,-7.9207)">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop3616" />
<stop
offset="1"
style="stop-color:#57BAAE"
id="stop3618" />
</linearGradient>
<path
style="fill:url(#SVGID_8_)"
inkscape:connector-curvature="0"
d="m 405.5,261.4 c 1.5,12.7 7.5,31.7 27.8,47.9 0,0 10.1,-15.4 0.4,-32.5 -9.7,-17.1 -23.8,-22.7 -28.8,-24.5 -0.2,3.6 0.4,6.8 0.6,9.1 z"
id="path123" />
<linearGradient
id="linearGradient3621"
gradientUnits="userSpaceOnUse"
x1="447.13129"
y1="274.66199"
x2="470.95151"
y2="274.66199"
gradientTransform="matrix(0.9997,0.0227,-0.0227,0.9997,-36.4014,-7.9207)">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop3623" />
<stop
offset="0.2327"
style="stop-color:#76BA97"
id="stop3625" />
<stop
offset="0.5485"
style="stop-color:#65AB90"
id="stop3627" />
<stop
offset="0.9106"
style="stop-color:#489186"
id="stop3629" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop3631" />
</linearGradient>
<path
style="fill:url(#SVGID_9_)"
inkscape:connector-curvature="0"
d="m 423.7,272.8 c -5.7,-10 -12.8,-16.8 -18.8,-20.5 -0.1,3.2 0.4,7 0.6,9.1 1.2,10.8 5.8,26.1 19.6,40.4 2.4,-5.5 5.5,-16.8 -1.4,-29 z"
id="path136" />
<g
id="g138">
<linearGradient
id="linearGradient3635"
gradientUnits="userSpaceOnUse"
x1="415.2153"
y1="260.93829"
x2="422.0509"
y2="252.7919">
<stop
offset="0"
style="stop-color:#4C9E96"
id="stop3637" />
<stop
offset="0.4859"
style="stop-color:#489790"
id="stop3639" />
<stop
offset="1"
style="stop-color:#408A83"
id="stop3641" />
</linearGradient>
<path
style="fill:url(#SVGID_10_)"
inkscape:connector-curvature="0"
d="m 411.9,246.7 c -2,-0.8 -4.9,-1.6 -6.8,-2.4 -0.3,2.5 -0.2,5.1 -0.2,8.1 4.4,1.6 16.1,6.2 25.5,19.3 0,-0.1 0,-0.2 0,-0.3 -0.2,-2.3 -1.1,-18.3 -18.5,-24.7 z"
id="path147" />
</g>
<g
id="g149">
<linearGradient
id="linearGradient3645"
gradientUnits="userSpaceOnUse"
x1="425.60641"
y1="203.1666"
x2="393.7475"
y2="239.4308">
<stop
offset="0"
style="stop-color:#7CC099"
id="stop3647" />
<stop
offset="0.3183"
style="stop-color:#77BF9C"
id="stop3649" />
<stop
offset="0.6757"
style="stop-color:#6ABDA3"
id="stop3651" />
<stop
offset="1"
style="stop-color:#57BAAE"
id="stop3653" />
</linearGradient>
<path
style="fill:url(#SVGID_11_)"
inkscape:connector-curvature="0"
d="m 433.7,212.6 c -5.9,-10.1 -19,-17.9 -27.5,-21 -8.5,-3.2 -18,-10.1 -18,-10.1 -2.1,-1.4 -3.8,-2.7 -5.2,-4 -0.4,3.6 -0.6,7.5 -0.4,11.6 4.2,3.2 9.7,6.5 16.9,9.5 1.7,0.7 6.9,2.8 7,2.9 l 6.5,2.6 -6.7,-1.9 c -0.2,-0.1 -5.5,-1.6 -7.3,-2.2 -6.8,-2.5 -12.1,-5.3 -16.2,-8.2 0.4,5 1.3,10.1 2.9,15.2 3.4,1.8 7.2,3.4 11.6,4.9 0.9,0.3 3.6,1.3 3.6,1.3 l 3.4,1.2 -3.5,-0.5 c -0.1,0 -3,-0.4 -4,-0.6 -3.7,-0.9 -7,-2 -10,-3.3 1.9,4.8 4.4,8.8 7.4,12.3 0.1,0 0.1,0 0.1,0 l 3.8,1 -3.2,-0.2 c 6.9,7.7 16.3,13.3 26.3,21.3 13.5,10.8 9.2,27.2 9.2,27.2 0,0 0.8,-0.6 1.5,-1.5 1.8,-2.1 5.1,-7 8.1,-16.9 5,-16.1 -0.4,-30.5 -6.3,-40.6 z"
id="path160" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -31,6 +31,34 @@ Page {
property bool swipeViewReady: 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
onViewReadyChanged: {
if (tabSettings.currentMainViewIndex > swipeView.count) {
@ -90,16 +118,21 @@ Page {
anchors.rightMargin: anchors.leftMargin
currentIndex: root.currentViewIndex
Component.onCompleted: {
if (engine.jsonRpcClient.ensureServerVersion(1.6)) {
swipeView.insertItem(0, favoritesViewComponent.createObject(swipeView))
}
root.swipeViewReady = true;
}
onCurrentIndexChanged: {
root.currentViewIndex = currentIndex
}
Component {
id: experienceViewComponent
Loader {
width: swipeView.width
height: swipeView.height
clip: true
readonly property string title: item ? item.title : ""
readonly property string icon: item ? item.icon : ""
}
}
Component {
id: favoritesViewComponent
FavoritesView {
@ -206,20 +239,6 @@ Page {
((systemProductType === "ios" && Screen.height === 375) ? -10 : -20) :
(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;
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 {
id: tabEntryComponent
MainPageTabButton {

View File

@ -14,7 +14,7 @@ ApplicationWindow {
minimumWidth: 360
minimumHeight: 480
visibility: ApplicationWindow.AutomaticVisibility
font: Qt.application.font
// font: Qt.application.font
// Those variables must be present in the Style
@ -50,7 +50,6 @@ ApplicationWindow {
RootItem {
id: rootItem
anchors.fill: parent
anchors.topMargin: PlatformHelper.getSafeAreaMargins(app)
}
NymeaDiscovery {

View File

@ -98,10 +98,9 @@ Item {
}
Binding {
target: _discovey
target: _discovery
property: "discovering"
when: engine.connection.currentHost === null
value: true
value: engine.connection.currentHost === null
}
Component.onCompleted: {

View File

@ -46,6 +46,23 @@ Page {
onClicked: pageStack.push(appLogComponent)
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 {

View File

@ -24,8 +24,8 @@ ColumnLayout {
}
readonly property State deviceState: device && stateType ? device.states.getState(stateType.id) : null
readonly property double from: dial.stateType.minValue
readonly property double to: dial.stateType.maxValue
readonly property double from: dial.stateType ? dial.stateType.minValue : 0
readonly property double to: dial.stateType ? dial.stateType.maxValue : 100
readonly property double anglePerStep: maxAngle / dial.steps
readonly property double startAngle: -(dial.steps * dial.anglePerStep) / 2
@ -90,7 +90,7 @@ ColumnLayout {
Label {
id: topLabel
Layout.fillWidth: true
text: rotateMouseArea.currentValue + dial.stateType.unitString
text: rotateMouseArea.currentValue + (dial.stateType ? dial.stateType.unitString : "")
font.pixelSize: app.largeFont * 1.5
horizontalAlignment: Text.AlignHCenter
visible: dial.showValueLabel && dial.stateType !== null
@ -101,7 +101,6 @@ ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Item {
id: innerDial
@ -110,7 +109,6 @@ ColumnLayout {
anchors.centerIn: parent
rotation: dial.startAngle
Rectangle {
anchors.fill: rotationButton
radius: height / 2
@ -167,7 +165,7 @@ ColumnLayout {
width: parent.width
height: width
radius: width / 2
color: dial.angleToValue(parent.rotation) <= dial.deviceState.value ? d.poweredColor : d.offColor
color: dial.deviceState && dial.angleToValue(parent.rotation) <= dial.deviceState.value ? d.poweredColor : d.offColor
Behavior on color { ColorAnimation { duration: 200 } }
}
}
@ -247,8 +245,8 @@ ColumnLayout {
dragging = false;
}
readonly property int decimals: dial.stateType.type.toLowerCase() === "int" ? 0 : 1
property var currentValue: dial.deviceState.value.toFixed(decimals)
readonly property int decimals: dial.stateType && dial.stateType.type.toLowerCase() === "int" ? 0 : 1
property var currentValue: dial.deviceState ? dial.deviceState.value.toFixed(decimals) : 0
property date lastVibration: new Date()
property int startX
property int startY

View File

@ -5,13 +5,28 @@ Item {
implicitHeight: app.iconSize * .8
implicitWidth: height
property bool on: false
// TODO: Convert to enum once we have Qt 5.10
// on, off, green, orange, red
property string state: "off"
Rectangle {
height: Math.min(parent.height, parent.height)
width: height
radius: width / 2
color: root.on ? "lightgreen" : "lightgray"
color: {
switch (root.state) {
case "on":
return app.accentColor
case "green":
return "#73c0b3";
case "off":
return "lightgray";
case "orange":
return "#fedf6f";
case "red":
return "#dd7777"
}
}
border.width: 1
border.color: app.foregroundColor
}

View File

@ -6,7 +6,7 @@ import Nymea 1.0
RowLayout {
id: root
spacing: (parent.width - app.iconSize*2*children.length) / 4
spacing: (parent.width - app.iconSize*2*children.length) / (children.length - 1)
// implicitWidth: app.iconSize * 2 * children.length + spacing * (children.length - 1)
implicitWidth: childrenRect.width

View File

@ -10,6 +10,7 @@ Item {
property alias from: slider.from
property alias to: slider.to
property alias stepSize: slider.stepSize
property alias snapMode: slider.snapMode
readonly property real rawValue: slider.value

View File

@ -57,7 +57,7 @@ Item {
Led {
visible: root.stateType.type.toLowerCase() === "bool"
on: root.valueState.value === true
state: root.valueState.value === true ? "on" : "off"
}
Label {

View File

@ -7,5 +7,5 @@ import "../../components"
Led {
property bool value
on: value === true
state: value === true ? "on" : "off"
}

View File

@ -118,7 +118,7 @@ DeviceListPageBase {
Led {
id: led
visible: sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() == "bool"
on: visible && sensorValueDelegate.stateValue.value === true
state: visible && sensorValueDelegate.stateValue.value === true ? "on" : "off"
}
Item {
Layout.preferredWidth: led.width

View File

@ -268,7 +268,7 @@ Page {
property var value
Led {
implicitHeight: app.smallFont
on: boolLed.value === "true"
state: boolLed.value === "true" ? "on" : "off"
}
}
}

View File

@ -23,6 +23,9 @@ DevicePageBase {
readonly property StateType boostStateType: device.deviceClass.stateTypes.findByName("boost")
readonly property State boostState: boostStateType ? device.states.getState(boostStateType.id) : null
Component.onCompleted: {
print("d:", root.device, root.targetTemperatureStateType, root.percentageStateType)
}
GridLayout {
anchors.fill: parent
@ -33,10 +36,11 @@ DevicePageBase {
id: dial
Layout.fillWidth: true
Layout.fillHeight: true
visible: root.targetTemperatureStateType || root.percentageStateType
// visible: root.targetTemperatureStateType || root.percentageStateType
device: root.device
stateType: root.targetTemperatureStateType ? root.targetTemperatureStateType : root.percentageStateType
}
Rectangle {

View File

@ -0,0 +1,97 @@
import QtQuick 2.3
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.2
import "qrc:/ui/components"
import Nymea 1.0
Item {
id: root
readonly property string title: qsTr("Garage gates")
readonly property string icon: Qt.resolvedUrl("qrc:/ui/images/shutter/shutter-050.svg")
DevicesProxy {
id: garagesFilterModel
engine: _engine
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 {
id: swipeView
anchors.fill: parent
Repeater {
model: garagesFilterModel
Item {
id: garageGateView
width: swipeView.width
height: swipeView.height
readonly property Device device: garagesFilterModel.get(index)
readonly property StateType openStateType: device.deviceClass.stateTypes.findByName("state")
readonly property State openState: openStateType ? device.states.getState(openStateType.id) : null
readonly property StateType intermediatePositionStateType: device.deviceClass.stateTypes.findByName("intermediatePosition")
readonly property State intermediatePositionState: intermediatePositionStateType ? device.states.getState(intermediatePositionStateType.id) : null
GridLayout {
id: layout
anchors.fill: parent
anchors.margins: app.margins
columns: app.landscape ? 2 : 1
Label {
id: label
text: garageGateView.device.name
font.pixelSize: app.largeFont
Layout.preferredWidth: layout.width
Layout.columnSpan: parent.columns
horizontalAlignment: Text.AlignHCenter
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumWidth: app.landscape ? layout.width / 2 : layout.width
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"
}
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: controls.implicitHeight
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
}
}

View File

@ -0,0 +1,432 @@
import QtQuick 2.3
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import "qrc:/ui/components"
import Nymea 1.0
import QtGraphicalEffects 1.0
Item {
id: root
readonly property string title: qsTr("Celsi°s")
readonly property string icon: Qt.resolvedUrl("qrc:/ui/images/radiator.svg")
readonly property Device duwWpDevice: duwWpFilterModel.count > 0 ? duwWpFilterModel.get(0) : null
readonly property Device duwLuDevice: duwLuFilterModel.count > 0 ? duwLuFilterModel.get(0) : null
readonly property State temperatureState: duwWpDevice ? duwWpDevice.states.getState(duwWpDevice.deviceClass.stateTypes.findByName("temperature").id) : null
readonly property State targetTemperatureState: duwWpDevice ? duwWpDevice.states.getState(duwWpDevice.deviceClass.stateTypes.findByName("targetTemperature").id) : null
readonly property State co2LevelState: duwLuDevice ? duwLuDevice.states.getState(duwLuDevice.deviceClass.stateTypes.findByName("co2").id) : null
readonly property State ventilationModeState: duwLuDevice ? duwLuDevice.states.getState(duwLuDevice.deviceClass.stateTypes.findByName("ventilationMode").id) : null
readonly property State ventilationLevelState: duwLuDevice ? duwLuDevice.states.getState(duwLuDevice.deviceClass.stateTypes.findByName("activeVentilationLevel").id) : null
function ventilationModeToSliderValue(ventilationMode) {
switch (ventilationMode) {
case "Automatic":
case "Party":
return 0
case "Manual level 0":
return 0;
case "Manual level 1":
return 1;
case "Manual level 2":
return 2;
case "Manual level 3":
return 3;
}
return 0;
}
function ventilationModeToUiMode(ventilationMode) {
switch (ventilationMode) {
case "Automatic":
return 0
case "Party":
return 1;
case "Manual level 0":
case "Manual level 1":
case "Manual level 2":
case "Manual level 3":
return 2;
}
}
function uiModeToVentilationMode(uiMode, sliderValue) {
switch (uiMode) {
case 0:
return "Automatic";
case 1:
return "Party";
case 2:
return "Manual level " + Math.floor(sliderValue)
}
}
function setVentilationMode(uiModeIndex, sliderIndex) {
var params =[];
var param = {};
param["paramTypeId"] = root.ventilationModeState.stateTypeId
param["value"] = root.uiModeToVentilationMode(uiModeIndex, sliderIndex)
params.push(param)
engine.deviceManager.executeAction(root.duwLuDevice.id, root.ventilationModeState.stateTypeId, params)
}
function setTargetTemp(targetTemp) {
// We don't want to spam with set value calls so we're going to queue them up and only send one at a time
d.queuedTargetTemp = targetTemp;
if (d.pendingCallId != -1) {
d.setTempPending = true;
return;
}
var params = []
var param = {}
param["paramTypeId"] = root.targetTemperatureState.stateTypeId
param["value"] = targetTemp
params.push(param)
d.pendingCallId = engine.deviceManager.executeAction(root.duwWpDevice.id, root.targetTemperatureState.stateTypeId, params)
d.setTempPending = false;
}
Connections {
target: engine.deviceManager
onExecuteActionReply: {
print("executeActionReply:", params["id"])
if (params["id"] === d.pendingCallId) {
d.pendingCallId = -1;
if (d.setTempPending) {
setTargetTemp(d.queuedTargetTemp)
}
}
}
}
QtObject {
id: d
property int pendingCallId: -1
property bool setTempPending: false
property real queuedTargetTemp: 0
}
DevicesProxy {
id: duwWpFilterModel
engine: _engine
filterDeviceClassId: "e548f962-92db-4110-8279-10fbcde35f93"
}
DevicesProxy {
id: duwLuFilterModel
engine: _engine
filterDeviceClassId: "0de8e21e-392a-4790-a78a-b1a7eaa7571b"
}
EmptyViewPlaceholder {
anchors.centerIn: parent
width: parent.width - app.margins * 2
text: qsTr("There is no drexel und weiss heating system set up yet.")
imageSource: "qrc:/ui/images/radiator.svg"
buttonVisible: false
buttonText: qsTr("Set up now")
visible: duwWpFilterModel.count === 0 && !engine.deviceManager.fetchingData
}
Item {
id: mainView
anchors.fill: parent
visible: root.duwWpDevice !== null
ColumnLayout {
anchors.fill: parent
anchors.margins: app.margins
ColumnLayout {
Label {
text: qsTr("Current air quality")
font.pixelSize: app.smallFont
}
RowLayout {
spacing: app.margins
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "qrc:/ui/images/weathericons/wind.svg"
color: app.accentColor
}
Led {
state: {
if (!root.co2LevelState) {
return "off"
}
if (root.co2LevelState.value < 600) {
return "green"
}
if (root.co2LevelState.value < 1200) {
return "orange"
}
return "red"
}
}
}
Label {
text: qsTr("Current temperature")
font.pixelSize: app.smallFont
}
RowLayout {
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "qrc:/ui/images/sensors/temperature.svg"
color: app.accentColor
}
Label {
text: root.temperatureState ? root.temperatureState.value.toFixed(1) + "°C" : "N/A"
Layout.fillWidth: true
font.pixelSize: app.largeFont * 1.5
}
}
}
ColumnLayout {
Label {
text: qsTr("Temperature, °C")
font.pixelSize: app.largeFont
}
Label {
text: (d.pendingCallId !== -1 || d.setTempPending) ? d.queuedTargetTemp.toFixed(1) :
root.targetTemperatureState ? root.targetTemperatureState.value.toFixed(1) : "N/A"
font.pixelSize: app.largeFont * 3
}
}
ColumnLayout {
Layout.fillWidth: false
Layout.bottomMargin: app.margins
ColorIcon {
Layout.preferredHeight: app.iconSize //* 1.5
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
color: app.accentColor
name: "qrc:/ui/images/magic.svg"
MouseArea {
anchors.fill: parent
onClicked: pageStack.push("qrc:/ui/magic/DeviceRulesPage.qml", {device: root.duwWpDevice})
}
}
Label {
text: qsTr("Automate this thing")
color: app.accentColor
font.pixelSize: app.smallFont
}
}
ColumnLayout {
RowLayout {
Layout.leftMargin: parent.width * .05
Layout.rightMargin: parent.width * .2
spacing: app.margins
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
color: app.accentColor
name: "qrc:/ui/images/ventilation.svg"
PropertyAnimation on rotation {
running: root.ventilationLevelState !== null
duration: root.ventilationLevelState !== null && root.ventilationLevelState.value > 0
? 2000 / root.ventilationLevelState.value
: 0
from: 0
to: 360
loops: Animation.Infinite
onDurationChanged: {
running = false;
running = true;
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.maximumHeight: app.iconSize
spacing: 0
Repeater {
model: ListModel {
ListElement { text: qsTr("Auto") }
ListElement { text: qsTr("Party") }
ListElement { text: qsTr("Manual") }
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
border.width: 1
border.color: app.accentColor
color: root.ventilationModeState && root.ventilationModeToUiMode(root.ventilationModeState.value) === index ? app.accentColor : "transparent"
Label {
anchors.centerIn: parent
text: model.text
font.pixelSize: app.smallFont
}
MouseArea {
anchors.fill: parent
onClicked: {
root.setVentilationMode(index, ventilationSlider.value)
}
}
}
}
}
}
Slider {
id: ventilationSlider
Layout.fillWidth: true
Layout.leftMargin: parent.width * .05
Layout.rightMargin: parent.width * .05
from: 0
to: 3
stepSize: 1
live: false
snapMode: Slider.SnapAlways
enabled: root.ventilationModeState && root.ventilationModeToUiMode(root.ventilationModeState.value) === 2
opacity: enabled ? 1 : .2
value: root.ventilationModeState ? root.ventilationModeToSliderValue(root.ventilationModeState.value) : 0
onMoved: root.setVentilationMode(2, valueAt(visualPosition))
}
}
// ProgressButton {
// imageSource: "qrc:/ui/images/system-shutdown.svg"
// Layout.preferredHeight: app.iconSize * 1.5
// Layout.preferredWidth: height
// Layout.alignment: Qt.AlignHCenter
// }
// Label {
// text: qsTr("Hold to turn off")
// font.pixelSize: app.smallFont
// Layout.fillWidth: true
// horizontalAlignment: Text.AlignHCenter
// }
}
Item {
height: parent.height * .85
width: height
anchors.left: parent.right
anchors.leftMargin: -width * .25
anchors.top: parent.top
anchors.topMargin: -height * .05
z: -1
Rectangle {
id: outerRadius
anchors.fill: parent
radius: width / 2
border.width: 3
color: "transparent"
border.color: app.accentColor
}
Glow {
anchors.fill: parent
source: outerRadius
// color: "#f45b69"
color: Qt.rgba(app.accentColor.r, app.accentColor.g, app.accentColor.b, .5)
radius: 8
samples: 17
spread: 0.5
}
Rectangle {
id: innerRadius
anchors.fill: parent
anchors.margins: parent.width * .02
radius: width / 2
border.width: 2
color: "transparent"
border.color: app.accentColor
Repeater {
id: ticksRepeater
model: 180
Item {
height: isBold ? 3 : 2
width: parent.width - 2
anchors.centerIn: parent
rotation: index * 360 / ticksRepeater.count
readonly property int isBold: index % 10 === 0
// Rectangle { anchors.fill: parent; color: "blue" }
Rectangle { height: parent.height; width: parent.isBold ? 20 : 10; color: app.accentColor }
}
}
}
MouseArea {
anchors.fill: parent
preventStealing: true
property real startAnglePress
property real startAngleDial
property real startTemp
property real lastValue
onPressed: {
startAnglePress = calculateAngle(mouseX, mouseY)
startAngleDial = innerRadius.rotation
startTemp = root.targetTemperatureState.value
lastValue = startTemp
print("angle:", calculateAngle(mouseX, mouseY))
}
onPositionChanged: {
var currentAngle = calculateAngle(mouseX, mouseY)
var angleDiff = currentAngle - startAnglePress
var tempDiff = Math.round(angleDiff / 2) / 10
var newTemp = startTemp + tempDiff
innerRadius.rotation = startAngleDial + angleDiff
if (lastValue.toFixed(1) === newTemp.toFixed(1)) {
return;
}
lastValue = newTemp
print("degree value changed", newTemp, lastValue)
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
root.setTargetTemp(newTemp);
}
function calculateAngle(mouseX, mouseY) {
// transform coords to center of dial
mouseX -= width / 2
mouseY -= height / 2
var rad = Math.atan(mouseY / mouseX);
var angle = rad * 180 / Math.PI
angle += 90;
if (mouseX < 0 && mouseY >= 0) angle = 180 + angle;
if (mouseX < 0 && mouseY < 0) angle = 180 + angle;
return angle;
}
}
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="svg4874" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
<style type="text/css">
.st0{fill:#808080;}
</style>
<title>settings</title>
<path class="st0" d="M30.1,75c-8.3-9-2.5-18.1-0.5-20.7c2.1-2.7,4.8-4.9,7.9-6.4c0-1.7,0.4-3.4,1.2-4.9c-2.1-0.1-3.6,0.9-5.5,2.2
c-2.1,1.7-4.6,2.8-7.2,3.2c-3.8,0.4-6.8-1.2-8.2-4.4c-2-4.4-0.6-10.7,3.1-14.1c9-8.3,18.1-2.5,20.7-0.5c1.2,0.9,2.3,2,3.3,3.1
c0.6,0.8,0.5,1.9-0.2,2.5c-0.8,0.6-1.9,0.5-2.5-0.2c-0.9-0.9-1.8-1.8-2.8-2.6c-2.6-1.9-9.4-5.9-16.2,0.3c-2.6,2.4-3.6,7.1-2.3,10.1
c0.8,1.8,2.3,2.5,4.6,2.3c2.2-0.3,3.9-1.4,5.6-2.6c2.3-1.7,5-3.5,9.1-2.6c0.6,0.1,1.2,0.3,1.8,0.5c0.2,0.1,0.4,0.2,0.6,0.4
c0.7,0.7,0.8,1.8,0.1,2.5c-0.4,0.4-0.7,0.8-1,1.3c-0.8,1.3-1.1,2.9-0.9,4.4c0.1,0.8-0.3,1.6-1.1,1.9c-3,1.2-5.7,3.2-7.6,5.8
c-1.9,2.6-5.9,9.4,0.3,16.2c2.4,2.6,7.1,3.6,10.1,2.3c1.8-0.8,2.5-2.3,2.3-4.6c-0.3-2.2-1.4-3.9-2.6-5.6c-1.7-2.3-3.5-5-2.6-9.1
c0.1-0.6,0.3-1.2,0.5-1.8c0.1-0.2,0.2-0.4,0.4-0.6c0.7-0.7,1.8-0.8,2.5-0.1c0.4,0.4,0.8,0.7,1.3,1c1.3,0.8,2.9,1.1,4.4,0.9
c0.8-0.1,1.6,0.3,1.9,1.1c1.2,3,3.2,5.7,5.8,7.6c2.6,1.9,9.4,5.9,16.2-0.3c2.6-2.4,3.6-7.1,2.3-10.1c-0.8-1.8-2.3-2.5-4.6-2.3
c-2.2,0.3-3.9,1.4-5.6,2.6c-2.4,1.7-5.1,3.5-9.2,2.6c-0.6-0.1-1.2-0.3-1.8-0.5c-0.2-0.1-0.4-0.2-0.6-0.4c-0.7-0.7-0.8-1.8-0.1-2.5
c0.4-0.4,0.7-0.8,1-1.3c0.8-1.3,1.1-2.9,0.9-4.4c-0.1-0.8,0.3-1.6,1.1-1.9c3-1.2,5.7-3.2,7.6-5.8c1.9-2.7,5.9-9.4-0.3-16.2
c-2.4-2.6-7.1-3.6-10.1-2.3c-1.8,0.8-2.5,2.3-2.3,4.6c0.3,2.2,1.4,3.9,2.6,5.6c1.7,2.4,3.5,5.1,2.6,9.2c-0.1,0.6-0.3,1.2-0.5,1.8
c-0.1,0.2-0.2,0.4-0.4,0.6c-0.7,0.7-1.8,0.8-2.5,0.1c-0.4-0.4-0.8-0.7-1.3-1c-1.3-0.8-2.9-1.1-4.4-0.9l0,0c-1,0.1-1.9-0.5-2-1.5
s0.5-1.9,1.5-2c2.2-0.3,4.4,0.1,6.3,1.1c0.1-2.1-0.9-3.6-2.2-5.5c-1.7-2.1-2.8-4.6-3.2-7.2c-0.4-3.8,1.2-6.8,4.4-8.2
c4.4-2,10.7-0.6,14.1,3.1c8.3,9,2.5,18.1,0.5,20.7c-2.1,2.7-4.8,4.9-7.9,6.4c0,1.7-0.4,3.4-1.2,4.9c2,0.1,3.5-0.9,5.4-2.2
c2.1-1.7,4.6-2.8,7.2-3.2c3.8-0.4,6.8,1.2,8.2,4.4c2,4.4,0.6,10.7-3.1,14.1c-9,8.3-18.1,2.5-20.7,0.5c-2.7-2.1-4.9-4.8-6.4-7.9
c-1.7,0-3.4-0.4-4.9-1.2c-0.1,2.1,0.9,3.6,2.2,5.5c1.7,2.1,2.8,4.6,3.2,7.2c0.4,3.8-1.2,6.8-4.4,8.2c-1.4,0.6-2.9,0.9-4.4,0.9
C36,79.1,32.5,77.7,30.1,75z"/>
<path class="st0" d="M6.2,48C6.2,24.9,24.9,6.2,48,6.2S89.8,24.9,89.8,48S71.1,89.8,48,89.8S6.2,71.1,6.2,48z M9.7,48L9.7,48
c0,21.2,17.1,38.3,38.3,38.3S86.3,69.2,86.3,48S69.2,9.7,48,9.7S9.7,26.8,9.7,48z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -511,7 +511,7 @@ MainPageTile {
Led {
Layout.preferredHeight: app.iconSize * .5
Layout.preferredWidth: height
on: sensorsRoot.shownStateType && sensorsRoot.device.stateValue(sensorsRoot.shownStateType.id) === true
state: sensorsRoot.shownStateType && sensorsRoot.device.stateValue(sensorsRoot.shownStateType.id) === true ? "on" : "off"
visible: sensorsRoot.shownStateType && sensorsRoot.shownStateType.type.toLowerCase() === "bool"
}
}

View File

@ -347,7 +347,7 @@ Item {
}
}
Led {
on: sensorsRoot.currentState.value === true
state: sensorsRoot.currentState.value === true ? "on" : "off"
visible: sensorsRoot.currentStateType.type.toLowerCase() === "bool"
}