Fixed REAME.md

This commit is contained in:
2025-12-29 13:56:48 +01:00
parent bf6e42192c
commit 7fb52c9cf9
2 changed files with 5 additions and 430 deletions

125
README.md
View File

@@ -1,8 +1,10 @@
# xtree # xtree
Bla blu moo! Das xtree-Widget-Set erweitert die Qt Model- und Viewklassen mit Hilfe der znode<T>-lib, um die Entwicklung von XML-basierten Anwendungen zu vereinfachen.
Der XML Datenbaum wird dabei auf eine Excel-artige Tabellenstruktur abgebildet (gemappt). Das mapping wird ebenfalls in XML ausgedrückt. Aus einem XML-Knoten wird eine Zeile in der Tabelle (Item-View) erzeugt, jedes XML-Attribut kann als ein Feld (Item) dargestellt werden.
...
## Build ## Build
@@ -21,122 +23,5 @@ make
| `doc/` | Quellcode-Dokumentation | `doc/` | Quellcode-Dokumentation
| `qml/` | QML Quellcode | `qml/` | QML Quellcode
| `src/` | c++ -Quellcode | `src/` | c++ -Quellcode
| `xml/` | XML modeldefinition & Demodaten | `xml/` | XML Modeldefinition & Demodaten
## keys
- Widgetset für XML Daten
- experimenteller qml support
- docs erzeugen
-
experimenelle
## Also, noch mal von vorn:
- Es geht um das Editieren von XML Daten in einer baumartigen Darstellung am Bildschirm.
- Es handelt sich vorwiegend um technische Daten: Strom, Spannung, unterschiedliche Betriebsparameter und sowas.
- Die Qt Viewerklassen arbeiten feldbasiert, die Datenfelder heissen 'Items', die Basisklasse zu einem Datenfeld heisst bei uns ```XQItem```
- Unser Darstellung der Datenfelder ist im Prinzip erstmal tabellenartig, bla blu
- Die QtLib unterscheidet zwischen 'rendering' und 'editing'
- bla blub
Also: itemtypes werden einfach beschrieben, mit properties, wie die properties intern implementiert werden, ist erstmal
egal: ein type sheet
pattern: model-view-controller
qt: model-view
wir: modelhub _only_
--
ein ItemType aggregiert gemeinsame Eigenschaften von Items, z.b. UnitType, EditorType, RenderTypezusammen, die ein Gruppe von Items gemeinsam
# Old stuff:
## Getting started
Das working directory muss aufs source directory zeigen, da liegen unter xml/
die Testfiles.
## Wo ich hinwill
- [ ] Alle models, menus etc. sollen in XML beschrieben werden, siehe xml/modelsheet.xml
- [ ] Es gibt nur eine Modelklasse: XQModel (ist ein QStandardItemModel)
- [ ] Datenlogik und Anwendungslogik sollen getrennt sein
- [ ] Dazu werden die Datenknoten (composites) in einen Wrapper verpackt und in den Items 'versteckt'
- [ ] Für jede Editorklasse XyzEditor.cpp gibt es eine Klasse XyzHub.cpp
- [ ] Im XyzHub wird die Anwendungslogik implementiert, d.h. die SIGNALs der UI werden mit Operationen auf das Model verbunden
- [ ] Operationen auf Datenknoten werden für die Anwendung transparent von der Datenschicht ausgeführt
- [ ] Die genaue Implementierung dafür ist mir noch unklar:
- [ ] ```ZQNode::nodeManager.applyCommand( ZQCommand( ZQ::PasteNode, ZQNode& ) )``` ???
## Basisklassen
- [ ] ```znode::zbasic_node<string_type>``` Knotenabstraction, vgl. ```std::basic_string<char_t>```
- [ ] ```ZQNode``` template-Instanziierung von zbasic_node mit QString
- [ ] ```XQModel``` ein QStandardItemModel mit ZQItems
- [ ] ```XQItem``` ein QStandardItem mit einem XQNodeWrapper
- [ ] (Sauberer wäre ein eigenes Model aus einem QAbstractItemModel, aber das ist dann wirklich Arbeit ...)
- [ ] ```XQNodeWrapper``` verpackt einen ZQNode* und vermittelt dessen Attributes an die ViewItems
- [ ] ```XQNodeManager``` operations on nodes, gibts noch nicht.
- [ ] Eigentlich ```znode::znode_manager<zbasic_node<string_type>...> ...``` für alle Anwendungsfälle
- [ ] ```XQModelReader``` erzeugt QModels aus XML, siehe XML/modelsheet.xml
- [ ] ```XQModelHub``` Datenmanager-Klasse, hier läuft alles zusammen
- [ ] ```class XQModelHub : public XQModel, public XQModelReader```: etwas fragwürdig, spart aber leidige Verpointerungen
# libPiGPIO
libPiGPIO: Eine C++ Softwarebibliothek für den Pi4 zur Einbindung elektronischer Steuerelemente
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
mkdir existing_repo
git remote add origin http://sourceworx.org:9099/opensource/libpigpio.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](http://sourceworx.org:9099/opensource/libpigpio/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.

