feat: initiale Projektstruktur nach Framework 1.7
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
# Ignorieren aller Dateien außer den explizit benötigten
|
||||||
|
*
|
||||||
|
!
|
||||||
|
# ERLAUBTE Dateien
|
||||||
|
!manifest.json
|
||||||
|
!fortunecookie.desktop
|
||||||
|
!apparmor.json
|
||||||
|
!clickable.yaml
|
||||||
|
|
||||||
|
# QML Verzeichnis und Dateien
|
||||||
|
!qml/
|
||||||
|
!qml/Main_mobile.qml
|
||||||
|
|
||||||
|
# Source Verzeichnis und Dateien
|
||||||
|
!src/
|
||||||
|
!src/fortune_cookie.py
|
||||||
|
!src/__init__.py
|
||||||
|
|
||||||
|
# Assets Verzeichnis und nur spezifische Dateien
|
||||||
|
!assets/
|
||||||
|
!assets/cookie_closed.png
|
||||||
|
!assets/cookie_open.png
|
||||||
|
!assets/fortune_cookie_title_new.svg
|
||||||
|
!assets/fortunes.json
|
||||||
|
!assets/chinese_music.mp3
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
# Build-Dateien
|
||||||
|
build/
|
||||||
|
click_pkg/
|
||||||
|
*.click
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
|
||||||
|
# Qt
|
||||||
|
*.qmlc
|
||||||
|
*.qrc
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# CMakeLists.txt Template für Ubuntu Touch Apps
|
||||||
|
# Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
#
|
||||||
|
# VERWENDUNG:
|
||||||
|
# 1. Kopiere diese Datei nach CMakeLists.txt in deinem Projekt
|
||||||
|
# 2. Ersetze fortunecookie mit deinem App-Namen
|
||||||
|
#
|
||||||
|
# WICHTIG (1.7):
|
||||||
|
# - builder: pure-qml-cmake (für QML+Python-Apps)
|
||||||
|
# - architecture: all (pure-qml-cmake erzwingt das)
|
||||||
|
# - CMAKE_AUTOMOC ON (für Qt5)
|
||||||
|
#
|
||||||
|
# Für Apps MIT nativem C++-Code:
|
||||||
|
# Füge zusätzliche Qt5-Komponenten hinzu
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
|
project(fortunecookie C CXX)
|
||||||
|
|
||||||
|
# Qt5
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
# Architektur-Triplet (für Qt5-Bibliotheken)
|
||||||
|
execute_process(
|
||||||
|
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
|
||||||
|
OUTPUT_VARIABLE ARCH_TRIPLET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
set(QT_IMPORTS_DIR "lib/${ARCH_TRIPLET}")
|
||||||
|
|
||||||
|
# Projekt-Metadaten
|
||||||
|
set(PROJECT_NAME "fortunecookie")
|
||||||
|
set(FULL_PROJECT_NAME "fortunecookie.darklithium")
|
||||||
|
set(DATA_DIR /)
|
||||||
|
|
||||||
|
# Manifest und Desktop-Datei generieren
|
||||||
|
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})
|
||||||
|
|
||||||
|
# Dateien installieren
|
||||||
|
install(DIRECTORY assets DESTINATION ${DATA_DIR})
|
||||||
|
install(DIRECTORY src DESTINATION ${DATA_DIR})
|
||||||
|
install(DIRECTORY qml DESTINATION ${DATA_DIR})
|
||||||
|
install(FILES ${PROJECT_NAME}.desktop.in DESTINATION ${DATA_DIR})
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# OPTIONAL: Für Apps mit Übersetzungen (po/)
|
||||||
|
# ============================================================================
|
||||||
|
# Falls du Übersetzungen brauchst, entkommentiere die folgenden Zeilen:
|
||||||
|
#
|
||||||
|
# find_program(INTLTOOL_MERGE intltool-merge)
|
||||||
|
# if(NOT INTLTOOL_MERGE)
|
||||||
|
# message(FATAL_ERROR "intltool-merge nicht gefunden, bitte intltool installieren")
|
||||||
|
# endif()
|
||||||
|
#
|
||||||
|
# find_program(INTLTOOL_EXTRACT intltool-extract)
|
||||||
|
# if(NOT INTLTOOL_EXTRACT)
|
||||||
|
# message(FATAL_ERROR "intltool-extract nicht gefunden, bitte intltool installieren")
|
||||||
|
# endif()
|
||||||
|
#
|
||||||
|
# file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po qml/*.qml)
|
||||||
|
# list(APPEND I18N_SRC_FILES ${PROJECT_NAME}.desktop.in.h)
|
||||||
|
#
|
||||||
|
# add_custom_target(${PROJECT_NAME}_desktop ALL
|
||||||
|
# COMMENT "Generiere Desktop-Datei..."
|
||||||
|
# COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.desktop.in ${PROJECT_NAME}.desktop
|
||||||
|
# COMMAND sed -i 's/${PROJECT_NAME}-//g' ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.desktop
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.desktop DESTINATION ${DATA_DIR})
|
||||||
|
# add_subdirectory(po)
|
||||||
@@ -0,0 +1,396 @@
|
|||||||
|
# 📁 START-UT-DEV Framework 1.7 - TEMPLATES
|
||||||
|
|
||||||
|
**Version:** 1.7
|
||||||
|
**Stand:** 30.05.2026
|
||||||
|
**Maintainer:** darklithium <dev@darklithium.de>
|
||||||
|
**Validiert durch:** referenz-app (metime-basiert) ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 ZWECK
|
||||||
|
|
||||||
|
Dieses Verzeichnis enthält **fertige Templates** für Ubuntu Touch App-Entwicklung mit:
|
||||||
|
- **QML** (UI)
|
||||||
|
- **Python** (Backend via PyOtherSide)
|
||||||
|
- **pure-qml-cmake** (Builder)
|
||||||
|
|
||||||
|
**Alle Templates sind validiert** durch die erfolgreiche referenz-app-Implementierung.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 STRUKTUR
|
||||||
|
|
||||||
|
```
|
||||||
|
TEMPLATES/
|
||||||
|
├── README.md # Diese Datei
|
||||||
|
├── CMakeLists.txt # CMake-Konfiguration (Standard 1.7)
|
||||||
|
├── clickable.yaml # Clickable-Konfiguration (Standard 1.7)
|
||||||
|
├── manifest.json.in # App-Manifest Template
|
||||||
|
├── app.apparmor # AppArmor-Profil Template
|
||||||
|
├── app.desktop.in # Desktop-Datei Template
|
||||||
|
├── python_module_template.py # Python-Modul Template
|
||||||
|
├── qml_main_template.qml # QML Hauptdatei Template
|
||||||
|
└── .git/ # Git-Hooks (Symlinks zu /DEV/git/hooks/)
|
||||||
|
└── hooks/
|
||||||
|
├── pre-commit # → /home/chrischi/DEV/git/hooks/pre-commit
|
||||||
|
└── commit-msg # → /home/chrischi/DEV/git/hooks/commit-msg
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 SCHNELLSTART: NEUE APP ERSTELLEN
|
||||||
|
|
||||||
|
### 1. Projektverzeichnis erstellen
|
||||||
|
```bash
|
||||||
|
mkdir -p /home/chrischi/DEV/UT/meine-app/{assets,qml,src}
|
||||||
|
cd /home/chrischi/DEV/UT/meine-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Framework einbinden (Symlink)
|
||||||
|
```bash
|
||||||
|
ln -s /home/chrischi/DEV/tools/START-UT-DEV/1.7 START-UT-DEV
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Templates kopieren & anpassen
|
||||||
|
```bash
|
||||||
|
# CMake & Clickable
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/CMakeLists.txt .
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/clickable.yaml .
|
||||||
|
|
||||||
|
# Manifest & Desktop
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/manifest.json.in .
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/app.apparmor meine-app.apparmor
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/app.desktop.in meine-app.desktop.in
|
||||||
|
|
||||||
|
# Python & QML
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/python_module_template.py src/meine-app.py
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/qml_main_template.qml qml/Main.qml
|
||||||
|
|
||||||
|
# Assets (Beispiel-Icon)
|
||||||
|
cp START-UT-DEV/1.7/TEMPLATES/../ASSETS/logo.svg assets/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Platzhalter ersetzen
|
||||||
|
**In allen Dateien `<app-name>` durch `meine-app` ersetzen:**
|
||||||
|
```bash
|
||||||
|
# Schnell-Ersetzung (Vorsicht: prüfe alle Dateien manuell!)
|
||||||
|
find . -type f -exec sed -i 's/<app-name>/meine-app/g' {} \;
|
||||||
|
sed -i 's/<App-Name>/Meine App/g' meine-app.desktop.in manifest.json.in
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Git einrichten (narrensicher)
|
||||||
|
```bash
|
||||||
|
# Git initialisieren
|
||||||
|
git init
|
||||||
|
|
||||||
|
# Hooks installieren (Symlinks!)
|
||||||
|
mkdir -p .git/hooks
|
||||||
|
cp -s /home/chrischi/DEV/git/hooks/pre-commit .git/hooks/
|
||||||
|
cp -s /home/chrischi/DEV/git/hooks/commit-msg .git/hooks/
|
||||||
|
chmod +x .git/hooks/*
|
||||||
|
|
||||||
|
# git-helper kopieren
|
||||||
|
cp /home/chrischi/DEV/git/git-helper.sh .
|
||||||
|
chmod +x git-helper.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Erstes Commit
|
||||||
|
```bash
|
||||||
|
./git-helper.sh commit 'feat: initiale Projektstruktur'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Build & Test
|
||||||
|
```bash
|
||||||
|
# Desktop-Test
|
||||||
|
qmlscene qml/Main.qml
|
||||||
|
|
||||||
|
# Clickable Build (für alle Architekturen)
|
||||||
|
clickable build --arch all
|
||||||
|
|
||||||
|
# Installation in QEMU
|
||||||
|
clickable install
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 TEMPLATES IM DETAIL
|
||||||
|
|
||||||
|
### 📄 CMakeLists.txt
|
||||||
|
**Zweck:** Build-Konfiguration für pure-qml-cmake
|
||||||
|
|
||||||
|
**Wichtige Punkte (1.7):**
|
||||||
|
- `CMAKE_AUTOMOC ON` (für Qt5)
|
||||||
|
- Architektur-Triplet via `dpkg-architecture`
|
||||||
|
- `PROJECT_NAME` und `FULL_PROJECT_NAME` anpassen
|
||||||
|
- `DATA_DIR /` (Root für Click-Container)
|
||||||
|
|
||||||
|
**Anpassungen:**
|
||||||
|
- `<app-name>` durch deinen App-Namen ersetzen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📄 clickable.yaml
|
||||||
|
**Zweck:** Clickable Build-Konfiguration
|
||||||
|
|
||||||
|
**Standard 1.7:**
|
||||||
|
```yaml
|
||||||
|
clickable_minimum_required: 8.8.0
|
||||||
|
builder: pure-qml-cmake
|
||||||
|
kill: qmlscene
|
||||||
|
```
|
||||||
|
|
||||||
|
**Für Apps mit nativem Code:**
|
||||||
|
- `builder: cmake` oder `builder: qmake`
|
||||||
|
- `kill: <app-name>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📄 manifest.json.in
|
||||||
|
**Zweck:** App-Manifest für Click-Pakete
|
||||||
|
|
||||||
|
**Wichtige Felder (1.7):**
|
||||||
|
- `name`: `<app-name>.darklithium` (Format: appname.maintainer)
|
||||||
|
- `maintainer`: `"Vorname Nachname <email>"` (OHNE spitze Klammern um den Namen!)
|
||||||
|
- `architecture`: `"all"` (für pure-qml-cmake)
|
||||||
|
- `framework`: `"ubuntu-sdk-20.04"`
|
||||||
|
|
||||||
|
**⚠️ WICHTIG:** Nur Standardfelder verwenden! Keine `permissions`, `policy_groups`, `read_path`, `write_path` (schlagen Validierung fehl).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📄 app.apparmor
|
||||||
|
**Zweck:** AppArmor-Sicherheitsprofil
|
||||||
|
|
||||||
|
**Standard 1.7:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"policy_version": 20.04,
|
||||||
|
"policy_groups": ["networking"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verfügbare Policy-Gruppen:**
|
||||||
|
- `networking` (HTTP, etc.)
|
||||||
|
- `content_exchange_source` (Dateiaustausch)
|
||||||
|
- `video` (Video-Wiedergabe)
|
||||||
|
- `pulseaudio` (Audio)
|
||||||
|
- `bluetooth` (Bluetooth)
|
||||||
|
- `location` (Standort)
|
||||||
|
- `contacts` (Kontakte)
|
||||||
|
- `calendar` (Kalender)
|
||||||
|
- `camera` (Kamera)
|
||||||
|
- `sensors` (Sensoren)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📄 app.desktop.in
|
||||||
|
**Zweck:** Desktop-Datei für Lomiri
|
||||||
|
|
||||||
|
**Wichtige Einträge (1.7):**
|
||||||
|
- `Exec=qmlscene %U qml/Main.qml` (für pure-QML-Apps)
|
||||||
|
- `X-Lomiri-Touch=true` (für Ubuntu Touch)
|
||||||
|
- `Icon=assets/logo.svg` (Standard)
|
||||||
|
- `X-Ubuntu-Applications=<app-name>` (ohne .desktop Endung)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🐍 python_module_template.py
|
||||||
|
**Zweck:** Python-Backend für PyOtherSide
|
||||||
|
|
||||||
|
**Wichtige Punkte (1.7):**
|
||||||
|
- **KEINE** dbus-Importe (PyOtherSide-Kompatibilität)
|
||||||
|
- **KEINE** Top-Level print() Statements
|
||||||
|
- **KEINE** Top-Level Code-Ausführung
|
||||||
|
- Plattform-Erkennung via `platform.machine()`
|
||||||
|
- **Ein Modul reicht** für 90% der Apps
|
||||||
|
|
||||||
|
**Beispiel-Funktionen:**
|
||||||
|
- `get_platform()` → "arm64" oder "amd64"
|
||||||
|
- `get_status_text()` → Status für UI
|
||||||
|
- `on_button_click()` → Button-Handler
|
||||||
|
- `get_data_dir()` → Persistentes Datenverzeichnis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🎨 qml_main_template.qml
|
||||||
|
**Zweck:** QML-Hauptdatei
|
||||||
|
|
||||||
|
**Wichtige Punkte (1.7):**
|
||||||
|
- **Imports:**
|
||||||
|
```qml
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3 // NEU 1.7!
|
||||||
|
import Lomiri.Components 1.3
|
||||||
|
import Lomiri.Components.Popups 1.3
|
||||||
|
import io.thp.pyotherside 1.4
|
||||||
|
```
|
||||||
|
- **fontSize:** **Immer als STRING** (`"large"`, `"x-large"`, `"medium"`) - nicht units.sp()
|
||||||
|
- **Layouts:** QtQuick.Layouts 1.3 für ColumnLayout, RowLayout
|
||||||
|
- **PyOtherSide:** `Qt.resolvedUrl("../src")` **FUNKTIONIERT!**
|
||||||
|
- **Button-Größen:** 20x8 GU (200x80 DP) für Touch-Optimierung
|
||||||
|
- **PageFooter:** **Existent NICHT** in Lomiri.Components 1.3 → als Label implementieren
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 GIT-HOOKS (SYMLINKS)
|
||||||
|
|
||||||
|
Die Hooks in `.git/hooks/` sind **Symlinks** zu `/home/chrischi/DEV/git/hooks/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
.git/hooks/
|
||||||
|
├── pre-commit → /home/chrischi/DEV/git/hooks/pre-commit
|
||||||
|
└── commit-msg → /home/chrischi/DEV/git/hooks/commit-msg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vorteile von Symlinks:
|
||||||
|
1. **Zentrale Updates:** Änderungen an den Hooks in `/DEV/git/hooks/` gelten sofort für alle Projekte
|
||||||
|
2. **Konsistenz:** Alle Projekte nutzen dieselben Hooks
|
||||||
|
3. **Wartung:** Nur eine Stelle zu pflegen
|
||||||
|
|
||||||
|
### Hooks im Detail:
|
||||||
|
|
||||||
|
#### pre-commit
|
||||||
|
Prüft vor jedem Commit:
|
||||||
|
- ✅ Branch-Naming (nur stable/testing/feature/bugfix/hotfix/release)
|
||||||
|
- ✅ Dateigrößen (max. 1MB)
|
||||||
|
- ✅ Sensible Daten (Passwörter, Keys, Tokens)
|
||||||
|
- ✅ Code-Style (kein Trailing Whitespace, LF Line Endings)
|
||||||
|
|
||||||
|
#### commit-msg
|
||||||
|
Prüft Commit-Messages:
|
||||||
|
- ✅ Subject-Länge (max. 72 Zeichen)
|
||||||
|
- ✅ Format: `<typ>: <beschreibung>`
|
||||||
|
- ✅ Typen: feat/fix/docs/style/refactor/test/chore/revert/perf/build/ci/WIP
|
||||||
|
- ✅ Beschreibung muss vorhanden sein
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 PROJEKTSTRUKTUR (STANDARD 1.7)
|
||||||
|
|
||||||
|
```
|
||||||
|
meine-app/
|
||||||
|
├── CMakeLists.txt # Build-Konfiguration
|
||||||
|
├── clickable.yaml # Clickable-Konfiguration
|
||||||
|
├── manifest.json.in # App-Manifest
|
||||||
|
├── meine-app.apparmor # AppArmor-Profil
|
||||||
|
├── meine-app.desktop.in # Desktop-Datei
|
||||||
|
├── .git/ # Git-Repository
|
||||||
|
│ └── hooks/ # Git-Hooks (Symlinks)
|
||||||
|
│ ├── pre-commit
|
||||||
|
│ └── commit-msg
|
||||||
|
├── START-UT-DEV/ # Framework (Symlink)
|
||||||
|
│ └── 1.7/
|
||||||
|
│ ├── TEMPLATES/ # Templates
|
||||||
|
│ └── TOOLS/ # Tools (git-helper.sh)
|
||||||
|
├── assets/ # Icons, Bilder
|
||||||
|
│ └── logo.svg # App-Icon
|
||||||
|
├── qml/ # QML-Dateien
|
||||||
|
│ └── Main.qml # Haupteinstiegspunkt
|
||||||
|
└── src/ # Python-Module
|
||||||
|
└── meine-app.py # Python-Backend
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 TESTING
|
||||||
|
|
||||||
|
### Desktop-Test (schnell)
|
||||||
|
```bash
|
||||||
|
qmlscene qml/Main.qml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clickable Build & Test
|
||||||
|
```bash
|
||||||
|
# Build für alle Architekturen
|
||||||
|
clickable build --arch all
|
||||||
|
|
||||||
|
# Installation in QEMU
|
||||||
|
clickable install
|
||||||
|
|
||||||
|
# Log prüfen
|
||||||
|
clickable log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git Workflow Test
|
||||||
|
```bash
|
||||||
|
# Feature-Branch erstellen
|
||||||
|
./git-helper.sh new-feature test-funktion
|
||||||
|
|
||||||
|
# Änderungen machen...
|
||||||
|
|
||||||
|
# Commit (wird durch Hooks validiert)
|
||||||
|
./git-helper.sh commit 'feat: Testfunktion hinzugefügt'
|
||||||
|
|
||||||
|
# Push
|
||||||
|
./git-helper.sh push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 BEST PRACTICES (1.7)
|
||||||
|
|
||||||
|
### ✅ DO:
|
||||||
|
- **Ein Python-Modul** für einfache Apps (modulare Trennung ist optional)
|
||||||
|
- **Qt.resolvedUrl("../src")** für PyOtherSide-Imports
|
||||||
|
- **fontSize als STRING** verwenden
|
||||||
|
- **Button-Größen:** 20x8 GU für Touch
|
||||||
|
- **Git-Hooks nutzen** (verhindern Fehler)
|
||||||
|
- **git-helper.sh nutzen** (einfache Befehle)
|
||||||
|
|
||||||
|
### ❌ DON'T:
|
||||||
|
- **dbus-Importe** in Python-Modulen (PyOtherSide-Kompatibilität)
|
||||||
|
- **Absolute Pfade** für PyOtherSide-Imports
|
||||||
|
- **Top-Level Code** in Python-Modulen (wird nicht ausgeführt)
|
||||||
|
- **units.sp()** für fontSize (String-Werte bevorzugen)
|
||||||
|
- **Direkte Commits auf stable** (nur über Merge)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 UPDATES
|
||||||
|
|
||||||
|
### Templates aktualisieren
|
||||||
|
Die Templates in `/DEV/tools/START-UT-DEV/1.7/TEMPLATES/` werden laufend verbessert.
|
||||||
|
|
||||||
|
**Aktualisierung für bestehendes Projekt:**
|
||||||
|
```bash
|
||||||
|
# CMakeLists.txt
|
||||||
|
cp /home/chrischi/DEV/tools/START-UT-DEV/1.7/TEMPLATES/CMakeLists.txt .
|
||||||
|
|
||||||
|
# clickable.yaml
|
||||||
|
cp /home/chrischi/DEV/tools/START-UT-DEV/1.7/TEMPLATES/clickable.yaml .
|
||||||
|
|
||||||
|
# Python-Template (neue Funktionen)
|
||||||
|
cp /home/chrischi/DEV/tools/START-UT-DEV/1.7/TEMPLATES/python_module_template.py src/meine-app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hooks aktualisieren
|
||||||
|
Da die Hooks **Symlinks** sind, werden sie automatisch aktualisiert, wenn die zentraler Hooks in `/DEV/git/hooks/` geändert werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 UNTERSTÜTZUNG
|
||||||
|
|
||||||
|
### Häufige Probleme
|
||||||
|
|
||||||
|
| Problem | Lösung |
|
||||||
|
|---------|--------|
|
||||||
|
| PyOtherSide-Modul wird nicht geladen | `Qt.resolvedUrl("../src")` verwenden |
|
||||||
|
| Button zu klein | 20x8 GU (200x80 DP) verwenden |
|
||||||
|
| fontSize funktioniert nicht | String-Werte (`"large"`) verwenden |
|
||||||
|
| Git-Hook blockiert Commit | `git commit --no-verify` (nur für Ausnahmen!) |
|
||||||
|
| PageFooter nicht verfügbar | Als Label implementieren |
|
||||||
|
|
||||||
|
### Referenz-App
|
||||||
|
- **Pfad:** `/home/chrischi/DEV/UT/referenz-app/`
|
||||||
|
- **Status:** ✅ ERFOLGREICH UMGESETZT
|
||||||
|
- **Dokumentation:** `IMPLEMENTATION.md`
|
||||||
|
|
||||||
|
### Manifest
|
||||||
|
- **Pfad:** `/home/chrischi/DEV/manifest.holy/manifest.holy`
|
||||||
|
- **Aktueller Stand:** Python/QML-Standards 1.7
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Letzte Aktualisierung:** 30.05.2026
|
||||||
|
**Version:** 1.7
|
||||||
|
**Maintainer:** darklithium <dev@darklithium.de>
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
/home/chrischi/DEV/tools/START-UT-DEV/1.7
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1 @@
|
|||||||
|
# Platzhalter: Hier soll cookie_crack.mp3 oder cookie_crack.wav hingelegt werden
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,280 @@
|
|||||||
|
{
|
||||||
|
"de": [
|
||||||
|
"Heute ist ein guter Tag für neue Abenteuer!",
|
||||||
|
"Achte auf kleine Zeichen – sie führen dich weiter.",
|
||||||
|
"Ein Lächeln bringt Glück in dein Leben.",
|
||||||
|
"Die größten Chancen kommen oft unerwartet.",
|
||||||
|
"Geduld ist der Schlüssel zu vielen Türen.",
|
||||||
|
"Ein offenes Herz sieht mehr als tausend Augen.",
|
||||||
|
"Vertraue dem Prozess, auch wenn du den Ausgang nicht kennst.",
|
||||||
|
"Alles fließt – auch deine Situation wird sich ändern.",
|
||||||
|
"Gib nicht auf, selbst wenn der Weg steinig erscheint.",
|
||||||
|
"Ein wahrer Freund ist ein Geschenk des Himmels.",
|
||||||
|
"Die beste Zeit, einen Baum zu pflanzen, war vor 20 Jahren. Die zweitbeste Zeit ist jetzt.",
|
||||||
|
"Glück ist kein Zufall, sondern die Folge von harter Arbeit und positiver Einstellung.",
|
||||||
|
"Wer andere glücklich macht, wird selbst glücklich sein.",
|
||||||
|
"Manchmal muss man einen Schritt zurückgehen, um zwei Schritte vorwärts zu kommen.",
|
||||||
|
"Das Leben ist wie ein Fahrrad. Um die Balance zu halten, muss man in Bewegung bleiben.",
|
||||||
|
"Ein kluger Mensch lernt aus der Erfahrung anderer.",
|
||||||
|
"Die größten Entdeckungen kommen oft aus Neugier.",
|
||||||
|
"Wer rastet, der rostet.",
|
||||||
|
"Ein gutes Buch und eine Tasse Tee sind die besten Begleiter.",
|
||||||
|
"Die Sonne scheint auch nach dem dunkelsten Tag wieder.",
|
||||||
|
"Glück ist die Fähigkeit, das Gute im Schlechten zu sehen.",
|
||||||
|
"Ein Lächeln kostet nichts und bringt viel zurück.",
|
||||||
|
"Wer nach vorne schaut, sieht die Zukunft.",
|
||||||
|
"Manchmal ist der Weg das Ziel.",
|
||||||
|
"Ein freundliches Wort kann einen schlechten Tag retten.",
|
||||||
|
"Die Natur ist die beste Quelle der Inspiration.",
|
||||||
|
"Der Weg ist das Ziel – genieße die Reise, nicht nur das Ziel.",
|
||||||
|
"Jeder Tag ist eine neue Chance, alles zu ändern.",
|
||||||
|
"Das Glück liegt in den kleinen Dingen des Lebens.",
|
||||||
|
"Was du aussäst, wirst du ernten.",
|
||||||
|
"Lache oft, liebe viel, vergiß nie wie gut das Leben sein kann.",
|
||||||
|
"Ein Tag ohne Lächeln ist ein verlorener Tag.",
|
||||||
|
"Die Zukunft gehört denen, die an die Schönheit ihrer Träume glauben.",
|
||||||
|
"Tu heute etwas, wofür dich dein zukünftiges Ich bedanken wird.",
|
||||||
|
"Der beste Weg, die Zukunft vorauszusagen, ist sie zu gestalten.",
|
||||||
|
"Träume sind nicht für die, die schlafen, sondern für die, die nicht aufgeben.",
|
||||||
|
"Jeder Moment ist eine neue Möglichkeit.",
|
||||||
|
"Das Geheimnis des Glücks liegt nicht im Besitz, sondern in der Freiheit von Besessenheit.",
|
||||||
|
"Lebe jeden Tag so, als wäre es dein letzter – eines Tages hast du recht.",
|
||||||
|
"Die größte Entdeckung einer Generation ist, dass ein Mensch sein Leben ändern kann, indem er seine Einstellung ändert.",
|
||||||
|
"Glück ist nicht etwas, das man findet, es ist etwas, das man schafft.",
|
||||||
|
"Die beste Rache ist ein gut geführtes Leben.",
|
||||||
|
"Gib jedem Tag die Chance, der beste Tag deines Lebens zu sein.",
|
||||||
|
"Man sieht nur mit dem Herzen gut. Das Wesentliche ist für die Augen unsichtbar.",
|
||||||
|
"Was immer du tun kannst oder träumst zu tun, fang damit an. Mut hat Genie, Kraft und Magie in sich.",
|
||||||
|
"Die einfachsten Dinge bringen oft das größte Glück.",
|
||||||
|
"Ein Leben ohne Risiko ist ein Leben ohne Chancen.",
|
||||||
|
"Alles, was du brauchst, ist bereits in dir.",
|
||||||
|
"Der einzige Weg, Großes zu erreichen, ist, es als eine Reihe kleiner Schritte zu betrachten.",
|
||||||
|
"Was du heute tust, wird deine morgen bewirken.",
|
||||||
|
"Ein positiver Geist bringt positive Dinge ins Leben.",
|
||||||
|
"Die beste Zeit, glücklich zu sein, ist jetzt. Der beste Ort, glücklich zu sein, ist hier. Der beste Weg, glücklich zu sein, ist mit anderen.",
|
||||||
|
"Lebe nicht in der Vergangenheit, träume nicht von der Zukunft, konzentriere dich auf den gegenwärtigen Moment.",
|
||||||
|
"Glück ist kein Zufall. Es ist das Ergebnis deiner täglichen Gewohnheiten.",
|
||||||
|
"Die Welt ist voll von wundervollen Dingen, die wir nicht sehen können.",
|
||||||
|
"Sei du selbst die Veränderung, die du in der Welt sehen möchtest.",
|
||||||
|
"Jeder Tag bietet eine neue Seite in deinem Lebensbuch.",
|
||||||
|
"Das Geheimnis des Erfolgs ist, den ersten Schritt zu tun.",
|
||||||
|
"Lächle, auch wenn dein Herz schmerzt. Lächle, auch wenn es Tränen gibt.",
|
||||||
|
"Die meisten unserer Ängste sind größtenteils imaginär.",
|
||||||
|
"Vertraue auf die Zeit. Sie ist ein wunderbarer Erzähler.",
|
||||||
|
"Ein Buch und eine Tasse Kaffee können die Welt verändern.",
|
||||||
|
"Die beste Investition, die du machen kannst, ist in dich selbst.",
|
||||||
|
"Alles fließt, nichts bleibt. Es gibt nichts Dauerhaftes außer der Veränderung.",
|
||||||
|
"Die größere Gefahr für die meisten von uns liegt nicht darin, dass unser Ziel zu hoch ist und wir es verfehlen, sondern darin, dass es zu niedrig ist und wir es erreichen.",
|
||||||
|
"Der einzige Ort, an dem Erfolg vor Arbeit kommt, ist im Wörterbuch.",
|
||||||
|
"Lebe so, als würdest du morgen sterben. Lerne so, als würdest du ewig leben.",
|
||||||
|
"Was immer du tust, tue es mit ganzem Herzen.",
|
||||||
|
"Ein Tag ohne Lachen ist ein verlorener Tag.",
|
||||||
|
"Das Leben ist wie eine Kamera – einfach lächeln und einen guten Tag haben.",
|
||||||
|
"Die besten Dinge im Leben sind nicht die, die man für Geld kaufen kann.",
|
||||||
|
"Denke daran, dass das Glück ein Weg, nicht ein Ziel.",
|
||||||
|
"Jeder Tag ist eine neue Gelegenheit, besser zu sein als gestern.",
|
||||||
|
"Die Sonne wird wieder scheinen, auch wenn es heute regnet.",
|
||||||
|
"Ein kluger Mann macht nicht alle Fehler selbst. Er gibt auch anderen eine Chance.",
|
||||||
|
"Der frühe Vogel fängt den Wurm, aber der zweite Mäuse bekommt den Käse.",
|
||||||
|
"Einfachheit ist die höchste Form der Raffinesse.",
|
||||||
|
"In der Mitte jeder Schwierigkeit liegt eine Gelegenheit.",
|
||||||
|
"Deine Einstellung, nicht deine Fähigkeiten, wird deine Höhe bestimmen.",
|
||||||
|
"Glück ist wie ein Schmetterling. Wenn du es jagst, fliegt es davon. Wenn du dich hinsetzt, kommt es und setzt sich auf deine Schulter.",
|
||||||
|
"Die beste Art, sich selbst zu finden, ist, sich im Dienst an anderen zu verlieren.",
|
||||||
|
"Erfolg ist nicht der Schlüssel zum Glück. Glück ist der Schlüssel zum Erfolg.",
|
||||||
|
"Der beste Rat, den ich je bekommen habe: Sei du selbst.",
|
||||||
|
"Das Leben ist kurz. Lächele, während du noch Zähne hast.",
|
||||||
|
"Ein Tag ohne Musik ist ein verlorener Tag.",
|
||||||
|
"Die größte Freude im Leben ist zu lieben und geliebt zu werden.",
|
||||||
|
"Lebe jeden Tag so, als wäre es dein letzter, eines Tages wirst du Recht haben.",
|
||||||
|
"Die beste Zeit, um glücklich zu sein, ist jetzt.",
|
||||||
|
"Ein wahres Zeichen von Reife ist, wenn jemand dich verletzt und du versuchst, sie zu verstehen, anstatt sie zu verletzen.",
|
||||||
|
"Der beste Weg, mit der Zukunft fertig zu werden, ist, sie Schritt für Schritt zu bewältigen.",
|
||||||
|
"Glück ist eine Richtung, kein Ort.",
|
||||||
|
"Die Schönheit des Lebens liegt in seinen Unvollkommenheiten.",
|
||||||
|
"Ein Freund ist jemand, der die Melodie deines Herzens kennt und sie mitsingt, wenn du sie vergisst.",
|
||||||
|
"Das Geheimnis, im Leben voranzukommen, ist, loszulassen und loszulassen.",
|
||||||
|
"Die besten Dinge im Leben kommen unerwartet.",
|
||||||
|
"Lächle, es ist ansteckend.",
|
||||||
|
"Die beste Medizin gegen Stress ist ein tiefer Atem und ein Lächeln.",
|
||||||
|
"Glück ist die Summe kleiner Glücksmomente.",
|
||||||
|
"Der beste Weg, die Zukunft vorherzusagen, ist, sie zu gestalten.",
|
||||||
|
"Ein Tag mit einem Lächeln ist ein guter Tag.",
|
||||||
|
"Die einfachsten Dinge sind oft die schönsten.",
|
||||||
|
"Ein Buch kann die Welt verändern, eine Idee kann die Geschichte schreiben.",
|
||||||
|
"Die beste Investition ist die in den eigenen Geist.",
|
||||||
|
"Alles, was du in deinem Leben siehst, ist das Ergebnis dessen, was du in deinem Geist siehst.",
|
||||||
|
"Die größte Kraft, die ein Mensch besitzen kann, ist die Macht, sein eigenes Denken zu verändern.",
|
||||||
|
"Der beste Weg, ein Ziel zu erreichen, ist, nie aufzugeben.",
|
||||||
|
"Lebe so, dass du am Ende des Tages sagen kannst: Es war ein guter Tag.",
|
||||||
|
"Die besten Erinnerungen sind die, die wir mit anderen teilen.",
|
||||||
|
"Ein wahrer Freund ist jemand, der dich versteht, auch wenn er nicht mit dir übereinstimmt.",
|
||||||
|
"Der beste Weg, das Leben zu genießen, ist, im Moment zu leben.",
|
||||||
|
"Glück ist kein Zustand, sondern eine Entscheidung.",
|
||||||
|
"Die größten Geschenke des Lebens sind die einfachen Freuden.",
|
||||||
|
"Ein Lächeln ist die kürzeste Distanz zwischen zwei Menschen.",
|
||||||
|
"Die beste Art zu leben ist, im Hier und Jetzt zu leben.",
|
||||||
|
"Jeder Tag ist eine neue Gelegenheit, das Leben in vollen Zügen zu genießen.",
|
||||||
|
"Der beste Freund ist jemand, der dich so liebt, wie du bist.",
|
||||||
|
"Ein Leben in Harmonie mit der Natur bringt wahre Freude.",
|
||||||
|
"Die beste Medizin für eine schlechte Laune ist ein gutes Gespräch.",
|
||||||
|
"Glück ist wie ein Garten: Es wächst, wenn es gepflegt wird.",
|
||||||
|
"Die größten Wunder des Lebens sind die kleinen Dinge, die wir oft übersehen.",
|
||||||
|
"Ein wahres Lächeln kommt von Herzen und kann jeden Tag erhellen.",
|
||||||
|
"Die beste Art, die Zukunft zu sehen, ist, mit einem Lächeln in den Spiegel zu schauen.",
|
||||||
|
"Lebe jeden Tag mit der Gewissheit, dass du das Beste daraus machst.",
|
||||||
|
"Die größte Freude liegt in den einfachen Dingen, die wir oft als selbstverständlich betrachten.",
|
||||||
|
"Ein guter Tag beginnt mit einer positiven Einstellung und einem Lächeln.",
|
||||||
|
"Das Leben ist ein Geschenk – verpacke es mit Liebe und Freude aus.",
|
||||||
|
"Die beste Art, Glück zu finden, ist, es mit anderen zu teilen.",
|
||||||
|
"Jeder Moment ist eine neue Gelegenheit, etwas Großartiges zu beginnen.",
|
||||||
|
"Ein wahrer Schatz im Leben ist ein Freund, der immer für dich da ist.",
|
||||||
|
"Die beste Zeit, um dankbar zu sein, ist jetzt.",
|
||||||
|
"Glück ist kein Ziel, sondern eine Lebensweise.",
|
||||||
|
"Ein Lächeln ist die universelle Sprache der Freundlichkeit.",
|
||||||
|
"Die besten Dinge im Leben sind die, die wir mit Liebe und Leidenschaft tun.",
|
||||||
|
"Lebe jeden Tag so, als wäre er ein Geschenk – denn das ist er.",
|
||||||
|
"Die größte Befriedigung kommt von innen, nicht von außen.",
|
||||||
|
"Ein wahres Lächeln kann die Welt verändern, einen Menschen nach dem anderen.",
|
||||||
|
"Die beste Art, die Zukunft zu gestalten, ist, heute das Beste zu geben.",
|
||||||
|
"Glück ist wie ein Baum: Es wächst, wenn es mit Liebe und Sorgfalt gepflegt wird.",
|
||||||
|
"Jeder Tag ist eine neue Seite in deinem Lebensbuch – schreibe eine schöne Geschichte."
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
"Today is a good day for new adventures!",
|
||||||
|
"Pay attention to small signs – they guide you.",
|
||||||
|
"A smile brings happiness to your life.",
|
||||||
|
"The greatest opportunities often come unexpectedly.",
|
||||||
|
"Patience is the key to many doors.",
|
||||||
|
"An open heart sees more than a thousand eyes.",
|
||||||
|
"Trust the process, even if you don't know the outcome.",
|
||||||
|
"Everything flows – your situation will change too.",
|
||||||
|
"Don't give up, even if the path seems rocky.",
|
||||||
|
"A true friend is a gift from heaven.",
|
||||||
|
"The best time to plant a tree was 20 years ago. The second best time is now.",
|
||||||
|
"Happiness is not a coincidence, but the result of hard work and positive attitude.",
|
||||||
|
"Who makes others happy will be happy themselves.",
|
||||||
|
"Sometimes you need to take a step back to move two steps forward.",
|
||||||
|
"Life is like a bicycle. To keep your balance, you must keep moving.",
|
||||||
|
"A wise person learns from the experience of others.",
|
||||||
|
"The greatest discoveries often come from curiosity.",
|
||||||
|
"Who rests, rusts.",
|
||||||
|
"A good book and a cup of tea are the best companions.",
|
||||||
|
"The sun also shines after the darkest day.",
|
||||||
|
"Happiness is the ability to see the good in the bad.",
|
||||||
|
"A smile costs nothing and brings back a lot.",
|
||||||
|
"The journey is the destination – enjoy the ride, not just the arrival.",
|
||||||
|
"Every day is a new opportunity to change everything.",
|
||||||
|
"Happiness lies in the little things of life.",
|
||||||
|
"You reap what you sow.",
|
||||||
|
"Laugh often, love much, never forget how good life can be.",
|
||||||
|
"A day without a smile is a lost day.",
|
||||||
|
"The future belongs to those who believe in the beauty of their dreams.",
|
||||||
|
"Do something today that your future self will thank you for.",
|
||||||
|
"The best way to predict the future is to create it.",
|
||||||
|
"Dreams are not for those who sleep, but for those who don't give up.",
|
||||||
|
"Every moment is a new opportunity.",
|
||||||
|
"The secret of happiness is not in possession, but in freedom from possession.",
|
||||||
|
"Live each day as if it were your last – one day you'll be right.",
|
||||||
|
"The greatest discovery of a generation is that a person can change their life by changing their attitude.",
|
||||||
|
"Happiness is not something you find, it is something you create.",
|
||||||
|
"The best revenge is a life well lived.",
|
||||||
|
"Give every day a chance to be the best day of your life.",
|
||||||
|
"One sees clearly only with the heart. What is essential is invisible to the eye.",
|
||||||
|
"Whatever you can do or dream you can, begin it. Boldness has genius, power and magic in it.",
|
||||||
|
"The simplest things often bring the greatest happiness.",
|
||||||
|
"A life without risk is a life without opportunity.",
|
||||||
|
"Everything you need is already within you.",
|
||||||
|
"The only way to achieve great things is to view them as a series of small steps.",
|
||||||
|
"What you do today determines your tomorrow.",
|
||||||
|
"A positive mind brings positive things into life.",
|
||||||
|
"The best time to be happy is now. The best place to be happy is here. The best way to be happy is with others.",
|
||||||
|
"Don't live in the past, don't dream of the future, concentrate on the present moment.",
|
||||||
|
"Happiness is not a coincidence. It is the result of your daily habits.",
|
||||||
|
"The world is full of wonderful things we cannot see.",
|
||||||
|
"Be the change that you wish to see in the world.",
|
||||||
|
"Every day offers a new page in your life's book.",
|
||||||
|
"The secret of success is to take the first step.",
|
||||||
|
"Smile, even if your heart aches. Smile, even if there are tears.",
|
||||||
|
"Most of our fears are largely imaginary.",
|
||||||
|
"Trust in time. It is a wonderful storyteller.",
|
||||||
|
"A book and a cup of coffee can change the world.",
|
||||||
|
"The best investment you can make is in yourself.",
|
||||||
|
"Everything flows, nothing stands still. There is nothing permanent except change.",
|
||||||
|
"The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.",
|
||||||
|
"The only place where success comes before work is in the dictionary.",
|
||||||
|
"Live as if you were to die tomorrow. Learn as if you were to live forever.",
|
||||||
|
"Whatever you do, do it with all your heart.",
|
||||||
|
"A day without laughter is a lost day.",
|
||||||
|
"Life is like a camera – just smile and have a good day.",
|
||||||
|
"The best things in life are not the ones you can buy with money.",
|
||||||
|
"Remember that happiness is a way, not a destination.",
|
||||||
|
"Every day is a new opportunity to be better than yesterday.",
|
||||||
|
"The sun will shine again, even if it's raining today.",
|
||||||
|
"A wise man doesn't make all the mistakes himself. He gives others a chance too.",
|
||||||
|
"The early bird catches the worm, but the second mouse gets the cheese.",
|
||||||
|
"Simplicity is the ultimate sophistication.",
|
||||||
|
"In the middle of every difficulty lies opportunity.",
|
||||||
|
"Your attitude, not your aptitude, will determine your altitude.",
|
||||||
|
"Happiness is like a butterfly. If you chase it, it will elude you. If you sit quietly, it may land on your shoulder.",
|
||||||
|
"The best way to find yourself is to lose yourself in the service of others.",
|
||||||
|
"Happiness is not the key to success. Success is the key to happiness.",
|
||||||
|
"The best advice I ever received: Be yourself.",
|
||||||
|
"Life is short. Smile while you still have teeth.",
|
||||||
|
"A day without music is a day wasted.",
|
||||||
|
"The greatest joy in life is to love and be loved.",
|
||||||
|
"Live each day as if it were your last, one day you will be right.",
|
||||||
|
"The best time to be happy is now.",
|
||||||
|
"A true sign of maturity is when someone hurts you and you try to understand them instead of hurting them back.",
|
||||||
|
"The best way to deal with the future is to take it one step at a time.",
|
||||||
|
"Happiness is a direction, not a place.",
|
||||||
|
"The beauty of life lies in its imperfections.",
|
||||||
|
"A friend is someone who knows the melody of your heart and sings it back to you when you have forgotten the words.",
|
||||||
|
"The secret of getting ahead is getting started and letting go of distractions.",
|
||||||
|
"The best things in life happen unexpectedly.",
|
||||||
|
"Smile, it's contagious.",
|
||||||
|
"The best medicine for stress is a deep breath and a smile.",
|
||||||
|
"Happiness is the sum of small happy moments.",
|
||||||
|
"The best way to predict the future is to create it with a smile.",
|
||||||
|
"A day with a smile is a good day.",
|
||||||
|
"The simplest things are often the most beautiful.",
|
||||||
|
"A book can change the world, an idea can write history.",
|
||||||
|
"The best investment is the one in your own mind.",
|
||||||
|
"Everything you see in your life is the result of what you see in your mind.",
|
||||||
|
"The greatest power a person can possess is the power to change their own thinking.",
|
||||||
|
"The best way to achieve a goal is to never give up.",
|
||||||
|
"Live so that at the end of the day you can say: It was a good day.",
|
||||||
|
"The best memories are the ones we share with others.",
|
||||||
|
"A true friend is someone who understands you even when they don't agree with you.",
|
||||||
|
"The best way to enjoy life is to live in the moment.",
|
||||||
|
"Happiness is not a condition, but a decision.",
|
||||||
|
"The greatest gifts in life are the simple joys.",
|
||||||
|
"A smile is the shortest distance between two people.",
|
||||||
|
"The best way to live is to live in the here and now.",
|
||||||
|
"Every day is a new opportunity to enjoy life to the fullest.",
|
||||||
|
"The best friend is someone who loves you for who you are.",
|
||||||
|
"A life in harmony with nature brings true joy.",
|
||||||
|
"The best medicine for a bad mood is a good conversation.",
|
||||||
|
"Happiness is like a garden: it grows when it is nurtured.",
|
||||||
|
"The greatest miracles of life are the small things we often overlook.",
|
||||||
|
"A true smile comes from the heart and can brighten any day.",
|
||||||
|
"The best way to see the future is to look in the mirror with a smile.",
|
||||||
|
"Live each day with the certainty that you are making the best of it.",
|
||||||
|
"The greatest joy lies in the simple things we often take for granted.",
|
||||||
|
"A good day starts with a positive attitude and a smile.",
|
||||||
|
"Life is a gift – wrap it with love and joy.",
|
||||||
|
"The best way to find happiness is to share it with others.",
|
||||||
|
"Every moment is a new opportunity to start something great.",
|
||||||
|
"A true treasure in life is a friend who is always there for you.",
|
||||||
|
"The best time to be grateful is now.",
|
||||||
|
"Happiness is not a destination, but a way of life.",
|
||||||
|
"A smile is the universal language of kindness.",
|
||||||
|
"The best things in life are the ones we do with love and passion.",
|
||||||
|
"Live each day as if it were a gift – because it is.",
|
||||||
|
"The greatest satisfaction comes from within, not from without.",
|
||||||
|
"A true smile can change the world, one person at a time.",
|
||||||
|
"The best way to shape the future is to give your best today.",
|
||||||
|
"Happiness is like a tree: it grows when nurtured with love and care.",
|
||||||
|
"Every day is a new page in your life's book – write a beautiful story."
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Clickable Konfiguration für Ubuntu Touch Apps
|
||||||
|
# Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
#
|
||||||
|
# VERWENDUNG:
|
||||||
|
# 1. Kopiere diese Datei nach clickable.yaml in deinem Projekt
|
||||||
|
# 2. Passe name, version und maintainer an
|
||||||
|
#
|
||||||
|
# WICHTIG (1.7):
|
||||||
|
# - builder: pure-qml-cmake (für QML+Python-Apps ohne nativen Code)
|
||||||
|
# - kill: qmlscene (für Desktop-Tests)
|
||||||
|
# - Architekur: nur "all" unterstützt (pure-qml-cmake erzwingt das)
|
||||||
|
#
|
||||||
|
# Für Apps MIT nativem C++-Code:
|
||||||
|
# builder: cmake oder qmake
|
||||||
|
# kill: fortunecookie
|
||||||
|
|
||||||
|
clickable_minimum_required: 8.8.0
|
||||||
|
builder: pure-qml-cmake # ✅ STANDARD 1.7 für QML+Python-Apps
|
||||||
|
kill: qmlscene
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"policy_version": 20.04,
|
||||||
|
"policy_groups": [
|
||||||
|
"networking",
|
||||||
|
"audio",
|
||||||
|
"content_exchange"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=Fortune Cookie
|
||||||
|
Comment=Glückskeks App mit Sprüchen, Musik und einfacher Verwaltung
|
||||||
|
Exec=qmlscene %U qml/Main.qml
|
||||||
|
Icon=assets/cookie_closed.png
|
||||||
|
Terminal=false
|
||||||
|
Categories=Utility;
|
||||||
|
X-Lomiri-Touch=true
|
||||||
|
X-Ubuntu-Applications=fortunecookie
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DESKTOP.FILE TEMPLATE für Ubuntu Touch Apps
|
||||||
|
* Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
*
|
||||||
|
* VERWENDUNG:
|
||||||
|
* 1. Kopiere diese Datei nach fortunecookie.desktop.in in deinem Projekt
|
||||||
|
* 2. Ersetze alle <...> Platzhalter mit deinen Werten
|
||||||
|
* 3. Benenne die Datei in fortunecookie.desktop.in um
|
||||||
|
*
|
||||||
|
* WICHTIG (1.7):
|
||||||
|
* ✅ Exec=qmlscene %U qml/Main.qml (für pure-QML-Apps mit pure-qml-cmake)
|
||||||
|
* ✅ X-Lomiri-Touch=true (für Lomiri/Ubuntu Touch)
|
||||||
|
* ✅ X-Ubuntu-Applications=fortunecookie (App-Name ohne .desktop Endung)
|
||||||
|
*
|
||||||
|
* ❌ VERMEIDEN:
|
||||||
|
* - Exec=fortunecookie (funktioniert nicht mit pure-qml-cmake!)
|
||||||
|
* - Terminal=true (UI-Apps brauchen kein Terminal)
|
||||||
|
*
|
||||||
|
* Beispiel für eine fertige Datei (metime.desktop.in):
|
||||||
|
* [Desktop Entry]
|
||||||
|
* Version=1.0
|
||||||
|
* Type=Application
|
||||||
|
* Name=Metime
|
||||||
|
* Comment=Mein Metime Manager
|
||||||
|
* Exec=qmlscene %U qml/Main.qml
|
||||||
|
* Icon=assets/cookie_closed.png
|
||||||
|
* Terminal=false
|
||||||
|
* Categories=Utility;
|
||||||
|
* X-Lomiri-Touch=true
|
||||||
|
* X-Ubuntu-Applications=metime
|
||||||
|
*/
|
||||||
Executable
+678
@@ -0,0 +1,678 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Git-Helper für Ubuntu Touch Entwicklung
|
||||||
|
# Version: 1.7
|
||||||
|
# Autor: darklithium <dev@darklithium.de>
|
||||||
|
#
|
||||||
|
# Zweck: Narrensicheres Git für Entwickler
|
||||||
|
# - Einfache Befehle für häufige Git-Operationen
|
||||||
|
# - Automatische Branch-Naming
|
||||||
|
# - Konsistente Workflows
|
||||||
|
#
|
||||||
|
# Verwendung:
|
||||||
|
# ./git-helper.sh <befehl> [argumente]
|
||||||
|
#
|
||||||
|
# Beispiele:
|
||||||
|
# ./git-helper.sh status
|
||||||
|
# ./git-helper.sh new-feature login-system
|
||||||
|
# ./git-helper.sh merge-stable
|
||||||
|
|
||||||
|
# --- KONFIGURATION ---
|
||||||
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||||
|
if [[ -z "$REPO_ROOT" ]]; then
|
||||||
|
echo "❌ Nicht in einem Git-Repository!"
|
||||||
|
echo " → cd /pfad/zu/deinem/git/repo"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | sed 's/refs\/heads\///')
|
||||||
|
MAINTAINER="darklithium <dev@darklithium.de>"
|
||||||
|
|
||||||
|
# Farben
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# --- FUNKTIONEN ---
|
||||||
|
|
||||||
|
# Hilfstext anzeigen
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
📖 Git-Helper v1.7 - Hilfstext
|
||||||
|
|
||||||
|
Verfügbare Befehle:
|
||||||
|
|
||||||
|
📊 STATUS & INFO
|
||||||
|
status Zeigt Git-Status an
|
||||||
|
branches Liste alle Branches
|
||||||
|
log Zeigt Commit-Historie
|
||||||
|
diff Zeigt unstaged Änderungen
|
||||||
|
diff-staged Zeigt staged Änderungen
|
||||||
|
|
||||||
|
🌿 BRANCHES
|
||||||
|
new-feature <name> Erstellt Feature-Branch (Basis: testing)
|
||||||
|
new-bugfix <name> Erstellt Bugfix-Branch (Basis: testing)
|
||||||
|
new-hotfix <name> Erstellt Hotfix-Branch (Basis: stable)
|
||||||
|
switch <branch> Wechselt zu Branch
|
||||||
|
delete <branch> Löscht Branch (lokal)
|
||||||
|
|
||||||
|
🔄 MERGE & REBASE
|
||||||
|
merge-stable Merged testing → stable
|
||||||
|
merge-testing Merged feature/* → testing
|
||||||
|
rebase-testing Rebase aktuellen Branch auf testing
|
||||||
|
|
||||||
|
📤 PUSH & PULL
|
||||||
|
push Pushed aktuellen Branch
|
||||||
|
pull Pullt Änderungen
|
||||||
|
push-all Pushed alle Branches
|
||||||
|
fetch Fetched alle Remote-Branches
|
||||||
|
|
||||||
|
🏷️ TAGS
|
||||||
|
tag <version> Erstellt Tag (z. B. v1.0.0)
|
||||||
|
tag-push <version> Pushed Tag zum Remote
|
||||||
|
tags Liste alle Tags
|
||||||
|
|
||||||
|
📝 COMMITS
|
||||||
|
commit <msg> Erstellt Commit mit Message
|
||||||
|
amend Ändert letzten Commit
|
||||||
|
revert <commit> Revertet einen Commit
|
||||||
|
|
||||||
|
🧹 AUFRÄUMEN
|
||||||
|
cleanup Löscht gemergte Branches
|
||||||
|
cleanup-all Löscht alle lokalen Branches außer stable/testing
|
||||||
|
|
||||||
|
📋 REVIEW
|
||||||
|
review Zeigt Commits zur Review
|
||||||
|
review-last Zeigt letzten Commit detailliert
|
||||||
|
|
||||||
|
❓ HILFE
|
||||||
|
help Zeigt diesen Hilfstext
|
||||||
|
version Zeigt Version
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
./git-helper.sh new-feature login-system
|
||||||
|
./git-helper.sh switch testing
|
||||||
|
./git-helper.sh merge-stable
|
||||||
|
./git-helper.sh push
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt aktuellen Status
|
||||||
|
cmd_status() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Git-Status ===${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Repository:${NC} $REPO_ROOT"
|
||||||
|
echo -e "${YELLOW}Aktueller Branch:${NC} $CURRENT_BRANCH"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Branch-Status
|
||||||
|
if [[ "$CURRENT_BRANCH" == "stable" || "$CURRENT_BRANCH" == "testing" ]]; then
|
||||||
|
echo -e "${GREEN}✅ Haupt-Branch${NC}"
|
||||||
|
elif [[ "$CURRENT_BRANCH" =~ ^feature/ ]]; then
|
||||||
|
echo -e "${BLUE}📌 Feature-Branch${NC}"
|
||||||
|
elif [[ "$CURRENT_BRANCH" =~ ^bugfix/ ]]; then
|
||||||
|
echo -e "${RED}🐛 Bugfix-Branch${NC}"
|
||||||
|
elif [[ "$CURRENT_BRANCH" =~ ^hotfix/ ]]; then
|
||||||
|
echo -e "${RED}🚨 Hotfix-Branch${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠️ Unbekannter Branch-Typ${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Änderungen:${NC}"
|
||||||
|
git status --short
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Remote-Status:${NC}"
|
||||||
|
git remote -v
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Liste alle Branches
|
||||||
|
cmd_branches() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Alle Branches ===${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}🟢 Haupt-Branches:${NC}"
|
||||||
|
git branch | grep -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//'
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}📌 Feature-Branches:${NC}"
|
||||||
|
git branch | grep -E '^\*?\s*feature/' | sed 's/^[ *]//'
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}🐛 Bugfix-Branches:${NC}"
|
||||||
|
git branch | grep -E '^\*?\s*bugfix/' | sed 's/^[ *]//'
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}🚨 Hotfix-Branches:${NC}"
|
||||||
|
git branch | grep -E '^\*?\s*hotfix/' | sed 's/^[ *]//'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt Commit-Historie
|
||||||
|
cmd_log() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Commit-Historie ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git log --oneline --graph --all -20
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt unstaged Änderungen
|
||||||
|
cmd_diff() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Unstaged Änderungen ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git diff
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt staged Änderungen
|
||||||
|
cmd_diff_staged() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Staged Änderungen ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git diff --cached
|
||||||
|
}
|
||||||
|
|
||||||
|
# Erstellt Feature-Branch
|
||||||
|
cmd_new_feature() {
|
||||||
|
local branch_name="feature/$1"
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh new-feature <name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob Branch schon existiert
|
||||||
|
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
|
||||||
|
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Basis-Branch prüfen (sollte testing sein)
|
||||||
|
if git show-ref --verify --quiet refs/heads/testing; then
|
||||||
|
BASE_BRANCH="testing"
|
||||||
|
elif git show-ref --verify --quiet refs/heads/stable; then
|
||||||
|
BASE_BRANCH="stable"
|
||||||
|
echo -e "${YELLOW}⚠️ testing-Branch nicht gefunden, verwende stable${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Basis-Branch (testing oder stable) nicht gefunden!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Branch erstellen und wechseln
|
||||||
|
git checkout -b "$branch_name" "$BASE_BRANCH"
|
||||||
|
echo -e "${GREEN}✅ Feature-Branch '$branch_name' erstellt (Basis: $BASE_BRANCH)${NC}"
|
||||||
|
echo " → git push --set-upstream origin $branch_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Erstellt Bugfix-Branch
|
||||||
|
cmd_new_bugfix() {
|
||||||
|
local branch_name="bugfix/$1"
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh new-bugfix <name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob Branch schon existiert
|
||||||
|
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
|
||||||
|
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Basis-Branch prüfen
|
||||||
|
if git show-ref --verify --quiet refs/heads/testing; then
|
||||||
|
BASE_BRANCH="testing"
|
||||||
|
elif git show-ref --verify --quiet refs/heads/stable; then
|
||||||
|
BASE_BRANCH="stable"
|
||||||
|
echo -e "${YELLOW}⚠️ testing-Branch nicht gefunden, verwende stable${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Basis-Branch (testing oder stable) nicht gefunden!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git checkout -b "$branch_name" "$BASE_BRANCH"
|
||||||
|
echo -e "${GREEN}✅ Bugfix-Branch '$branch_name' erstellt (Basis: $BASE_BRANCH)${NC}"
|
||||||
|
echo " → git push --set-upstream origin $branch_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Erstellt Hotfix-Branch
|
||||||
|
cmd_new_hotfix() {
|
||||||
|
local branch_name="hotfix/$1"
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh new-hotfix <name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob Branch schon existiert
|
||||||
|
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
|
||||||
|
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Hotfix muss von stable kommen
|
||||||
|
if ! git show-ref --verify --quiet refs/heads/stable; then
|
||||||
|
echo -e "${RED}❌ stable-Branch nicht gefunden!${NC}"
|
||||||
|
echo " → Hotfix-Branches müssen von stable ausgehen"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git checkout -b "$branch_name" stable
|
||||||
|
echo -e "${GREEN}✅ Hotfix-Branch '$branch_name' erstellt (Basis: stable)${NC}"
|
||||||
|
echo " → git push --set-upstream origin $branch_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wechselt Branch
|
||||||
|
cmd_switch() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh switch <branch>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Branch-Namen validieren
|
||||||
|
case "$1" in
|
||||||
|
stable|testing|feature/*|bugfix/*|hotfix/*|release/*)
|
||||||
|
git checkout "$1"
|
||||||
|
echo -e "${GREEN}✅ Zu Branch '$1' gewechselt${NC}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}❌ Ungültiger Branch-Name: '$1'${NC}"
|
||||||
|
echo " → Erlaubt: stable, testing, feature/*, bugfix/*, hotfix/*"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Löscht Branch
|
||||||
|
cmd_delete() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh delete <branch>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nicht stable oder testing löschen
|
||||||
|
if [[ "$1" == "stable" || "$1" == "testing" ]]; then
|
||||||
|
echo -e "${RED}❌ Cannot delete main branches (stable/testing)!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob Branch existiert
|
||||||
|
if ! git show-ref --verify --quiet refs/heads/"$1"; then
|
||||||
|
echo -e "${RED}❌ Branch '$1' existiert nicht!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob Branch aktuell aktiv ist
|
||||||
|
if [[ "$1" == "$CURRENT_BRANCH" ]]; then
|
||||||
|
echo -e "${RED}❌ Kann aktiven Branch nicht löschen!${NC}"
|
||||||
|
echo " → Wechsle zuerst zu einem anderen Branch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git branch -D "$1"
|
||||||
|
echo -e "${GREEN}✅ Branch '$1' gelöscht (lokal)${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Merged testing → stable
|
||||||
|
cmd_merge_stable() {
|
||||||
|
# Prüfe ob auf stable Branch
|
||||||
|
if [[ "$CURRENT_BRANCH" != "stable" ]]; then
|
||||||
|
echo -e "${RED}❌ Nicht auf stable-Branch!${NC}"
|
||||||
|
echo " → git checkout stable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe ob testing existiert
|
||||||
|
if ! git show-ref --verify --quiet refs/heads/testing; then
|
||||||
|
echo -e "${RED}❌ testing-Branch existiert nicht!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}🔍 Prüfe ob testing in stable gemerged ist...${NC}"
|
||||||
|
if git merge --no-commit --no-ff testing 2>/dev/null; then
|
||||||
|
echo -e "${GREEN}✅ testing kann in stable gemerged werden${NC}"
|
||||||
|
git merge --no-ff testing -m "merge: testing → stable"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}✅ testing erfolgreich in stable gemerged!${NC}"
|
||||||
|
echo " → git push origin stable"
|
||||||
|
echo " → git push origin testing"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Merge-Konflikte!${NC}"
|
||||||
|
echo " → Konflikte manuell lösen und dann:"
|
||||||
|
echo " → git commit"
|
||||||
|
echo " → git merge --continue"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Merged feature/* → testing
|
||||||
|
cmd_merge_testing() {
|
||||||
|
# Prüfe ob auf testing Branch
|
||||||
|
if [[ "$CURRENT_BRANCH" != "testing" ]]; then
|
||||||
|
echo -e "${RED}❌ Nicht auf testing-Branch!${NC}"
|
||||||
|
echo " → git checkout testing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Zeige alle Feature-Branches
|
||||||
|
echo -e "${YELLOW}Verfügbare Feature-Branches:${NC}"
|
||||||
|
git branch | grep -E '^\s*feature/' | sed 's/^[ *]//' | sed 's/feature\///'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Branch-Namen abfragen
|
||||||
|
read -p "Welchen Feature-Branch möchtest du mergen? (Name ohne 'feature/')? " branch_name
|
||||||
|
FULL_BRANCH="feature/$branch_name"
|
||||||
|
|
||||||
|
# Prüfe ob Branch existiert
|
||||||
|
if ! git show-ref --verify --quiet refs/heads/"$FULL_BRANCH"; then
|
||||||
|
echo -e "${RED}❌ Branch '$FULL_BRANCH' existiert nicht!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}🔍 Prüfe ob $FULL_BRANCH in testing gemerged ist...${NC}"
|
||||||
|
if git merge --no-commit --no-ff "$FULL_BRANCH" 2>/dev/null; then
|
||||||
|
echo -e "${GREEN}✅ $FULL_BRANCH kann in testing gemerged werden${NC}"
|
||||||
|
git merge --no-ff "$FULL_BRANCH" -m "merge: $FULL_BRANCH → testing"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}✅ $FULL_BRANCH erfolgreich in testing gemerged!${NC}"
|
||||||
|
echo " → git push origin testing"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Merge-Konflikte!${NC}"
|
||||||
|
echo " → Konflikte manuell lösen und dann:"
|
||||||
|
echo " → git commit"
|
||||||
|
echo " → git merge --continue"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rebase auf testing
|
||||||
|
cmd_rebase_testing() {
|
||||||
|
if ! git show-ref --verify --quiet refs/heads/testing; then
|
||||||
|
echo -e "${RED}❌ testing-Branch existiert nicht!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}🔍 Rebase $CURRENT_BRANCH auf testing...${NC}"
|
||||||
|
if git rebase testing; then
|
||||||
|
echo -e "${GREEN}✅ $CURRENT_BRANCH auf testing gerebased!${NC}"
|
||||||
|
echo " → git push --force-with-lease"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Rebase-Konflikte!${NC}"
|
||||||
|
echo " → Konflikte lösen mit:"
|
||||||
|
echo " → git rebase --continue (wenn gelöst)"
|
||||||
|
echo " → git rebase --abort (zum Abbrechen)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Push
|
||||||
|
cmd_push() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
# Push aktuellen Branch
|
||||||
|
git push
|
||||||
|
echo -e "${GREEN}✅ $CURRENT_BRANCH gepusht${NC}"
|
||||||
|
else
|
||||||
|
git push origin "$1"
|
||||||
|
echo -e "${GREEN}✅ Branch '$1' gepusht${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pull
|
||||||
|
cmd_pull() {
|
||||||
|
git pull
|
||||||
|
echo -e "${GREEN}✅ Änderungen gepullt${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Push alle Branches
|
||||||
|
cmd_push_all() {
|
||||||
|
git push --all
|
||||||
|
echo -e "${GREEN}✅ Alle Branches gepusht${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch
|
||||||
|
cmd_fetch() {
|
||||||
|
git fetch --all
|
||||||
|
echo -e "${GREEN}✅ Alle Remote-Branches gefetched${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Erstellt Tag
|
||||||
|
cmd_tag() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlende Versionsnummer!${NC}"
|
||||||
|
echo " → ./git-helper.sh tag v1.0.0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe Format (sollte wie v1.0.0 aussehen)
|
||||||
|
if ! [[ "$1" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Tag-Format sollte vMAJOR.MINOR.PATCH sein (z. B. v1.0.0)${NC}"
|
||||||
|
read -p "Fortfahren mit '$1'? (j/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
git tag -a "$1" -m "Release $1"
|
||||||
|
echo -e "${GREEN}✅ Tag '$1' erstellt${NC}"
|
||||||
|
echo " → git-helper.sh tag-push $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pushed Tag
|
||||||
|
cmd_tag_push() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlender Tag-Name!${NC}"
|
||||||
|
echo " → ./git-helper.sh tag-push v1.0.0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git push origin "$1"
|
||||||
|
echo -e "${GREEN}✅ Tag '$1' gepusht${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Liste alle Tags
|
||||||
|
cmd_tags() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Alle Tags ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git tag -l
|
||||||
|
}
|
||||||
|
|
||||||
|
# Erstellt Commit
|
||||||
|
cmd_commit() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlende Commit-Message!${NC}"
|
||||||
|
echo " → ./git-helper.sh commit 'feat: neue Funktion'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe Format (sollte Typ: Beschreibung sein)
|
||||||
|
if ! [[ "$1" =~ ^[a-z]+:\ .+ ]]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Commit-Message sollte Format <Typ>: <Beschreibung> haben${NC}"
|
||||||
|
echo " Beispiel: feat: neue Funktion"
|
||||||
|
echo ""
|
||||||
|
read -p "Fortfahren mit '$1'? (j/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
git commit -m "$1"
|
||||||
|
echo -e "${GREEN}✅ Commit erstellt: $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ändert letzten Commit
|
||||||
|
cmd_amend() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
git commit --amend --no-edit
|
||||||
|
echo -e "${GREEN}✅ Letzter Commit geändert (gleiche Message)${NC}"
|
||||||
|
else
|
||||||
|
git commit --amend -m "$1"
|
||||||
|
echo -e "${GREEN}✅ Letzter Commit geändert: $1${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Revertet Commit
|
||||||
|
cmd_revert() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo -e "${RED}❌ Fehlende Commit-ID!${NC}"
|
||||||
|
echo " → ./git-helper.sh revert <commit-hash>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git revert "$1"
|
||||||
|
echo -e "${GREEN}✅ Commit $1 revertet${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Löscht gemergte Branches
|
||||||
|
cmd_cleanup() {
|
||||||
|
echo -e "${YELLOW}🔍 Suche gemergte Branches...${NC}"
|
||||||
|
|
||||||
|
# Alle Branches außer stable und testing
|
||||||
|
MERGED_BRANCHES=$(git branch --merged stable | grep -v -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//' | sed 's/^[[:space:]]*//')
|
||||||
|
|
||||||
|
if [[ -z "$MERGED_BRANCHES" ]]; then
|
||||||
|
echo -e "${GREEN}✅ Keine gemergten Branches zum Löschen gefunden${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Gemergte Branches:${NC}"
|
||||||
|
echo "$MERGED_BRANCHES"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Alle gemergten Branches löschen? (j/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[JjYy]$ ]]; then
|
||||||
|
for branch in $MERGED_BRANCHES; do
|
||||||
|
git branch -D "$branch"
|
||||||
|
echo -e "${GREEN}✅ Gelöscht: $branch${NC}"
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}✅ Alle gemergten Branches gelöscht${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}❌ Abgebrochen${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Löscht alle lokalen Branches außer stable/testing
|
||||||
|
cmd_cleanup_all() {
|
||||||
|
echo -e "${RED}⚠️ WARNING: Dies löscht ALLE lokalen Branches außer stable und testing!${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Fortfahren? (j/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
|
||||||
|
echo -e "${YELLOW}❌ Abgebrochen${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Alle Branches außer stable und testing
|
||||||
|
ALL_BRANCHES=$(git branch | grep -v -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//' | sed 's/^[[:space:]]*//')
|
||||||
|
|
||||||
|
if [[ -z "$ALL_BRANCHES" ]]; then
|
||||||
|
echo -e "${GREEN}✅ Keine zusätzlichen Branches gefunden${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for branch in $ALL_BRANCHES; do
|
||||||
|
git branch -D "$branch"
|
||||||
|
echo -e "${GREEN}✅ Gelöscht: $branch${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${GREEN}✅ Alle lokalen Branches (außer stable/testing) gelöscht${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt Commits zur Review
|
||||||
|
cmd_review() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Commits zur Review (nicht gepusht) ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git log --oneline origin/$CURRENT_BRANCH..$CURRENT_BRANCH
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ $? -eq 0 && -n "$(git log --oneline origin/$CURRENT_BRANCH..$CURRENT_BRANCH 2>/dev/null)" ]]; then
|
||||||
|
echo -e "${YELLOW}📝 Tipp: Nutze diese Commits für Code-Review${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt letzten Commit detailliert
|
||||||
|
cmd_review_last() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== Letzter Commit ===${NC}"
|
||||||
|
echo ""
|
||||||
|
git show HEAD --stat
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zeigt Version
|
||||||
|
cmd_version() {
|
||||||
|
echo "Git-Helper v1.7"
|
||||||
|
echo "Framework: START-UT-DEV 1.7"
|
||||||
|
echo "Maintainer: darklithium <dev@darklithium.de>"
|
||||||
|
echo "Stand: 30.05.2026"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- HAUPTPROGRAMM ---
|
||||||
|
|
||||||
|
# Keine Argumente → Hilfe anzeigen
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Command Dispatch
|
||||||
|
COMMAND="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$COMMAND" in
|
||||||
|
status) cmd_status ;;
|
||||||
|
branches) cmd_branches ;;
|
||||||
|
log) cmd_log ;;
|
||||||
|
diff) cmd_diff ;;
|
||||||
|
diff-staged) cmd_diff_staged ;;
|
||||||
|
|
||||||
|
new-feature) cmd_new_feature "$1" ;;
|
||||||
|
new-bugfix) cmd_new_bugfix "$1" ;;
|
||||||
|
new-hotfix) cmd_new_hotfix "$1" ;;
|
||||||
|
|
||||||
|
switch) cmd_switch "$1" ;;
|
||||||
|
delete) cmd_delete "$1" ;;
|
||||||
|
|
||||||
|
merge-stable) cmd_merge_stable ;;
|
||||||
|
merge-testing) cmd_merge_testing ;;
|
||||||
|
rebase-testing) cmd_rebase_testing ;;
|
||||||
|
|
||||||
|
push) cmd_push "$1" ;;
|
||||||
|
pull) cmd_pull ;;
|
||||||
|
push-all) cmd_push_all ;;
|
||||||
|
fetch) cmd_fetch ;;
|
||||||
|
|
||||||
|
tag) cmd_tag "$1" ;;
|
||||||
|
tag-push) cmd_tag_push "$1" ;;
|
||||||
|
tags) cmd_tags ;;
|
||||||
|
|
||||||
|
commit) cmd_commit "$*" ;;
|
||||||
|
amend) cmd_amend "$*" ;;
|
||||||
|
revert) cmd_revert "$1" ;;
|
||||||
|
|
||||||
|
cleanup) cmd_cleanup ;;
|
||||||
|
cleanup-all) cmd_cleanup_all ;;
|
||||||
|
|
||||||
|
review) cmd_review ;;
|
||||||
|
review-last) cmd_review_last ;;
|
||||||
|
|
||||||
|
help) show_help ;;
|
||||||
|
version) cmd_version ;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo -e "${RED}❌ Unbekannter Befehl: $COMMAND${NC}"
|
||||||
|
echo ""
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "fortunecookie.darklithium",
|
||||||
|
"title": "Fortune Cookie",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Glückskeks App mit Sprüchen, Musik und einfacher Listenverwaltung",
|
||||||
|
"maintainer": "Christian Franz <dev@darklithium.de>",
|
||||||
|
"architecture": "all",
|
||||||
|
"framework": "ubuntu-sdk-20.04",
|
||||||
|
"hooks": {
|
||||||
|
"fortunecookie": {
|
||||||
|
"apparmor": "fortunecookie.apparmor",
|
||||||
|
"desktop": "fortunecookie.desktop"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MANIFEST.JSON.IN TEMPLATE für Ubuntu Touch Apps
|
||||||
|
* Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
*
|
||||||
|
* VERWENDUNG:
|
||||||
|
* 1. Kopiere diese Datei nach manifest.json.in in deinem Projekt
|
||||||
|
* 2. Ersetze alle <...> Platzhalter mit deinen Werten
|
||||||
|
*
|
||||||
|
* WICHTIG (1.7):
|
||||||
|
* ✅ Nur Standardfelder verwenden!
|
||||||
|
* ✅ architecture: "all" (pure-qml-cmake erzwingt das)
|
||||||
|
* ✅ framework: "ubuntu-sdk-20.04"
|
||||||
|
* ✅ maintainer: Format "Vorname Nachname <email>" (keine spitzen Klammern um den Namen!)
|
||||||
|
*
|
||||||
|
* ❌ VERMEIDEN (schlägt Validierung fehl):
|
||||||
|
* - "permissions": []
|
||||||
|
* - "policy_groups": []
|
||||||
|
* - "read_path": []
|
||||||
|
* - "write_path": []
|
||||||
|
*
|
||||||
|
* Beispiel für eine fertige Datei:
|
||||||
|
* {
|
||||||
|
* "name": "meine-app.darklithium",
|
||||||
|
* "title": "Meine App",
|
||||||
|
* "version": "0.1.0",
|
||||||
|
* "description": "Beschreibung",
|
||||||
|
* "maintainer": "Christian Franz <dev@darklithium.de>",
|
||||||
|
* "architecture": "all",
|
||||||
|
* "framework": "ubuntu-sdk-20.04",
|
||||||
|
* "hooks": {
|
||||||
|
* "meine-app": {
|
||||||
|
* "apparmor": "meine-app.apparmor",
|
||||||
|
* "desktop": "meine-app.desktop"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* UNIVERSELLER QML Haupt-Template für Ubuntu Touch Apps
|
||||||
|
* Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
*
|
||||||
|
* VERWENDUNG:
|
||||||
|
* 1. Kopiere diese Datei nach qml/Main.qml
|
||||||
|
* 2. Ersetze '<app-name>' mit deinem App-Namen
|
||||||
|
* 3. Passe Titel und UI-Elemente an
|
||||||
|
* 4. Füge deine Python-Modul-Imports hinzu
|
||||||
|
*
|
||||||
|
* WICHTIG (1.7):
|
||||||
|
* - Immer QtQuick 2.7 und Lomiri.Components 1.3 verwenden
|
||||||
|
* - QtQuick.Layouts 1.3 für Layouts importieren
|
||||||
|
* - fontSize als STRING verwenden ("large", "x-large", "medium")
|
||||||
|
* - PageFooter existiert NICHT → als Label implementieren
|
||||||
|
* - PyOtherSide mit Qt.resolvedUrl("../src") einbinden
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3 // ✅ NEU 1.7: Notwendig für ColumnLayout!
|
||||||
|
import Lomiri.Components 1.3
|
||||||
|
import Lomiri.Components.Popups 1.3
|
||||||
|
import io.thp.pyotherside 1.4
|
||||||
|
|
||||||
|
MainView {
|
||||||
|
id: root
|
||||||
|
objectName: 'mainView'
|
||||||
|
|
||||||
|
// APP META-DATEN (Anpassen!)
|
||||||
|
applicationName: '<app-name>.darklithium'
|
||||||
|
width: units.gu(45)
|
||||||
|
height: units.gu(75)
|
||||||
|
theme.name: "Lomiri.Components.Themes.SuruDark"
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// PYTHON-MODUL (STANDARD 1.7)
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
Python {
|
||||||
|
id: py
|
||||||
|
Component.onCompleted: {
|
||||||
|
// ✅ STANDARD 1.7: Qt.resolvedUrl funktioniert!
|
||||||
|
addImportPath(Qt.resolvedUrl("../src"));
|
||||||
|
|
||||||
|
importModule('<app-name>', function() {
|
||||||
|
console.log("Python-Modul <app-name> geladen");
|
||||||
|
// Initialisierung nach erfolgreicher Modul-Ladung
|
||||||
|
statusLabel.text = py.call_sync("<app-name>.get_status_text", []);
|
||||||
|
footerLabel.text = py.call_sync("<app-name>.get_platform", []);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onError: {
|
||||||
|
console.log('Python Fehler: ' + traceback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// HAUPTSSeITE (Anpassen nach Bedarf)
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: mainPage
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// Header
|
||||||
|
header: PageHeader {
|
||||||
|
title: "<App-Name>" // App-Name anpassen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptinhalt (ColumnLayout für vertikale Anordnung)
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: units.gu(2) // 2 GU Abstand zwischen Elementen
|
||||||
|
|
||||||
|
// Status-Label (optional)
|
||||||
|
Label {
|
||||||
|
id: statusLabel
|
||||||
|
text: "Lade..."
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
fontSize: "large" // ✅ NEU 1.7: String-Wert!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptinhalt hier einfügen
|
||||||
|
// Beispiel: Textfeld
|
||||||
|
Label {
|
||||||
|
id: contentLabel
|
||||||
|
text: "Hier steht Beispieltext"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
fontSize: "x-large" // ✅ NEU 1.7: String-Wert!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Beispiel: Button
|
||||||
|
Button {
|
||||||
|
id: testButton
|
||||||
|
text: "Test Button"
|
||||||
|
Layout.fillWidth: false
|
||||||
|
Layout.preferredWidth: units.gu(20) // 200 DP (Touch-optimiert!)
|
||||||
|
Layout.preferredHeight: units.gu(8) // 80 DP
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (py) {
|
||||||
|
py.call("<app-name>.on_button_click", [], function() {
|
||||||
|
contentLabel.text = py.call_sync("<app-name>.get_content_text", []);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================
|
||||||
|
// FOOTER (Workaround für Lomiri.Components 1.3)
|
||||||
|
// ================================================================
|
||||||
|
// ⚠️ WICHTIG: PageFooter existiert NICHT in Lomiri.Components 1.3!
|
||||||
|
Label {
|
||||||
|
id: footerLabel
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottomMargin: units.gu(2)
|
||||||
|
text: "Plattform: ?"
|
||||||
|
fontSize: "medium" // ✅ NEU 1.7: String-Wert!
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
"""
|
||||||
|
UNIVERSELLES PYTHON-MODUL TEMPLATE für Ubuntu Touch Apps
|
||||||
|
Basierend auf metime und Referenz-App (Version 1.7)
|
||||||
|
|
||||||
|
VERWENDUNG:
|
||||||
|
1. Kopiere diese Datei nach src/<app-name>.py
|
||||||
|
2. Ersetze '<app-name>' mit deinem App-Namen
|
||||||
|
3. Füge deine Funktionen hinzu
|
||||||
|
|
||||||
|
WICHTIG (1.7):
|
||||||
|
- KEINE dbus-Importe in diesem Modul! (PyOtherSide-Kompatibilität)
|
||||||
|
- Keine Top-Level print() Statements
|
||||||
|
- Keine Top-Level Code-Ausführung
|
||||||
|
- Ein Modul reicht für 90% der Apps (modulare Trennung ist OPTIONAL)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# APP-METADATEN (Anpassen!)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
APP_NAME = "<app-name>" # App-Name (z. B. "meine-app")
|
||||||
|
APP_VERSION = "0.1.0" # Version (Semantic Versioning)
|
||||||
|
MAINTAINER = "Christian Franz <dev@darklithium.de>" # Maintainer
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# PLATTFORM-ERKENNUNG (1.7 Standard)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
def get_platform():
|
||||||
|
"""
|
||||||
|
Gibt die aktuelle Plattform zurück (arm64/amd64).
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
str: "arm64" oder "amd64"
|
||||||
|
"""
|
||||||
|
machine = platform.machine().lower()
|
||||||
|
if "arm" in machine or "aarch" in machine:
|
||||||
|
return "arm64"
|
||||||
|
return "amd64"
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# STATUS-FUNKTIONEN
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
def get_status_text():
|
||||||
|
"""
|
||||||
|
Gibt einen Status-Text für die UI zurück.
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
str: Status-Text mit App-Name, Version und Plattform
|
||||||
|
"""
|
||||||
|
plat = get_platform()
|
||||||
|
return f"{APP_NAME} v{APP_VERSION} | Plattform: {plat}"
|
||||||
|
|
||||||
|
def get_platform():
|
||||||
|
"""Alias für get_platform (für QML-Aufrufe)."""
|
||||||
|
return get_platform()
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# UI-FUNKTIONEN (Beispiele - anpassen!)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
def get_content_text():
|
||||||
|
"""
|
||||||
|
Gibt den aktuellen Inhaltstext zurück.
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
str: Text für die UI
|
||||||
|
"""
|
||||||
|
return "Button wurde geklickt! (Python → QML)"
|
||||||
|
|
||||||
|
def on_button_click():
|
||||||
|
"""
|
||||||
|
Wird aufgerufen, wenn der Button in QML geklickt wird.
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
bool: True bei Erfolg
|
||||||
|
"""
|
||||||
|
print("Button clicked") # Log für Debugging
|
||||||
|
return True
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# DATENVERZEICHNIS (Optional - für persistente Daten)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
def get_data_dir():
|
||||||
|
"""
|
||||||
|
Gibt das Datenverzeichnis der App zurück.
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
str: Pfad zum Datenverzeichnis
|
||||||
|
"""
|
||||||
|
app_dir = os.path.join(
|
||||||
|
os.path.expanduser("~"),
|
||||||
|
".local",
|
||||||
|
"share",
|
||||||
|
f"{APP_NAME}.darklithium"
|
||||||
|
)
|
||||||
|
os.makedirs(app_dir, exist_ok=True)
|
||||||
|
return app_dir
|
||||||
|
|
||||||
|
def get_data_file_path(filename):
|
||||||
|
"""
|
||||||
|
Gibt den Pfad zu einer Daten-Datei zurück.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): Dateiname
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
str: Vollständiger Pfad zur Datei
|
||||||
|
"""
|
||||||
|
return os.path.join(get_data_dir(), filename)
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# BEISPIEL: DATEN LADEN/SPEICHERN
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
def load_data(filename="data.json"):
|
||||||
|
"""
|
||||||
|
Lädt JSON-Daten aus einer Datei.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): Dateiname
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
dict: Geladene Daten (oder {} bei Fehler)
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
file_path = get_data_file_path(filename)
|
||||||
|
try:
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except (FileNotFoundError, json.JSONDecodeError):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def save_data(data, filename="data.json"):
|
||||||
|
"""
|
||||||
|
Speichert Daten in eine JSON-Datei.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): Zu speichernde Daten
|
||||||
|
filename (str): Dateiname
|
||||||
|
|
||||||
|
Rückgabe:
|
||||||
|
bool: True bei Erfolg
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
file_path = get_data_file_path(filename)
|
||||||
|
try:
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Fehler beim Speichern: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# BEISPIEL: EINFACHE LOGIK
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# Zähler für Button-Klicks (Beispiel)
|
||||||
|
_click_counter = 0
|
||||||
|
|
||||||
|
def increment_counter():
|
||||||
|
"""Inkrementiert den Klick-Zähler."""
|
||||||
|
global _click_counter
|
||||||
|
_click_counter += 1
|
||||||
|
return _click_counter
|
||||||
|
|
||||||
|
def get_counter():
|
||||||
|
"""Gibt den aktuellen Zählerstand zurück."""
|
||||||
|
global _click_counter
|
||||||
|
return _click_counter
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# MAIN (wird nicht automatisch ausgeführt - PyOtherSide lädt nur Funktionen)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# Hinweis: In PyOtherSide wird nur importiert, was in QML aufgerufen wird.
|
||||||
|
# Top-Level Code wird NICHT ausgeführt!
|
||||||
|
|
||||||
|
# Beispiel für Initialisierung (wird erst beim ersten Aufruf ausgeführt):
|
||||||
|
_initialized = False
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Initialisiert das Modul (wird beim ersten Aufruf aus QML ausgeführt)."""
|
||||||
|
global _initialized
|
||||||
|
if not _initialized:
|
||||||
|
print(f"{APP_NAME} Modul initialisiert")
|
||||||
|
_initialized = True
|
||||||
|
return _initialized
|
||||||
Reference in New Issue
Block a user