Commit 6ec44f0c authored by Richard Lee's avatar Richard Lee
Browse files

Initial commit

parents
build
.clickable
project(domoticz C CXX)
cmake_minimum_required(VERSION 3.0.0)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(Qt5Core)
find_package(Qt5Qml)
find_package(Qt5Quick)
# Automatically create moc files
set(CMAKE_AUTOMOC ON)
# Components PATH
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE ARCH_TRIPLET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(QT_IMPORTS_DIR "lib/${ARCH_TRIPLET}")
set(PROJECT_NAME "domoticz")
set(FULL_PROJECT_NAME "domoticz.applee")
set(CMAKE_INSTALL_PREFIX /)
set(DATA_DIR /)
set(DESKTOP_FILE_NAME ${PROJECT_NAME}.desktop)
# This command figures out the target architecture for use in the manifest file
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_ARCH
OUTPUT_VARIABLE CLICK_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json DESTINATION ${CMAKE_INSTALL_PREFIX})
install(FILES ${PROJECT_NAME}.apparmor DESTINATION ${DATA_DIR})
install(DIRECTORY qml DESTINATION ${DATA_DIR})
install(DIRECTORY assets DESTINATION ${DATA_DIR})
# Translations
file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po qml/*.qml qml/*.js)
list(APPEND I18N_SRC_FILES ${DESKTOP_FILE_NAME}.in.h)
find_program(INTLTOOL_MERGE intltool-merge)
if(NOT INTLTOOL_MERGE)
message(FATAL_ERROR "Could not find intltool-merge, please install the intltool package")
endif()
find_program(INTLTOOL_EXTRACT intltool-extract)
if(NOT INTLTOOL_EXTRACT)
message(FATAL_ERROR "Could not find intltool-extract, please install the intltool package")
endif()
add_custom_target(${DESKTOP_FILE_NAME} ALL
COMMENT "Merging translations into ${DESKTOP_FILE_NAME}..."
COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${CMAKE_SOURCE_DIR}/${DESKTOP_FILE_NAME}.in ${DESKTOP_FILE_NAME}
COMMAND sed -i 's/${PROJECT_NAME}-//g' ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME} DESTINATION ${DATA_DIR})
add_subdirectory(po)
# Make source files visible in qtcreator
file(GLOB_RECURSE PROJECT_SRC_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
qml/*.qml
qml/*.js
*.json
*.json.in
*.apparmor
*.desktop.in
)
add_custom_target(${PROJECT_NAME}_FILES ALL SOURCES ${PROJECT_SRC_FILES})
This diff is collapsed.
# Domoticz
Simple QML app to control Domoticz home automation services
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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"
viewBox="0 0 4118 4118"
xml:space="preserve"
version="1.1"
id="svg8"
sodipodi:docname="temp.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
width="4118"
height="4118"
style="clip-rule:evenodd;fill-rule:evenodd;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"><metadata
id="metadata12"><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><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="960"
id="namedview10"
showgrid="false"
inkscape:zoom="0.16209539"
inkscape:cx="1990.8019"
inkscape:cy="1935.5107"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg8"
inkscape:measure-start="3251.17,2554.05"
inkscape:measure-end="2887.19,1678.02" />
<defs
id="defs4">
<style
type="text/css"
id="style2">
.fil0 {fill:black}
</style>
</defs>
<path
class="fil0"
d="m 2418.898,2761.1688 c 208.9857,120.5687 349.075,346.7784 349.075,605.1398 0,385.8196 -313.4785,699.2981 -699.2982,699.2981 -385.8196,0 -699.2981,-313.4785 -699.2981,-699.2981 0,-258.3614 140.0892,-484.5711 349.075,-605.1398 V 401.4682 c 0,-191.76155 157.3133,-349.074915 349.0748,-349.074915 191.7616,0 349.075,157.313365 349.075,349.074915 V 706.90877 H 2573.44 v 89.56527 H 2416.6015 V 1177.7007 H 2573.44 v 89.5652 h -156.8385 v 379.9752 H 2573.44 v 89.5652 h -156.8385 v 380.9294 H 2573.44 v 89.5652 h -156.8385 v 557.3127 z m -214.727,129.7548 V 1454.4344 h -270.9924 v 1436.4892 c -207.8373,58.5619 -359.4093,249.1752 -359.4093,475.385 0,273.2889 221.6166,494.9055 494.9055,494.9055 273.289,0 494.9056,-221.6166 494.9056,-494.9055 0,-226.2098 -151.572,-416.8231 -359.4094,-475.385 z m 88.417,-57.4136 V 401.4682 c 0,-122.86519 -101.048,-223.91319 -223.9132,-223.91319 -122.8651,0 -223.9131,101.048 -223.9131,223.91319 V 2833.51 l -63.1551,36.7447 c -176.834,102.1963 -287.0682,291.6613 -287.0682,497.2022 0,316.9232 257.2132,572.9881 572.9881,572.9881 316.9234,0 572.9881,-257.2132 572.9881,-572.9881 0,-205.5409 -109.0859,-393.8576 -287.0681,-497.2022 l -63.155,-36.7447 z"
id="path6"
style="fill:#808080;fill-opacity:0.82745098;stroke-width:1.14827287"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssscsssccccccccccccccccccccccsssccsssccsssccc" />
</svg>
\ No newline at end of file
{
"template": "pure-qml-cmake",
"kill": "qmlscene"
}
{
"policy_groups": [
"networking",
"push-notification-client"
],
"policy_version": 16.04
}
[Desktop Entry]
_Name=Domoticz
Exec=qmlscene qml/Main.qml
Icon=assets/logo.svg
Terminal=false
Type=Application
X-Ubuntu-Touch=true
{
"name": "domoticz.applee",
"description": "Simple QML app to control Domoticz home automation services",
"architecture": "@CLICK_ARCH@",
"title": "Domoticz",
"hooks": {
"domoticz": {
"apparmor": "domoticz.apparmor",
"desktop": "domoticz.desktop"
}
},
"version": "1.0",
"maintainer": "Richard Lee <apps-lee@outlook.fr>",
"framework" : "ubuntu-sdk-16.04"
}
include(FindGettext)
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
set(DOMAIN ${FULL_PROJECT_NAME})
set(POT_FILE ${DOMAIN}.pot)
file(GLOB PO_FILES *.po)
# Creates the .pot file containing the translations template
add_custom_target(${POT_FILE} ALL
COMMENT "Generating translation template"
COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini
--srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_NAME}.in
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE}
-D ${CMAKE_CURRENT_SOURCE_DIR}
-D ${CMAKE_CURRENT_BINARY_DIR}
--from-code=UTF-8
--c++ --qt --language=javascript --add-comments=TRANSLATORS
--keyword=tr --keyword=tr:1,2 --keyword=N_ --keyword=_
--package-name='${DOMAIN}'
${I18N_SRC_FILES}
COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR})
# Builds the binary translations catalog for each language
# it finds source translations (*.po) for
foreach(PO_FILE ${PO_FILES})
get_filename_component(LANG ${PO_FILE} NAME_WE)
gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE})
set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/share/locale/${LANG}/LC_MESSAGES)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo
DESTINATION ${INSTALL_DIR}
RENAME ${DOMAIN}.mo)
endforeach(PO_FILE)
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the domoticz.applee package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: domoticz.applee\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-28 16:39+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../qml/Advanced.qml:17
msgid "Details"
msgstr ""
#: ../qml/DeviceList.qml:29 ../qml/DeviceList.qml:163
msgid "Dashboard"
msgstr ""
#: ../qml/DeviceList.qml:167
msgid "Switches"
msgstr ""
#: ../qml/DeviceList.qml:171
msgid "Temperature"
msgstr ""
#: ../qml/DeviceList.qml:175
msgid "Weather"
msgstr ""
#: ../qml/DeviceList.qml:179
msgid "Utility"
msgstr ""
#: ../qml/PageSettings.qml:18
msgid "Parameters"
msgstr ""
#: ../qml/PageSettings.qml:40
msgid "Server address"
msgstr ""
#: ../qml/PageSettings.qml:48
msgid "Port"
msgstr ""
#: ../qml/PageSettings.qml:56
msgid "Login (optional)"
msgstr ""
#: ../qml/PageSettings.qml:63
msgid "Password (optional)"
msgstr ""
#: ../qml/PageSettings.qml:69
msgid "Save settings"
msgstr ""
#: domoticz.desktop.in.h:1
msgid "Domoticz"
msgstr ""
import QtQuick 2.4
import QtQuick.Layouts 1.1
import Ubuntu.Components 1.3
Page {
anchors.fill: parent
visible: false
property alias info: infoLabel
property alias details: txtDetails
property alias slider: level
property var myType
property var myIdx
header: PageHeader {
id: header
title: i18n.tr('Details')
} // PageHeader
Rectangle { // List of switches
id: advancedPage
anchors.top: header.bottom
anchors.leftMargin: units.gu(2)
anchors.left: parent.left
width: parent.width-units.gu(2)
height: parent.height - header.height
Column {
anchors.fill: parent
spacing: units.gu(2)
Rectangle { height: units.gu(5); width: parent.width
Label { anchors.centerIn: parent; id: infoLabel }
}
Row {
visible: (myType == "Light")
width: parent.width
spacing: units.gu(2)
Icon {
width: units.gu(5)
height: units.gu(5)
name: "preferences-color-symbolic"
color: UbuntuColors.ash
}
Slider {
id: level
height: units.gu(5)
width: parent.width - units.gu(11)
function formatValue(v) { return v.toFixed(0) }
minimumValue: 0
maximumValue: 100
value: 100
stepSize: 1
live: false
onValueChanged: apiFct.callRequest(baseDomoticzUrl+"/json.htm?type=command&param=switchlight&idx="+myIdx+"&switchcmd=Set%20Level&level="+value)
}
} // Row
Rectangle { height: units.gu(5); width: parent.width
Label { anchors.centerIn: parent; width: parent.width; id: txtDetails }
}
} // Column
} // Rectangle : List of switches
// Utility functions
Functions {id: myFct}
Requests {id: apiFct}
} // Page
import QtQuick 2.4
import QtQuick.Layouts 1.1
import Ubuntu.Components 1.3
Page {
anchors.fill: parent
visible: false
Component.onCompleted: apiFct.getDevices(currentUrl, false)
property var dashboardUrl: baseDomoticzUrl+"/json.htm?type=devices&used=true&filter=all&favorite=1&order=Name"
property var switchesUrl: baseDomoticzUrl+"/json.htm?type=devices&filter=light&used=true&order=Name"
property var temperatureUrl: baseDomoticzUrl+"/json.htm?type=devices&filter=temp&used=true&order=Name"
property var weatherUrl: baseDomoticzUrl+"/json.htm?type=devices&filter=weather&used=true&order=Name"
property var utilityUrl: baseDomoticzUrl+"/json.htm?type=devices&filter=utility&used=true&order=Name"
property var currentUrl: dashboardUrl
property var currentPage: 0
header: PageHeader {
id: header
leadingActionBar {
actions: [
Action {
iconName: "navigation-menu"
onTriggered: stack.push(params)
}
]
}
title: i18n.tr('Dashboard')
trailingActionBar {
actions: [
Action {
iconName: "info"
onTriggered: Qt.openUrlExternally("https://www.domoticz.com/")
}
]
}
} // PageHeader
Rectangle { // List of switches
id: deviceList
anchors.top: header.bottom
anchors.leftMargin: units.gu(1)
anchors.left: parent.left
anchors.bottom: foot.top
width: parent.width-units.gu(1)
height: parent.height - header.height
Component {
id: devDelegate
ListItem {
height: units.gu(6)
trailingActions: ListItemActions {
actions: [
Action {
iconName: "filters"
onTriggered: {
advanced.slider.maximumValue = model.maxLevel
advanced.slider.value = model.level
advanced.details.text = model.devData
advanced.info.text = model.name
advanced.myType = model.type
advanced.myIdx = model.idx
stack.push(advanced)
}
},
Action {
iconName: "history"
},
Action {
iconName: (model.favorite) ? "starred" : "non-starred"
}
]
} // trailingActions
Row {
id: currentDev
anchors.centerIn: parent
spacing: units.gu(1)
// Switches actions
property var switchOn: baseDomoticzUrl+"/json.htm?type=command&param=switchlight&idx="+idx+"&switchcmd=On"
property var switchOff: baseDomoticzUrl+"/json.htm?type=command&param=switchlight&idx="+idx+"&switchcmd=Off"
Icon {
visible: ((currentPage != 2)&&(type != "temperature"))
width: units.gu(5)
height: units.gu(5)
name: myFct.getDeviceIconName (type, is.checked)
color: myFct.getDeviceIconColor(type, is.checked)
}
Icon {
visible: ((type == 'temperature')||(currentPage==2))
width: units.gu(5)
height: units.gu(5)
source: "../assets/temp.svg"
color: myFct.getTemperatureColor(temperature)
}
Rectangle {
width: units.gu(28)
height: units.gu(5)
Text { anchors.centerIn: parent; text: name; font.pointSize: units.gu(1.4) ; width: parent.width }
}
Rectangle {
width: units.gu(11)
height: units.gu(5)
Switch { id: is; visible: (currentPage == 1); anchors.centerIn: parent; checked: (status == "Off") ? false : true
onClicked: (checked) ? apiFct.callRequest(currentDev.switchOn) : apiFct.callRequest(currentDev.switchOff)
}
Text { visible: (currentPage == 2); anchors.centerIn: parent; text: temperature+" °C"; font.pointSize: units.gu(1.4); font.bold: true}
Text { visible: (currentPage == 3); anchors.centerIn: parent; text: meteoData ; font.pointSize: units.gu(1.4)}
Text { visible: (currentPage == 4); anchors.centerIn: parent; text: devData ; font.pointSize: units.gu(1.4)}
} // Rectangle : type specific field
} // Row
} // ListItem
} // Component : delegate
UbuntuListView {
id: testlist
anchors.fill: parent
currentIndex: -1
model: ListModel { id: devModel }
delegate: devDelegate
pullToRefresh {
id: refresher
enabled: true
onRefresh: apiFct.getDevices(currentUrl, true)
}
} // UbuntuListView
} // Rectangle : List of switches
Footer {id: foot}
Rectangle { // Logs
visible: debug
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: units.gu(1.5)
height: units.gu(30)
width: parent.width
color: UbuntuColors.porcelain
TextArea {
id: message
text: ""
wrapMode: Text.WordWrap
readOnly: true
width: parent.width
height: parent.height
} // TextArea
} // Rectangle : Logs
// Function used to refresh page content depending on the data type expected
function refresh(pageIndex) {
currentPage = pageIndex
switch (pageIndex) {
case 0:
header.title = i18n.tr('Dashboard')
currentUrl = dashboardUrl
break
case 1:
header.title = i18n.tr('Switches')
currentUrl = switchesUrl
break
case 2:
header.title = i18n.tr('Temperature')
currentUrl = temperatureUrl
break
case 3:
header.title = i18n.tr('Weather')
currentUrl = weatherUrl
break
case 4:
header.title = i18n.tr('Utility')
currentUrl = utilityUrl
break
}
apiFct.getDevices(currentUrl, false)
}
// Utility functions
Functions {id: myFct}
Requests {id: apiFct}
} // Page
import QtQuick 2.4
import QtQuick.Layouts 1.1
import Ubuntu.Components 1.3
Rectangle { // PageList (footer)
id: footer
property var maxNbPages: 4
anchors.bottom: parent.bottom
anchors.left: parent.left
border.color: UbuntuColors.ash
border.width: 5
width: parent.width
height: units.gu(7)
Row {
anchors.fill: parent
// anchors.centerIn: parent
// anchors.verticalCenterOffset: swipe.dragging ? swipe.distance : 0
// spacing: units.gu(0.6)
Rectangle {
height: parent.height
width: parent.width / (maxNbPages +1)
color: (currentPage == 0) ? UbuntuColors.blue : UbuntuColors.porcelain
Icon{ anchors.centerIn: parent; width: parent.height-40; height: parent.height-40; name: "starred"}
MouseArea {anchors.fill: parent; onClicked: refresh(0)}
}
Rectangle {
height: parent.height
width: parent.width / (maxNbPages +1)
color: (currentPage == 1) ? UbuntuColors.blue : UbuntuColors.porcelain
Icon{ anchors.centerIn: parent; width: parent.height-40; height: parent.height-40; name: "torch-off"}
MouseArea {anchors.fill: parent; onClicked: refresh(1)}
}
Rectangle {
height: parent.height
width: parent.width / (maxNbPages +1)
color: (currentPage == 2) ? UbuntuColors.blue : UbuntuColors.porcelain
Icon{ anchors.centerIn: parent; width: parent.height-40; height: parent.height-40; source: "../assets/temp.svg"}
MouseArea {anchors.fill: parent; onClicked: refresh(2)}
}
Rectangle {
height: parent.height
width: parent.width / (maxNbPages +1)
color: (currentPage == 3) ? UbuntuColors.blue : UbuntuColors.porcelain
Icon{ anchors.centerIn: parent; width: parent.height-40; height: parent.height-40; name: "weather-few-clouds-symbolic"}
MouseArea {anchors.fill: parent; onClicked: refresh(3)}
}
Rectangle {
height: parent.height
width: parent.width / (maxNbPages +1)
color: (currentPage == 4) ? UbuntuColors.blue : UbuntuColors.porcelain