View File

@@ -14,321 +14,11 @@
#include <QDebug> #include <QDebug>
#include <QApplication> #include <QApplication>
#include <QMetaType>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle> #include <QQuickStyle>
#include <QUrl>
#include <QQmlContext>
#include <QStyleFactory>
#include <xqchildmodel.h>
#include <xqquickwidget.h>
#include <xqmainwindow.h> #include <xqmainwindow.h>
using namespace Qt::Literals::StringLiterals;
#include <iostream>
#include <vector>
#include <memory> // Für std::unique_ptr
#include <iterator> // Für std::forward_iterator_tag
#include <algorithm> // Für std::find_if, std::next
#include <cstddef> // Für std::ptrdiff_t
#include <string>
/**
* @brief Eine generische Baumstruktur, die als Knoten selbst fungiert.
*
* Diese Klasse implementiert einen Baum, bei dem jedes 'Tree'-Objekt
* einen Knoten im Baum darstellt. Sie verwendet std::unique_ptr
* für die Verwaltung der Kind-Knoten und ist durch Iteratoren
* mit STL-Algorithmen kompatibel (Pre-Order-Traversierung).
*
* @tparam T Der Typ des zu speichernden Wertes.
*/
template <typename T>
class Tree
{
public:
// --- Öffentliche Typ-Aliase ---
using value_type = T;
using reference = T&;
using const_reference = const T&;
// --- Element-Zugriff ---
value_type value;
// --- Struktur ---
// Wir verwenden unique_ptr, um das Eigentum klar zu definieren.
// Der Elternknoten besitzt seine Kinder.
std::vector<std::unique_ptr<Tree<T>>> children;
// Nicht-besitzender Rohzeiger auf den Elternknoten für die Navigation nach oben.
// Dieser ist für die Iterator-Implementierung entscheidend.
Tree<T>* parent = nullptr;
// --- Konstruktoren ---
explicit Tree(const T& val, Tree<T>* p = nullptr) : value(val), parent(p) {}
explicit Tree(T&& val, Tree<T>* p = nullptr) : value(std::move(val)), parent(p) {}
// Verhindere Kopieren, da unique_ptr nicht kopierbar ist (aber verschiebbar).
Tree(const Tree&) = delete;
Tree& operator=(const Tree&) = delete;
// Standard-Move-Konstruktor und -Zuweisung sind in Ordnung.
Tree(Tree&&) = default;
Tree& operator=(Tree&&) = default;
// --- Methoden ---
/**
* @brief Fügt ein neues Kind mit einem Wert hinzu (Kopie).
* @return Ein nicht-besitzender Zeiger auf den neu erstellten Knoten.
*/
Tree<T>* addChild(const T& val) {
auto newNode = std::make_unique<Tree<T>>(val, this);
children.push_back(std::move(newNode));
return children.back().get();
}
/**
* @brief Fügt ein neues Kind mit einem Wert hinzu (Move).
* @return Ein nicht-besitzender Zeiger auf den neu erstellten Knoten.
*/
Tree<T>* addChild(T&& val) {
auto newNode = std::make_unique<Tree<T>>(std::move(val), this);
children.push_back(std::move(newNode));
return children.back().get();
}
private:
// --- Private Basis-Iterator-Klasse (Template-Magie zur Vermeidung von Code-Duplizierung) ---
// Wir definieren einen Template-Iterator, der sowohl für const als auch für non-const funktioniert.
template <bool IsConst>
class BaseIterator {
public:
// Iterator-Traits (Eigenschaften)
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
// Abhängige Typen: TreeT ist 'const Tree<T>' oder 'Tree<T>'
using TreeT = std::conditional_t<IsConst, const Tree<T>, Tree<T>>;
// value_type ist immer T (der Wert, nicht der Knoten)
using value_type = T;
using pointer = std::conditional_t<IsConst, const T*, T*>;
using reference = std::conditional_t<IsConst, const T&, T&>;
private:
TreeT* current_node;
public:
// Konstruktor
explicit BaseIterator(TreeT* node) : current_node(node) {}
// Dereferenzierung
reference operator*() const { return current_node->value; }
pointer operator->() const { return &(current_node->value); }
// Vergleichsoperatoren
bool operator==(const BaseIterator& other) const {
return current_node == other.current_node;
}
bool operator!=(const BaseIterator& other) const {
return current_node != other.current_node;
}
// --- Inkrement (Kernlogik der Pre-Order-Traversierung) ---
// (Präfix-Version: ++it)
BaseIterator& operator++() {
if (!current_node) {
return *this; // Bereits am Ende
}
// 1. Priorität: Gehe zum ersten Kind (Tiefensuche)
if (!current_node->children.empty()) {
current_node = current_node->children.front().get();
return *this;
}
// 2. Priorität: Gehe zum nächsten Geschwisterknoten oder gehe nach oben
while (current_node) {
// Wenn wir zur Wurzel zurückgekehrt sind und keine Geschwister haben, sind wir fertig.
if (!current_node->parent) {
current_node = nullptr; // Ende erreicht
return *this;
}
TreeT* parent_node = current_node->parent;
// Finde den aktuellen Knoten in der Kind-Liste des Elternteils
auto it = std::find_if(parent_node->children.begin(), parent_node->children.end(),
[this](const auto& child_ptr) {
return child_ptr.get() == current_node;
});
// Finde das nächste Geschwister
auto next_sibling_it = std::next(it);
if (next_sibling_it != parent_node->children.end()) {
// 2a. Nächstes Geschwister gefunden
current_node = next_sibling_it->get();
return *this;
}
// 2b. Kein nächstes Geschwister, gehe eine Ebene nach oben
// Die Schleife wird mit dem parent_node wiederholt
current_node = parent_node;
}
return *this; // Sollte jetzt nullptr sein
}
// (Postfix-Version: it++)
BaseIterator operator++(int) {
BaseIterator temp = *this;
++(*this);
return temp;
}
};
public:
// --- Öffentliche Iterator-Typen ---
using iterator = BaseIterator<false>;
using const_iterator = BaseIterator<true>;
// --- Iterator-Methoden (STL-Kompatibilität) ---
iterator begin() { return iterator(this); }
iterator end() { return iterator(nullptr); }
const_iterator begin() const { return const_iterator(this); }
const_iterator end() const { return const_iterator(nullptr); }
const_iterator cbegin() const { return const_iterator(this); }
const_iterator cend() const { return const_iterator(nullptr); }
};
class Interface
{
virtual int moo() = 0;
};
class Aspect
{
virtual int moo()
{
qDebug() << " --- Aspect moo";
return 42;
}
};
class DoWork : public Interface, public Aspect
{
};
int firz(int argc, char *argv[])
{
QApplication app(argc, argv);
// hat am wenigsten darstellungfehler (alternative: fusion)
QQuickStyle::setStyle("Imagine");
XQMainWindow window;
// 1. Baum erstellen
// Der Benutzer erstellt den Wurzelknoten direkt.
Tree<std::string> root("Root");
// Kinder hinzufügen. Die addChild-Methode gibt einen Zeiger
// auf den neuen Knoten zurück, sodass wir sie verketten können.
auto* a = root.addChild("A");
auto* b = root.addChild("B");
auto* c = root.addChild("C");
// Enkelkinder hinzufügen
a->addChild("A1");
a->addChild("A2");
auto* b1 = b->addChild("B1 (suche mich)");
c->addChild("C1");
c->addChild("C2");
c->addChild("C3");
b1->addChild("B1.1");
/*
* Der Baum sieht nun so aus (Pre-Order):
* 1. Root
* 2. A
* 3. A1
* 4. A2
* 5. B
* 6. B1 (suche mich)
* 7. B1.1
* 8. C
* 9. C1
* 10. C2
* 11. C3
*/
// 2. Verwendung mit Range-Based 'for' (dank begin/end)
std::cout << "--- Pre-Order Traversierung (Range-based for) ---" << std::endl;
for (const std::string& value : root) {
std::cout << value << " -> ";
}
std::cout << "end" << std::endl;
// 3. Verwendung mit <algorithm> (z.B. std::find_if)
std::cout << "\n--- STL std::find_if ---" << std::endl;
// Finde den ersten Knoten, dessen Wert "B1 (suche mich)" ist.
// Wir verwenden cbegin/cend, da wir den Baum nicht ändern wollen.
auto found_it = std::find_if(root.cbegin(), root.cend(), [](const std::string& val) {
return val == "B1 (suche mich)";
});
if (found_it != root.cend()) {
// *found_it gibt den Wert (std::string) zurück
std::cout << "Gefunden: " << *found_it << std::endl;
}
else
{
std::cout << "Nicht gefunden." << std::endl;
}
// 4. Verwendung mit <numeric> (z.B. std::count_if)
std::cout << "\n--- STL std::count_if ---" << std::endl;
int count = std::count_if(root.cbegin(), root.cend(), [](const std::string& val)
{
return val.length() > 5; // Zähle alle Strings mit mehr als 5 Zeichen
});
std::cout << "Knoten mit > 5 Zeichen: " << count << std::endl;
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {