├── .gitignore ├── LICENSE.GPL3 ├── README.md ├── android ├── AndroidManifest.xml ├── appicon1024.png ├── appicon256.png ├── appicon512.png ├── apptheme.xml ├── build.gradle ├── feature_graphic.png ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── gradlew.upstream └── res │ ├── drawable-hdpi │ ├── icon.png │ ├── splash.xml │ └── splashimage.png │ ├── drawable-ldpi │ └── icon.png │ ├── drawable-mdpi │ └── icon.png │ └── values │ └── libs.xml ├── appicon.svg ├── berrylan.pro ├── clipboardhelper.cpp ├── clipboardhelper.h ├── components ├── BerryLanHeader.qml ├── BerryLanItemDelegate.qml ├── BerryLanPage.qml ├── ColorIcon.qml ├── HelpPage.qml ├── StatusView.qml └── WaitView.qml ├── fonts ├── Montserrat │ ├── Montserrat-Black.ttf │ ├── Montserrat-BlackItalic.ttf │ ├── Montserrat-Bold.ttf │ ├── Montserrat-BoldItalic.ttf │ ├── Montserrat-ExtraBold.ttf │ ├── Montserrat-ExtraBoldItalic.ttf │ ├── Montserrat-ExtraLight.ttf │ ├── Montserrat-ExtraLightItalic.ttf │ ├── Montserrat-Italic.ttf │ ├── Montserrat-Light.ttf │ ├── Montserrat-LightItalic.ttf │ ├── Montserrat-Medium.ttf │ ├── Montserrat-MediumItalic.ttf │ ├── Montserrat-Regular.ttf │ ├── Montserrat-SemiBold.ttf │ ├── Montserrat-SemiBoldItalic.ttf │ ├── Montserrat-Thin.ttf │ ├── Montserrat-ThinItalic.ttf │ └── OFL.txt ├── Open_Sans │ └── LICENSE.txt └── Rajdhani │ ├── OFL.txt │ ├── Rajdhani-Bold.ttf │ ├── Rajdhani-Light.ttf │ ├── Rajdhani-Medium.ttf │ ├── Rajdhani-Regular.ttf │ └── Rajdhani-SemiBold.ttf ├── images ├── .directory ├── back.svg ├── bluetooth.svg ├── eye.svg ├── github.svg ├── help.svg ├── link.svg ├── next.svg ├── nymea.svg ├── refresh.svg ├── settings.svg ├── wifi-0.svg ├── wifi-100.svg ├── wifi-33.svg ├── wifi-66.svg └── wifi.svg ├── ios ├── AppIcon.svg ├── AppIcons.xcassets │ └── AppIcon.appiconset │ │ ├── AppIcon1024x1024.png │ │ ├── AppIcon167x167.png │ │ ├── AppIcon20x20.png │ │ ├── AppIcon20x20@2x.png │ │ ├── AppIcon20x20@3x.png │ │ ├── AppIcon29x29.png │ │ ├── AppIcon29x29@2x.png │ │ ├── AppIcon29x29@3x.png │ │ ├── AppIcon40x40.png │ │ ├── AppIcon40x40@2x.png │ │ ├── AppIcon40x40@3x.png │ │ ├── AppIcon60x60@2x.png │ │ ├── AppIcon60x60@3x.png │ │ ├── AppIcon76x76@2x.png │ │ └── Contents.json ├── Info.plist.in ├── LaunchImage-iOS7@2x.png ├── LaunchScreen1.xib └── exportappicons.sh ├── logo.svg ├── main.cpp ├── main.qml ├── permissionhelper.cpp ├── permissionhelper.h ├── permissionhelperandroid.cpp ├── permissionhelperandroid.h ├── permissionhelperios.cpp ├── permissionhelperios.h ├── permissionhelperios.mm ├── qml.qrc ├── qtquickcontrols2.conf ├── splash.svg ├── styles ├── Button.qml ├── TextField.qml ├── berrylanbusyindicator.cpp └── berrylanbusyindicator.h ├── translations ├── berrylan-bg.ts ├── berrylan-cs.ts ├── berrylan-de_DE.ts ├── berrylan-en.ts ├── berrylan-en_US.ts ├── berrylan-es.ts ├── berrylan-fr.ts ├── berrylan-hu.ts ├── berrylan-it.ts ├── berrylan-ko.ts ├── berrylan-nl.ts └── berrylan-pt.ts ├── version.txt └── wifisetup ├── bluetoothdevice.cpp ├── bluetoothdevice.h ├── bluetoothdeviceinfo.cpp ├── bluetoothdeviceinfo.h ├── bluetoothdeviceinfos.cpp ├── bluetoothdeviceinfos.h ├── bluetoothdiscovery.cpp ├── bluetoothdiscovery.h ├── btwifisetup.cpp ├── btwifisetup.h ├── wirelessaccesspoint.cpp ├── wirelessaccesspoint.h ├── wirelessaccesspoints.cpp ├── wirelessaccesspoints.h ├── wirelessaccesspointsproxy.cpp └── wirelessaccesspointsproxy.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | translations/*.qm 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BerryLan 2 | 3 | **Raspberry Pi WIFI setup** 4 | 5 | Get your headless Raspian into your WIFI without the Console 6 | 7 | ![BerryLan](https://berrylan.app/assets/gif/overview.gif) 8 | 9 | ## Download & installation 10 | 11 | You can setup the wireless LAN of your headless Raspberry PI in just three steps. 12 | 13 | #### Etch the image 14 | 15 | Download the BerryLan flavoured [Raspbian image](https://downloads.nymea.io/images/raspberrypi/latest) and flash the SD Card. We recommend Etcher to do that. 16 | 17 | #### Power on 18 | 19 | Insert the SD Card and power on your Raspberry Pi. All you need is your Raspberry and a power supply. 20 | 21 | #### Get the App 22 | 23 | Install the BerryLan iOS or Android App and follow the instructions. 24 | That's it, have fun! 25 | 26 | ## Features 27 | 28 | ### Plain Raspbian 29 | Everything is like you are used to - we just add BerryLan. 30 | 31 | #### IP Address 32 | The app displays you the IP Address at the end of the setup process. 33 | 34 | #### Instant Feedback 35 | 36 | The app tells you if there might be an issue with the WLAN. 37 | 38 | ## Licensing 39 | 40 | BerryLan, being a nymea tool, follows the nymea license model (dual-licensed GPLv3 and nymea commercial). 41 | For more informations please visit https://www.nymea.io/documentation/overview/license 42 | 43 | ## Installation on a plain Raspbian 44 | 45 | Add the nymea repository to your system: 46 | 47 | echo -e "deb http://repository.nymea.io $(lsb_release -s -c) main" | sudo tee /etc/apt/sources.list.d/nymea.list 48 | sudo wget -O /etc/apt/trusted.gpg.d/nymea.gpg https://repository.nymea.io/nymea.gpg 49 | 50 | Install the dependencies: 51 | 52 | sudo apt-get update 53 | sudo apt-get install nymea-networkmanager dirmngr 54 | 55 | Disable dhcpcd: 56 | 57 | sudo systemctl disable dhcpcd 58 | reboot 59 | 60 | Thats it! Have fun with BerryLan! 61 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 68 | 69 | 70 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /android/appicon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/appicon1024.png -------------------------------------------------------------------------------- /android/appicon256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/appicon256.png -------------------------------------------------------------------------------- /android/appicon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/appicon512.png -------------------------------------------------------------------------------- /android/apptheme.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | jcenter() 15 | google() 16 | } 17 | } 18 | 19 | apply plugin: 'com.android.application' 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | } 24 | 25 | android { 26 | /******************************************************* 27 | * The following variables: 28 | * - androidBuildToolsVersion, 29 | * - androidCompileSdkVersion 30 | * - qt5AndroidDir - holds the path to qt android files 31 | * needed to build any Qt application 32 | * on Android. 33 | * 34 | * are defined in gradle.properties file. This file is 35 | * updated by QtCreator and androiddeployqt tools. 36 | * Changing them manually might break the compilation! 37 | *******************************************************/ 38 | 39 | compileSdkVersion androidCompileSdkVersion.toInteger() 40 | 41 | buildToolsVersion androidBuildToolsVersion 42 | 43 | sourceSets { 44 | main { 45 | manifest.srcFile 'AndroidManifest.xml' 46 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] 47 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] 48 | res.srcDirs = [qt5AndroidDir + '/res', 'res'] 49 | resources.srcDirs = ['src'] 50 | renderscript.srcDirs = ['src'] 51 | assets.srcDirs = ['assets'] 52 | jniLibs.srcDirs = ['libs'] 53 | } 54 | } 55 | 56 | lintOptions { 57 | abortOnError false 58 | } 59 | 60 | defaultConfig { 61 | resConfigs "en", "de" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /android/feature_graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/feature_graphic.png -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Feb 20 10:43:22 EST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BASEDIR=$(dirname "$0") 4 | BERRYLAN_VERSION=`cat $BASEDIR/../version.txt | head -n 1` 5 | BERRYLAN_VERSION_CODE=`cat $BASEDIR/../version.txt | head -n 2 | tail -n 1` 6 | echo "Setting version to $BERRYLAN_VERSION ($BERRYLAN_VERSION_CODE)" 7 | sed -i "s/android:versionName=\"[0-9\.a-zA-Z_]*\"/android:versionName=\"$BERRYLAN_VERSION\"/" AndroidManifest.xml 8 | sed -i "s/android:versionCode=\"[0-9]*\"/android:versionCode=\"$BERRYLAN_VERSION_CODE\"/" AndroidManifest.xml 9 | ./gradlew.upstream $@ 10 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS=-Xmx1024m -Dfile.encoding=UTF-8 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/gradlew.upstream: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="-Xmx1024m -Dfile.encoding=UTF-8" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /android/res/drawable-hdpi/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/res/drawable-hdpi/splashimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/res/drawable-hdpi/splashimage.png -------------------------------------------------------------------------------- /android/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /android/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/android/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /android/res/values/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://download.qt.io/ministro/android/qt5/qt-5.9 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /berrylan.pro: -------------------------------------------------------------------------------- 1 | QT += quick bluetooth svg quickcontrols2 2 | QT += webview 3 | CONFIG += c++11 4 | 5 | # The following define makes your compiler emit warnings if you use 6 | # any feature of Qt which as been marked deprecated (the exact warnings 7 | # depend on your compiler). Please consult the documentation of the 8 | # deprecated API in order to know how to port your code away from it. 9 | DEFINES += QT_DEPRECATED_WARNINGS 10 | 11 | # read version info from version.txt 12 | VERSION_INFO=$$cat(version.txt) 13 | APP_VERSION=$$member(VERSION_INFO, 0) 14 | APP_REVISION=$$member(VERSION_INFO, 1) 15 | 16 | # You can also make your code fail to compile if you use deprecated APIs. 17 | # In order to do so, uncomment the following line. 18 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 19 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 20 | 21 | SOURCES += \ 22 | clipboardhelper.cpp \ 23 | main.cpp \ 24 | permissionhelper.cpp \ 25 | wifisetup/btwifisetup.cpp \ 26 | wifisetup/bluetoothdevice.cpp \ 27 | wifisetup/bluetoothdeviceinfo.cpp \ 28 | wifisetup/bluetoothdeviceinfos.cpp \ 29 | wifisetup/bluetoothdiscovery.cpp \ 30 | wifisetup/wirelessaccesspoints.cpp \ 31 | wifisetup/wirelessaccesspoint.cpp \ 32 | wifisetup/wirelessaccesspointsproxy.cpp \ 33 | 34 | 35 | HEADERS += \ 36 | clipboardhelper.h \ 37 | permissionhelper.h \ 38 | wifisetup/btwifisetup.h \ 39 | wifisetup/bluetoothdevice.h \ 40 | wifisetup/bluetoothdeviceinfo.h \ 41 | wifisetup/bluetoothdeviceinfos.h \ 42 | wifisetup/bluetoothdiscovery.h \ 43 | wifisetup/wirelessaccesspoints.h \ 44 | wifisetup/wirelessaccesspoint.h \ 45 | wifisetup/wirelessaccesspointsproxy.h \ 46 | 47 | 48 | RESOURCES += qml.qrc 49 | 50 | # Additional import path used to resolve QML modules in Qt Creator's code model 51 | QML_IMPORT_PATH = 52 | 53 | # Additional import path used to resolve QML modules just for Qt Quick Designer 54 | QML_DESIGNER_IMPORT_PATH = 55 | 56 | # Default rules for deployment. 57 | qnx: target.path = /tmp/$${TARGET}/bin 58 | else: unix:!android: target.path = /opt/$${TARGET}/bin 59 | !isEmpty(target.path): INSTALLS += target 60 | 61 | android: { 62 | QT += androidextras 63 | 64 | HEADERS += permissionhelperandroid.h 65 | SOURCES += permissionhelperandroid.cpp 66 | 67 | DISTFILES += \ 68 | android/AndroidManifest.xml \ 69 | android/gradle/wrapper/gradle-wrapper.jar \ 70 | android/gradlew \ 71 | android/res/values/libs.xml \ 72 | android/build.gradle \ 73 | android/gradle/wrapper/gradle-wrapper.properties \ 74 | android/gradlew.bat 75 | 76 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 77 | QMAKE_POST_LINK += cp $$PWD/version.txt $$OUT_PWD/ 78 | } 79 | 80 | ios: { 81 | QMAKE_TARGET_BUNDLE_PREFIX = io.guh 82 | QMAKE_BUNDLE = berrylan 83 | 84 | HEADERS += permissionhelperios.h 85 | SOURCES += permissionhelperios.cpp 86 | OBJECTIVE_SOURCES += permissionhelperios.mm 87 | 88 | # Configure generated xcode project to have our bundle id 89 | xcode_product_bundle_identifier_setting.value = $${QMAKE_TARGET_BUNDLE_PREFIX}.$${QMAKE_BUNDLE} 90 | QMAKE_ASSET_CATALOGS += ios/AppIcons.xcassets 91 | plist.input = ios/Info.plist.in 92 | plist.output = $$OUT_PWD/Info.plist 93 | QMAKE_SUBSTITUTES += plist 94 | QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist 95 | OTHER_FILES += ios/Info.plist.in 96 | ios_launch_images.files += $$files(ios/LaunchImage*.png) ios/LaunchScreen1.xib 97 | QMAKE_BUNDLE_DATA += ios_launch_images 98 | 99 | ios_icon_files.files += $$files(ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon*.png) 100 | QMAKE_BUNDLE_DATA += ios_icon_files 101 | 102 | IOS_DEVELOPMENT_TEAM.name = DEVELOPMENT_TEAM 103 | IOS_DEVELOPMENT_TEAM.value = Z45PLKLTHM 104 | QMAKE_MAC_XCODE_SETTINGS += IOS_DEVELOPMENT_TEAM 105 | 106 | } 107 | 108 | TRANSLATIONS += $$files($$absolute_path(translations)/*.ts, true) 109 | # Run lrelease with the qmake run so we're ready to build 110 | system("lrelease $$TRANSLATIONS") 111 | 112 | # and add make targets for manual lupdate and lrelease runs 113 | for(ts, $$list($${SOURCES})) { ABS_SOURCES += $$absolute_path($${ts}) } 114 | for(qrc, $$list($${RESOURCES})) { ABS_RESOURCES += $$absolute_path($${qrc}) } 115 | lupdate.commands = lupdate $${ABS_SOURCES} $${ABS_RESOURCES} -ts $${TRANSLATIONS} 116 | lrelease.commands = lrelease $${TRANSLATIONS} 117 | QMAKE_EXTRA_TARGETS += lupdate lrelease 118 | -------------------------------------------------------------------------------- /clipboardhelper.cpp: -------------------------------------------------------------------------------- 1 | #include "clipboardhelper.h" 2 | 3 | #include 4 | #include 5 | 6 | ClipboardHelper::ClipboardHelper(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | QString ClipboardHelper::text() const 12 | { 13 | return QGuiApplication::clipboard()->text(); 14 | } 15 | 16 | void ClipboardHelper::setText(const QString &text) 17 | { 18 | QGuiApplication::clipboard()->setText(text); 19 | emit textChanged(); 20 | } 21 | -------------------------------------------------------------------------------- /clipboardhelper.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIPBOARDHELPER_H 2 | #define CLIPBOARDHELPER_H 3 | 4 | #include 5 | 6 | class ClipboardHelper : public QObject 7 | { 8 | Q_OBJECT 9 | Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) 10 | public: 11 | explicit ClipboardHelper(QObject *parent = nullptr); 12 | 13 | QString text() const; 14 | void setText(const QString &text); 15 | 16 | signals: 17 | void textChanged(); 18 | 19 | }; 20 | 21 | #endif // CLIPBOARDHELPER_H 22 | -------------------------------------------------------------------------------- /components/BerryLanHeader.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | 5 | ColumnLayout { 6 | id: root 7 | spacing: 0 8 | 9 | property string text 10 | 11 | property bool backButtonVisible: false 12 | property bool settingsButtonVisible: false 13 | 14 | signal backClicked() 15 | signal settingsClicked() 16 | 17 | RowLayout { 18 | Layout.margins: app.margins 19 | 20 | ColorIcon { 21 | Layout.preferredHeight: app.iconSize * .8 22 | Layout.preferredWidth: height 23 | name: "../images/back.svg" 24 | visible: root.backButtonVisible 25 | MouseArea { 26 | anchors.fill: parent 27 | onClicked: root.backClicked() 28 | } 29 | } 30 | Item { // just to keep the label centered 31 | Layout.preferredHeight: app.iconSize * .8 32 | Layout.preferredWidth: height 33 | visible: !root.backButtonVisible && root.settingsButtonVisible 34 | } 35 | Label { 36 | Layout.fillWidth: true 37 | Layout.preferredHeight: app.iconSize * .8 38 | text: root.text.toUpperCase() 39 | horizontalAlignment: Text.AlignHCenter 40 | verticalAlignment: Text.AlignVCenter 41 | font.pixelSize: app.largeFont 42 | font.family: "Rajdhani" 43 | font.weight: Font.DemiBold 44 | } 45 | Item { // just to keep the label centered 46 | Layout.preferredHeight: app.iconSize * .8 47 | Layout.preferredWidth: height 48 | visible: root.backButtonVisible && !root.settingsButtonVisible 49 | } 50 | ColorIcon { 51 | Layout.preferredHeight: app.iconSize * .8 52 | Layout.preferredWidth: height 53 | name: "../images/settings.svg" 54 | visible: root.settingsButtonVisible 55 | MouseArea { 56 | anchors.fill: parent 57 | onClicked: root.settingsClicked() 58 | } 59 | } 60 | } 61 | 62 | Rectangle { 63 | Layout.fillWidth: true 64 | Layout.preferredHeight: 2 65 | color: "#D8D8D8" 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /components/BerryLanItemDelegate.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | import QtQuick.Controls.Material 2.2 5 | 6 | ItemDelegate { 7 | id: root 8 | height: 60 9 | 10 | leftPadding: app.margins 11 | rightPadding: app.margins 12 | topPadding: 0 13 | bottomPadding: 0 14 | 15 | property string iconSource 16 | 17 | contentItem: ColumnLayout { 18 | Rectangle { 19 | Layout.fillWidth: true 20 | Layout.preferredHeight: index === 0 ? 1 : 0 21 | color: Material.foreground 22 | } 23 | 24 | RowLayout { 25 | ColorIcon { 26 | Layout.preferredHeight: app.iconSize 27 | Layout.preferredWidth: app.iconSize 28 | name: root.iconSource 29 | } 30 | 31 | Label { 32 | Layout.fillWidth: true 33 | text: root.text 34 | font.pixelSize: app.largeFont 35 | elide: Text.ElideRight 36 | } 37 | 38 | ColorIcon { 39 | Layout.preferredHeight: app.iconSize 40 | Layout.preferredWidth: app.iconSize 41 | name: "../images/next.svg" 42 | } 43 | } 44 | 45 | Rectangle { 46 | Layout.fillWidth: true 47 | Layout.preferredHeight: 1 48 | color: Material.foreground 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /components/BerryLanPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | import QtQuick.Window 2.3 5 | 6 | Page { 7 | id: root 8 | property int step: 0 9 | property bool backButtonVisible: false 10 | property bool settingsButtonVisible: false 11 | 12 | property alias content: contentItemContainer.data 13 | 14 | signal helpClicked() 15 | signal backClicked() 16 | signal settingsClicked(); 17 | 18 | header: BerryLanHeader { 19 | text: root.title 20 | backButtonVisible: root.backButtonVisible 21 | onBackClicked: root.backClicked() 22 | settingsButtonVisible: root.settingsButtonVisible 23 | onSettingsClicked: root.settingsClicked() 24 | } 25 | 26 | ColumnLayout { 27 | anchors.fill: parent 28 | 29 | StatusView { 30 | Layout.fillWidth: true 31 | step: root.step 32 | } 33 | 34 | Item { 35 | id: contentItemContainer 36 | Layout.fillWidth: true 37 | Layout.fillHeight: true 38 | } 39 | } 40 | 41 | footer: Item { 42 | id: footer 43 | height: app.iconSize * 1.5 + ((systemProductType === "ios" && Screen.height === 812) ? 10 : 0) 44 | RowLayout { 45 | anchors { top: parent.top; margins: app.margins; horizontalCenter: parent.horizontalCenter } 46 | height: app.iconSize 47 | Label { 48 | Layout.fillWidth: true 49 | Layout.preferredHeight: app.iconSize * .8 50 | text: qsTr("an open source tool by") 51 | font.pixelSize: app.smallFont 52 | horizontalAlignment: Text.AlignRight 53 | verticalAlignment: Text.AlignBottom 54 | } 55 | Image { 56 | Layout.preferredHeight: app.iconSize 57 | sourceSize.height: app.iconSize 58 | source: "../images/nymea.svg" 59 | MouseArea { 60 | anchors.fill: parent 61 | onClicked: Qt.openUrlExternally("https://nymea.io") 62 | } 63 | } 64 | Label { 65 | Layout.preferredHeight: app.iconSize * .8 66 | text: "n y m e a " 67 | font.pixelSize: app.smallFont 68 | horizontalAlignment: Text.AlignRight 69 | verticalAlignment: Text.AlignBottom 70 | } 71 | } 72 | ColorIcon { 73 | width: app.iconSize 74 | height: app.iconSize 75 | anchors { right: parent.right; top: parent.top; margins: app.margins } 76 | name: "../images/help.svg" 77 | 78 | MouseArea { 79 | anchors.fill: parent 80 | onClicked: root.helpClicked() 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /components/ColorIcon.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Canonical, Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; version 3. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | import QtQuick 2.4 18 | 19 | /*! 20 | \qmltype Icon 21 | \inqmlmodule Ubuntu.Components 0.1 22 | \ingroup ubuntu 23 | \brief The Icon component displays an icon from the icon theme. 24 | 25 | The icon theme contains a set of standard icons referred to by their name. 26 | Using icons whenever possible enhances consistency accross applications. 27 | Each icon has a name and can have different visual representations depending 28 | on the size requested. 29 | 30 | Icons can also be colorized. Setting the \l color property will make all pixels 31 | with the \l keyColor (by default #808080) colored. 32 | 33 | Example: 34 | \qml 35 | Icon { 36 | width: 64 37 | height: 64 38 | name: "search" 39 | } 40 | \endqml 41 | 42 | Example of colorization: 43 | \qml 44 | Icon { 45 | width: 64 46 | height: 64 47 | name: "search" 48 | color: UbuntuColors.warmGrey 49 | } 50 | \endqml 51 | 52 | Icon themes are created following the 53 | \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html}{Freedesktop Icon Theme Specification}. 54 | */ 55 | Item { 56 | id: icon 57 | 58 | /*! 59 | The name of the icon to display. 60 | \qmlproperty string name 61 | */ 62 | property string name 63 | 64 | /*! 65 | The color that all pixels that originally are of color \l keyColor should take. 66 | \qmlproperty color color 67 | */ 68 | property alias color: colorizedImage.keyColorOut 69 | 70 | /*! 71 | The color of the pixels that should be colorized. 72 | By default it is set to #808080. 73 | \qmlproperty color keyColor 74 | */ 75 | property alias keyColor: colorizedImage.keyColorIn 76 | 77 | property int margins: 0 78 | 79 | property alias status: image.status 80 | 81 | Image { 82 | id: image 83 | 84 | /* Necessary so that icons are not loaded before a size is set. */ 85 | property bool ready: false 86 | Component.onCompleted: ready = true 87 | 88 | anchors.fill: parent 89 | anchors.margins: parent.margins 90 | source: ready && width > 0 && height > 0 && icon.name ? icon.name : "" 91 | sourceSize { 92 | width: width 93 | height: height 94 | } 95 | cache: true 96 | visible: !colorizedImage.active 97 | } 98 | 99 | ShaderEffect { 100 | id: colorizedImage 101 | 102 | anchors.fill: parent 103 | anchors.margins: parent.margins 104 | visible: active && image.status == Image.Ready 105 | 106 | // Whether or not a color has been set. 107 | property bool active: keyColorOut != Qt.rgba(0.0, 0.0, 0.0, 0.0) 108 | 109 | property Image source: image 110 | property color keyColorOut: Qt.rgba(0.0, 0.0, 0.0, 0.0) 111 | property color keyColorIn: "black"// "#808080" 112 | property real threshold: 0.1 113 | 114 | fragmentShader: " 115 | varying highp vec2 qt_TexCoord0; 116 | uniform sampler2D source; 117 | uniform highp vec4 keyColorOut; 118 | uniform highp vec4 keyColorIn; 119 | uniform lowp float threshold; 120 | uniform lowp float qt_Opacity; 121 | void main() { 122 | lowp vec4 sourceColor = texture2D(source, qt_TexCoord0); 123 | gl_FragColor = mix(vec4(keyColorOut.rgb, 1.0) * sourceColor.a, sourceColor, step(threshold, distance(sourceColor.rgb / sourceColor.a, keyColorIn.rgb))) * qt_Opacity; 124 | }" 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /components/HelpPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | import QtWebView 1.1 5 | 6 | Page { 7 | header: BerryLanHeader { 8 | text: qsTr("About BerryLan") 9 | backButtonVisible: true 10 | onBackClicked: pageStack.pop() 11 | } 12 | 13 | WebView { 14 | anchors.fill: parent 15 | url: "https://www.berrylan.app/faq.html" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /components/StatusView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Layouts 1.3 3 | import QtQuick.Controls 2.2 4 | import BerryLan 1.0 5 | import QtQuick.Controls.Material 2.2 6 | 7 | Item { 8 | id: root 9 | implicitHeight: app.iconSize * 4 10 | 11 | property int step: 0 12 | 13 | RowLayout { 14 | anchors.centerIn: parent 15 | Rectangle { 16 | Layout.preferredWidth: app.iconSize * 1.5 17 | Layout.preferredHeight: app.iconSize * 1.5 18 | radius: height / 2 19 | color: "#D8D8D8" 20 | BusyIndicator { 21 | anchors.fill: parent 22 | anchors.margins: -6 23 | visible: step === 0 24 | } 25 | 26 | Rectangle { 27 | anchors.centerIn: parent 28 | height: root.step > 1 ? parent.height : 0 29 | width: height 30 | radius: height / 2 31 | color: "#e71d36" 32 | Behavior on height { 33 | NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } 34 | } 35 | } 36 | 37 | ColorIcon { 38 | height: app.iconSize 39 | width: app.iconSize 40 | name: "../images/bluetooth.svg" 41 | anchors.centerIn: parent 42 | color: "white" 43 | } 44 | border.width: root.step > 0 ? 3 : 0 45 | border.color: "#e71d36" 46 | 47 | MouseArea { 48 | anchors.fill: parent 49 | onClicked: root.step-- 50 | } 51 | 52 | } 53 | Rectangle { 54 | Layout.preferredWidth: app.iconSize 55 | Layout.preferredHeight: 4 56 | // color: root.step > 2 ? "#e71d36" : "#D8D8D8" 57 | color: "#D8D8D8" 58 | Rectangle { 59 | anchors.fill: parent 60 | anchors.rightMargin: root.step > 2 ? 0 : parent.width 61 | color: "#e71d36" 62 | Behavior on anchors.rightMargin { 63 | NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } 64 | } 65 | } 66 | } 67 | 68 | Rectangle { 69 | Layout.preferredWidth: app.iconSize * 1.5 70 | Layout.preferredHeight: app.iconSize * 1.5 71 | radius: height / 2 72 | // color: root.step > 4 ? "#e71d36" : "#D8D8D8" 73 | color: "#D8D8D8" 74 | 75 | BusyIndicator { 76 | anchors.fill: parent 77 | anchors.margins: -6 78 | visible: step === 3 79 | } 80 | 81 | Rectangle { 82 | anchors.centerIn: parent 83 | height: root.step > 4 ? parent.height : 0 84 | width: height 85 | radius: height / 2 86 | color: "#e71d36" 87 | Behavior on height { 88 | NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } 89 | } 90 | } 91 | ColorIcon { 92 | height: app.iconSize 93 | width: app.iconSize 94 | name: "../images/wifi.svg" 95 | anchors.centerIn: parent 96 | color: "white" 97 | } 98 | border.width: root.step > 3 ? 3 : 0 99 | border.color: "#e71d36" 100 | } 101 | Rectangle { 102 | Layout.preferredWidth: app.iconSize 103 | Layout.preferredHeight: 4 104 | // color: root.step > 5 ? "#e71d36" : "#D8D8D8" 105 | color: "#D8D8D8" 106 | Rectangle { 107 | anchors.fill: parent 108 | anchors.rightMargin: root.step > 5 ? 0 : parent.width 109 | color: "#e71d36" 110 | Behavior on anchors.rightMargin { 111 | NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } 112 | } 113 | } 114 | } 115 | Rectangle { 116 | Layout.preferredWidth: app.iconSize * 1.5 117 | Layout.preferredHeight: app.iconSize * 1.5 118 | radius: height / 2 119 | // color: root.step > 7 ? "#e71d36" : "#D8D8D8" 120 | color: "#D8D8D8" 121 | 122 | BusyIndicator { 123 | anchors.fill: parent 124 | anchors.margins: -6 125 | visible: step === 6 126 | } 127 | Rectangle { 128 | anchors.centerIn: parent 129 | height: root.step > 7 ? parent.height : 0 130 | width: height 131 | radius: height / 2 132 | color: "#e71d36" 133 | Behavior on height { 134 | NumberAnimation { duration: 150; easing.type: Easing.InOutQuad } 135 | } 136 | } 137 | ColorIcon { 138 | height: app.iconSize 139 | width: app.iconSize 140 | name: "../images/link.svg" 141 | anchors.centerIn: parent 142 | color: "white" 143 | } 144 | border.width: root.step > 6 ? 3 : 0 145 | border.color: "#e71d36" 146 | 147 | MouseArea { 148 | anchors.fill: parent 149 | onClicked: root.step++ 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /components/WaitView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | 5 | Item { 6 | id: root 7 | 8 | property string text 9 | property string buttonText 10 | 11 | signal buttonClicked() 12 | 13 | ColumnLayout { 14 | anchors.centerIn: parent 15 | width: parent.width - app.margins * 2 16 | spacing: app.margins * 4 17 | 18 | Label { 19 | Layout.fillWidth: true 20 | Layout.margins: app.margins 21 | text: root.text 22 | horizontalAlignment: Text.AlignHCenter 23 | wrapMode: Text.WordWrap 24 | font.pixelSize: app.largeFont 25 | } 26 | 27 | Button { 28 | Layout.alignment: Qt.AlignHCenter 29 | text: root.buttonText 30 | visible: root.buttonText != "" 31 | onClicked: root.buttonClicked() 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Black.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-BlackItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-BoldItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-ExtraBold.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-ExtraLight.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Italic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Light.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-LightItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Medium.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-MediumItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-SemiBold.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-Thin.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/Montserrat-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Montserrat/Montserrat-ThinItalic.ttf -------------------------------------------------------------------------------- /fonts/Montserrat/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /fonts/Rajdhani/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Indian Type Foundry (info@indiantypefoundry.com). 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /fonts/Rajdhani/Rajdhani-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Rajdhani/Rajdhani-Bold.ttf -------------------------------------------------------------------------------- /fonts/Rajdhani/Rajdhani-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Rajdhani/Rajdhani-Light.ttf -------------------------------------------------------------------------------- /fonts/Rajdhani/Rajdhani-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Rajdhani/Rajdhani-Medium.ttf -------------------------------------------------------------------------------- /fonts/Rajdhani/Rajdhani-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Rajdhani/Rajdhani-Regular.ttf -------------------------------------------------------------------------------- /fonts/Rajdhani/Rajdhani-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/fonts/Rajdhani/Rajdhani-SemiBold.ttf -------------------------------------------------------------------------------- /images/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | PreviewsShown=true 3 | Timestamp=2018,9,7,9,43,55 4 | Version=4 5 | -------------------------------------------------------------------------------- /images/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 24 | 28 | 29 | 30 | 63 | 67 | 71 | 75 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 107 | 111 | 115 | 119 | 123 | 124 | 126 | 127 | 129 | image/svg+xml 130 | 132 | 133 | 134 | 135 | 136 | 141 | 145 | 149 | 156 | 160 | 165 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /images/bluetooth.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml 46 | 48 | 51 | 52 | -------------------------------------------------------------------------------- /images/eye.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 59 | 63 | 68 | 73 | 78 | 83 | 88 | 93 | 98 | 103 | 108 | 113 | 118 | 123 | 128 | 129 | 131 | 132 | 134 | image/svg+xml 135 | 137 | 138 | 139 | 140 | 141 | 146 | 150 | 157 | 161 | 169 | 175 | 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /images/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /images/help.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 18 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /images/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /images/next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 24 | 28 | 29 | 30 | 68 | 72 | 77 | 82 | 87 | 92 | 97 | 102 | 107 | 112 | 117 | 122 | 127 | 132 | 137 | 142 | 143 | 145 | 146 | 148 | image/svg+xml 149 | 151 | 152 | 153 | 154 | 155 | 160 | 165 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /images/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /images/wifi-0.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 21 | 22 | 23 | 24 | 25 | 35 | -------------------------------------------------------------------------------- /images/wifi-100.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 21 | 22 | 23 | 24 | 25 | 33 | -------------------------------------------------------------------------------- /images/wifi-33.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 21 | 22 | 23 | 24 | 25 | 34 | -------------------------------------------------------------------------------- /images/wifi-66.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 21 | 22 | 23 | 24 | 25 | 33 | -------------------------------------------------------------------------------- /images/wifi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon1024x1024.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon167x167.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20@2x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon20x20@3x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/AppIcons.xcassets/AppIcon.appiconset/AppIcon76x76@2x.png -------------------------------------------------------------------------------- /ios/AppIcons.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "AppIcon20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "AppIcon20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "AppIcon29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "AppIcon29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "AppIcon40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "AppIcon40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "AppIcon60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "AppIcon60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "AppIcon20x20.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "AppIcon20x20@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "AppIcon29x29.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "AppIcon29x29@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "AppIcon40x40.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "AppIcon40x40@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "AppIcon76x76@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "83.5x83.5", 95 | "idiom" : "ipad", 96 | "filename" : "AppIcon167x167.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "1024x1024", 101 | "idiom" : "ios-marketing", 102 | "filename" : "AppIcon1024x1024.png", 103 | "scale" : "1x" 104 | } 105 | ], 106 | "info" : { 107 | "version" : 1, 108 | "author" : "xcode" 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /ios/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | BerryLan 7 | CFBundleExecutable 8 | berrylan 9 | CFBundleGetInfoString 10 | Created by Qt/QMake 11 | CFBundleIdentifier 12 | io.guh.berrylan 13 | CFBundleName 14 | berrylan 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $$APP_VERSION 19 | CFBundleSignature 20 | ${QMAKE_PKGINFO_TYPEINFO} 21 | CFBundleVersion 22 | $$APP_REVISION 23 | LSRequiresIPhoneOS 24 | 25 | NOTE 26 | This file was generated by Qt/QMake. 27 | UILaunchStoryboardName 28 | LaunchScreen1 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationPortraitUpsideDown 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | NSBluetoothPeripheralUsageDescription 37 | This app allows configuring WiFi on Raspberry Pi devices using a Bluetooth setup. 38 | NSBluetoothAlwaysUsageDescription 39 | This app allows configuring WiFi on Raspberry Pi devices using a Bluetooth setup. 40 | CFBundleIconFiles 41 | 42 | AppIcon29x29.png 43 | AppIcon29x29@2x.png 44 | AppIcon40x40@2x.png 45 | AppIcon60x60@2x.png 46 | AppIcon167x167.png 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ios/LaunchImage-iOS7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nymea/berrylan/998c7c4e13123b45053d519a0cac7bf4474e6455/ios/LaunchImage-iOS7@2x.png -------------------------------------------------------------------------------- /ios/LaunchScreen1.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ios/exportappicons.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function exportImage() { 4 | size=$1 5 | scaleFactor=$2 6 | echo Exporting AppIcon with size $size and scale factor $scaleFactor 7 | if [ ${scaleFactor} -ne 1 ]; then 8 | finalSize=$((size * scaleFactor)) 9 | echo final size is ${finalSize} 10 | inkscape AppIcon.svg -e AppIcons.xcassets/AppIcon.appiconset/AppIcon${size}x${size}@${scaleFactor}x.png -C -w $finalSize -h $finalSize 11 | else 12 | inkscape AppIcon.svg -e AppIcons.xcassets/AppIcon.appiconset/AppIcon${size}x${size}.png -C -w ${size} -h ${size} 13 | fi 14 | } 15 | 16 | SIZES=( 17 | "20:1" 18 | "20:2" 19 | "20:3" 20 | "29:1" 21 | "29:2" 22 | "29:3" 23 | "40:1" 24 | "40:2" 25 | "40:3" 26 | "60:2" 27 | "60:3" 28 | "76:2" 29 | "167:1" 30 | "1024:1" 31 | ) 32 | 33 | for size in "${SIZES[@]}" ; do 34 | pixels="${size%%:*}" 35 | scale="${size##*:}" 36 | exportImage $pixels $scale 37 | done 38 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef Q_OS_ANDROID 16 | #include 17 | #endif 18 | 19 | #include "wifisetup/bluetoothdiscovery.h" 20 | #include "wifisetup/btwifisetup.h" 21 | #include "wifisetup/wirelessaccesspoint.h" 22 | #include "wifisetup/wirelessaccesspoints.h" 23 | #include "wifisetup/wirelessaccesspointsproxy.h" 24 | 25 | #include "clipboardhelper.h" 26 | #include "permissionhelper.h" 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | 31 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 32 | QGuiApplication app(argc, argv); 33 | 34 | app.setApplicationName("berrylan"); 35 | app.setOrganizationName("nymea"); 36 | 37 | QCommandLineParser parser; 38 | QCommandLineOption demoOption("demo"); 39 | parser.addOption(demoOption); 40 | parser.process(app); 41 | 42 | QtWebView::initialize(); 43 | // QQuickStyle::setStyle(":/styles"); 44 | QQuickStyle::setStyle("Material"); 45 | 46 | foreach (const QFileInfo &di, QDir(":/fonts/").entryInfoList(QDir::Dirs)) { 47 | qDebug() << "Adding font path:" << di.absoluteFilePath(); 48 | foreach (const QFileInfo &fi, QDir(di.absoluteFilePath()).entryInfoList()) { 49 | qDebug() << "Adding font:" << fi.absoluteFilePath(); 50 | QFontDatabase::addApplicationFont(fi.absoluteFilePath()); 51 | } 52 | } 53 | QFont applicationFont; 54 | applicationFont.setFamily("Montserrat"); 55 | applicationFont.setCapitalization(QFont::MixedCase); 56 | applicationFont.setPixelSize(20); 57 | applicationFont.setWeight(QFont::Light); 58 | QGuiApplication::setFont(applicationFont); 59 | 60 | QTranslator qtTranslator; 61 | qtTranslator.load("qt_" + QLocale::system().name(), 62 | QLibraryInfo::location(QLibraryInfo::TranslationsPath)); 63 | app.installTranslator(&qtTranslator); 64 | 65 | QTranslator appTranslator; 66 | qDebug() << "Loading translation file:" << ":/translations/berrylan-" + QLocale::system().name(); 67 | appTranslator.load(":/translations/berrylan-" + QLocale::system().name()); 68 | app.installTranslator(&appTranslator); 69 | 70 | qmlRegisterType("BerryLan", 1, 0, "BtWiFiSetup"); 71 | qmlRegisterType("BerryLan", 1, 0, "BluetoothDiscovery"); 72 | qmlRegisterUncreatableType("BerryLan", 1, 0, "BluetoothDeviceInfos", "Get it from BluetoothDiscovery"); 73 | qmlRegisterType("BerryLan", 1, 0, "BluetoothDeviceInfosProxy"); 74 | qmlRegisterUncreatableType("BerryLan", 1, 0, "BluetoothDeviceInfo", "Get it from BluetoothDeviceInfos"); 75 | qmlRegisterUncreatableType("BerryLan", 1, 0, "WirelessAccessPoints", "Get it from NetworkManagerController"); 76 | qmlRegisterUncreatableType("BerryLan", 1, 0, "WirelessAccessPoint", "Get it from WirelessAccessPoints"); 77 | qmlRegisterType("BerryLan", 1, 0, "WirelessAccessPointsProxy"); 78 | 79 | qmlRegisterSingletonType("BerryLan", 1, 0, "PermissionHelper", PermissionHelper::permissionsHelperProvider); 80 | 81 | QQmlApplicationEngine engine; 82 | 83 | ClipboardHelper clipBoard; 84 | 85 | engine.rootContext()->setContextProperty("systemProductType", QSysInfo::productType()); 86 | engine.rootContext()->setContextProperty("clipBoard", &clipBoard); 87 | 88 | engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 89 | if (engine.rootObjects().isEmpty()) 90 | return -1; 91 | 92 | #ifdef Q_OS_ANDROID 93 | QtAndroid::hideSplashScreen(250); 94 | #endif 95 | 96 | return app.exec(); 97 | } 98 | -------------------------------------------------------------------------------- /permissionhelper.cpp: -------------------------------------------------------------------------------- 1 | #include "permissionhelper.h" 2 | 3 | #ifdef Q_OS_ANDROID 4 | #include "permissionhelperandroid.h" 5 | #elif defined(Q_OS_IOS) 6 | #include "permissionhelperios.h" 7 | #endif 8 | 9 | Q_LOGGING_CATEGORY(dcPermissionHelper, "Permissions") 10 | 11 | PermissionHelper* PermissionHelper::s_instance = nullptr; 12 | 13 | PermissionHelper *PermissionHelper::instance() 14 | { 15 | if (!s_instance) { 16 | #ifdef Q_OS_ANDROID 17 | s_instance = new PermissionHelperAndroid(); 18 | #elif defined(Q_OS_IOS) 19 | s_instance = new PermissionHelperIOS(); 20 | #else 21 | s_instance = new PermissionHelper(); 22 | #endif 23 | } 24 | return s_instance; 25 | } 26 | 27 | QObject *PermissionHelper::permissionsHelperProvider(QQmlEngine *engine, QJSEngine *scriptEngine) 28 | { 29 | Q_UNUSED(engine) 30 | Q_UNUSED(scriptEngine) 31 | return instance(); 32 | } 33 | 34 | PermissionHelper::PermissionHelper(QObject *parent) : QObject(parent) 35 | { 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /permissionhelper.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMISSIONHELPER_H 2 | #define PERMISSIONHELPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | Q_DECLARE_LOGGING_CATEGORY(dcPermissionHelper) 8 | 9 | class PermissionHelper : public QObject 10 | { 11 | Q_OBJECT 12 | Q_PROPERTY(PermissionStatus localNetworkPermission READ localNetworkPermission NOTIFY localNetworkPermissionChanged) 13 | Q_PROPERTY(PermissionStatus bluetoothPermission READ bluetoothPermission NOTIFY bluetoothPermissionChanged) 14 | Q_PROPERTY(PermissionStatus foregroundLocationPermission READ foregroundLocationPermission NOTIFY foregroundLocationPermissionChanged) 15 | Q_PROPERTY(PermissionStatus backgroundLocationPermission READ backgroundLocationPermission NOTIFY backgroundLocationPermissionChanged) 16 | Q_PROPERTY(PermissionStatus notificationsPermission READ notificationsPermission NOTIFY notificationsPermissionChanged) 17 | 18 | public: 19 | enum Permission { 20 | PermissionNone = 0x00, 21 | PermissionLocalNetwork = 0x01, 22 | PermissionBluetooth = 0x02, 23 | PermissionForegroundLocation = 0x04, 24 | PermissionBackgroundLocation = 0x08, 25 | PermissionNotifications = 0x10 26 | }; 27 | Q_ENUM(Permission) 28 | Q_DECLARE_FLAGS(Permissions, Permission) 29 | Q_FLAG(Permissions) 30 | 31 | enum PermissionStatus { 32 | PermissionStatusNotDetermined, 33 | PermissionStatusGranted, 34 | PermissionStatusDenied, 35 | }; 36 | Q_ENUM(PermissionStatus) 37 | 38 | static QObject* permissionsHelperProvider(QQmlEngine *engine, QJSEngine *scriptEngine); 39 | static PermissionHelper* instance(); 40 | virtual ~PermissionHelper() override = default; 41 | 42 | virtual PermissionStatus localNetworkPermission() const { return PermissionStatusGranted; } 43 | virtual PermissionStatus bluetoothPermission() const { return PermissionStatusGranted; } 44 | virtual PermissionStatus foregroundLocationPermission() const { return PermissionStatusGranted; } 45 | virtual PermissionStatus backgroundLocationPermission() const { return PermissionStatusGranted; } 46 | virtual PermissionStatus notificationsPermission() const { return PermissionStatusGranted; } 47 | 48 | Q_INVOKABLE virtual void requestPermission(Permission permission) { Q_UNUSED(permission) } 49 | Q_INVOKABLE virtual void openPermissionSettings() {} 50 | 51 | signals: 52 | void localNetworkPermissionChanged(); 53 | void bluetoothPermissionChanged(); 54 | void foregroundLocationPermissionChanged(); 55 | void backgroundLocationPermissionChanged(); 56 | void notificationsPermissionChanged(); 57 | 58 | protected: 59 | explicit PermissionHelper(QObject *parent = nullptr); 60 | 61 | private: 62 | static PermissionHelper *s_instance; 63 | }; 64 | 65 | #endif // PERMISSIONHELPER_H 66 | -------------------------------------------------------------------------------- /permissionhelperandroid.cpp: -------------------------------------------------------------------------------- 1 | #include "permissionhelperandroid.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static QHash permissionMap = { 9 | {PermissionHelper::PermissionBluetooth, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}}, 10 | {PermissionHelper::PermissionForegroundLocation, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}}, 11 | {PermissionHelper::PermissionBackgroundLocation, {"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_BACKGROUND_LOCATION"}} 12 | }; 13 | 14 | PermissionHelperAndroid::PermissionHelperAndroid(QObject *parent) : PermissionHelper(parent) 15 | { 16 | qCDebug(dcPermissionHelper()) << "Creating Permission helper" << this; 17 | 18 | connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){ 19 | if (state == Qt::ApplicationActive) { 20 | emit bluetoothPermissionChanged(); 21 | emit foregroundLocationPermissionChanged(); 22 | emit backgroundLocationPermissionChanged(); 23 | } 24 | }); 25 | } 26 | 27 | PermissionHelperAndroid::~PermissionHelperAndroid() 28 | { 29 | qCDebug(dcPermissionHelper()) << "Destroying Permission helper" << this; 30 | } 31 | 32 | PermissionHelper::PermissionStatus PermissionHelperAndroid::bluetoothPermission() const 33 | { 34 | return permission(PermissionHelper::PermissionBluetooth); 35 | } 36 | 37 | void PermissionHelperAndroid::requestPermission(PermissionHelper::Permission permission) 38 | { 39 | qCDebug(dcPermissionHelper()) << "Requesting"; 40 | m_requestedPermissions.append(permission); 41 | QtAndroid::requestPermissions({permissionMap.value(permission)}, &permissionResultCallback); 42 | } 43 | 44 | void PermissionHelperAndroid::openPermissionSettings() 45 | { 46 | qCDebug(dcPermissionHelper()) << "Opening permission settings"; 47 | 48 | QAndroidJniObject settingsAction = QAndroidJniObject::getStaticObjectField("android/provider/Settings", "ACTION_APPLICATION_DETAILS_SETTINGS"); 49 | 50 | QAndroidJniObject packageName = QtAndroid::androidActivity().callObjectMethod("getPackageName", "()Ljava/lang/String;"); 51 | QString packageUri = QString("package:%1").arg(packageName.toString()); 52 | QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", QAndroidJniObject::fromString(packageUri).object()); 53 | 54 | jint flag = QAndroidJniObject::getStaticField("android/content/Intent", "FLAG_ACTIVITY_NEW_TASK"); 55 | 56 | QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;Landroid/net/Uri;)V", settingsAction.object(), uri.object()); 57 | intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("android.intent.category.DEFAULT").object()); 58 | intent.callObjectMethod("addFlags", "(I)Landroid/content/Intent;", flag); 59 | 60 | QtAndroid::androidActivity().callMethod("startActivity", "(Landroid/content/Intent;)V", intent.object()); 61 | } 62 | 63 | PermissionHelper::PermissionStatus PermissionHelperAndroid::permission(PermissionHelper::Permission permission) const 64 | { 65 | PermissionStatus status = PermissionStatusGranted; 66 | QStringList androidPermissions = permissionMap.value(permission); 67 | foreach (const QString androidPermission, androidPermissions) { 68 | qCDebug(dcPermissionHelper()) << "Checking permission:" << androidPermission; 69 | qCDebug(dcPermissionHelper()) << "checked:" << m_requestedPermissions; 70 | qCDebug(dcPermissionHelper()) << "Done"; 71 | if (QtAndroid::checkPermission(androidPermission) == QtAndroid::PermissionResult::Denied) { 72 | if (m_requestedPermissions.contains(permission)) { 73 | return PermissionStatusDenied; 74 | } 75 | status = PermissionStatusNotDetermined; 76 | } 77 | } 78 | return status; 79 | } 80 | 81 | void PermissionHelperAndroid::permissionResultCallback(const QtAndroid::PermissionResultMap &results) 82 | { 83 | // qCDebug(dcPermissionHelper()) << "Permission result callback" << results; 84 | foreach (const QString &key, results.keys()) { 85 | qCDebug(dcPermissionHelper()) << "Permission result:" << key << (results.value(key) == QtAndroid::PermissionResult::Granted); 86 | } 87 | 88 | emit PermissionHelper::instance()->bluetoothPermissionChanged(); 89 | emit PermissionHelper::instance()->foregroundLocationPermissionChanged(); 90 | emit PermissionHelper::instance()->backgroundLocationPermissionChanged(); 91 | } 92 | -------------------------------------------------------------------------------- /permissionhelperandroid.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMISSIONHELPERANDROID_H 2 | #define PERMISSIONHELPERANDROID_H 3 | 4 | #include "permissionhelper.h" 5 | 6 | #include 7 | 8 | class PermissionHelperAndroid : public PermissionHelper 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit PermissionHelperAndroid(QObject *parent = nullptr); 13 | ~PermissionHelperAndroid() override; 14 | 15 | PermissionStatus bluetoothPermission() const override; 16 | 17 | void requestPermission(PermissionHelper::Permission permission) override; 18 | void openPermissionSettings() override; 19 | signals: 20 | 21 | private: 22 | PermissionStatus permission(PermissionHelper::Permission permission) const; 23 | static void permissionResultCallback(const QtAndroid::PermissionResultMap &results); 24 | 25 | QList m_requestedPermissions; 26 | 27 | }; 28 | 29 | #endif // PERMISSIONHELPERANDROID_H 30 | -------------------------------------------------------------------------------- /permissionhelperios.cpp: -------------------------------------------------------------------------------- 1 | #include "permissionhelperios.h" 2 | 3 | PermissionHelperIOS::PermissionHelperIOS(QObject *parent) : PermissionHelper(parent) 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /permissionhelperios.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMISSIONHELPERIOS_H 2 | #define PERMISSIONHELPERIOS_H 3 | 4 | #include "permissionhelper.h" 5 | 6 | #if __OBJC__ 7 | @class CBCentralManager; 8 | #else 9 | typedef void CBCentralManager; 10 | #endif 11 | 12 | 13 | class PermissionHelperIOS : public PermissionHelper 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit PermissionHelperIOS(QObject *parent = nullptr); 18 | 19 | PermissionStatus bluetoothPermission() const override; 20 | 21 | 22 | void requestPermission(Permission permission) override; 23 | void openPermissionSettings() override; 24 | 25 | CBCentralManager *m_bluetoothManager = nullptr; 26 | }; 27 | 28 | #endif // PERMISSIONHELPERIOS_H 29 | -------------------------------------------------------------------------------- /permissionhelperios.mm: -------------------------------------------------------------------------------- 1 | #include "permissionhelperios.h" 2 | 3 | #import 4 | #import 5 | 6 | @interface BluetoothManagerDelegate: NSObject 7 | @end 8 | @implementation BluetoothManagerDelegate 9 | - (void)centralManagerDidUpdateState:(CBCentralManager *)manager { 10 | qDebug() << "Bt cental manager state update!"; 11 | emit PermissionHelper::instance()->bluetoothPermissionChanged(); 12 | ((PermissionHelperIOS*)PermissionHelperIOS::instance())->m_bluetoothManager = nil; 13 | } 14 | @end 15 | 16 | PermissionHelper::PermissionStatus PermissionHelperIOS::bluetoothPermission() const 17 | { 18 | // iOS 13.0 would have an api but it's more complicated and also deprecated... Ignoring... 19 | if (@available(iOS 13.1, *)) { 20 | switch (CBCentralManager.authorization) { 21 | case CBManagerAuthorizationAllowedAlways: 22 | case CBManagerAuthorizationRestricted: 23 | return PermissionStatusGranted; 24 | case CBManagerAuthorizationDenied: 25 | return PermissionStatusDenied; 26 | case CBManagerAuthorizationNotDetermined: 27 | return PermissionStatusNotDetermined; 28 | } 29 | } 30 | // Before iOS 13, Bluetooth permissions are not required 31 | return PermissionStatusGranted; 32 | } 33 | 34 | void PermissionHelperIOS::openPermissionSettings() 35 | { 36 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; 37 | } 38 | 39 | 40 | void PermissionHelperIOS::requestPermission(PermissionHelper::Permission permission) 41 | { 42 | if (permission == PermissionHelper::PermissionBluetooth) { 43 | // Instantiating a Bluetooth manager just trigger the popup... 44 | // This will leak, but would be only once... 45 | BluetoothManagerDelegate *delegate = [[BluetoothManagerDelegate alloc] init]; 46 | m_bluetoothManager = [[CBCentralManager alloc] initWithDelegate:delegate queue:nil]; 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | components/BerryLanHeader.qml 5 | components/ColorIcon.qml 6 | components/StatusView.qml 7 | images/bluetooth.svg 8 | images/github.svg 9 | images/help.svg 10 | images/link.svg 11 | images/refresh.svg 12 | images/wifi.svg 13 | components/BerryLanPage.qml 14 | images/eye.svg 15 | images/nymea.svg 16 | fonts/Rajdhani/Rajdhani-Bold.ttf 17 | fonts/Rajdhani/Rajdhani-Light.ttf 18 | fonts/Rajdhani/Rajdhani-Medium.ttf 19 | fonts/Rajdhani/Rajdhani-Regular.ttf 20 | fonts/Rajdhani/Rajdhani-SemiBold.ttf 21 | components/WaitView.qml 22 | components/BerryLanItemDelegate.qml 23 | images/next.svg 24 | styles/TextField.qml 25 | qtquickcontrols2.conf 26 | styles/Button.qml 27 | fonts/Montserrat/Montserrat-Black.ttf 28 | fonts/Montserrat/Montserrat-BlackItalic.ttf 29 | fonts/Montserrat/Montserrat-Bold.ttf 30 | fonts/Montserrat/Montserrat-BoldItalic.ttf 31 | fonts/Montserrat/Montserrat-ExtraBold.ttf 32 | fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf 33 | fonts/Montserrat/Montserrat-ExtraLight.ttf 34 | fonts/Montserrat/Montserrat-ExtraLightItalic.ttf 35 | fonts/Montserrat/Montserrat-Italic.ttf 36 | fonts/Montserrat/Montserrat-Light.ttf 37 | fonts/Montserrat/Montserrat-LightItalic.ttf 38 | fonts/Montserrat/Montserrat-Medium.ttf 39 | fonts/Montserrat/Montserrat-MediumItalic.ttf 40 | fonts/Montserrat/Montserrat-Regular.ttf 41 | fonts/Montserrat/Montserrat-SemiBold.ttf 42 | fonts/Montserrat/Montserrat-SemiBoldItalic.ttf 43 | fonts/Montserrat/Montserrat-Thin.ttf 44 | fonts/Montserrat/Montserrat-ThinItalic.ttf 45 | fonts/Montserrat/OFL.txt 46 | components/HelpPage.qml 47 | images/back.svg 48 | translations/berrylan-de_DE.qm 49 | translations/berrylan-bg.qm 50 | translations/berrylan-it.qm 51 | images/wifi-33.svg 52 | images/wifi-0.svg 53 | images/wifi-66.svg 54 | images/wifi-100.svg 55 | images/settings.svg 56 | 57 | 58 | -------------------------------------------------------------------------------- /qtquickcontrols2.conf: -------------------------------------------------------------------------------- 1 | [Controls] 2 | Style=Material 3 | FallbackStyle=Material 4 | -------------------------------------------------------------------------------- /styles/Button.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Templates 2.2 as T 3 | import QtQuick.Controls 2.2 4 | import QtQuick.Controls.impl 2.2 5 | import QtQuick.Controls.Material 2.2 6 | import QtQuick.Controls.Material.impl 2.2 7 | 8 | T.Button { 9 | id: control 10 | 11 | implicitWidth: Math.max(background ? background.implicitWidth : 0, 12 | contentItem.implicitWidth + leftPadding + rightPadding) 13 | implicitHeight: Math.max(background ? background.implicitHeight : 0, 14 | contentItem.implicitHeight + topPadding + bottomPadding) 15 | baselineOffset: contentItem.y + contentItem.baselineOffset 16 | 17 | // external vertical padding is 6 (to increase touch area) 18 | padding: 12 19 | leftPadding: padding - 4 20 | rightPadding: padding - 4 21 | 22 | Material.elevation: flat ? control.down || control.hovered ? 2 : 0 23 | : control.down ? 8 : 2 24 | Material.background: flat ? "transparent" : undefined 25 | 26 | contentItem: Text { 27 | text: control.text 28 | font: control.font 29 | color: app.primaryColor 30 | horizontalAlignment: Text.AlignHCenter 31 | verticalAlignment: Text.AlignVCenter 32 | elide: Text.ElideRight 33 | } 34 | 35 | // TODO: Add a proper ripple/ink effect for mouse/touch input and focus state 36 | background: Rectangle { 37 | implicitWidth: 64 38 | implicitHeight: 40 39 | 40 | // external vertical padding is 6 (to increase touch area) 41 | y: 6 42 | width: parent.width 43 | height: parent.height - 12 44 | radius: 8 45 | color: !control.enabled ? control.Material.hintTextColor : 46 | control.flat && control.highlighted ? control.Material.accentColor : 47 | control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground 48 | 49 | PaddedRectangle { 50 | y: parent.height - 4 51 | width: parent.width 52 | height: 4 53 | radius: 2 54 | topPadding: -2 55 | clip: true 56 | visible: control.checkable && (!control.highlighted || control.flat) 57 | color: control.checked && control.enabled ? control.Material.accentColor : control.Material.secondaryTextColor 58 | } 59 | 60 | // The layer is disabled when the button color is transparent so you can do 61 | // Material.background: "transparent" and get a proper flat button without needing 62 | // to set Material.elevation as well 63 | layer.enabled: control.enabled && control.Material.buttonColor.a > 0 64 | layer.effect: ElevationEffect { 65 | elevation: control.Material.elevation 66 | } 67 | 68 | Ripple { 69 | clipRadius: 2 70 | width: parent.width 71 | height: parent.height 72 | pressed: control.pressed 73 | anchor: control 74 | active: control.down || control.visualFocus || control.hovered 75 | color: control.Material.rippleColor 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /styles/TextField.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Templates 2.2 as T 3 | import QtQuick.Controls 2.2 4 | import QtQuick.Controls.impl 2.2 5 | import QtQuick.Controls.Material 2.2 6 | import QtQuick.Controls.Material.impl 2.2 7 | 8 | T.TextField { 9 | id: control 10 | 11 | implicitWidth: Math.max(background ? background.implicitWidth : 0, 12 | placeholderText ? placeholder.implicitWidth + leftPadding + rightPadding : 0) 13 | || contentWidth + leftPadding + rightPadding 14 | implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, 15 | background ? background.implicitHeight : 0, 16 | placeholder.implicitHeight + topPadding + bottomPadding) 17 | 18 | topPadding: 10 19 | bottomPadding: 10 20 | leftPadding: 10 21 | rightPadding: 10 22 | 23 | color: enabled ? Material.foreground : Material.hintTextColor 24 | selectionColor: Material.accentColor 25 | selectedTextColor: Material.primaryHighlightedTextColor 26 | verticalAlignment: TextInput.AlignVCenter 27 | 28 | cursorDelegate: CursorDelegate { } 29 | 30 | PlaceholderText { 31 | id: placeholder 32 | x: control.leftPadding 33 | y: control.topPadding 34 | width: control.width - (control.leftPadding + control.rightPadding) 35 | height: control.height - (control.topPadding + control.bottomPadding) 36 | text: control.placeholderText 37 | font: control.font 38 | color: control.Material.hintTextColor 39 | verticalAlignment: control.verticalAlignment 40 | elide: Text.ElideRight 41 | visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) 42 | 43 | } 44 | 45 | background: Rectangle { 46 | y: control.height - height - control.bottomPadding / 2 47 | implicitWidth: 120 48 | height: control.activeFocus ? 2 : 1 49 | color: control.activeFocus ? control.Material.accentColor : control.Material.hintTextColor 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /styles/berrylanbusyindicator.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2017 The Qt Company Ltd. 4 | ** Contact: http://www.qt.io/licensing/ 5 | ** 6 | ** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL3$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and The Qt Company. For licensing terms 14 | ** and conditions see http://www.qt.io/terms-conditions. For further 15 | ** information use the contact form at http://www.qt.io/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 3 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 3 requirements 23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. 24 | ** 25 | ** GNU General Public License Usage 26 | ** Alternatively, this file may be used under the terms of the GNU 27 | ** General Public License version 2.0 or later as published by the Free 28 | ** Software Foundation and appearing in the file LICENSE.GPL included in 29 | ** the packaging of this file. Please review the following information to 30 | ** ensure the GNU General Public License version 2.0 requirements will be 31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. 32 | ** 33 | ** $QT_END_LICENSE$ 34 | ** 35 | ****************************************************************************/ 36 | #ifndef QQUICKMATERIALBUSYINDICATOR_P_H 37 | #define QQUICKMATERIALBUSYINDICATOR_P_H 38 | // 39 | // W A R N I N G 40 | // ------------- 41 | // 42 | // This file is not part of the Qt API. It exists purely as an 43 | // implementation detail. This header file may change from version to 44 | // version without notice, or even be removed. 45 | // 46 | // We mean it. 47 | // 48 | #include 49 | #include 50 | 51 | class BerryLanBusyIndicator : public QQuickItem 52 | { 53 | Q_OBJECT 54 | Q_PROPERTY(QColor color READ color WRITE setColor FINAL) 55 | Q_PROPERTY(bool running READ isRunning WRITE setRunning FINAL) 56 | Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth FINAL) 57 | public: 58 | explicit BerryLanBusyIndicator(QQuickItem *parent = nullptr); 59 | QColor color() const; 60 | void setColor(QColor color); 61 | bool isRunning() const; 62 | void setRunning(bool running); 63 | int penWidth() const; 64 | void setPenWidth(int penWidth); 65 | int elapsed() const; 66 | protected: 67 | void itemChange(ItemChange change, const ItemChangeData &data) override; 68 | QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; 69 | private: 70 | int m_elapsed = 0; 71 | QColor m_color = Qt::black; 72 | int m_penWidth = -1; 73 | }; 74 | 75 | #endif // QQUICKMATERIALBUSYINDICATOR_P_H 76 | -------------------------------------------------------------------------------- /translations/berrylan-cs.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | 16 | 17 | 18 | Connected to %1 19 | 20 | 21 | 22 | Disconnecting from %1... 23 | 24 | 25 | 26 | Discovering services of %1... 27 | 28 | 29 | 30 | %1 connected and discovered. 31 | 32 | 33 | 34 | %1 disconnected. 35 | 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /translations/berrylan-en.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | 16 | 17 | 18 | Connected to %1 19 | 20 | 21 | 22 | Disconnecting from %1... 23 | 24 | 25 | 26 | Discovering services of %1... 27 | 28 | 29 | 30 | %1 connected and discovered. 31 | 32 | 33 | 34 | %1 disconnected. 35 | 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /translations/berrylan-en_US.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | 16 | 17 | 18 | Connected to %1 19 | 20 | 21 | 22 | Disconnecting from %1... 23 | 24 | 25 | 26 | Discovering services of %1... 27 | 28 | 29 | 30 | %1 connected and discovered. 31 | 32 | 33 | 34 | %1 disconnected. 35 | 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /translations/berrylan-hu.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | 16 | 17 | 18 | Connected to %1 19 | 20 | 21 | 22 | Disconnecting from %1... 23 | 24 | 25 | 26 | Discovering services of %1... 27 | 28 | 29 | 30 | %1 connected and discovered. 31 | 32 | 33 | 34 | %1 disconnected. 35 | 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /translations/berrylan-nl.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | Verbinden met %1... 16 | 17 | 18 | Connected to %1 19 | Verbonden met %1 20 | 21 | 22 | Disconnecting from %1... 23 | Afmelden van %1... 24 | 25 | 26 | Discovering services of %1... 27 | Diensten ontdekken van %1... 28 | 29 | 30 | %1 connected and discovered. 31 | %1 verbonden en gevonden. 32 | 33 | 34 | %1 disconnected. 35 | %1 afgemeld. 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /translations/berrylan-pt.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BerryLanPage 6 | 7 | an open source tool by 8 | 9 | 10 | 11 | 12 | BluetoothDevice 13 | 14 | Connecting to %1... 15 | 16 | 17 | 18 | Connected to %1 19 | 20 | 21 | 22 | Disconnecting from %1... 23 | 24 | 25 | 26 | Discovering services of %1... 27 | 28 | 29 | 30 | %1 connected and discovered. 31 | 32 | 33 | 34 | %1 disconnected. 35 | 36 | 37 | 38 | 39 | HelpPage 40 | 41 | About BerryLan 42 | 43 | 44 | 45 | 46 | main 47 | 48 | BerryLan 49 | 50 | 51 | 52 | Sorry, the password is wrong. 53 | 54 | 55 | 56 | Try again 57 | 58 | 59 | 60 | Devices 61 | 62 | 63 | 64 | Network 65 | 66 | 67 | 68 | Login 69 | 70 | 71 | 72 | Connecting 73 | 74 | 75 | 76 | Connected 77 | 78 | 79 | 80 | Bluetooth doesn't seem to be available on this device. BerryLan requires a working Bluetooth connection. 81 | 82 | 83 | 84 | Bluetooth seems to be disabled. Please enable Bluetooth on your device in order to use BerryLan. 85 | 86 | 87 | 88 | Searching for your 89 | Raspberry Pi 90 | 91 | 92 | 93 | Connecting to your Raspberry Pi 94 | 95 | 96 | 97 | OK 98 | 99 | 100 | 101 | Connecting the Raspberry Pi to %1 102 | 103 | 104 | 105 | Thanks for using BerryLan! 106 | 107 | 108 | 109 | Open Access Point 110 | 111 | 112 | 113 | Name 114 | 115 | 116 | 117 | Password 118 | 119 | 120 | 121 | Opening access point "%1" on the Raspberry Pi 122 | 123 | 124 | 125 | Access point name: %1 126 | 127 | 128 | 129 | IP Address: %1 130 | 131 | 132 | 133 | IP address copied to clipboard. 134 | 135 | 136 | 137 | Close access point 138 | 139 | 140 | 141 | Berrylan doesn't seem to have permissions to scan for Bluetooth devices. 142 | 143 | 144 | 145 | Bluetooth access has been denied. Please grant permissions in the settings. 146 | 147 | 148 | 149 | Request permission 150 | 151 | 152 | 153 | Open settings 154 | 155 | 156 | 157 | Hidden network 158 | 159 | 160 | 161 | Settings 162 | 163 | 164 | 165 | BerryLan tries to detect the network setup capabilities on the devices it finds. However, old installations might not suport this. Disable filtering if your devices aren't being found. 166 | 167 | 168 | 169 | Filtering enabled 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 1.0.51 2 | 51 3 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdevice.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #include "bluetoothdevice.h" 32 | 33 | BluetoothDevice::BluetoothDevice(const QBluetoothDeviceInfo &deviceInfo, QObject *parent) : 34 | QObject(parent), 35 | m_deviceInfo(deviceInfo), 36 | m_connected(false) 37 | { 38 | m_controller = QLowEnergyController::createCentral(deviceInfo, this); 39 | // m_controller->setRemoteAddressType(QLowEnergyController::PublicAddress); 40 | 41 | connect(m_controller, &QLowEnergyController::connected, this, &BluetoothDevice::onConnected); 42 | connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothDevice::onDisconnected); 43 | connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothDevice::onDeviceStateChanged); 44 | connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onDeviceError(QLowEnergyController::Error))); 45 | 46 | connect(m_controller, SIGNAL(discoveryFinished()), this, SIGNAL(serviceDiscoveryFinished())); 47 | } 48 | 49 | QString BluetoothDevice::name() const 50 | { 51 | return m_deviceInfo.name(); 52 | } 53 | 54 | QBluetoothAddress BluetoothDevice::address() const 55 | { 56 | return m_deviceInfo.address(); 57 | } 58 | 59 | QString BluetoothDevice::addressString() const 60 | { 61 | #ifdef Q_OS_MAC 62 | // On OS X and iOS we do not have addresses, 63 | // only unique UUIDs generated by Core Bluetooth. 64 | return m_deviceInfo.deviceUuid().toString(); 65 | #else 66 | return m_deviceInfo.address().toString(); 67 | #endif 68 | } 69 | 70 | bool BluetoothDevice::connected() const 71 | { 72 | return m_connected; 73 | } 74 | 75 | QString BluetoothDevice::statusText() const 76 | { 77 | return m_statusText; 78 | } 79 | 80 | void BluetoothDevice::connectDevice() 81 | { 82 | if (m_controller->state() != QLowEnergyController::UnconnectedState) { 83 | qDebug() << "Controller in state:" << m_controller->state() << "Not connecting..."; 84 | return; 85 | } 86 | qDebug() << "QLoweEnergyController connecting..."; 87 | m_controller->connectToDevice(); 88 | } 89 | 90 | void BluetoothDevice::disconnectDevice() 91 | { 92 | m_controller->disconnectFromDevice(); 93 | } 94 | 95 | void BluetoothDevice::setConnected(const bool &connected) 96 | { 97 | m_connected = connected; 98 | emit connectedChanged(); 99 | } 100 | 101 | void BluetoothDevice::setStatusText(const QString &statusText) 102 | { 103 | m_statusText = statusText; 104 | emit statusTextChanged(); 105 | } 106 | 107 | QLowEnergyController *BluetoothDevice::controller() 108 | { 109 | return m_controller; 110 | } 111 | 112 | void BluetoothDevice::onConnected() 113 | { 114 | qDebug() << "BluetoothDevice: Connected to" << name() << addressString(); 115 | m_controller->discoverServices(); 116 | } 117 | 118 | void BluetoothDevice::onDisconnected() 119 | { 120 | qWarning() << "BluetoothDevice: Disconnected from" << name() << addressString(); 121 | setConnected(false); 122 | setStatusText("Disconnected from " + name()); 123 | } 124 | 125 | void BluetoothDevice::onDeviceError(const QLowEnergyController::Error &error) 126 | { 127 | qWarning() << "BluetoothDevice: Error" << name() << addressString() << ": " << error << m_controller->errorString(); 128 | setConnected(false); 129 | } 130 | 131 | void BluetoothDevice::onDeviceStateChanged(const QLowEnergyController::ControllerState &state) 132 | { 133 | switch (state) { 134 | case QLowEnergyController::ConnectingState: 135 | qDebug() << "BluetoothDevice: Connecting..."; 136 | setStatusText(QString(tr("Connecting to %1...").arg(name()))); 137 | break; 138 | case QLowEnergyController::ConnectedState: 139 | qDebug() << "BluetoothDevice: Connected!"; 140 | setStatusText(QString(tr("Connected to %1").arg(name()))); 141 | break; 142 | case QLowEnergyController::ClosingState: 143 | qDebug() << "BluetoothDevice: Connection: Closing..."; 144 | setStatusText(QString(tr("Disconnecting from %1...").arg(name()))); 145 | break; 146 | case QLowEnergyController::DiscoveringState: 147 | qDebug() << "BluetoothDevice: Discovering..."; 148 | setStatusText(QString(tr("Discovering services of %1...").arg(name()))); 149 | break; 150 | case QLowEnergyController::DiscoveredState: 151 | qDebug() << "BluetoothDevice: Discovered!"; 152 | setStatusText(QString(tr("%1 connected and discovered.").arg(name()))); 153 | setConnected(true); 154 | break; 155 | case QLowEnergyController::UnconnectedState: 156 | qDebug() << "BluetoothDevice: Not connected."; 157 | setStatusText(QString(tr("%1 disconnected.").arg(name()))); 158 | break; 159 | default: 160 | qDebug() << "BluetoothDevice: Unhandled state entered:" << state; 161 | break; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdevice.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef BLUETOOTHDEVICE_H 32 | #define BLUETOOTHDEVICE_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | class BluetoothDevice : public QObject 42 | { 43 | Q_OBJECT 44 | Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) 45 | Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged) 46 | 47 | public: 48 | explicit BluetoothDevice(const QBluetoothDeviceInfo &deviceInfo, QObject *parent = nullptr); 49 | 50 | QString name() const; 51 | QBluetoothAddress address() const; 52 | QString addressString() const; 53 | bool connected() const; 54 | QString statusText() const; 55 | 56 | Q_INVOKABLE void connectDevice(); 57 | Q_INVOKABLE void disconnectDevice(); 58 | 59 | private: 60 | QBluetoothDeviceInfo m_deviceInfo; 61 | QLowEnergyController *m_controller; 62 | bool m_connected; 63 | QString m_statusText; 64 | 65 | void setConnected(const bool &connected); 66 | 67 | protected: 68 | QLowEnergyController *controller(); 69 | void setStatusText(const QString &statusText); 70 | 71 | signals: 72 | void connectedChanged(); 73 | void serviceDiscoveryFinished(); 74 | 75 | void statusTextChanged(); 76 | 77 | private slots: 78 | void onConnected(); 79 | void onDisconnected(); 80 | 81 | void onDeviceError(const QLowEnergyController::Error &error); 82 | void onDeviceStateChanged(const QLowEnergyController::ControllerState &state); 83 | 84 | }; 85 | 86 | #endif // BLUETOOTHDEVICE_H 87 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdeviceinfo.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #include "bluetoothdeviceinfo.h" 32 | 33 | #include 34 | 35 | BluetoothDeviceInfo::BluetoothDeviceInfo() 36 | { 37 | } 38 | 39 | BluetoothDeviceInfo::BluetoothDeviceInfo(const QBluetoothDeviceInfo &deviceInfo) 40 | { 41 | m_deviceInfo = deviceInfo; 42 | } 43 | 44 | BluetoothDeviceInfo::~BluetoothDeviceInfo() 45 | { 46 | qDebug() << "~BluetoothDeviceInfo"; 47 | } 48 | 49 | QString BluetoothDeviceInfo::address() const 50 | { 51 | return m_deviceInfo.address().toString(); 52 | } 53 | 54 | QString BluetoothDeviceInfo::name() const 55 | { 56 | return m_deviceInfo.name(); 57 | } 58 | 59 | bool BluetoothDeviceInfo::isLowEnergy() const 60 | { 61 | return m_deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration; 62 | } 63 | 64 | int BluetoothDeviceInfo::signalStrength() const 65 | { 66 | return (m_deviceInfo.rssi() + 100) * 2; 67 | } 68 | 69 | QBluetoothDeviceInfo BluetoothDeviceInfo::bluetoothDeviceInfo() const 70 | { 71 | return m_deviceInfo; 72 | } 73 | 74 | void BluetoothDeviceInfo::setBluetoothDeviceInfo(const QBluetoothDeviceInfo &deviceInfo) 75 | { 76 | m_deviceInfo = QBluetoothDeviceInfo(deviceInfo); 77 | emit deviceChanged(); 78 | } 79 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdeviceinfo.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef BLUETOOTHDEVICEINFO_H 32 | #define BLUETOOTHDEVICEINFO_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | class BluetoothDeviceInfo : public QObject 40 | { 41 | Q_OBJECT 42 | Q_PROPERTY(QString name READ name NOTIFY deviceChanged) 43 | Q_PROPERTY(QString address READ address NOTIFY deviceChanged) 44 | Q_PROPERTY(int signalStrength READ signalStrength NOTIFY deviceChanged) 45 | 46 | public: 47 | BluetoothDeviceInfo(); 48 | BluetoothDeviceInfo(const QBluetoothDeviceInfo &deviceInfo); 49 | ~BluetoothDeviceInfo(); 50 | 51 | QString address() const; 52 | QString name() const; 53 | bool isLowEnergy() const; 54 | int signalStrength() const; 55 | 56 | QBluetoothDeviceInfo bluetoothDeviceInfo() const; 57 | void setBluetoothDeviceInfo(const QBluetoothDeviceInfo &deviceInfo); 58 | 59 | signals: 60 | void deviceChanged(); 61 | 62 | private: 63 | QBluetoothDeviceInfo m_deviceInfo; 64 | 65 | }; 66 | 67 | #endif // BLUETOOTHDEVICEINFO_H 68 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdeviceinfos.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef BLUETOOTHDEVICEINFOS_H 32 | #define BLUETOOTHDEVICEINFOS_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "bluetoothdeviceinfo.h" 40 | 41 | class BluetoothDeviceInfos : public QAbstractListModel 42 | { 43 | Q_OBJECT 44 | Q_PROPERTY(int count READ rowCount NOTIFY countChanged) 45 | public: 46 | enum BluetoothDeviceInfoRole { 47 | BluetoothDeviceInfoRoleName = Qt::DisplayRole, 48 | BluetoothDeviceInfoRoleAddress, 49 | BluetoothDeviceInfoRoleLe, 50 | BluetoothDeviceInfoRoleSignalStrength 51 | }; 52 | Q_ENUM(BluetoothDeviceInfoRole) 53 | 54 | explicit BluetoothDeviceInfos(QObject *parent = nullptr); 55 | 56 | QList deviceInfos(); 57 | 58 | int rowCount(const QModelIndex & parent = QModelIndex()) const; 59 | QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; 60 | 61 | int count() const; 62 | Q_INVOKABLE BluetoothDeviceInfo *get(int index) const; 63 | 64 | void addBluetoothDeviceInfo(BluetoothDeviceInfo *deviceInfo); 65 | Q_INVOKABLE void clearModel(); 66 | 67 | signals: 68 | void countChanged(); 69 | 70 | protected: 71 | QHash roleNames() const; 72 | 73 | private: 74 | QList m_deviceInfos; 75 | }; 76 | 77 | class BluetoothDeviceInfosProxy: public QSortFilterProxyModel 78 | { 79 | Q_OBJECT 80 | Q_PROPERTY(BluetoothDeviceInfos* model READ model WRITE setModel NOTIFY modelChanged) 81 | Q_PROPERTY(int count READ rowCount NOTIFY countChanged) 82 | 83 | // Workaround for allowing particular names, even if they'd fail the filters below (used for legacy compatibility) 84 | Q_PROPERTY(QStringList nameWhitelist READ nameWhitelist WRITE setNameWhitelist NOTIFY nameWhitelistChanged) 85 | 86 | Q_PROPERTY(bool filterForLowEnergy READ filterForLowEnergy WRITE setFilterForLowEnergy NOTIFY filterForLowEnergyChanged) 87 | Q_PROPERTY(QString filterForServiceUUID READ filterForServiceUUID WRITE setFilterForServiceUUID NOTIFY filterForServiceUUIDChanged) 88 | Q_PROPERTY(QString filterForName READ filterForName WRITE setFilterForName NOTIFY filterForNameChanged) 89 | public: 90 | BluetoothDeviceInfosProxy(QObject *parent = nullptr); 91 | 92 | BluetoothDeviceInfos* model() const; 93 | void setModel(BluetoothDeviceInfos *model); 94 | 95 | QStringList nameWhitelist() const; 96 | void setNameWhitelist(const QStringList &nameWhitelist); 97 | 98 | bool filterForLowEnergy() const; 99 | void setFilterForLowEnergy(bool filterForLowEnergy); 100 | 101 | QString filterForServiceUUID() const; 102 | void setFilterForServiceUUID(const QString &filterForServiceUUID); 103 | 104 | QString filterForName() const; 105 | void setFilterForName(const QString &name); 106 | 107 | Q_INVOKABLE BluetoothDeviceInfo* get(int index) const; 108 | 109 | signals: 110 | void modelChanged(); 111 | void countChanged(); 112 | void nameWhitelistChanged(); 113 | void filterForLowEnergyChanged(); 114 | void filterForServiceUUIDChanged(); 115 | void filterForNameChanged(); 116 | 117 | protected: 118 | bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; 119 | 120 | private: 121 | BluetoothDeviceInfos *m_model = nullptr; 122 | QStringList m_nameWhitelist; 123 | bool m_filterForLowEnergy = false; 124 | QUuid m_filterForServiceUUID; 125 | QString m_filterForName; 126 | }; 127 | 128 | #endif // BLUETOOTHDEVICEINFOS_H 129 | -------------------------------------------------------------------------------- /wifisetup/bluetoothdiscovery.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef BLUETOOTHDISCOVERY_H 32 | #define BLUETOOTHDISCOVERY_H 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "bluetoothdeviceinfos.h" 39 | 40 | class BluetoothDiscovery : public QObject 41 | { 42 | Q_OBJECT 43 | Q_PROPERTY(bool bluetoothAvailable READ bluetoothAvailable NOTIFY bluetoothAvailableChanged) 44 | Q_PROPERTY(bool bluetoothEnabled READ bluetoothEnabled WRITE setBluetoothEnabled NOTIFY bluetoothEnabledChanged) 45 | Q_PROPERTY(bool discoveryEnabled READ discoveryEnabled WRITE setDiscoveryEnabled NOTIFY discoveryEnabledChanged) 46 | Q_PROPERTY(bool discovering READ discovering NOTIFY discoveringChanged) 47 | Q_PROPERTY(BluetoothDeviceInfos *deviceInfos READ deviceInfos CONSTANT) 48 | 49 | public: 50 | explicit BluetoothDiscovery(QObject *parent = nullptr); 51 | 52 | bool bluetoothAvailable() const; 53 | bool bluetoothEnabled() const; 54 | void setBluetoothEnabled(bool bluetoothEnabled); 55 | 56 | bool discoveryEnabled() const; 57 | void setDiscoveryEnabled(bool discoveryEnabled); 58 | 59 | bool discovering() const; 60 | 61 | BluetoothDeviceInfos *deviceInfos(); 62 | 63 | signals: 64 | void bluetoothAvailableChanged(bool bluetoothAvailable); 65 | void bluetoothEnabledChanged(bool bluetoothEnabled); 66 | void discoveryEnabledChanged(bool discoveryEnabled); 67 | void discoveringChanged(); 68 | 69 | private slots: 70 | void onBluetoothHostModeChanged(const QBluetoothLocalDevice::HostMode &hostMode); 71 | void deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo); 72 | void discoveryFinished(); 73 | void discoveryCancelled(); 74 | void onError(const QBluetoothDeviceDiscoveryAgent::Error &error); 75 | 76 | private slots: 77 | void start(); 78 | void stop(); 79 | 80 | private: 81 | QBluetoothLocalDevice *m_localDevice = nullptr; 82 | QBluetoothDeviceDiscoveryAgent *m_discoveryAgent = nullptr; 83 | BluetoothDeviceInfos *m_deviceInfos; 84 | 85 | bool m_bluetoothAvailable = false; 86 | #ifdef Q_OS_IOS 87 | bool m_bluetoothEnabled = false; 88 | #endif 89 | bool m_discoveryEnabled = false; 90 | }; 91 | 92 | #endif // BLUETOOTHDISCOVERY_H 93 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspoint.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #include "wirelessaccesspoint.h" 32 | 33 | #include 34 | 35 | WirelessAccessPoint::WirelessAccessPoint(QObject *parent): 36 | QObject(parent) 37 | { 38 | 39 | } 40 | 41 | QString WirelessAccessPoint::ssid() const 42 | { 43 | return m_ssid; 44 | } 45 | 46 | void WirelessAccessPoint::setSsid(const QString ssid) 47 | { 48 | if (m_ssid == ssid) 49 | return; 50 | 51 | m_ssid = ssid; 52 | emit ssidChanged(m_ssid); 53 | } 54 | 55 | QString WirelessAccessPoint::macAddress() const 56 | { 57 | return m_macAddress; 58 | } 59 | 60 | void WirelessAccessPoint::setMacAddress(const QString &macAddress) 61 | { 62 | if (m_macAddress == macAddress) 63 | return; 64 | 65 | m_macAddress = macAddress; 66 | emit macAddressChanged(m_macAddress); 67 | } 68 | 69 | QString WirelessAccessPoint::hostAddress() const 70 | { 71 | return m_hostAddress; 72 | } 73 | 74 | void WirelessAccessPoint::setHostAddress(const QString &hostAddress) 75 | { 76 | if (m_hostAddress == hostAddress) 77 | return; 78 | 79 | m_hostAddress = hostAddress; 80 | emit hostAddressChanged(m_hostAddress); 81 | } 82 | 83 | int WirelessAccessPoint::signalStrength() const 84 | { 85 | return m_signalStrength; 86 | } 87 | 88 | void WirelessAccessPoint::setSignalStrength(int signalStrength) 89 | { 90 | if (m_signalStrength == signalStrength) 91 | return; 92 | 93 | m_signalStrength = signalStrength; 94 | emit signalStrengthChanged(m_signalStrength); 95 | } 96 | 97 | bool WirelessAccessPoint::isProtected() const 98 | { 99 | return m_isProtected; 100 | } 101 | 102 | void WirelessAccessPoint::setProtected(bool isProtected) 103 | { 104 | if (m_isProtected == isProtected) 105 | return; 106 | 107 | m_isProtected = isProtected; 108 | emit isProtectedChanged(m_isProtected); 109 | 110 | } 111 | 112 | double WirelessAccessPoint::frequency() const 113 | { 114 | return m_frequency; 115 | } 116 | 117 | void WirelessAccessPoint::setFrequency(double frequency) 118 | { 119 | if (!qFuzzyCompare(m_frequency,frequency)) { 120 | m_frequency = frequency; 121 | emit frequencyChanged(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspoint.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef WIRELESSACCESSPOINT_H 32 | #define WIRELESSACCESSPOINT_H 33 | 34 | #include 35 | #include 36 | 37 | class WirelessAccessPoint : public QObject 38 | { 39 | Q_OBJECT 40 | Q_PROPERTY(QString ssid READ ssid NOTIFY ssidChanged) 41 | Q_PROPERTY(QString macAddress READ macAddress NOTIFY macAddressChanged) 42 | Q_PROPERTY(QString hostAddress READ hostAddress NOTIFY hostAddressChanged) 43 | Q_PROPERTY(int signalStrength READ signalStrength NOTIFY signalStrengthChanged) 44 | Q_PROPERTY(bool isProtected READ isProtected NOTIFY isProtectedChanged) 45 | Q_PROPERTY(double frequency READ frequency NOTIFY frequencyChanged) 46 | 47 | public: 48 | WirelessAccessPoint(QObject *parent = nullptr); 49 | 50 | QString ssid() const; 51 | void setSsid(const QString ssid); 52 | 53 | QString macAddress() const; 54 | void setMacAddress(const QString &macAddress); 55 | 56 | QString hostAddress() const; 57 | void setHostAddress(const QString &hostAddress); 58 | 59 | int signalStrength() const; 60 | void setSignalStrength(int signalStrength); 61 | 62 | bool isProtected() const; 63 | void setProtected(bool isProtected); 64 | 65 | double frequency() const; 66 | void setFrequency(double frequency); 67 | 68 | signals: 69 | void ssidChanged(const QString &ssid); 70 | void macAddressChanged(const QString &macAddress); 71 | void hostAddressChanged(const QString &hostAddress); 72 | void signalStrengthChanged(int signalStrength); 73 | void isProtectedChanged(bool isProtected); 74 | void frequencyChanged(); 75 | 76 | private: 77 | QString m_ssid; 78 | QString m_macAddress; 79 | QString m_hostAddress; 80 | int m_signalStrength = 0; 81 | bool m_isProtected = false; 82 | double m_frequency = 0; 83 | }; 84 | 85 | #endif // WIRELESSACCESSPOINT_H 86 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspoints.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #include "wirelessaccesspoints.h" 32 | #include "wirelessaccesspoint.h" 33 | 34 | #include 35 | 36 | WirelessAccessPoints::WirelessAccessPoints(QObject *parent) : QAbstractListModel(parent) 37 | { 38 | 39 | } 40 | 41 | QList WirelessAccessPoints::wirelessAccessPoints() 42 | { 43 | return m_wirelessAccessPoints; 44 | } 45 | 46 | void WirelessAccessPoints::setWirelessAccessPoints(QList wirelessAccessPoints) 47 | { 48 | beginResetModel(); 49 | 50 | // Delete all 51 | qDeleteAll(m_wirelessAccessPoints); 52 | m_wirelessAccessPoints.clear(); 53 | 54 | m_wirelessAccessPoints = wirelessAccessPoints; 55 | endResetModel(); 56 | 57 | emit countChanged(); 58 | } 59 | 60 | int WirelessAccessPoints::rowCount(const QModelIndex &parent) const 61 | { 62 | Q_UNUSED(parent) 63 | return m_wirelessAccessPoints.count(); 64 | } 65 | 66 | QVariant WirelessAccessPoints::data(const QModelIndex &index, int role) const 67 | { 68 | if (index.row() < 0 || index.row() >= m_wirelessAccessPoints.count()) 69 | return QVariant(); 70 | 71 | WirelessAccessPoint *accessPoint = m_wirelessAccessPoints.at(index.row()); 72 | switch (role) { 73 | case WirelessAccesspointRoleSsid: 74 | return accessPoint->ssid(); 75 | case WirelessAccesspointRoleMacAddress: 76 | return accessPoint->macAddress(); 77 | case WirelessAccesspointRoleHostAddress: 78 | return accessPoint->hostAddress(); 79 | case WirelessAccesspointRoleSignalStrength: 80 | return accessPoint->signalStrength(); 81 | case WirelessAccesspointRoleProtected: 82 | return accessPoint->isProtected(); 83 | case WirelessAccessPointRoleFrequency: 84 | return accessPoint->frequency(); 85 | } 86 | 87 | return QVariant(); 88 | } 89 | 90 | int WirelessAccessPoints::count() const 91 | { 92 | return m_wirelessAccessPoints.count(); 93 | } 94 | 95 | WirelessAccessPoint *WirelessAccessPoints::getAccessPoint(const QString &ssid) const 96 | { 97 | foreach (WirelessAccessPoint *accessPoint, m_wirelessAccessPoints) { 98 | if (accessPoint->ssid() == ssid) 99 | return accessPoint; 100 | } 101 | 102 | return nullptr; 103 | } 104 | 105 | WirelessAccessPoint *WirelessAccessPoints::get(int index) 106 | { 107 | if (index < 0 || index >= m_wirelessAccessPoints.count()) { 108 | return nullptr; 109 | } 110 | 111 | return m_wirelessAccessPoints.at(index); 112 | } 113 | 114 | void WirelessAccessPoints::clearModel() 115 | { 116 | beginResetModel(); 117 | qDeleteAll(m_wirelessAccessPoints); 118 | m_wirelessAccessPoints.clear(); 119 | endResetModel(); 120 | emit countChanged(); 121 | } 122 | 123 | void WirelessAccessPoints::addWirelessAccessPoint(WirelessAccessPoint *accessPoint) 124 | { 125 | accessPoint->setParent(this); 126 | 127 | beginInsertRows(QModelIndex(), m_wirelessAccessPoints.count(), m_wirelessAccessPoints.count()); 128 | qDebug() << "WirelessAccessPoints: access point added" << accessPoint->ssid() << accessPoint->macAddress(); 129 | m_wirelessAccessPoints.append(accessPoint); 130 | endInsertRows(); 131 | 132 | connect(accessPoint, &WirelessAccessPoint::signalStrengthChanged, this, [accessPoint, this]() { 133 | int idx = m_wirelessAccessPoints.indexOf(accessPoint); 134 | if (idx < 0) return; 135 | emit dataChanged(index(idx), index(idx), {WirelessAccesspointRoleSignalStrength}); 136 | }); 137 | connect(accessPoint, &WirelessAccessPoint::hostAddressChanged, this, [accessPoint, this]() { 138 | int idx = m_wirelessAccessPoints.indexOf(accessPoint); 139 | if (idx < 0) return; 140 | emit dataChanged(index(idx), index(idx), {WirelessAccesspointRoleHostAddress}); 141 | }); 142 | 143 | emit countChanged(); 144 | } 145 | 146 | void WirelessAccessPoints::removeWirelessAccessPoint(WirelessAccessPoint *accessPoint) 147 | { 148 | int index = m_wirelessAccessPoints.indexOf(accessPoint); 149 | beginRemoveRows(QModelIndex(), index, index); 150 | qDebug() << "WirelessAccessPoints: access point removed" << accessPoint->ssid() << accessPoint->macAddress(); 151 | m_wirelessAccessPoints.removeAt(index); 152 | endRemoveRows(); 153 | 154 | emit countChanged(); 155 | } 156 | 157 | QHash WirelessAccessPoints::roleNames() const 158 | { 159 | QHash roles; 160 | roles[WirelessAccesspointRoleSsid] = "ssid"; 161 | roles[WirelessAccesspointRoleMacAddress] = "macAddress"; 162 | roles[WirelessAccesspointRoleHostAddress] = "hostAddress"; 163 | roles[WirelessAccesspointRoleSignalStrength] = "signalStrength"; 164 | roles[WirelessAccesspointRoleProtected] = "protected"; 165 | roles[WirelessAccessPointRoleFrequency] = "frequency"; 166 | return roles; 167 | } 168 | 169 | 170 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspoints.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef WIRELESSACCESSPOINTS_H 32 | #define WIRELESSACCESSPOINTS_H 33 | 34 | #include 35 | #include 36 | 37 | class WirelessAccessPoint; 38 | 39 | class WirelessAccessPoints : public QAbstractListModel 40 | { 41 | Q_OBJECT 42 | Q_PROPERTY(int count READ rowCount NOTIFY countChanged) 43 | 44 | public: 45 | enum BluetoothDeviceInfoRole { 46 | WirelessAccesspointRoleSsid = Qt::DisplayRole, 47 | WirelessAccesspointRoleMacAddress, 48 | WirelessAccesspointRoleHostAddress, 49 | WirelessAccesspointRoleSignalStrength, 50 | WirelessAccesspointRoleProtected, 51 | WirelessAccessPointRoleFrequency 52 | }; 53 | 54 | explicit WirelessAccessPoints(QObject *parent = nullptr); 55 | 56 | QList wirelessAccessPoints(); 57 | void setWirelessAccessPoints(QList wirelessAccessPoints); 58 | 59 | int rowCount(const QModelIndex & parent = QModelIndex()) const; 60 | QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; 61 | 62 | int count() const; 63 | Q_INVOKABLE WirelessAccessPoint *getAccessPoint(const QString &ssid) const; 64 | Q_INVOKABLE WirelessAccessPoint *get(int index); 65 | 66 | void clearModel(); 67 | 68 | void addWirelessAccessPoint(WirelessAccessPoint *accessPoint); 69 | void removeWirelessAccessPoint(WirelessAccessPoint *accessPoint); 70 | 71 | signals: 72 | void countChanged(); 73 | 74 | protected: 75 | QHash roleNames() const; 76 | 77 | private: 78 | QList m_wirelessAccessPoints; 79 | 80 | 81 | }; 82 | 83 | #endif // WIRELESSACCESSPOINTS_H 84 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspointsproxy.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #include "wirelessaccesspointsproxy.h" 32 | 33 | #include "wirelessaccesspoint.h" 34 | #include "wirelessaccesspoints.h" 35 | 36 | #include 37 | 38 | WirelessAccessPointsProxy::WirelessAccessPointsProxy(QObject *parent) : QSortFilterProxyModel(parent) 39 | { 40 | 41 | } 42 | 43 | WirelessAccessPoints *WirelessAccessPointsProxy::accessPoints() const 44 | { 45 | return m_accessPoints; 46 | } 47 | 48 | void WirelessAccessPointsProxy::setAccessPoints(WirelessAccessPoints *accessPoints) 49 | { 50 | m_accessPoints = accessPoints; 51 | emit accessPointsChanged(); 52 | setSourceModel(m_accessPoints); 53 | connect(accessPoints, &WirelessAccessPoints::countChanged, this, &WirelessAccessPointsProxy::countChanged); 54 | setSortRole(WirelessAccessPoints::WirelessAccesspointRoleSignalStrength); 55 | sort(0, Qt::DescendingOrder); 56 | } 57 | 58 | WirelessAccessPoint *WirelessAccessPointsProxy::get(int index) const 59 | { 60 | return m_accessPoints->get(mapToSource(this->index(index, 0)).row()); 61 | } 62 | -------------------------------------------------------------------------------- /wifisetup/wirelessaccesspointsproxy.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * 3 | * Copyright 2013 - 2020, nymea GmbH 4 | * Contact: contact@nymea.io 5 | * 6 | * This file is part of nymea. 7 | * This project including source code and documentation is protected by 8 | * copyright law, and remains the property of nymea GmbH. All rights, including 9 | * reproduction, publication, editing and translation, are reserved. The use of 10 | * this project is subject to the terms of a license agreement to be concluded 11 | * with nymea GmbH in accordance with the terms of use of nymea GmbH, available 12 | * under https://nymea.io/license 13 | * 14 | * GNU General Public License Usage 15 | * Alternatively, this project may be redistributed and/or modified under the 16 | * terms of the GNU General Public License as published by the Free Software 17 | * Foundation, GNU version 3. This project is distributed in the hope that it 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 19 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 20 | * Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License along with 23 | * this project. If not, see . 24 | * 25 | * For any further details and any questions please contact us under 26 | * contact@nymea.io or see our FAQ/Licensing Information on 27 | * https://nymea.io/license/faq 28 | * 29 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30 | 31 | #ifndef WIRELESSACCESSPOINTSPROXY_H 32 | #define WIRELESSACCESSPOINTSPROXY_H 33 | 34 | #include 35 | #include 36 | 37 | class WirelessAccessPoint; 38 | class WirelessAccessPoints; 39 | 40 | class WirelessAccessPointsProxy : public QSortFilterProxyModel 41 | { 42 | Q_OBJECT 43 | Q_PROPERTY(int count READ rowCount NOTIFY countChanged) 44 | Q_PROPERTY(WirelessAccessPoints* accessPoints READ accessPoints WRITE setAccessPoints) 45 | public: 46 | explicit WirelessAccessPointsProxy(QObject *parent = nullptr); 47 | 48 | WirelessAccessPoints *accessPoints() const; 49 | void setAccessPoints(WirelessAccessPoints *accessPoints); 50 | 51 | Q_INVOKABLE WirelessAccessPoint* get(int index) const; 52 | 53 | signals: 54 | void countChanged(); 55 | void accessPointsChanged(); 56 | 57 | private: 58 | WirelessAccessPoints *m_accessPoints = nullptr; 59 | 60 | }; 61 | 62 | #endif // WIRELESSACCESSPOINTSPROXY_H 63 | --------------------------------------------------------------------------------