Initial project setup.
This commit is contained in:
commit
b56e219bcf
18 changed files with 855 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
build/
|
||||||
|
pantalaimon-arm64
|
||||||
|
pantalaimon-armhf
|
88
CMakeLists.txt
Normal file
88
CMakeLists.txt
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
|
project(pantalaimon C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
find_package(Qt5Core)
|
||||||
|
find_package(Qt5Qml)
|
||||||
|
find_package(Qt5Quick)
|
||||||
|
|
||||||
|
# Automatically create moc files
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
# Components PATH
|
||||||
|
execute_process(
|
||||||
|
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
|
||||||
|
OUTPUT_VARIABLE ARCH_TRIPLET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
set(QT_IMPORTS_DIR "lib/${ARCH_TRIPLET}")
|
||||||
|
|
||||||
|
set(PROJECT_NAME "pantalaimon")
|
||||||
|
set(FULL_PROJECT_NAME "pantalaimon.thrrgilag")
|
||||||
|
set(CMAKE_INSTALL_PREFIX /)
|
||||||
|
set(DATA_DIR /)
|
||||||
|
set(DESKTOP_FILE_NAME ${PROJECT_NAME}.desktop)
|
||||||
|
|
||||||
|
# This command figures out the target architecture for use in the manifest file
|
||||||
|
# Either via the environment variable ARCH (set by Clickable) or dpkg
|
||||||
|
if(DEFINED ENV{ARCH})
|
||||||
|
set(CLICK_ARCH "$ENV{ARCH}")
|
||||||
|
else()
|
||||||
|
execute_process(
|
||||||
|
COMMAND dpkg-architecture -qDEB_HOST_ARCH
|
||||||
|
OUTPUT_VARIABLE CLICK_ARCH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||||
|
install(FILES ${PROJECT_NAME}.apparmor DESTINATION ${DATA_DIR})
|
||||||
|
install(DIRECTORY assets DESTINATION ${DATA_DIR})
|
||||||
|
install(DIRECTORY src DESTINATION ${DATA_DIR})
|
||||||
|
|
||||||
|
install(DIRECTORY qml DESTINATION ${DATA_DIR})
|
||||||
|
# example config file for local testing
|
||||||
|
# install(FILES example.conf DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME pantalaimon.conf)
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po qml/*.qml qml/*.js)
|
||||||
|
list(APPEND I18N_SRC_FILES ${DESKTOP_FILE_NAME}.in.h)
|
||||||
|
|
||||||
|
find_program(INTLTOOL_MERGE intltool-merge)
|
||||||
|
if(NOT INTLTOOL_MERGE)
|
||||||
|
message(FATAL_ERROR "Could not find intltool-merge, please install the intltool package")
|
||||||
|
endif()
|
||||||
|
find_program(INTLTOOL_EXTRACT intltool-extract)
|
||||||
|
if(NOT INTLTOOL_EXTRACT)
|
||||||
|
message(FATAL_ERROR "Could not find intltool-extract, please install the intltool package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(${DESKTOP_FILE_NAME} ALL
|
||||||
|
COMMENT "Merging translations into ${DESKTOP_FILE_NAME}..."
|
||||||
|
COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${CMAKE_SOURCE_DIR}/${DESKTOP_FILE_NAME}.in ${DESKTOP_FILE_NAME}
|
||||||
|
COMMAND sed -i 's/${PROJECT_NAME}-//g' ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME} DESTINATION ${DATA_DIR})
|
||||||
|
|
||||||
|
# TODO: figure out how to cross compile this
|
||||||
|
install(PROGRAMS ${PROJECT_NAME}-${CLICK_ARCH} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME ${PROJECT_NAME})
|
||||||
|
|
||||||
|
add_subdirectory(po)
|
||||||
|
|
||||||
|
# Make source files visible in qtcreator
|
||||||
|
file(GLOB_RECURSE PROJECT_SRC_FILES
|
||||||
|
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
qml/*.qml
|
||||||
|
qml/*.js
|
||||||
|
src/*
|
||||||
|
*.json
|
||||||
|
*.json.in
|
||||||
|
*.apparmor
|
||||||
|
*.desktop.in
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(${PROJECT_NAME}_FILES ALL SOURCES ${PROJECT_SRC_FILES})
|
17
LICENSE
Normal file
17
LICENSE
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
Apache Software License 2.0
|
||||||
|
|
||||||
|
Copyright (c) 2020, Morgan McMillian
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
26
README.md
Normal file
26
README.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Pantalaimon
|
||||||
|
|
||||||
|
End-to-end encryption aware Matrix reverse proxy daemon for Ubuntu Touch.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Proper app icon
|
||||||
|
- [ ] Cross compile python+pantalaimon
|
||||||
|
- [ ] Fix image fetching
|
||||||
|
- [ ] Ability to verify, ingore, or blacklist devices
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
This project is not currently setup for cross building. A binary will need to
|
||||||
|
be compiled on a device for each target architecture.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
* Images (including avatars) are not fetched
|
||||||
|
* No user interaction to verify, ignore, or blacklist devices
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (C) 2020 Morgan McMillian
|
||||||
|
|
||||||
|
Licensed under the Apache Software License 2.0
|
24
assets/logo.svg
Normal file
24
assets/logo.svg
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg style="enable-background:new" xmlns="http://www.w3.org/2000/svg" height="512" viewBox="0 0 512.40002 512" width="512.4" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="a" y2="494" gradientUnits="userSpaceOnUse" x2="256" gradientTransform="matrix(1 0 0 1.076 0 -19.36)" y1="18" x1="256">
|
||||||
|
<stop style="stop-color:#eaeaea" offset="0"/>
|
||||||
|
<stop style="stop-color:#f4f4f4" offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect style="color:#000000;enable-background:accumulate;fill:url(#a)" height="512" width="512" y="0" x="0"/>
|
||||||
|
<path style="opacity:.1" d="m256 112c-79.5 0-144 64.5-144 144s64.5 144 144 144 144-64.5 144-144-64.5-144-144-144zm49.47 39.98c3.098 0.0797 6.222 0.9104 9.096 2.568 9.197 5.312 12.34 17.07 7.029 26.26-5.305 9.196-17.06 12.34-26.25 7.029-9.19-5.305-12.34-17.06-7.039-26.25 3.653-6.322 10.35-9.787 17.17-9.611zm-49.48 20.5c7.731 0 15.21 1.074 22.31 3.035 1.253 7.726 5.837 14.84 13.15 19.06 7.298 4.207 15.74 4.629 23.05 1.867 14.22 13.98 23.47 32.99 24.81 54.17l-27.39 0.4043c-2.5-28.7-26.6-51.2-55.9-51.2-8.451 0-16.47 1.88-23.65 5.225l-13.4-23.9c11.16-5.522 23.72-8.645 37.01-8.645zm-46.33 14.03 14.06 23.54c-14.44 10.16-23.88 26.95-23.88 45.95s9.437 35.78 23.88 45.94l-14.06 23.55c-16.83-11.24-29.34-28.43-34.54-48.55 6.069-4.952 9.953-12.49 9.953-20.94 0-8.451-3.884-15.99-9.953-20.94 5.201-20.12 17.72-37.3 34.54-48.55zm-51.58 50.26c10.62 0 19.22 8.608 19.22 19.23s-8.605 19.22-19.22 19.22-19.23-8.605-19.23-19.22 8.607-19.23 19.23-19.23zm153.8 24.21 27.4 0.4023c-1.348 21.18-10.6 40.19-24.81 54.17-7.31-2.762-15.75-2.347-23.05 1.867-7.309 4.227-11.89 11.34-13.15 19.06-7.104 1.967-14.58 3.041-22.31 3.041-13.29 0-25.86-3.124-37.01-8.652l13.36-23.94c7.186 3.344 15.2 5.225 23.65 5.225 29.34 0 53.41-22.49 55.93-51.18zm-7.482 60.6c6.816-0.1758 13.51 3.289 17.16 9.607 5.311 9.197 2.16 20.95-7.035 26.25-9.196 5.311-20.95 2.159-26.25-7.037-5.312-9.191-2.159-20.94 7.037-26.25 2.872-1.658 5.994-2.49 9.092-2.57z"/>
|
||||||
|
<g transform="translate(0,18)">
|
||||||
|
<path style="opacity:.3;color:#000000;enable-background:accumulate;fill:#fff" d="m256 256l-147.8 256h403.8v-256h-122.7-133.3z" transform="translate(0,-18)"/>
|
||||||
|
<path style="opacity:.15;color:#000000;enable-background:accumulate;fill:#fff" d="m0 0v512h108.2l76.4-132.3 71.4-123.7-68.9-120-0.2 0.3-78.7-136.3h-108.2z" transform="translate(0,-18)"/>
|
||||||
|
</g>
|
||||||
|
<path d="m-208.3 605.6c-7.842 0-14.55 5.029-17.32 12.19-0.0612-0.00067-0.1208 0-0.1823 0-7.088 0-12.83 6.002-12.83 13.41 0 7.404 5.746 13.41 12.83 13.41h17.5 16.33c5.155 0 9.333-4.365 9.333-9.75 0-4.543-2.974-8.363-7-9.445 0.001-0.1029 0-0.2015 0-0.3047 0-10.77-8.357-19.5-18.67-19.5z" style="stroke-width:4;color:#000000;stroke:#ccc;enable-background:accumulate;display:none;fill:#fff"/>
|
||||||
|
<path style="stroke-width:4;color:#000000;stroke:#ccc;enable-background:accumulate;display:none;fill:none" d="m288.9 828.1c-6.349 0-11.78 4.072-14.02 9.867-0.0496-0.00055-0.0978 0-0.1476 0-5.738 0-10.39 4.86-10.39 10.85 0 5.995 4.652 10.85 10.39 10.85h14.17 13.22c4.173 0 7.557-3.534 7.557-7.894 0-3.678-2.408-6.771-5.667-7.647 0.001-0.0833 0-0.1632 0-0.2467 0-8.719-6.766-15.79-15.11-15.79z"/>
|
||||||
|
<g style="display:none" transform="translate(0 -558.4)">
|
||||||
|
<path d="m166.1 576.4h179.9c145.3 0 166.1 20.74 166.1 165.9v144.2c0 145.2-20.76 165.9-166.1 165.9h-179.9c-145.3 0-166.1-20-166.1-165.5v-144.2c0-145.2 20.76-165.9 166.1-165.9z" style="stroke:#00f;fill:#00f;display:inline;fill-opacity:.08118"/>
|
||||||
|
<circle style="stroke-width:.8333;fill-opacity:.08118;color:#000000;stroke:#00f;enable-background:accumulate;display:inline;fill:#00f" cx="256" transform="matrix(1.2 0 0 1.2 -51.2 528.8)" cy="238" r="120"/>
|
||||||
|
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="272" width="272" y="678.4" x="120"/>
|
||||||
|
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="240" width="304" y="694.4" x="104"/>
|
||||||
|
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="304" width="240" y="662.4" x="136"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
5
clickable.json
Normal file
5
clickable.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"clickable_minimum_required": "6.12.2",
|
||||||
|
"builder": "cmake",
|
||||||
|
"kill": "qmlscene"
|
||||||
|
}
|
94
dev-build.sh
Executable file
94
dev-build.sh
Executable file
|
@ -0,0 +1,94 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PROJECT_DIR=~/pantalaimon-build
|
||||||
|
TMP_DIR="${PROJECT_DIR}/tmp"
|
||||||
|
|
||||||
|
VIRTENV_DIR="${PROJECT_DIR}/virtenv"
|
||||||
|
|
||||||
|
OLM_DIR="${PROJECT_DIR}/olm"
|
||||||
|
PANTALAIMON_DIR="${PROJECT_DIR}/pantalaimon"
|
||||||
|
|
||||||
|
PYTHON_VERSION_MINOR="3.7"
|
||||||
|
PYTHON_VERSION_PATCH="7"
|
||||||
|
PYTHON_VERSION="${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}"
|
||||||
|
PYTHON_DIR="${PROJECT_DIR}/python"
|
||||||
|
PYTHON_SRC_DIR="${TMP_DIR}/Python-${PYTHON_VERSION}"
|
||||||
|
PYTHON="${PYTHON_DIR}/bin/python${PYTHON_VERSION_MINOR}"
|
||||||
|
|
||||||
|
mkdir -p "${PROJECT_DIR}"
|
||||||
|
mkdir -p "${TMP_DIR}"
|
||||||
|
|
||||||
|
PACKAGES="make cmake build-essential zlibc python3-venv libffi-dev ppa-purge libssl-dev libsqlite3-dev"
|
||||||
|
|
||||||
|
PANTALAIMON_PATCH_CONTENT="
|
||||||
|
diff --git a/pantalaimon/main.py b/pantalaimon/main.py
|
||||||
|
index 896d29e..3e0fee8 100644
|
||||||
|
--- a/pantalaimon/main.py
|
||||||
|
+++ b/pantalaimon/main.py
|
||||||
|
@@ -32,6 +32,7 @@ from pantalaimon.log import logger
|
||||||
|
from pantalaimon.thread_messages import DaemonResponse
|
||||||
|
from pantalaimon.ui import UI_ENABLED
|
||||||
|
|
||||||
|
+keyring.core.set_keyring(keyring.core.load_keyring('keyring.backends.SecretService.Keyring'))
|
||||||
|
|
||||||
|
def create_dirs(data_dir, conf_dir):
|
||||||
|
try:
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "Remounting RootFS writable..."
|
||||||
|
sudo mount -o remount,rw /
|
||||||
|
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y ${PACKAGES}
|
||||||
|
|
||||||
|
if [ ! -e "${OLM_DIR}/usr/local/lib/libolm.so" ]; then
|
||||||
|
cd "${TMP_DIR}"
|
||||||
|
echo "Downloading Olm..."
|
||||||
|
wget -qO- "https://gitlab.matrix.org/matrix-org/olm/-/archive/master/olm-master.tar.gz" | tar -xz
|
||||||
|
|
||||||
|
echo "Building Olm..."
|
||||||
|
cd olm-master
|
||||||
|
cmake . -Bbuild
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
echo "Installing Olm..."
|
||||||
|
cd build
|
||||||
|
make install DESTDIR="${OLM_DIR}"
|
||||||
|
else
|
||||||
|
echo "Olm found. Skipping Olm Install..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "${PYTHON}" ]; then
|
||||||
|
echo "Downloading Python..."
|
||||||
|
cd "${TMP_DIR}"
|
||||||
|
wget -qO- "https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" | tar -xz
|
||||||
|
|
||||||
|
echo "Installing Python..."
|
||||||
|
cd "${PYTHON_SRC_DIR}"
|
||||||
|
./configure --prefix="${PYTHON_DIR}" --enable-shared
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
else
|
||||||
|
echo "Python found. Skipping Python Install..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH=${PYTHON_DIR}/lib:${OLM_DIR}/usr/local/lib:${LD_LIBRARY_PATH}
|
||||||
|
export LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
echo "Installing PyInstaller..."
|
||||||
|
${PYTHON} -m pip install --upgrade pyinstaller
|
||||||
|
|
||||||
|
echo "Installing Pantalaimon..."
|
||||||
|
CFLAGS=-I"${OLM_DIR}/usr/local/include -I${OLM_DIR}/usr/local/include" LDFLAGS="-L${OLM_DIR}/usr/local/lib" ${PYTHON} -m pip install --upgrade pantalaimon
|
||||||
|
|
||||||
|
echo "Bundling Pantalaimon..."
|
||||||
|
cd ${PROJECT_DIR}
|
||||||
|
echo "${PANTALAIMON_PATCH_CONTENT}" > main.patch
|
||||||
|
patch ${PYTHON_DIR}/lib/python${PYTHON_VERSION_MINOR}/site-packages/pantalaimon/main.py main.patch
|
||||||
|
${PYTHON_DIR}/bin/pyinstaller --onefile ${PYTHON_DIR}/bin/pantalaimon
|
||||||
|
|
||||||
|
echo "Cleaning up, reverting changes to RootFS..."
|
||||||
|
sudo apt autoremove -y ${PACKAGES}
|
||||||
|
sudo apt clean
|
||||||
|
|
6
example.conf
Normal file
6
example.conf
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[matrix.org]
|
||||||
|
Homeserver = https://matrix.org
|
||||||
|
ListenAddress = localhost
|
||||||
|
ListenPort = 8009
|
||||||
|
IgnoreVerification = True
|
||||||
|
UseKeyring = False
|
15
manifest.json.in
Normal file
15
manifest.json.in
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "pantalaimon.thrrgilag",
|
||||||
|
"description": "End-to-end encryption aware Matrix reverse proxy daemon for Ubuntu Touch",
|
||||||
|
"architecture": "@CLICK_ARCH@",
|
||||||
|
"title": "Pantalaimon UT",
|
||||||
|
"hooks": {
|
||||||
|
"pantalaimon": {
|
||||||
|
"apparmor": "pantalaimon.apparmor",
|
||||||
|
"desktop": "pantalaimon.desktop"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.1.0",
|
||||||
|
"maintainer": "Morgan McMillian <thrrgilag@dreamfall.space>",
|
||||||
|
"framework" : "ubuntu-sdk-16.04"
|
||||||
|
}
|
5
pantalaimon.apparmor
Normal file
5
pantalaimon.apparmor
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"template": "unconfined",
|
||||||
|
"policy_groups": ["networking"],
|
||||||
|
"policy_version": 16.04
|
||||||
|
}
|
7
pantalaimon.desktop.in
Normal file
7
pantalaimon.desktop.in
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
_Name=Pantalaimon UT
|
||||||
|
Exec=qmlscene %U qml/Main.qml
|
||||||
|
Icon=assets/logo.svg
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
X-Ubuntu-Touch=true
|
34
po/CMakeLists.txt
Normal file
34
po/CMakeLists.txt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
include(FindGettext)
|
||||||
|
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
|
||||||
|
|
||||||
|
set(DOMAIN ${FULL_PROJECT_NAME})
|
||||||
|
set(POT_FILE ${DOMAIN}.pot)
|
||||||
|
file(GLOB PO_FILES *.po)
|
||||||
|
|
||||||
|
# Creates the .pot file containing the translations template
|
||||||
|
add_custom_target(${POT_FILE} ALL
|
||||||
|
COMMENT "Generating translation template"
|
||||||
|
COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini
|
||||||
|
--srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_NAME}.in
|
||||||
|
|
||||||
|
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE}
|
||||||
|
-D ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
-D ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
--from-code=UTF-8
|
||||||
|
--c++ --qt --language=javascript --add-comments=TRANSLATORS
|
||||||
|
--keyword=tr --keyword=tr:1,2 --keyword=N_ --keyword=_
|
||||||
|
--package-name='${DOMAIN}'
|
||||||
|
--sort-by-file
|
||||||
|
${I18N_SRC_FILES}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
# Builds the binary translations catalog for each language
|
||||||
|
# it finds source translations (*.po) for
|
||||||
|
foreach(PO_FILE ${PO_FILES})
|
||||||
|
get_filename_component(LANG ${PO_FILE} NAME_WE)
|
||||||
|
gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE})
|
||||||
|
set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/share/locale/${LANG}/LC_MESSAGES)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo
|
||||||
|
DESTINATION ${INSTALL_DIR}
|
||||||
|
RENAME ${DOMAIN}.mo)
|
||||||
|
endforeach(PO_FILE)
|
66
po/pantalaimon.thrrgilag.pot
Normal file
66
po/pantalaimon.thrrgilag.pot
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the pantalaimon.thrrgilag package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: pantalaimon.thrrgilag\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2020-07-14 00:16+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: ../qml/Components/EditServerPage.qml:19
|
||||||
|
msgid "Homeserver Configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/Components/EditServerPage.qml:24
|
||||||
|
msgid "Save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/Components/EditServerPage.qml:83
|
||||||
|
msgid "Description:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/Components/EditServerPage.qml:103
|
||||||
|
msgid "Homeserver:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/Components/EditServerPage.qml:124
|
||||||
|
msgid "Listen on 127.0.0.1:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:19 pantalaimon.desktop.in.h:1
|
||||||
|
msgid "Pantalaimon UT"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:24
|
||||||
|
msgid "About"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:36
|
||||||
|
msgid "Service start disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:36
|
||||||
|
msgid "Service start enabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:106
|
||||||
|
msgid "Delete homeserver"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:124
|
||||||
|
msgid "No homeservers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../qml/SettingsPage.qml:177
|
||||||
|
msgid "Add Homeserver"
|
||||||
|
msgstr ""
|
146
qml/Components/EditServerPage.qml
Normal file
146
qml/Components/EditServerPage.qml
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Ubuntu.Components 1.3
|
||||||
|
import Ubuntu.Components.ListItems 1.3
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: bottomEdgeComponent
|
||||||
|
|
||||||
|
property int idx: 0
|
||||||
|
property bool editmode: false
|
||||||
|
property alias instance: instance.text
|
||||||
|
property alias homeserver: homeserver.text
|
||||||
|
property alias listenport: listenport.text
|
||||||
|
|
||||||
|
signal save()
|
||||||
|
|
||||||
|
header: PageHeader {
|
||||||
|
id: header
|
||||||
|
title: i18n.tr('Homeserver Configuration')
|
||||||
|
|
||||||
|
trailingActionBar.actions: [
|
||||||
|
Action {
|
||||||
|
iconName: 'ok'
|
||||||
|
text: i18n.tr('Save')
|
||||||
|
onTriggered: {
|
||||||
|
var data = {
|
||||||
|
name: instance.text,
|
||||||
|
homeserver: homeserver.text,
|
||||||
|
listenport: listenport.text
|
||||||
|
}
|
||||||
|
if (editmode) {
|
||||||
|
listModel.set(idx, data);
|
||||||
|
pageStack.pop();
|
||||||
|
} else {
|
||||||
|
listModel.append(data)
|
||||||
|
bottomEdge.collapse();
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
width: bottomEdge.width
|
||||||
|
height: bottomEdge.height
|
||||||
|
|
||||||
|
function resetdata() {
|
||||||
|
console.log("debug: resetdata");
|
||||||
|
instance.text = "";
|
||||||
|
homeserver.text = "";
|
||||||
|
listenport.text = "8009"; // TODO: maybe autoincrement based on existing entries?
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: header.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
contentHeight: contentColumn.height + units.gu(4)
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: contentColumn
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: parent.top;
|
||||||
|
left: parent.left;
|
||||||
|
right: parent.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
height: units.gu(6)
|
||||||
|
leftPadding: units.gu(2)
|
||||||
|
spacing: units.gu(1)
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: i18n.tr('Description:')
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: instance
|
||||||
|
text: ""
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
height: units.gu(6)
|
||||||
|
leftPadding: units.gu(2)
|
||||||
|
spacing: units.gu(1)
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: i18n.tr('Homeserver:')
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: homeserver
|
||||||
|
text: ""
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
height: units.gu(6)
|
||||||
|
leftPadding: units.gu(2)
|
||||||
|
spacing: units.gu(1)
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: i18n.tr('Listen on 127.0.0.1:')
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: listenport
|
||||||
|
text: "8009"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
inputMethodHints: Qt.ImhDigitsOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: bottomEdge
|
||||||
|
|
||||||
|
onCollapseCompleted: {
|
||||||
|
resetdata();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
qml/Main.qml
Normal file
21
qml/Main.qml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Ubuntu.Components 1.3
|
||||||
|
//import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
|
||||||
|
MainView {
|
||||||
|
id: root
|
||||||
|
objectName: 'mainView'
|
||||||
|
applicationName: 'pantalaimon.thrrgilag'
|
||||||
|
automaticOrientation: true
|
||||||
|
|
||||||
|
width: units.gu(45)
|
||||||
|
height: units.gu(75)
|
||||||
|
|
||||||
|
PageStack {
|
||||||
|
id: pageStack
|
||||||
|
|
||||||
|
Component.onCompleted: push(Qt.resolvedUrl('SettingsPage.qml'))
|
||||||
|
}
|
||||||
|
}
|
198
qml/SettingsPage.qml
Normal file
198
qml/SettingsPage.qml
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Ubuntu.Components 1.3
|
||||||
|
import Ubuntu.Components.ListItems 1.3 as ListItems
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
import io.thp.pyotherside 1.3
|
||||||
|
|
||||||
|
import "Components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: settingsPage
|
||||||
|
|
||||||
|
property bool is_running: false
|
||||||
|
property bool upstart: false
|
||||||
|
property string status_msg
|
||||||
|
|
||||||
|
header: PageHeader {
|
||||||
|
id: header
|
||||||
|
title: i18n.tr('Pantalaimon UT')
|
||||||
|
|
||||||
|
trailingActionBar.actions: [
|
||||||
|
Action {
|
||||||
|
iconName: 'info'
|
||||||
|
text: i18n.tr('About')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItem {
|
||||||
|
id: upstartState
|
||||||
|
anchors.top: header.bottom
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
ListItems.Standard {
|
||||||
|
anchors.fill: parent
|
||||||
|
text: upstart ? i18n.tr("Service start enabled") : i18n.tr("Service start disabled")
|
||||||
|
control: Switch {
|
||||||
|
checked: upstart
|
||||||
|
onClicked: {
|
||||||
|
if (checked) {
|
||||||
|
py.call('service.add', [], function(result) {});
|
||||||
|
} else {
|
||||||
|
py.call('service.remove', [], function(result) {});
|
||||||
|
}
|
||||||
|
get_status();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItem {
|
||||||
|
id: serviceState
|
||||||
|
anchors.top: upstartState.bottom
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
ListItems.Standard {
|
||||||
|
anchors.fill: parent
|
||||||
|
text: status_msg
|
||||||
|
control: Switch {
|
||||||
|
enabled: upstart
|
||||||
|
checked: is_running
|
||||||
|
onClicked: {
|
||||||
|
if (checked) {
|
||||||
|
py.call('service.start', [], function(result) {});
|
||||||
|
} else {
|
||||||
|
py.call('service.stop', [], function(result) {});
|
||||||
|
}
|
||||||
|
get_status();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: listView
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height - bottomEdgeHint.height
|
||||||
|
anchors.top: serviceState.bottom
|
||||||
|
visible: (listView.count !== 0)
|
||||||
|
model: ListModel {
|
||||||
|
id: listModel
|
||||||
|
}
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
delegate: ListItem {
|
||||||
|
ListItems.Standard {
|
||||||
|
anchors.fill: parent
|
||||||
|
text: name
|
||||||
|
progression: true
|
||||||
|
onClicked: {
|
||||||
|
var item = listModel.get(index);
|
||||||
|
console.log(item);
|
||||||
|
pageStack.push(editConfigPage, {
|
||||||
|
idx: index,
|
||||||
|
instance: item.name,
|
||||||
|
homeserver: item.homeserver,
|
||||||
|
listenport: item.listenport
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leadingActions: ListItemActions {
|
||||||
|
actions: [
|
||||||
|
Action {
|
||||||
|
iconName: "delete"
|
||||||
|
text: i18n.tr("Delete homeserver")
|
||||||
|
onTriggered: {
|
||||||
|
console.log("debug: delete " + index);
|
||||||
|
listModel.remove(index);
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: (listView.count === 0)
|
||||||
|
// color: "lightgrey"
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: i18n.tr("No homeservers")
|
||||||
|
fontSize: "x-large"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Python {
|
||||||
|
id: py
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
addImportPath(Qt.resolvedUrl('../src/'));
|
||||||
|
|
||||||
|
importModule('config', function() {
|
||||||
|
py.call('config.load', [], function(result) {
|
||||||
|
for (var i=0; i<result.length; i++) {
|
||||||
|
listModel.append(result[i])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("debug: python config loaded...");
|
||||||
|
});
|
||||||
|
|
||||||
|
importModule('service', function() {
|
||||||
|
console.log("debug: python service loaded...");
|
||||||
|
get_status();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveConfig() {
|
||||||
|
var lmdata = []
|
||||||
|
for (var i = 0; i < listModel.count; ++i) {
|
||||||
|
lmdata.push(listModel.get(i));
|
||||||
|
}
|
||||||
|
py.call("config.save", [JSON.stringify(lmdata)], function(result) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_status() {
|
||||||
|
py.call("service.check_upstart", [], function(result) {
|
||||||
|
upstart = result;
|
||||||
|
});
|
||||||
|
py.call("service.status", [], function(result) {
|
||||||
|
is_running = result[0];
|
||||||
|
status_msg = result[1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BottomEdge {
|
||||||
|
id: bottomEdge
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
hint {
|
||||||
|
id: bottomEdgeHint
|
||||||
|
text: i18n.tr("Add Homeserver")
|
||||||
|
iconName: "add"
|
||||||
|
status: BottomEdgeHint.Locked
|
||||||
|
onStatusChanged: if (status === BottomEdgeHint.Inactive) bottomEdge.hint.status = BottomEdgeHint.Locked
|
||||||
|
}
|
||||||
|
|
||||||
|
contentComponent: EditServerPage {
|
||||||
|
id: bottomEdgeComponent
|
||||||
|
|
||||||
|
onSave: saveConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: editConfigPage
|
||||||
|
|
||||||
|
EditServerPage {
|
||||||
|
editmode: true
|
||||||
|
onSave: saveConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
src/config.py
Normal file
46
src/config.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import configparser
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
CONFFILE = '/home/phablet/.config/pantalaimon/pantalaimon.conf'
|
||||||
|
# CONFFILE = 'pantalaimon.conf'
|
||||||
|
|
||||||
|
def load():
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
if os.path.exists(CONFFILE):
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read_file(open(CONFFILE))
|
||||||
|
|
||||||
|
for instance in config.sections():
|
||||||
|
item = {'name': instance}
|
||||||
|
item['homeserver'] = config[instance].get('homeserver')
|
||||||
|
item['listenaddress'] = config[instance].get('listenaddress')
|
||||||
|
item['listenport'] = config[instance].get('listenport')
|
||||||
|
item['ignoreverification'] = config[instance].get('ignoreverification')
|
||||||
|
item['usekeyring'] = config[instance].get('usekeyring')
|
||||||
|
|
||||||
|
entries.append(item)
|
||||||
|
|
||||||
|
return entries
|
||||||
|
|
||||||
|
def save(data):
|
||||||
|
logging.debug("save config")
|
||||||
|
dataobj = json.loads(data)
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
|
||||||
|
for item in dataobj:
|
||||||
|
config[item['name']] = {}
|
||||||
|
config[item['name']]['homeserver'] = item['homeserver']
|
||||||
|
config[item['name']]['listenaddress'] = "127.0.0.1"
|
||||||
|
config[item['name']]['listenport'] = item['listenport']
|
||||||
|
config[item['name']]['ignoreverification'] = "true"
|
||||||
|
config[item['name']]['usekeyring'] = "false"
|
||||||
|
|
||||||
|
with open(CONFFILE,'w') as configfile:
|
||||||
|
config.write(configfile)
|
||||||
|
|
54
src/service.py
Normal file
54
src/service.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import subprocess
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
UPSTARTFILE = '/home/phablet/.config/upstart/pantalaimon.conf'
|
||||||
|
|
||||||
|
def status():
|
||||||
|
statuscmd = ['status', 'pantalaimon']
|
||||||
|
r = subprocess.run(statuscmd, stdout=subprocess.PIPE)
|
||||||
|
logging.debug(r)
|
||||||
|
running = "running" in r.stdout.decode()
|
||||||
|
return (running, r.stdout)
|
||||||
|
|
||||||
|
def start():
|
||||||
|
success = False
|
||||||
|
statuscmd = ['start', 'pantalaimon']
|
||||||
|
r = subprocess.run(statuscmd)
|
||||||
|
logging.debug(r)
|
||||||
|
if r.returncode == 0:
|
||||||
|
success = True
|
||||||
|
return success
|
||||||
|
|
||||||
|
def stop():
|
||||||
|
success = False
|
||||||
|
statuscmd = ['stop', 'pantalaimon']
|
||||||
|
r = subprocess.run(statuscmd)
|
||||||
|
logging.debug(r)
|
||||||
|
if r.returncode == 0:
|
||||||
|
success = True
|
||||||
|
return success
|
||||||
|
|
||||||
|
def add():
|
||||||
|
logging.debug('adding service file')
|
||||||
|
script = """
|
||||||
|
start on started unity8
|
||||||
|
respawn
|
||||||
|
exec /opt/click.ubuntu.com/pantalaimon.thrrgilag/current/pantalaimon
|
||||||
|
"""
|
||||||
|
with open(UPSTARTFILE, 'w') as upstart_file:
|
||||||
|
print(script, file=upstart_file)
|
||||||
|
start()
|
||||||
|
|
||||||
|
def remove():
|
||||||
|
logging.debug('removing service file')
|
||||||
|
stop()
|
||||||
|
os.remove(UPSTARTFILE)
|
||||||
|
|
||||||
|
def check_upstart():
|
||||||
|
return os.path.exists(UPSTARTFILE)
|
||||||
|
|
||||||
|
def check_env():
|
||||||
|
logging.debug(os.environ)
|
Loading…
Reference in a new issue