Compare commits
53 Commits
experiment
...
defa6a1906
Author | SHA1 | Date | |
---|---|---|---|
defa6a1906 | |||
![]() |
35ebcd2986 | ||
93879db3dd | |||
5a7e309c24 | |||
f509668c47 | |||
e063ed7f75 | |||
9192c0beb2 | |||
3ee5b1adfc | |||
2180b62bf1 | |||
![]() |
bf49d8321f | ||
![]() |
28aa03b31a | ||
fa6499e3da | |||
0f8addbe7f | |||
b6890257f1 | |||
10752908ca | |||
32c5121fcd | |||
![]() |
d07ef3fbf9 | ||
fd94b2d354 | |||
cc441d094c | |||
![]() |
d5c1f8925c | ||
fd41138175 | |||
![]() |
03b0dafdcc | ||
a0064b2566 | |||
![]() |
cbe8b92582 | ||
809ef10c0d | |||
![]() |
95b7b026ff | ||
05bc5ad5d9 | |||
93ec52933e | |||
3ac129ef26 | |||
50703a4c44 | |||
1531ec14f1 | |||
0fe15d6043 | |||
89c671295f | |||
a9dacca684 | |||
3887748c1a | |||
b8f0893d59 | |||
9c6f7688d7 | |||
8d26c32e51 | |||
c9b61c1c2b | |||
d6ccac1d85 | |||
5d2fb1b378 | |||
89c5fd21f1 | |||
f8bd0886d3 | |||
![]() |
831daf898c | ||
![]() |
3e7b65dca5 | ||
147769bf60 | |||
![]() |
527de65074 | ||
4d49a495fd | |||
952409ab1a | |||
c6454f3106 | |||
04b0f650d6 | |||
6ee677c595 | |||
5057edb9ad |
7
.gitignore
vendored
@@ -7,9 +7,6 @@ release/
|
||||
enc_temp_folder/
|
||||
ui_*
|
||||
*autosave
|
||||
doc/~$ree_thoughts.docx
|
||||
doc/~WRL0004.tmp
|
||||
UsersC998D~1.HOLAppDataLocalTemptmpj0mbo3rd
|
||||
xml/fitzefatz.xml
|
||||
build*
|
||||
doc/
|
||||
src/xtree.vcxproj.user
|
||||
doc/html/
|
||||
|
86
README.md
@@ -1,4 +1,36 @@
|
||||
# XTree
|
||||
# xtree
|
||||
|
||||
Bla blu moo!
|
||||
|
||||
...
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
git clone https://gitea.sourceworx.org/chris/xtree.git
|
||||
cd xtree/src
|
||||
qmake xtree.pro
|
||||
make
|
||||
```
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
| |
|
||||
|--------|
|
||||
| `deprecated/` | Reste & Fehlversuche
|
||||
| `doc/` | Quellcode-Dokumentation
|
||||
| `qml/` | QML Quellcode
|
||||
| `src/` | c++ -Quellcode
|
||||
| `xml/` | XML modeldefinition & Demodaten
|
||||
|
||||
## keys
|
||||
|
||||
- Widgetset für XML Daten
|
||||
- experimenteller qml support
|
||||
- docs erzeugen
|
||||
-
|
||||
|
||||
experimenelle
|
||||
|
||||
## Also, noch mal von vorn:
|
||||
|
||||
@@ -56,3 +88,55 @@ die Testfiles.
|
||||
- [ ] ```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.
|
||||
|
2987
doc/Doxyfile
Normal file
6
doc/doxygen-awesome-css/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
docs/html
|
||||
.DS_Store
|
||||
.idea
|
||||
|
||||
node_modules
|
||||
*.tgz
|
3
doc/doxygen-awesome-css/.npmignore
Normal file
@@ -0,0 +1,3 @@
|
||||
*
|
||||
!doxygen-awesome*
|
||||
|
2932
doc/doxygen-awesome-css/Doxyfile
Normal file
21
doc/doxygen-awesome-css/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
39
doc/doxygen-awesome-css/Makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
.POSIX:
|
||||
|
||||
PROJECT = doxygen-awesome-css
|
||||
|
||||
# Paths
|
||||
PREFIX = /usr/local
|
||||
DATADIR = share
|
||||
INSTALLDIR = $(DESTDIR)$(PREFIX)/$(DATADIR)/$(PROJECT)
|
||||
|
||||
# Utilities
|
||||
INSTALL = install -m 644
|
||||
MKDIR = mkdir -p
|
||||
RM = rm -f
|
||||
|
||||
# Files to be installed
|
||||
FILES = doxygen-awesome-darkmode-toggle.js \
|
||||
doxygen-awesome-fragment-copy-button.js \
|
||||
doxygen-awesome-interactive-toc.js \
|
||||
doxygen-awesome-paragraph-link.js \
|
||||
doxygen-awesome-sidebar-only-darkmode-toggle.css \
|
||||
doxygen-awesome-sidebar-only.css \
|
||||
doxygen-awesome-tabs.js \
|
||||
doxygen-awesome.css
|
||||
|
||||
# Empty targets so that `make` and `make clean` do not cause errors
|
||||
all:
|
||||
clean:
|
||||
|
||||
install:
|
||||
$(MKDIR) $(INSTALLDIR)
|
||||
$(INSTALL) $(FILES) $(INSTALLDIR)/
|
||||
|
||||
uninstall:
|
||||
$(RM) -r $(INSTALLDIR)/
|
||||
|
||||
.PHONY: all clean install uninstall
|
207
doc/doxygen-awesome-css/README.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Doxygen Awesome
|
||||
|
||||
[](https://github.com/jothepro/doxygen-awesome-css/releases/latest)
|
||||
[](https://github.com/jothepro/doxygen-awesome-css/blob/main/LICENSE)
|
||||

|
||||
|
||||
<div class="title_screenshot">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
**Doxygen Awesome** is a custom CSS theme for Doxygen HTML documentation with lots of customization parameters.
|
||||
|
||||
## Motivation
|
||||
|
||||
I really like how the Doxygen HTML documentation is structured! But IMHO it looks a bit outdated.
|
||||
|
||||
This theme is an attempt to update the visuals of Doxygen without changing its overall layout too much.
|
||||
|
||||
## Features
|
||||
|
||||
- 🌈 Clean, modern design
|
||||
- 🚀 Heavily customizable by adjusting CSS variables
|
||||
- 🧩 No changes to the HTML structure of Doxygen are required
|
||||
- 📱 Improved mobile usability
|
||||
- 🌘 Dark mode support!
|
||||
- 🥇 Works best with **doxygen 1.9.1** - **1.9.4** and **1.9.6** - **1.12.0**
|
||||
|
||||
## Examples
|
||||
|
||||
Some websites using this theme:
|
||||
|
||||
- [Documentation of this repository](https://jothepro.github.io/doxygen-awesome-css/)
|
||||
- [wxWidgets](https://docs.wxwidgets.org/3.2/)
|
||||
- [OpenCV 5.x](https://docs.opencv.org/5.x/)
|
||||
- [Zephyr](https://docs.zephyrproject.org/latest/doxygen/html/index.html)
|
||||
- [FELTOR](https://mwiesenberger.github.io/feltor/dg/html/modules.html)
|
||||
- [Spatial Audio Framework (SAF)](https://leomccormack.github.io/Spatial_Audio_Framework/index.html)
|
||||
- [Randolf Richardson's C++ classes](https://www.randolf.ca/c++/docs/)
|
||||
- [libCloudSync](https://jothepro.github.io/libCloudSync/)
|
||||
- [libsl3](https://a4z.github.io/libsl3/)
|
||||
- [DuMu<sup>x</sup>](https://dumux.org/docs/doxygen/master/)
|
||||
|
||||
## Installation
|
||||
|
||||
To use the theme when generating your documentation, bring the required CSS and JS files from this repository into your project.
|
||||
|
||||
This can be done in several ways:
|
||||
|
||||
- manually copying the files
|
||||
- adding the project as a Git submodule
|
||||
- downloading the project with CMake FetchContent
|
||||
- adding the project as a npm/xpm dependency
|
||||
- installing the theme system-wide
|
||||
|
||||
All theme files are located in the root of this repository and start with the prefix `doxygen-awesome-`. You may not need all of them. Follow the install instructions to figure out what files are required for your setup.
|
||||
|
||||
### Git submodule
|
||||
For projects that use git, add the repository as a submodule and check out the desired release:
|
||||
|
||||
```sh
|
||||
git submodule add https://github.com/jothepro/doxygen-awesome-css.git
|
||||
cd doxygen-awesome-css
|
||||
git checkout v2.3.4
|
||||
```
|
||||
|
||||
### CMake with FetchContent
|
||||
|
||||
For project that build with CMake, the `FetchContent` module can be used to download the repository at configure-time.
|
||||
|
||||
Add the following snippet to your `CMakeLists.txt`
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
doxygen-awesome-css
|
||||
URL https://github.com/jothepro/doxygen-awesome-css/archive/refs/heads/main.zip
|
||||
)
|
||||
FetchContent_MakeAvailable(doxygen-awesome-css)
|
||||
|
||||
# Save the location the files were cloned into
|
||||
# This allows us to get the path to doxygen-awesome.css
|
||||
FetchContent_GetProperties(doxygen-awesome-css SOURCE_DIR AWESOME_CSS_DIR)
|
||||
|
||||
# Generate the Doxyfile
|
||||
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in)
|
||||
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
|
||||
```
|
||||
|
||||
This downloads the latest main (but any other revision could be used) and unpacks in the build folder. The `Doxyfile.in` can reference this location in the `HTML_EXTRA_STYLESHEET` field
|
||||
|
||||
```text
|
||||
HTML_EXTRA_STYLESHEET = @AWESOME_CSS_DIR@/doxygen-awesome.css
|
||||
```
|
||||
|
||||
When the configure stage of CMake is run, the `Doxyfile.in` is rendered to Doxyfile and Doxygen can be run as usual.
|
||||
|
||||
### npm/xpm dependency
|
||||
|
||||
In the npm ecosystem, this project can be added as a development dependency
|
||||
to your project:
|
||||
|
||||
```sh
|
||||
cd your-project
|
||||
npm install https://github.com/jothepro/doxygen-awesome-css#v2.3.4 --save-dev
|
||||
|
||||
ls -l node_module/@jothepro/doxygen-awesome-css
|
||||
```
|
||||
|
||||
Similarly, in the [xPack](https://xpack.github.io) ecosystem, this project can be added
|
||||
as a development dependency to an [`xpm`](https://xpack.github.io/xpm/)
|
||||
managed project.
|
||||
|
||||
### System-wide
|
||||
|
||||
You can even install the theme system-wide by running `make install`.
|
||||
The files will be installed to `/usr/local/share/` by default,
|
||||
but you can customize the install location with `make PREFIX=/my/custom/path install`.
|
||||
|
||||
### Choosing a layout
|
||||
|
||||
There are two layout options. Choose one of them and configure Doxygen accordingly:
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <b class="tab-title">Base Theme</b><div class="darkmode_inverted_image">
|
||||

|
||||
</div>
|
||||
Comes with the typical Doxygen titlebar. Optionally the treeview in the sidebar can be enabled.
|
||||
|
||||
Required files: `doxygen-awesome.css`
|
||||
|
||||
Required `Doxyfile` configuration:
|
||||
```
|
||||
GENERATE_TREEVIEW = YES # optional. Also works without treeview
|
||||
DISABLE_INDEX = NO
|
||||
FULL_SIDEBAR = NO
|
||||
HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css
|
||||
HTML_COLORSTYLE = LIGHT # required with Doxygen >= 1.9.5
|
||||
```
|
||||
|
||||
- <b class="tab-title">Sidebar-Only Theme</b><div class="darkmode_inverted_image">
|
||||

|
||||
</div>
|
||||
Hides the top titlebar to give more space to the content. The treeview must be enabled in order for this theme to work.
|
||||
|
||||
Required files: `doxygen-awesome.css`, `doxygen-awesome-sidebar-only.css`
|
||||
|
||||
Required `Doxyfile` configuration:
|
||||
```
|
||||
|
||||
GENERATE_TREEVIEW = YES # required!
|
||||
DISABLE_INDEX = NO
|
||||
FULL_SIDEBAR = NO
|
||||
HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \
|
||||
doxygen-awesome-css/doxygen-awesome-sidebar-only.css
|
||||
HTML_COLORSTYLE = LIGHT # required with Doxygen >= 1.9.5
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
@warning
|
||||
- This theme is not compatible with the `FULL_SIDEBAR = YES` option provided by Doxygen!
|
||||
- `HTML_COLORSTYLE` must be set to `LIGHT` since Doxygen 1.9.5!
|
||||
|
||||
### Further installation instructions
|
||||
|
||||
- [Installing extensions](docs/extensions.md)
|
||||
- [Customizing the theme (colors, spacing, border-radius, ...)](docs/customization.md)
|
||||
- [Tips and Tricks for further configuration](docs/tricks.md)
|
||||
|
||||
## Browser support
|
||||
|
||||
Tested with
|
||||
|
||||
- Chrome 119, Chrome 119 for Android, Chrome 119 for iOS
|
||||
- Safari 17, Safari for iOS 16
|
||||
- Firefox 118, Firefox 120 for Android, Firefox 119 for iOS
|
||||
- Edge 119
|
||||
- Opera 108
|
||||
|
||||
|
||||
The theme does not strive to be backward compatible with (significantly) older browser versions.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
Thanks for all the bug reports and inspiring feedback on GitHub!
|
||||
|
||||
Special thanks to all the contributors:
|
||||
<br><br>
|
||||
<a href="https://github.com/jothepro/doxygen-awesome-css/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=jothepro/doxygen-awesome-css" />
|
||||
</a>
|
||||
|
||||
|
||||
<div class="section_buttons">
|
||||
|
||||
| Read Next |
|
||||
|---------------------------------:|
|
||||
| [Extensions](docs/extensions.md) |
|
||||
|
||||
</div>
|
121
doc/doxygen-awesome-css/docs/customization.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Customization
|
||||
|
||||
[TOC]
|
||||
|
||||
|
||||
## CSS-Variables
|
||||
|
||||
This theme is highly customizable because a lot of things are parameterized with CSS variables.
|
||||
|
||||
Just to give you an idea of how flexible the styling is, click this button:
|
||||
|
||||
<div class="alter-theme-button" onclick="toggle_alternative_theme()" onkeypress="if (event.keyCode == 13) toggle_alternative_theme()" tabindex=0>Alter theme</div>
|
||||
|
||||
<br><hr>
|
||||
|
||||
### Setup
|
||||
|
||||
It is recommended to add your own `custom.css` and overwrite the variables there:
|
||||
```
|
||||
HTML_EXTRA_STYLESHEET = doxygen-awesome.css custom.css
|
||||
```
|
||||
|
||||
Make sure to override the variables in the correct spot. All variables should be customized where they have been defined, in the `html` tag selector:
|
||||
|
||||
```css
|
||||
html {
|
||||
/* override light-mode variables here */
|
||||
}
|
||||
```
|
||||
|
||||
For dark-mode overrides, you have to choose where to put them, depending on whether the dark-mode toggle extension is installed or not:
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <b class="tab-title">dark-mode toggle is installed</b>
|
||||
```css
|
||||
html.dark-mode {
|
||||
/* define dark-mode variable overrides here if you DO use doxygen-awesome-darkmode-toggle.js */
|
||||
}
|
||||
```
|
||||
- <b class="tab-title">dark-mode toggle is **NOT** installed</b>
|
||||
The dark-mode is enabled automatically depending on the system preference:
|
||||
```css
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html:not(.light-mode) {
|
||||
/* define dark-mode variable overrides here if you DON'T use doxygen-awesome-darkmode-toggle.js */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Available variables
|
||||
|
||||
The following list gives an overview of the variables defined in [`doxygen-awesome.css`](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css).
|
||||
|
||||
The list is not complete. To explore all available variables, have a look at the CSS starting from [here](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css#L30).
|
||||
All variables are defined at the beginning of the stylesheet.
|
||||
|
||||
| Parameter | Default (Light) | Default (Dark) |
|
||||
| :---------------------------------- | :---------------------------------------------------------- | :---------------------------------------------------------- |
|
||||
| **Color Scheme**:<br>primary theme colors. This will affect the entire websites color scheme: links, arrows, labels, ... |||
|
||||
| `--primary-color` | <code style="background:#1779c4;color:white">#1779c4</code> | <code style="background:#1982d2;color:white">#1982d2</code> |
|
||||
| `--primary-dark-color` | <code style="background:#335c80;color:white">#335c80</code> | <code style="background:#5ca8e2;color:black">#5ca8e2</code> |
|
||||
| `--primary-light-color` | <code style="background:#70b1e9;color:black">#70b1e9</code> | <code style="background:#4779ac;color:white">#4779ac</code> |
|
||||
| **Page Colors**:<br>background and foreground (text-color) of the documentation. |||
|
||||
| `--page-background-color` | <code style="background:#ffffff;color:black">#ffffff</code> | <code style="background:#1C1D1F;color:white">#1C1D1F</code> |
|
||||
| `--page-foreground-color` | <code style="background:#2f4153;color:white">#2f4153</code> | <code style="background:#d2dbde;color:black">#d2dbde</code> |
|
||||
| `--page-secondary-foreground-color` | <code style="background:#6f7e8e;color:white">#6f7e8e</code> | <code style="background:#859399;color:white">#859399</code> |
|
||||
| **Spacing:**<br>default spacings. Most ui components reference these values for spacing, to provide uniform spacing on the page. |||
|
||||
| `--spacing-small` | `5px` | |
|
||||
| `--spacing-medium` | `10px` | |
|
||||
| `--spacing-large` | `16px` | |
|
||||
| **Border Radius**:<br>border radius for all rounded ui components. Will affect many components, like dropdowns, memitems, codeblocks, ... |||
|
||||
| `--border-radius-small` | `4px` | |
|
||||
| `--border-radius-medium` | `6px` | |
|
||||
| `--border-radius-large` | `8px` | |
|
||||
| **Content Width**:<br>The content is centered and constrained in its width. To make the content fill the whole page, set the following variable to `auto`. |||
|
||||
| `--content-maxwidth` | `1000px` | |
|
||||
| **Code Fragment Colors**:<br>Color-Scheme of multiline codeblocks |||
|
||||
| `--fragment-background` | <code style="background:#F8F9FA;color:black">#F8F9FA</code> | <code style="background:#282c34;color:white">#282c34</code> |
|
||||
| `--fragment-foreground` | <code style="background:#37474F;color:white">#37474F</code> | <code style="background:#dbe4eb;color:black">#dbe4eb</code> |
|
||||
| **Arrow Opacity**:<br>By default the arrows in the sidebar are only visible on hover. You can override this behavior so they are visible all the time. |||
|
||||
| `--side-nav-arrow-opacity` | `0` | |
|
||||
| `--side-nav-arrow-hover-opacity` | `0.9` | |
|
||||
| ...and many more |||
|
||||
|
||||
|
||||
If you miss a configuration option or find a bug, please consider [opening an issue](https://github.com/jothepro/doxygen-awesome-css/issues)!
|
||||
|
||||
## Doxygen generator
|
||||
|
||||
The theme overrides most colors with the `--primary-color-*` variables.
|
||||
|
||||
But there are a few small images and graphics that the theme cannot adjust or replace. To make these blend in better with
|
||||
the rest, it is recommended to adjust the [doxygen color settings](https://www.doxygen.nl/manual/customize.html#minor_tweaks_colors)
|
||||
to something that matches the chosen color scheme.
|
||||
|
||||
For the default color scheme, these values work out quite well:
|
||||
|
||||
```
|
||||
# Doxyfile
|
||||
HTML_COLORSTYLE_HUE = 209
|
||||
HTML_COLORSTYLE_SAT = 255
|
||||
HTML_COLORSTYLE_GAMMA = 113
|
||||
```
|
||||
|
||||
## Share your customizations
|
||||
|
||||
If you have customized the theme with custom colors, spacings, font-sizes, etc. and you want to share your creation with others, you can do this [here](https://github.com/jothepro/doxygen-awesome-css/discussions/13).
|
||||
|
||||
I am always curious to learn about how you made the theme look even better!
|
||||
|
||||
|
||||
<div class="section_buttons">
|
||||
|
||||
| Previous | Next |
|
||||
|:----------------------------|---------------------------:|
|
||||
| [Extensions](extensions.md) | [Tips & Tricks](tricks.md) |
|
||||
|
||||
</div>
|
284
doc/doxygen-awesome-css/docs/extensions.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Extensions
|
||||
|
||||
[TOC]
|
||||
|
||||
On top of the base theme provided by `doxygen-awesome.css`, this repository comes with Javascript extensions that require additional setup steps to get them running.
|
||||
|
||||
The extensions require customizations in the header HTML template.
|
||||
This is how you can create the default template with Doxygen:
|
||||
|
||||
1. Create default header template:
|
||||
```sh
|
||||
doxygen -w html header.html delete_me.html delete_me.css
|
||||
```
|
||||
|
||||
2. Reference the template in your `Doxyfile`:
|
||||
```
|
||||
HTML_HEADER = header.html
|
||||
```
|
||||
|
||||
[More details on header customization](https://www.doxygen.nl/manual/customize.html#minor_tweaks_header_css)
|
||||
|
||||
## Dark Mode Toggle {#extension-dark-mode-toggle}
|
||||
|
||||
Adds a button next to the search bar to enable and disable the dark theme variant manually:
|
||||
|
||||
<div class="darkmode_inverted_image bordered_image">
|
||||
|
||||
{width=250px}
|
||||
</div>
|
||||
|
||||
### Installation
|
||||
|
||||
1. Add the required resources in your `Doxyfile`:
|
||||
- **HTML_EXTRA_FILES:** `doxygen-awesome-darkmode-toggle.js`
|
||||
- **HTML_EXTRA_STYLESHEET:** `doxygen-awesome-sidebar-only-darkmode-toggle.css`
|
||||
<em>(ONLY required for the sidebar-only theme variant!)</em>
|
||||
2. In the `header.html` template, include `doxygen-awesome-darkmode-toggle.js` at the end of the `<head>` and then initialize it:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<!-- ... other metadata & script includes ... -->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeDarkModeToggle.init()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
### Customizing
|
||||
|
||||
Changing the tooltip of the button:
|
||||
```js
|
||||
DoxygenAwesomeDarkModeToggle.title = "Zwischen hellem/dunklem Modus wechseln"
|
||||
```
|
||||
|
||||
Changing Icons. Both Emoji or SVG icons are supported:
|
||||
```js
|
||||
DoxygenAwesomeDarkModeToggle.lightModeIcon = '🌞'
|
||||
// icon from https://fonts.google.com/icons
|
||||
DoxygenAwesomeDarkModeToggle.darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#009793"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M8.1,14.15C9.77,14.63,11,16.17,11,18c0,0.68-0.19,1.31-0.48,1.87c0.48,0.09,0.97,0.14,1.48,0.14 c1.48,0,2.9-0.41,4.13-1.15c-2.62-0.92-5.23-2.82-6.8-5.86C7.74,9.94,7.78,7.09,8.29,4.9c-2.57,1.33-4.3,4.01-4.3,7.1c0,0,0,0,0,0 c0.01,0,0.01,0,0.02,0C5.66,12,7.18,12.83,8.1,14.15z" opacity=".3"/><path d="M19.78,17.51c-2.47,0-6.57-1.33-8.68-5.43C8.77,7.57,10.6,3.6,11.63,2.01C6.27,2.2,1.98,6.59,1.98,12 c0,0.14,0.02,0.28,0.02,0.42C2.61,12.16,3.28,12,3.98,12c0,0,0,0,0,0c0-3.09,1.73-5.77,4.3-7.1C7.78,7.09,7.74,9.94,9.32,13 c1.57,3.04,4.18,4.95,6.8,5.86c-1.23,0.74-2.65,1.15-4.13,1.15c-0.5,0-1-0.05-1.48-0.14c-0.37,0.7-0.94,1.27-1.64,1.64 c0.98,0.32,2.03,0.5,3.11,0.5c3.5,0,6.58-1.8,8.37-4.52C20.18,17.5,19.98,17.51,19.78,17.51z"/><path d="M7,16l-0.18,0C6.4,14.84,5.3,14,4,14c-1.66,0-3,1.34-3,3s1.34,3,3,3c0.62,0,2.49,0,3,0c1.1,0,2-0.9,2-2 C9,16.9,8.1,16,7,16z"/></g></g></svg>`
|
||||
```
|
||||
|
||||
All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`!
|
||||
|
||||
|
||||
## Fragment Copy Button {#extension-copy-button}
|
||||
|
||||
Shows a copy button when the user hovers over a code fragment:
|
||||
|
||||
<div class="darkmode_inverted_image bordered_image">
|
||||
|
||||
{width=490}
|
||||
</div>
|
||||
|
||||
### Installation
|
||||
|
||||
1. Add the required resources in your `Doxyfile`:
|
||||
- **HTML_EXTRA_FILES:** `doxygen-awesome-fragment-copy-button.js`
|
||||
- **HTML_COPY_CLIPBOARD:** `NO` required with Doxygen >= 1.10.0
|
||||
2. In the `header.html` template, include `doxygen-awesome-fragment-copy-button.js` at the end of the `<head>` and then initialize it:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<!-- ... other metadata & script includes ... -->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeFragmentCopyButton.init()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
### Customizing
|
||||
|
||||
The tooltip of the button can be changed:
|
||||
```js
|
||||
DoxygenAwesomeFragmentCopyButton.title = "In die Zwischenablage kopieren"
|
||||
```
|
||||
|
||||
The icon can be changed. It must be an SVG:
|
||||
```js
|
||||
DoxygenAwesomeFragmentCopyButton.copyIcon = `<svg ...>`
|
||||
DoxygenAwesomeFragmentCopyButton.successIcon = `<svg ...>`
|
||||
```
|
||||
|
||||
All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`!
|
||||
|
||||
## Paragraph Linking {#extension-para}
|
||||
|
||||
Provides a button on hover behind every headline to allow easy creation of a permanent link to the headline:
|
||||
|
||||
<div class="darkmode_inverted_image bordered_image">
|
||||
|
||||
{width=220}
|
||||
</div>
|
||||
|
||||
Works for all headlines and for many documentation section titles.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Add the required resources in your `Doxyfile`:
|
||||
- **HTML_EXTRA_FILES:** `doxygen-awesome-paragraph-link.js`
|
||||
2. In the `header.html` template, include `doxygen-awesome-paragraph-link.js` at the end of the `<head>` and then initialize it:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<!-- ... other metadata & script includes ... -->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeParagraphLink.init()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
### Customizing
|
||||
|
||||
The button tooltip can be changed:
|
||||
```js
|
||||
DoxygenAwesomeParagraphLink.title = "Abschnitt verknüpfen"
|
||||
```
|
||||
|
||||
The icon of the button can be changed. Both plain characters or SVG icons are supported:
|
||||
```js
|
||||
DoxygenAwesomeParagraphLink.icon = "¶"
|
||||
```
|
||||
|
||||
All customizations must be applied before calling `DoxygenAwesomeParagraphLink.init()`!
|
||||
|
||||
## Interactive TOC {#extension-toc}
|
||||
|
||||
On large screens, the Table of Contents (TOC) is anchored on the top right of the page. This extension visualizes the reading progress by dynamically highlighting the currently active section.
|
||||
|
||||
On small screens, the extension hides the TOC by default. The user can open it manually when needed:
|
||||
|
||||
|
||||
<div class="darkmode_inverted_image bordered_image">
|
||||
|
||||
{width=380}
|
||||
</div>
|
||||
|
||||
### Installation
|
||||
|
||||
1. Add the required resources in your `Doxyfile`:
|
||||
- **HTML_EXTRA_FILES:** `doxygen-awesome-interactive-toc.js`
|
||||
2. In the `header.html` template, include `doxygen-awesome-interactive-toc.js` at the end of the `<head>` and then initialize it:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<!-- ... other metadata & script includes ... -->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeInteractiveToc.init()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
### Customizing
|
||||
|
||||
The offset for when a headline is considered active can be changed. A smaller value means that the headline of the section must be closer to the top of the viewport before it is highlighted in the TOC:
|
||||
```js
|
||||
DoxygenAwesomeInteractiveToc.topOffset = 45
|
||||
```
|
||||
|
||||
Hiding the TOC on small screens can be disabled. It is still interactive and can be hidden by the user but will now be open by default:
|
||||
```js
|
||||
DoxygenAwesomeInteractiveToc.hideMobileMenu = false
|
||||
```
|
||||
|
||||
## Tabs {#extension-tabs}
|
||||
|
||||
@warning Experimental feature! Please report bugs [here](https://github.com/jothepro/doxygen-awesome-css/issues).
|
||||
|
||||
This extension allows to arrange list content in tabs:
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <b class="tab-title">Tab 1</b>
|
||||
This is the content of tab 1
|
||||
- <b class="tab-title">Tab 2</b>
|
||||
This is the content of tab 2
|
||||
1. it has a list
|
||||
2. with multiple items
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. Add the required resources in your `Doxyfile`:
|
||||
- **HTML_EXTRA_FILES:** `doxygen-awesome-tabs.js`
|
||||
2. In the `header.html` template, include `doxygen-awesome-tabs.js` at the end of the `<head>` and then initialize it:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<!-- ... other metadata & script includes ... -->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-tabs.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeTabs.init()
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Each list that is supposed to be displayed as tabs has to be wrapped with the `tabbed` CSS class.
|
||||
Each item in the list must start with an element that has the class `tab-title`. It will then be used as tab title.
|
||||
|
||||
```md
|
||||
<div class="tabbed">
|
||||
|
||||
- <b class="tab-title">Tab 1</b> This is the content of tab 1
|
||||
- <b class="tab-title">Tab 2</b> This is the content of tab 2
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
## Page Navigation {#extension-page-navigation}
|
||||
|
||||
@warning Experimental feature! Please report bugs [here](https://github.com/jothepro/doxygen-awesome-css/issues).
|
||||
|
||||
To allow the user to easily navigate from one document to another, "Next" and "Previous" buttons can be added at the end of a Markdown document.
|
||||
|
||||
### Installation
|
||||
|
||||
The feature is shipped inside the default `doxygen-awesome.css`. No additional stylesheets or scripts need to be added.
|
||||
|
||||
### Usage
|
||||
|
||||
The following conditions must be met for the feature to work properly:
|
||||
- The navigation must be inside a Markdown table with 1-2 columns.
|
||||
- The alignment of the column defines the alignment of the arrow on the navigation button.
|
||||
- the table must be wrapped inside a `<div>` with the class `section_buttons`.
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <span class="tab-title">Code</span>
|
||||
```md
|
||||
<div class="section_buttons">
|
||||
|
||||
| Previous | Next |
|
||||
|:------------------|----------------------------------:|
|
||||
| [Home](README.md) | [Customization](customization.md) |
|
||||
|
||||
</div>
|
||||
```
|
||||
- <span class="tab-title">Result</span>
|
||||
<div class="section_buttons">
|
||||
| Previous | Next |
|
||||
|:------------------|----------------------------------:|
|
||||
| [Home](README.md) | [Customization](customization.md) |
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="section_buttons">
|
||||
|
||||
| Previous | Next |
|
||||
|:------------------|----------------------------------:|
|
||||
| [Home](README.md) | [Customization](customization.md) |
|
||||
</div>
|
BIN
doc/doxygen-awesome-css/docs/img/darkmode_toggle.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/doxygen-awesome-css/docs/img/fancy_scrollbars_firefox.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
doc/doxygen-awesome-css/docs/img/fancy_scrollbars_webkit.gif
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
doc/doxygen-awesome-css/docs/img/fragment_copy_button.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
doc/doxygen-awesome-css/docs/img/interactive_toc_mobile.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
doc/doxygen-awesome-css/docs/img/paragraph_link.png
Normal file
After Width: | Height: | Size: 12 KiB |
127
doc/doxygen-awesome-css/docs/tricks.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Tips & Tricks
|
||||
|
||||
[TOC]
|
||||
|
||||
## Diagrams with Graphviz {#tricks-graphviz}
|
||||
|
||||
To get the best-looking class diagrams for your documentation, generate them with Graphviz as vector graphics with transparent background:
|
||||
|
||||
```
|
||||
# Doxyfile
|
||||
HAVE_DOT = YES
|
||||
DOT_IMAGE_FORMAT = svg
|
||||
DOT_TRANSPARENT = YES
|
||||
```
|
||||
|
||||
In case `INTERACTIVE_SVG = YES` is set in the Doxyfile, all user-defined dotgraphs must be wrapped with the `interactive_dotgraph` CSS class for them to be rendered correctly:
|
||||
|
||||
```md
|
||||
<div class="interactive_dotgraph">
|
||||
|
||||
\dotfile graph.dot
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
@note Both the default overflow scrolling behavior in this theme and the interactive editor enabled by `INTERACTIVE_SVG` are unsatisfying workarounds IMHO. Consider designing your graphs to be narrow enough to fit the page to avoid scrolling.
|
||||
|
||||
## Disable Dark Mode {#tricks-darkmode}
|
||||
|
||||
If you don't want the theme to automatically switch to dark mode depending on the browser preference,
|
||||
you can disable dark mode by adding the `light-mode` class to the HTML tag in the header template:
|
||||
|
||||
```html
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" class="light-mode">
|
||||
```
|
||||
|
||||
The same can be done to always enable dark mode:
|
||||
|
||||
```html
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" class="dark-mode">
|
||||
```
|
||||
|
||||
|
||||
@warning This only works if you don't use the dark-mode toggle extension.
|
||||
|
||||
## Choosing Sidebar Width {#tricks-sidebar}
|
||||
|
||||
If you have enabled the sidebar-only theme variant, make sure to carefully choose a proper width for your sidebar.
|
||||
It should be wide enough to hold the icon, project title and version number. If the content is too wide, it will be
|
||||
cut off.
|
||||
|
||||
```css
|
||||
html {
|
||||
/* Make sure sidebar is wide enough to contain the page title (logo + title + version) */
|
||||
--side-nav-fixed-width: 335px;
|
||||
}
|
||||
```
|
||||
|
||||
The chosen width should also be set in the Doxyfile:
|
||||
|
||||
```
|
||||
# Doxyfile
|
||||
TREEVIEW_WIDTH = 335
|
||||
```
|
||||
|
||||
## Formatting Tables {#tricks-tables}
|
||||
|
||||
By default tables in this theme are left-aligned and as wide as required to fit their content.
|
||||
Those properties can be changed for individual tables.
|
||||
|
||||
### Centering
|
||||
|
||||
Tables can be centered by wrapping them in the `<center>` HTML tag.
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <span class="tab-title">Code</span>
|
||||
```md
|
||||
<center>
|
||||
| This table | is centered |
|
||||
|------------|----------------------|
|
||||
| test 1 | test 2 |
|
||||
</center>
|
||||
```
|
||||
- <span class="tab-title">Result</span>
|
||||
<center>
|
||||
| This table | is centered |
|
||||
|------------|----------------------|
|
||||
| test 1 | test 2 |
|
||||
</center>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
### Full Width
|
||||
|
||||
To make tables span the full width of the page, no matter how wide the content is, wrap the table in the `full_width_table` CSS class.
|
||||
|
||||
@warning Apply with caution! This breaks the overflow scrolling of the table. Content might be cut off on small screens!
|
||||
|
||||
<div class="tabbed">
|
||||
|
||||
- <span class="tab-title">Code</span>
|
||||
```md
|
||||
<div class="full_width_table">
|
||||
| This table | spans the full width |
|
||||
|------------|----------------------|
|
||||
| test 1 | test 2 |
|
||||
</div>
|
||||
```
|
||||
- <span class="tab-title">Result</span>
|
||||
<div class="full_width_table">
|
||||
| This table | spans the full width |
|
||||
|------------|----------------------|
|
||||
| test 1 | test 2 |
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="section_buttons">
|
||||
|
||||
| Previous | Next |
|
||||
|:----------------------------------|---------------------------------------:|
|
||||
| [Customization](customization.md) | [Example](https://jothepro.github.io/doxygen-awesome-css/class_my_library_1_1_example.html) |
|
||||
|
||||
</div>
|
157
doc/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeDarkModeToggle extends HTMLElement {
|
||||
// SVG icons from https://fonts.google.com/icons
|
||||
// Licensed under the Apache 2.0 license:
|
||||
// https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
static lightModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FCBF00"><rect fill="none" height="24" width="24"/><circle cx="12" cy="12" opacity=".3" r="3"/><path d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg>`
|
||||
static darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FE9700"><rect fill="none" height="24" width="24"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z" opacity=".3"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg>`
|
||||
static title = "Toggle Light/Dark Mode"
|
||||
|
||||
static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode"
|
||||
static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode"
|
||||
|
||||
static _staticConstructor = function() {
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference)
|
||||
// Update the color scheme when the browsers preference changes
|
||||
// without user interaction on the website.
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
|
||||
})
|
||||
// Update the color scheme when the tab is made visible again.
|
||||
// It is possible that the appearance was changed in another tab
|
||||
// while this tab was in the background.
|
||||
document.addEventListener("visibilitychange", visibilityState => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
|
||||
}
|
||||
});
|
||||
}()
|
||||
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle')
|
||||
toggleButton.title = DoxygenAwesomeDarkModeToggle.title
|
||||
toggleButton.updateIcon()
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
toggleButton.updateIcon()
|
||||
})
|
||||
document.addEventListener("visibilitychange", visibilityState => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
toggleButton.updateIcon()
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
|
||||
})
|
||||
$(window).resize(function(){
|
||||
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.onclick=this.toggleDarkMode
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` for dark-mode, `false` for light-mode system preference
|
||||
*/
|
||||
static get systemPreference() {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` for dark-mode, `false` for light-mode user preference
|
||||
*/
|
||||
static get userPreference() {
|
||||
return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) ||
|
||||
(DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))
|
||||
}
|
||||
|
||||
static set userPreference(userPreference) {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference
|
||||
if(!userPreference) {
|
||||
if(DoxygenAwesomeDarkModeToggle.systemPreference) {
|
||||
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)
|
||||
} else {
|
||||
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)
|
||||
}
|
||||
} else {
|
||||
if(!DoxygenAwesomeDarkModeToggle.systemPreference) {
|
||||
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)
|
||||
} else {
|
||||
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)
|
||||
}
|
||||
}
|
||||
DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()
|
||||
}
|
||||
|
||||
static enableDarkMode(enable) {
|
||||
if(enable) {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = true
|
||||
document.documentElement.classList.add("dark-mode")
|
||||
document.documentElement.classList.remove("light-mode")
|
||||
} else {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = false
|
||||
document.documentElement.classList.remove("dark-mode")
|
||||
document.documentElement.classList.add("light-mode")
|
||||
}
|
||||
}
|
||||
|
||||
static onSystemPreferenceChanged() {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
|
||||
}
|
||||
|
||||
static onUserPreferenceChanged() {
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
|
||||
}
|
||||
|
||||
toggleDarkMode() {
|
||||
DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference
|
||||
this.updateIcon()
|
||||
}
|
||||
|
||||
updateIcon() {
|
||||
if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) {
|
||||
this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon
|
||||
} else {
|
||||
this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);
|
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeFragmentCopyButton extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.onclick=this.copyContent
|
||||
}
|
||||
static title = "Copy to clipboard"
|
||||
static copyIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>`
|
||||
static successIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg>`
|
||||
static successDuration = 980
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
if(navigator.clipboard) {
|
||||
const fragments = document.getElementsByClassName("fragment")
|
||||
for(const fragment of fragments) {
|
||||
const fragmentWrapper = document.createElement("div")
|
||||
fragmentWrapper.className = "doxygen-awesome-fragment-wrapper"
|
||||
const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button")
|
||||
fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
|
||||
fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title
|
||||
|
||||
fragment.parentNode.replaceChild(fragmentWrapper, fragment)
|
||||
fragmentWrapper.appendChild(fragment)
|
||||
fragmentWrapper.appendChild(fragmentCopyButton)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
copyContent() {
|
||||
const content = this.previousSibling.cloneNode(true)
|
||||
// filter out line number from file listings
|
||||
content.querySelectorAll(".lineno, .ttc").forEach((node) => {
|
||||
node.remove()
|
||||
})
|
||||
let textContent = content.textContent
|
||||
// remove trailing newlines that appear in file listings
|
||||
let numberOfTrailingNewlines = 0
|
||||
while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') {
|
||||
numberOfTrailingNewlines++;
|
||||
}
|
||||
textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines)
|
||||
navigator.clipboard.writeText(textContent);
|
||||
this.classList.add("success")
|
||||
this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon
|
||||
window.setTimeout(() => {
|
||||
this.classList.remove("success")
|
||||
this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
|
||||
}, DoxygenAwesomeFragmentCopyButton.successDuration);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton)
|
91
doc/doxygen-awesome-css/doxygen-awesome-interactive-toc.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeInteractiveToc {
|
||||
static topOffset = 38
|
||||
static hideMobileMenu = true
|
||||
static headers = []
|
||||
|
||||
static init() {
|
||||
window.addEventListener("load", () => {
|
||||
let toc = document.querySelector(".contents > .toc")
|
||||
if(toc) {
|
||||
toc.classList.add("interactive")
|
||||
if(!DoxygenAwesomeInteractiveToc.hideMobileMenu) {
|
||||
toc.classList.add("open")
|
||||
}
|
||||
document.querySelector(".contents > .toc > h3")?.addEventListener("click", () => {
|
||||
if(toc.classList.contains("open")) {
|
||||
toc.classList.remove("open")
|
||||
} else {
|
||||
toc.classList.add("open")
|
||||
}
|
||||
})
|
||||
|
||||
document.querySelectorAll(".contents > .toc > ul a").forEach((node) => {
|
||||
let id = node.getAttribute("href").substring(1)
|
||||
DoxygenAwesomeInteractiveToc.headers.push({
|
||||
node: node,
|
||||
headerNode: document.getElementById(id)
|
||||
})
|
||||
|
||||
document.getElementById("doc-content")?.addEventListener("scroll",this.throttle(DoxygenAwesomeInteractiveToc.update, 100))
|
||||
})
|
||||
DoxygenAwesomeInteractiveToc.update()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static update() {
|
||||
let active = DoxygenAwesomeInteractiveToc.headers[0]?.node
|
||||
DoxygenAwesomeInteractiveToc.headers.forEach((header) => {
|
||||
let position = header.headerNode.getBoundingClientRect().top
|
||||
header.node.classList.remove("active")
|
||||
header.node.classList.remove("aboveActive")
|
||||
if(position < DoxygenAwesomeInteractiveToc.topOffset) {
|
||||
active = header.node
|
||||
active?.classList.add("aboveActive")
|
||||
}
|
||||
})
|
||||
active?.classList.add("active")
|
||||
active?.classList.remove("aboveActive")
|
||||
}
|
||||
|
||||
static throttle(func, delay) {
|
||||
let lastCall = 0;
|
||||
return function (...args) {
|
||||
const now = new Date().getTime();
|
||||
if (now - lastCall < delay) {
|
||||
return;
|
||||
}
|
||||
lastCall = now;
|
||||
return setTimeout(() => {func(...args)}, delay);
|
||||
};
|
||||
}
|
||||
}
|
51
doc/doxygen-awesome-css/doxygen-awesome-paragraph-link.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeParagraphLink {
|
||||
// Icon from https://fonts.google.com/icons
|
||||
// Licensed under the Apache 2.0 license:
|
||||
// https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
static icon = `<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 24 24" width="20px"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z"/></svg>`
|
||||
static title = "Permanent Link"
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
document.querySelectorAll(".contents a.anchor[id], .contents .groupheader > a[id]").forEach((node) => {
|
||||
let anchorlink = document.createElement("a")
|
||||
anchorlink.setAttribute("href", `#${node.getAttribute("id")}`)
|
||||
anchorlink.setAttribute("title", DoxygenAwesomeParagraphLink.title)
|
||||
anchorlink.classList.add("anchorlink")
|
||||
node.classList.add("anchor")
|
||||
anchorlink.innerHTML = DoxygenAwesomeParagraphLink.icon
|
||||
node.parentElement.appendChild(anchorlink)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
|
||||
#MSearchBox {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px);
|
||||
}
|
||||
|
||||
#MSearchField {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height));
|
||||
}
|
||||
}
|
116
doc/doxygen-awesome-css/doxygen-awesome-sidebar-only.css
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
html {
|
||||
/* side nav width. MUST be = `TREEVIEW_WIDTH`.
|
||||
* Make sure it is wide enough to contain the page title (logo + title + version)
|
||||
*/
|
||||
--side-nav-fixed-width: 335px;
|
||||
--menu-display: none;
|
||||
|
||||
--top-height: 120px;
|
||||
--toc-sticky-top: -25px;
|
||||
--toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px);
|
||||
}
|
||||
|
||||
#projectname {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
html {
|
||||
--searchbar-background: var(--page-background-color);
|
||||
}
|
||||
|
||||
#side-nav {
|
||||
min-width: var(--side-nav-fixed-width);
|
||||
max-width: var(--side-nav-fixed-width);
|
||||
top: var(--top-height);
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#nav-tree, #side-nav {
|
||||
height: calc(100vh - var(--top-height)) !important;
|
||||
}
|
||||
|
||||
#nav-tree {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#top {
|
||||
display: block;
|
||||
border-bottom: none;
|
||||
height: var(--top-height);
|
||||
margin-bottom: calc(0px - var(--top-height));
|
||||
max-width: var(--side-nav-fixed-width);
|
||||
overflow: hidden;
|
||||
background: var(--side-nav-background);
|
||||
}
|
||||
#main-nav {
|
||||
float: left;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.ui-resizable-handle {
|
||||
cursor: default;
|
||||
width: 1px !important;
|
||||
background: var(--separator-color);
|
||||
box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
|
||||
}
|
||||
|
||||
#nav-path {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
left: var(--side-nav-fixed-width);
|
||||
bottom: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#doc-content {
|
||||
height: calc(100vh - 31px) !important;
|
||||
padding-bottom: calc(3 * var(--spacing-large));
|
||||
padding-top: calc(var(--top-height) - 80px);
|
||||
box-sizing: border-box;
|
||||
margin-left: var(--side-nav-fixed-width) !important;
|
||||
}
|
||||
|
||||
#MSearchBox {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
|
||||
}
|
||||
|
||||
#MSearchField {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
|
||||
}
|
||||
|
||||
#MSearchResultsWindow {
|
||||
left: var(--spacing-medium) !important;
|
||||
right: auto;
|
||||
}
|
||||
}
|
90
doc/doxygen-awesome-css/doxygen-awesome-tabs.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeTabs {
|
||||
|
||||
static init() {
|
||||
window.addEventListener("load", () => {
|
||||
document.querySelectorAll(".tabbed:not(:empty)").forEach((tabbed, tabbedIndex) => {
|
||||
let tabLinkList = []
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
|
||||
tab.id = "tab_" + tabbedIndex + "_" + tabIndex
|
||||
let header = tab.querySelector(".tab-title")
|
||||
let tabLink = document.createElement("button")
|
||||
tabLink.classList.add("tab-button")
|
||||
tabLink.appendChild(header)
|
||||
header.title = header.textContent
|
||||
tabLink.addEventListener("click", () => {
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab) => {
|
||||
tab.classList.remove("selected")
|
||||
})
|
||||
tabLinkList.forEach((tabLink) => {
|
||||
tabLink.classList.remove("active")
|
||||
})
|
||||
tab.classList.add("selected")
|
||||
tabLink.classList.add("active")
|
||||
})
|
||||
tabLinkList.push(tabLink)
|
||||
if(tabIndex == 0) {
|
||||
tab.classList.add("selected")
|
||||
tabLink.classList.add("active")
|
||||
}
|
||||
})
|
||||
let tabsOverview = document.createElement("div")
|
||||
tabsOverview.classList.add("tabs-overview")
|
||||
let tabsOverviewContainer = document.createElement("div")
|
||||
tabsOverviewContainer.classList.add("tabs-overview-container")
|
||||
tabLinkList.forEach((tabLink) => {
|
||||
tabsOverview.appendChild(tabLink)
|
||||
})
|
||||
tabsOverviewContainer.appendChild(tabsOverview)
|
||||
tabbed.before(tabsOverviewContainer)
|
||||
|
||||
function resize() {
|
||||
let maxTabHeight = 0
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
|
||||
let visibility = tab.style.display
|
||||
tab.style.display = "block"
|
||||
maxTabHeight = Math.max(tab.offsetHeight, maxTabHeight)
|
||||
tab.style.display = visibility
|
||||
})
|
||||
tabbed.style.height = `${maxTabHeight + 10}px`
|
||||
}
|
||||
|
||||
resize()
|
||||
new ResizeObserver(resize).observe(tabbed)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
static resize(tabbed) {
|
||||
|
||||
}
|
||||
}
|
2683
doc/doxygen-awesome-css/doxygen-awesome.css
Normal file
@@ -0,0 +1,54 @@
|
||||
html.alternative {
|
||||
/* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
|
||||
--primary-color: #AF7FE4;
|
||||
--primary-dark-color: #9270E4;
|
||||
--primary-light-color: #7aabd6;
|
||||
--primary-lighter-color: #cae1f1;
|
||||
--primary-lightest-color: #e9f1f8;
|
||||
|
||||
/* page base colors */
|
||||
--page-background-color: white;
|
||||
--page-foreground-color: #2c3e50;
|
||||
--page-secondary-foreground-color: #67727e;
|
||||
|
||||
|
||||
--border-radius-large: 22px;
|
||||
--border-radius-small: 9px;
|
||||
--border-radius-medium: 14px;
|
||||
--spacing-small: 8px;
|
||||
--spacing-medium: 14px;
|
||||
--spacing-large: 19px;
|
||||
|
||||
--top-height: 125px;
|
||||
|
||||
--side-nav-background: #324067;
|
||||
--side-nav-foreground: #F1FDFF;
|
||||
--header-foreground: var(--side-nav-foreground);
|
||||
--searchbar-background: var(--side-nav-foreground);
|
||||
--searchbar-border-radius: var(--border-radius-medium);
|
||||
--header-background: var(--side-nav-background);
|
||||
--header-foreground: var(--side-nav-foreground);
|
||||
|
||||
--toc-background: rgb(243, 240, 252);
|
||||
--toc-foreground: var(--page-foreground-color);
|
||||
}
|
||||
|
||||
html.alternative.dark-mode {
|
||||
color-scheme: dark;
|
||||
|
||||
--primary-color: #AF7FE4;
|
||||
--primary-dark-color: #9270E4;
|
||||
--primary-light-color: #4779ac;
|
||||
--primary-lighter-color: #191e21;
|
||||
--primary-lightest-color: #191a1c;
|
||||
|
||||
--page-background-color: #1C1D1F;
|
||||
--page-foreground-color: #d2dbde;
|
||||
--page-secondary-foreground-color: #859399;
|
||||
--separator-color: #3a3246;
|
||||
--side-nav-background: #171D32;
|
||||
--side-nav-foreground: #F1FDFF;
|
||||
--toc-background: #20142C;
|
||||
--searchbar-background: var(--page-background-color);
|
||||
|
||||
}
|
57
doc/doxygen-awesome-css/doxygen-custom/custom.css
Normal file
@@ -0,0 +1,57 @@
|
||||
.github-corner svg {
|
||||
fill: var(--primary-light-color);
|
||||
color: var(--page-background-color);
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.github-corner svg {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
#projectnumber {
|
||||
margin-right: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.alter-theme-button {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: var(--page-background-color) !important;
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: var(--spacing-small) var(--spacing-medium);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.alter-theme-button:hover {
|
||||
background: var(--primary-dark-color);
|
||||
}
|
||||
|
||||
html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */
|
||||
html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
|
||||
filter: brightness(89%) hue-rotate(180deg) invert();
|
||||
}
|
||||
|
||||
.bordered_image {
|
||||
border-radius: var(--border-radius-small);
|
||||
border: 1px solid var(--separator-color);
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */
|
||||
html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
|
||||
border-radius: var(--border-radius-small);
|
||||
}
|
||||
|
||||
.title_screenshot {
|
||||
filter: drop-shadow(0px 3px 10px rgba(0,0,0,0.22));
|
||||
max-width: 500px;
|
||||
margin: var(--spacing-large) 0;
|
||||
}
|
||||
|
||||
.title_screenshot .caption {
|
||||
display: none;
|
||||
}
|
90
doc/doxygen-awesome-css/doxygen-custom/header.html
Normal file
@@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
|
||||
<!-- BEGIN opengraph metadata -->
|
||||
<meta property="og:title" content="Doxygen Awesome" />
|
||||
<meta property="og:image" content="https://repository-images.githubusercontent.com/348492097/4f16df80-88fb-11eb-9d31-4015ff22c452" />
|
||||
<meta property="og:description" content="Custom CSS theme for doxygen html-documentation with lots of customization parameters." />
|
||||
<meta property="og:url" content="https://jothepro.github.io/doxygen-awesome-css/" />
|
||||
<!-- END opengraph metadata -->
|
||||
|
||||
<!-- BEGIN twitter metadata -->
|
||||
<meta name="twitter:image:src" content="https://repository-images.githubusercontent.com/348492097/4f16df80-88fb-11eb-9d31-4015ff22c452" />
|
||||
<meta name="twitter:title" content="Doxygen Awesome" />
|
||||
<meta name="twitter:description" content="Custom CSS theme for doxygen html-documentation with lots of customization parameters." />
|
||||
<!-- END twitter metadata -->
|
||||
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="icon" type="image/svg+xml" href="logo.drawio.svg"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-tabs.js"></script>
|
||||
<script type="text/javascript" src="$relpath^toggle-alternative-theme.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeFragmentCopyButton.init()
|
||||
DoxygenAwesomeDarkModeToggle.init()
|
||||
DoxygenAwesomeParagraphLink.init()
|
||||
DoxygenAwesomeInteractiveToc.init()
|
||||
DoxygenAwesomeTabs.init()
|
||||
</script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- https://tholman.com/github-corners/ -->
|
||||
<a href="https://github.com/jothepro/doxygen-awesome-css" class="github-corner" title="View source on GitHub" target="_blank" rel="noopener noreferrer">
|
||||
<svg viewBox="0 0 250 250" width="40" height="40" style="position: absolute; top: 0; border: 0; right: 0; z-index: 99;" aria-hidden="true">
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
||||
|
||||
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td id="projectalign" style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
@@ -0,0 +1,12 @@
|
||||
|
||||
let original_theme_active = true;
|
||||
|
||||
function toggle_alternative_theme() {
|
||||
if(original_theme_active) {
|
||||
document.documentElement.classList.add("alternative")
|
||||
original_theme_active = false;
|
||||
} else {
|
||||
document.documentElement.classList.remove("alternative")
|
||||
original_theme_active = true;
|
||||
}
|
||||
}
|
BIN
doc/doxygen-awesome-css/img/screenshot.png
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
doc/doxygen-awesome-css/img/testimage.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
117
doc/doxygen-awesome-css/img/theme-variants-base.drawio.svg
Normal file
@@ -0,0 +1,117 @@
|
||||
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="491px" height="261px" viewBox="-0.5 -0.5 491 261" content="<mxfile><diagram id="6E4AiNPWWr3a8GvC3Ypl" name="Page-1">xZfLrpswEIafBqndIIzBwLK5tZt2k0pd+wQHrBqcOs6tT98xmABxmrYiUUEK+Pd1vhkPjofn1fmjorvys8yZ8MIgP3t44YVhihL4NcKlFZIkbYVC8byVUC+s+U9mxcCqB56z/aihllJovhuLG1nXbKNHGlVKnsbNtlKMZ93RgjnCekOFq37juS6tWXHQ658YL8puZhTYmop2ja2wL2kuTwMJLz08V1Lq9q06z5kw7Doubb/Vb2qvC1Os1n/ToVvHkYqDNc4uTF86awslDzsPz+BR58x0DKBE1cY6JoWSO69dypEpzc73vELfugl6wyFgmKyYVhdod+rRRpldZznAGhIrUuvO4tq3txherNH3AZA/2z+2+1RyzdY7ujG1Jwhv0EpdwfgLBK97reR3NpdCqqY3JktzQ00h6H5vBwEEmvKaKVt28V0dc8vvP3GKHE5zsMEs97m4ls09FUlXm6V+jNteNtVEkZ/a7DPgBi19Qlx0KI19hKfTCx16X7kW7I0qUN99oUdeUM1l7RkbwfRgzWB/le+nwd1yIQZoF8vlYrV6GKMvjcMGPUqyqPudzhU7XNfwZXCwPpfjKjH36zg+jFQUEj/Br4vU2CG6go8Ra4DOFKP5Rh2q3X4i0deSg4wHu3lwZQ7GuwGKsY9HF5nOM3EjtNnaD/ihKfy2kJUHekjM/aR0ihPkJ2GEcJJhFOAoHmVWdLu9Qzd4A+R3naM0TOLsTiDf+I6k052Q3vnIE6EtruZI0hEjPw7m7DXr2Q0kUphnk7q7AWDqdoy2znEroNWPfFfLmt2kGCtRwYsaioJtzQjGTRyOoB+sXPE8N5PcDZXxZjQLtGe1cPJp43x1U5qROEZdQIT/Ggyw24ahkJL4JcEAxf443dQN/pPg5S8=</diagram></mxfile>">
|
||||
<defs/>
|
||||
<g>
|
||||
<rect x="0" y="0" width="490" height="260" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<rect x="198.53" y="44.87" width="219.66" height="185.13" fill="rgb(255, 255, 255)" stroke="#e3e3e3" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 137px; margin-left: 200px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="308" y="141" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Content
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="0" y="0" width="490" height="44.87" fill="#deedff" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 488px; height: 1px; padding-top: 22px; margin-left: 1px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Titlebar (Navigation + Search)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="245" y="26" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Titlebar (Navigation + Search)
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="0" y="44.87" width="126.73" height="185.13" fill="#f7f7f7" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 125px; height: 1px; padding-top: 137px; margin-left: 1px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Sidebar (Navigation)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="63" y="141" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Sidebar (Navigation)
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="0" y="226.67" width="490" height="33.33" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 488px; height: 1px; padding-top: 243px; margin-left: 1px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Footer (Breadcrumbs)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="245" y="247" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Footer (Breadcrumbs)
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="371.72" y="14.87" width="101.38" height="16.67" rx="2.5" ry="2.5" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 99px; height: 1px; padding-top: 23px; margin-left: 373px;">
|
||||
<div data-drawio-colors="color: #262626; " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(38, 38, 38); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Search
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="422" y="27" fill="#262626" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Search
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 32px; height: 1px; padding-top: 23px; margin-left: 19px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;">
|
||||
<div style="display: inline-block; font-size: 20px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
<font color="#262626">
|
||||
Title
|
||||
</font>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="19" y="29" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="20px">
|
||||
Tit...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
</g>
|
||||
<switch>
|
||||
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
|
||||
<a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
|
||||
<text text-anchor="middle" font-size="10px" x="50%" y="100%">
|
||||
Text is not SVG - cannot display
|
||||
</text>
|
||||
</a>
|
||||
</switch>
|
||||
</svg>
|
After Width: | Height: | Size: 9.5 KiB |
@@ -0,0 +1,102 @@
|
||||
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="491px" height="261px" viewBox="-0.5 -0.5 491 261" content="<mxfile><diagram id="6E4AiNPWWr3a8GvC3Ypl" name="Page-1">xZZNj5swEIZ/DdL2gjAGA8cmm7SX9pJKPTvBAasGU8f56q/vOJjFLOxqpbC7WIrMO/5gnhlP7OFldfmmaFP+kDkTXhjkFw8/emGYogR+jXBthSRJW6FQPG8l1Asb/o9ZMbDqkefsMBiopRSaN0NxJ+ua7fRAo0rJ83DYXorhrg0t2EjY7KgYq795rkvrVhz0+nfGi7LbGQXWUtFusBUOJc3l2ZHwysNLJaVue9VlyYRh13Fp561fsD59mGK1ftOErJ1xouJonbMfpq+dt4WSx2a8sN3rxJRmlynsdNut0HsGGcFkxbS6wrhzzy7KLJDS4RYSK1Ibr+Jpbu8SdKxX0x6+wUHwr86ZGR94eHEuuWabhu6M9Qz5C1qpK1j/EUH3oJX8w5ZSSHWbjcnKNLBMIMpeYPRJLLrz48BYylqb752XyerW7mXSWbPUj8Osf2z1sMUDEZ9YxYEIs3xCJjhi7GM8A0o0QrmBorSlyjPpTgTst9jCCylM7+EX14DWmIBJ8JOeeEE1l/WX+8jvuRAO93Vi2odkKQqJn4TvlajhiO4aaiIzcB8WitF8p45Vc7iT3jtRuriEIoSTDKMARzEe5C2Qggx1n1ESY4L9MIlTEgYkzUgcj3Hf0tl9yAz08Ti3GVW78hXa6B7aeyhCjh4S02aLApQHJwrpsHpEaBiEcSVBAfK7yVEK4cjGUUDPQ5nOEIVo4p+rrSuG1+1/tkNG/h7NjWHRw3OktgLZAtQuAHu3a7S2UVyBrX4teLWs2bPqYyUqeFHDq2B7s4KJE4eL01crVzzPzSaTuTI8u+YD7dUvDD4mGRCaDqN7JLHv5kJKJs7kDNkAr/0l8GZzbtJ49R8=</diagram></mxfile>">
|
||||
<defs/>
|
||||
<g>
|
||||
<rect x="0" y="0" width="490" height="260" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<rect x="198.53" y="16.67" width="219.66" height="233.33" fill="rgb(255, 255, 255)" stroke="#e3e3e3" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 133px; margin-left: 200px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="308" y="137" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Content
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="0" y="0" width="126.72" height="260" fill="#f7f7f7" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 125px; height: 1px; padding-top: 130px; margin-left: 1px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Sidebar
|
||||
<br/>
|
||||
(Title + Navigation)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="63" y="134" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Sidebar...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="126.72" y="226.67" width="363.28" height="33.33" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 361px; height: 1px; padding-top: 243px; margin-left: 128px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Footer (Breadcrumbs)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="308" y="247" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Footer (Breadcrumbs)
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="12.67" y="41.67" width="101.38" height="16.67" rx="2.5" ry="2.5" fill="rgb(255, 255, 255)" stroke="#6e6e6e" pointer-events="none"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 99px; height: 1px; padding-top: 50px; margin-left: 14px;">
|
||||
<div data-drawio-colors="color: #262626; " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(38, 38, 38); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
Search
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="63" y="54" fill="#262626" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
Search
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 32px; height: 1px; padding-top: 20px; margin-left: 15px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;">
|
||||
<div style="display: inline-block; font-size: 20px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">
|
||||
<font color="#262626">
|
||||
Title
|
||||
</font>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="15" y="26" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="20px">
|
||||
Tit...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
</g>
|
||||
<switch>
|
||||
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
|
||||
<a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
|
||||
<text text-anchor="middle" font-size="10px" x="50%" y="100%">
|
||||
Text is not SVG - cannot display
|
||||
</text>
|
||||
</a>
|
||||
</switch>
|
||||
</svg>
|
After Width: | Height: | Size: 8.2 KiB |
169
doc/doxygen-awesome-css/include/MyLibrary/example.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace MyLibrary {
|
||||
|
||||
enum Color { red = 1, green = 2, blue = 3 };
|
||||
|
||||
/**
|
||||
* @brief Example class to demonstrate the features of the custom CSS.
|
||||
*
|
||||
* @author jothepro
|
||||
*
|
||||
*/
|
||||
class Example {
|
||||
public:
|
||||
/**
|
||||
* @brief brief summary
|
||||
*
|
||||
* doxygen test documentation
|
||||
*
|
||||
* @param test this is the only parameter of this test function. It does nothing!
|
||||
*
|
||||
* # Supported elements
|
||||
*
|
||||
* These elements have been tested with the custom CSS.
|
||||
*
|
||||
* ## Tables
|
||||
*
|
||||
* <div class="tabbed">
|
||||
*
|
||||
* - <b class="tab-title">Basic</b>
|
||||
* This theme supports normal markdown tables:<br>
|
||||
* | Item | Title | Description | More |
|
||||
* |-----:|-------|-----------------------|--------------------------------------------|
|
||||
* | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. |
|
||||
* | 2 | Bar | Also a placeholder | More lorem ipsum. |
|
||||
* | 3 | Baz | The third placeholder | More lorem ipsum. |
|
||||
* - <b class="tab-title">Centered</b>
|
||||
* <center>
|
||||
* A table can be centered with the `<center>` html tag:<br>
|
||||
* | Item | Title | Description | More |
|
||||
* |-----:|-------|-----------------------|--------------------------------------------|
|
||||
* | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. |
|
||||
* | 2 | Bar | Also a placeholder | More lorem ipsum. |
|
||||
* | 3 | Baz | The third placeholder | More lorem ipsum. |
|
||||
* </center>
|
||||
* - <b class="tab-title">Stretched</b>
|
||||
* A table wrapped in `<div class="full_width_table">` fills the full page width.
|
||||
* <div class="full_width_table">
|
||||
* | Item | Title | Description | More |
|
||||
* |-----:|-------|-----------------------|--------------------------------------------|
|
||||
* | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. |
|
||||
* | 2 | Bar | Also a placeholder | More lorem ipsum. |
|
||||
* | 3 | Baz | The third placeholder | More lorem ipsum. |
|
||||
* </div>
|
||||
* **Caution**: This will break the overflow scrolling support!
|
||||
* - <b class="tab-title">Complex</b>
|
||||
* Complex [Doxygen tables](https://www.doxygen.nl/manual/tables.html) are also supported as seen in @ref multi_row "this example":<br>
|
||||
* <table>
|
||||
* <caption id="multi_row">Complex table</caption>
|
||||
* <tr><th>Column 1 <th>Column 2 <th>Column 3
|
||||
* <tr><td rowspan="2">cell row=1+2,col=1<td>cell row=1,col=2<td>cell row=1,col=3
|
||||
* <tr><td rowspan="2">cell row=2+3,col=2 <td>cell row=2,col=3
|
||||
* <tr><td>cell row=3,col=1 <td>cell row=3,col=3
|
||||
* </table>
|
||||
* - <b class="tab-title">Overflow Scrolling</b> The table content is scrollable if the table gets too wide.<br>
|
||||
* | first_column | second_column | third_column | fourth_column | fifth_column | sixth_column | seventh_column | eighth_column | ninth_column |
|
||||
* |--------------|---------------|--------------|---------------|--------------|--------------|----------------|---------------|--------------|
|
||||
* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
||||
* - <b class="tab-title">Images</b>A table can contain images:<br>
|
||||
* | Column 1 | Column 2 |
|
||||
* |---------------------------|-------------------------------------------------|
|
||||
* |  | ← the image should not be inverted in dark-mode |
|
||||
*
|
||||
*
|
||||
* </div>
|
||||
*
|
||||
* ## Diagrams
|
||||
*
|
||||
* Graphviz diagrams support dark mode and can be scrolled once they get too wide:
|
||||
*
|
||||
* \dot Graphviz with a caption
|
||||
* digraph example {
|
||||
* node [fontsize="12"];
|
||||
* rankdir="LR"
|
||||
* a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k;
|
||||
* }
|
||||
* \enddot
|
||||
*
|
||||
* ## Lists
|
||||
*
|
||||
* - element 1
|
||||
* - element 2
|
||||
*
|
||||
* 1. element 1
|
||||
* ```
|
||||
* code in lists
|
||||
* ```
|
||||
* 2. element 2
|
||||
*
|
||||
* ## Quotes
|
||||
*
|
||||
* > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
|
||||
* > ut labore et dolore magna aliqua. Vitae proin sagittis nisl rhoncus mattis rhoncus urna neque viverra.
|
||||
* > Velit sed ullamcorper morbi tincidunt ornare.
|
||||
* >
|
||||
* > Lorem ipsum dolor sit amet consectetur adipiscing elit duis.
|
||||
* *- jothepro*
|
||||
*
|
||||
* ## Code block
|
||||
*
|
||||
* ```cpp
|
||||
* auto x = "code within md fences";
|
||||
* ```
|
||||
*
|
||||
* @code{.cpp}
|
||||
* // code within @code block
|
||||
* while(true) {
|
||||
* auto example = std::make_shared<Example>(5);
|
||||
* example->test("test");
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* // code within indented code block
|
||||
* auto test = std::shared_ptr<Example(5);
|
||||
*
|
||||
*
|
||||
* Inline `code` elements in a text. *Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.* This also works within multiline text and does not break the `layout`.
|
||||
*
|
||||
*
|
||||
* ## Special hints
|
||||
*
|
||||
* @warning this is a warning only for demonstration purposes
|
||||
*
|
||||
* @note this is a note to show that notes work. They can also include `code`:
|
||||
* @code{.c}
|
||||
* void this_looks_awesome();
|
||||
* @endcode
|
||||
*
|
||||
* @bug example bug
|
||||
*
|
||||
* @deprecated None of this will be deprecated, because it's beautiful!
|
||||
*
|
||||
* @invariant This is an invariant
|
||||
*
|
||||
* @pre This is a precondition
|
||||
*
|
||||
* @post This is a postcondition
|
||||
*
|
||||
* @todo This theme is never finished!
|
||||
*
|
||||
* @remark This is awesome!
|
||||
*
|
||||
*/
|
||||
std::string test(const std::string& test);
|
||||
|
||||
virtual int virtualfunc() = 0;
|
||||
|
||||
static bool staticfunc();
|
||||
|
||||
|
||||
};
|
||||
|
||||
class SecondExample {
|
||||
std::string foo();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "example.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace MyLibrary {
|
||||
|
||||
/**
|
||||
* @brief some subclass
|
||||
*/
|
||||
template<typename TemplatedClass>
|
||||
class SubclassExample : public Example {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @bug second bug
|
||||
* @return
|
||||
*/
|
||||
int virtualfunc() override;
|
||||
|
||||
/**
|
||||
* @brief Template function function
|
||||
*/
|
||||
template <typename T>
|
||||
std::shared_ptr<std::string> function_template_test(std::shared_ptr<T>& param);
|
||||
|
||||
/**
|
||||
* @brief Extra long function with lots of parameters and many template types.
|
||||
*
|
||||
* Also has a long return type.
|
||||
*
|
||||
* @param param1 first parameter
|
||||
* @param param2 second parameter
|
||||
* @param parameter3 third parameter
|
||||
*/
|
||||
template <typename T, typename Foo, typename Bar, typename Alice, typename Bob, typename Charlie, typename Hello, typename World>
|
||||
std::pair<std::string, std::string> long_function_with_many_parameters(std::shared_ptr<T>& param1, std::shared_ptr<std::string>& param2, bool parameter3, Alice paramater4 Bob parameter 5) {
|
||||
if(true) {
|
||||
std::cout << "this even has some code." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
1
doc/doxygen-awesome-css/logo.drawio.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="61px" height="74px" viewBox="-0.5 -0.5 61 74" content="<mxfile host="drawio-plugin" modified="2021-03-16T23:58:23.462Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36" version="13.7.9" etag="JoeaGLJ54FcERO7YrWLQ" type="embed"><diagram id="JMB9aH8b_oZ7EWDuqJgx" name="Page-1">7VdNc5swEP01HDsjkGPDsSVJe+lMZnzoWYENaAwsI8ux6a+vCCtA4KSu62kmSS+M9LT7tB9P0uDxuDx8VaLOv2MKhRew9ODxay8Igigy3xZoCOC8AzIl0w7yB2AtfwKBjNCdTGHrGGrEQsvaBROsKki0gwmlcO+aPWDh7lqLDGbAOhHFHP0hU513aHjFBvwbyCy3O/uMVkphjQnY5iLF/QjiNx6PFaLuRuUhhqKtna1L53f7zGofmIJKn+RAcTyKYkfJUWC6sdlmCnc1mYHScDhWY3Fvzdk8Br/PzCgCsAStGmNCRJy2JDH4pIV8VMG+edS4rCcZcjMDSu+ZVP3fpwpV+rnVh5ndF5hsPP4l16VhvPbN8AErTWI0re7mMRaonpw5Y8tlHBvcsNzKwnpttVDaslZYgcXIhj3NFW56LS1bbrM44l6m4Wq5MLhxzEDfgZKmAKDWtUhklRFNgqVM7LYb0Enu8I9j9dkVC80KtgS6Lb3fGnYVgXSm/1Ez2fFu7oeTYA/CuIUWU1AILR9d/mN9pR3uUJqde7F88leOWhYLl2GLO5UAOY2FP+GxMm3c6CwNlXlKY9oompFZ3Rps59EOkuw8BoH2BTtNs8EfaZbUdYZkXQGuXhDgR9DYRBycXURj00D+UmMT2ktJLnr9B8HG0IzFcPkHYfUe3oPZqfOjMEiDs1+KEw5n9P/+/1f3f/gq1394lt7erqQ+0HVvpsPPRWc+/KHxm18=</diagram></mxfile>"><defs/><g><path d="M 13 57 L 13.01 57.01 L 15.87 50.14 L 18.37 43.14 L 20.91 36.15 L 23.67 29.25 L 26.4 22.33 Q 30 13 33.71 22.28 L 33.55 22.22 L 35.48 26.91 L 37.49 31.64 L 39.48 36.36 L 41.2 40.97 L 43.05 45.63" fill="none" stroke="#010508" stroke-opacity="0.1" stroke-width="6" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 47.51 56.77 L 47.65 56.93 L 45.43 54.91 L 43.41 53.11 L 41.43 51.35 L 39.63 49.8 L 37.48 47.86 L 37.39 47.64 L 39.79 47.17 L 41.9 45.98 L 44.24 45.37 L 46.48 44.52 L 48.62 43.4 L 48.54 43.39 L 48.58 46.09 L 48.04 48.74 L 48.04 51.43 L 47.8 54.1 L 47.51 56.77 Z Z" fill-opacity="0.1" fill="#010508" stroke="#010508" stroke-opacity="0.1" stroke-width="6" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="all"/><path d="M 10 43 L 9.94 42.88 L 12.16 41.98 L 14.31 40.96 L 16.51 40.01 L 18.62 38.89 L 20.88 38.1 Q 30 34 40 34 L 40 33.75 L 42 33.83 L 44 33.8 L 46 33.79 L 48 34.05 L 50 34" fill="none" stroke="#010508" stroke-opacity="0.1" stroke-width="7" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 10 54 L 9.97 53.99 L 12.69 47.07 L 15.43 40.16 L 18.07 33.21 L 20.65 26.24 L 23.4 19.33 Q 27 10 30.71 19.28 L 30.66 19.26 L 32.46 23.91 L 34.55 28.66 L 36.26 33.27 L 38.35 38.03 L 40.05 42.63" fill="none" stroke="#1982d2" stroke-width="6" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 44.51 53.77 L 44.56 53.83 L 42.48 51.97 L 40.5 50.21 L 38.48 48.41 L 36.41 46.56 L 34.48 44.86 L 34.55 45.02 L 36.72 44 L 39 43.24 L 41.21 42.28 L 43.48 41.51 L 45.62 40.4 L 45.78 40.42 L 45.51 43.09 L 45.01 45.74 L 44.87 48.42 L 44.94 51.12 L 44.51 53.77 Z Z" fill="#1982d2" stroke="#1982d2" stroke-width="6" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="all"/><path d="M 7 40 L 7.02 40.05 L 9.28 39.25 L 11.33 38 L 13.48 36.96 L 15.73 36.14 L 17.88 35.1 Q 27 31 37 31 L 37 30.79 L 39 31.11 L 41 30.85 L 43 30.78 L 45 30.89 L 47 31" fill="none" stroke="#1982d2" stroke-width="8" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" pointer-events="stroke"/></g></svg>
|
After Width: | Height: | Size: 3.5 KiB |
34
doc/doxygen-awesome-css/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@jothepro/doxygen-awesome-css",
|
||||
"version": "2.3.4",
|
||||
"description": "Custom CSS theme for doxygen html-documentation with lots of customization parameters.",
|
||||
"main": "",
|
||||
"scripts": {
|
||||
"npm-pack": "npm pack",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jothepro/doxygen-awesome-css.git"
|
||||
},
|
||||
"homepage": "https://jothepro.github.io/doxygen-awesome-css/",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jothepro/doxygen-awesome-css/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"doxygen",
|
||||
"css",
|
||||
"theme",
|
||||
"awesome"
|
||||
],
|
||||
"author": {
|
||||
"name": "jothepro",
|
||||
"url": "https://github.com/jothepro",
|
||||
"git": "https://github.com/jothepro/doxygen-awesome-css"
|
||||
},
|
||||
"license": "MIT",
|
||||
"config": {},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"xpack": {}
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
|
||||
// SPDX-FileCopyrightText: 2025 basysKom GmbH
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Control {
|
||||
id: container
|
||||
|
||||
required property int column
|
||||
required property var model
|
||||
property int sortOrder: Qt.AscendingOrder
|
||||
|
||||
signal clicked(int sortOrder)
|
||||
|
||||
padding: 8
|
||||
|
||||
background: Rectangle {
|
||||
color: tapHandler.pressed ? "gray" : "lightgray"
|
||||
|
||||
TapHandler {
|
||||
id: tapHandler
|
||||
|
||||
onTapped: {
|
||||
if (container.sortOrder === Qt.AscendingOrder) {
|
||||
container.sortOrder = Qt.DescendingOrder
|
||||
} else {
|
||||
container.sortOrder = Qt.AscendingOrder
|
||||
}
|
||||
|
||||
container.clicked(container.sortOrder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
text: container.model.display
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Control {
|
||||
id: container
|
||||
|
||||
required property int row
|
||||
required property var model
|
||||
|
||||
padding: 8
|
||||
|
||||
background: Rectangle {
|
||||
color: tapHandler.pressed ? "gray" : "lightgray"
|
||||
|
||||
TapHandler {
|
||||
id: tapHandler
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
text: container.model.display
|
||||
}
|
||||
}
|
161
qml/XMain.qml
@@ -1,161 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
|
||||
// SPDX-FileCopyrightText: 2025 basysKom GmbH
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: Application.displayName
|
||||
|
||||
header: ToolBar {
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Rows"
|
||||
}
|
||||
SpinBox {
|
||||
id: rowSettings
|
||||
from: 1
|
||||
to: 20
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
Label {
|
||||
text: "Columns"
|
||||
}
|
||||
SpinBox {
|
||||
id: columnSettings
|
||||
from: 1
|
||||
to: 20
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
CheckBox {
|
||||
id: movableColumnsSetting
|
||||
|
||||
text: "Movable columns"
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
CheckBox {
|
||||
id: resizableColumnsSetting
|
||||
|
||||
text: "Resizable columns"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Selection"
|
||||
}
|
||||
ComboBox {
|
||||
id: selectionSetting
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [
|
||||
{ text: "disabled", value: TableView.SelectionDisabled },
|
||||
{ text: "by cells", value: TableView.SelectCells },
|
||||
{ text: "by rows", value: TableView.SelectRows },
|
||||
{ text: "by columns", value: TableView.SelectColumns }
|
||||
]
|
||||
|
||||
onCurrentIndexChanged: tableView.selectionModel.clear()
|
||||
}
|
||||
Label {
|
||||
text: "Longpress to start selection, modify selection with CTRL/SHIFT of by mouse"
|
||||
visible: selectionSetting.currentIndex > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: tableBackground
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
color: Application.styleHints.colorScheme === Qt.Light ? palette.mid : palette.midlight
|
||||
|
||||
HorizontalHeaderView {
|
||||
id: horizontalHeader
|
||||
|
||||
anchors.left: tableView.left
|
||||
anchors.top: parent.top
|
||||
|
||||
syncView: tableView
|
||||
movableColumns: movableColumnsSetting.checked
|
||||
resizableColumns: resizableColumnsSetting.checked
|
||||
clip: true
|
||||
boundsBehavior: tableView.boundsBehavior
|
||||
|
||||
delegate: HorizontalHeaderViewDelegate {
|
||||
onClicked: (sortOrder) => tableView.model.sort(column, sortOrder)
|
||||
}
|
||||
}
|
||||
|
||||
VerticalHeaderView {
|
||||
id: verticalHeader
|
||||
|
||||
anchors.top: tableView.top
|
||||
anchors.left: parent.left
|
||||
|
||||
syncView: tableView
|
||||
clip: true
|
||||
boundsBehavior: tableView.boundsBehavior
|
||||
|
||||
delegate: VerticalHeaderViewDelegate {}
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: tableView
|
||||
|
||||
anchors.left: verticalHeader.right
|
||||
anchors.top: horizontalHeader.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
rowHeightProvider: (row) => 40
|
||||
boundsBehavior: TableView.StopAtBounds
|
||||
selectionModel: ItemSelectionModel {}
|
||||
selectionBehavior: selectionSetting.currentValue
|
||||
|
||||
model: SortFilterModel {
|
||||
sourceModel: TableModel {
|
||||
columns: columnSettings.value
|
||||
rows: rowSettings.value
|
||||
|
||||
// when adding a new column its width isn't properly applied to the header, so we do that manually
|
||||
onColumnsInserted: {
|
||||
if (columns > 1) {
|
||||
horizontalHeader.setColumnWidth(columns - 1, tableView.implicitColumnWidth(columns - 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate: TableViewDelegate {
|
||||
implicitWidth: tableView.width / columnSettings.to
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
SelectionRectangle {
|
||||
target: tableView
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
|
||||
ApplicationWindow
|
||||
{
|
||||
visible: true
|
||||
width: 600
|
||||
height: 400
|
||||
title: "TableView mit myChildModel"
|
||||
|
||||
TreeView
|
||||
{
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
|
||||
model: myChildModel
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
implicitWidth: 150
|
||||
implicitHeight: 40
|
||||
border.color: "#cccccc"
|
||||
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: display
|
||||
font.pixelSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Window
|
||||
{
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("StringListModel")
|
||||
|
||||
TableView
|
||||
{
|
||||
id: childTableView
|
||||
anchors.fill: parent
|
||||
|
||||
model: myChildModel // z. B. QStandardItemModel mit 9 Spalten
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
required property string display
|
||||
|
||||
//height: 5
|
||||
//width: childTableView.width
|
||||
color : "blue"
|
||||
border.color: "#ccc"
|
||||
width: childTableView.width;
|
||||
|
||||
RowLayout
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
|
||||
TextField
|
||||
{
|
||||
text : display
|
||||
font.pixelSize: 10
|
||||
Layout.fillWidth: true
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
color : "white"
|
||||
}
|
||||
|
||||
onEditingFinished:
|
||||
{
|
||||
console.log("Editing finished, new text is :"+ text + " at index :" + index)
|
||||
model.names = text //The roles here are defined in model class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
// // Optional: Spaltenbreiten setzen
|
||||
// onModelChanged: {
|
||||
// for (let i = 0; i < model.columns; ++i)
|
||||
// table.setColumnWidth(i, 100)
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
83
qml/xqtreeview.qml
Normal file
@@ -0,0 +1,83 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
|
||||
TreeView
|
||||
{
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
|
||||
model: xtrChildModel
|
||||
|
||||
columnWidthProvider: function(column)
|
||||
{
|
||||
var z= 1.7*(width / columns);
|
||||
return z;
|
||||
}
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
required property int row
|
||||
required property int column
|
||||
required property var model
|
||||
|
||||
border.width: 0
|
||||
|
||||
implicitWidth: 30
|
||||
implicitHeight: 20
|
||||
border.color: "#cccccc"
|
||||
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
|
||||
//color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
|
||||
//color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
|
||||
|
||||
|
||||
|
||||
TextField
|
||||
{
|
||||
id: currentEntry
|
||||
anchors.centerIn: parent
|
||||
text: display
|
||||
font.pixelSize: 12
|
||||
|
||||
|
||||
// Ändere die Border-Farbe je nachdem, ob das Feld den Fokus hat
|
||||
property color borderColor: currentEntry.activeFocus ? "dodgerblue" : "gray"
|
||||
property int borderWidth: currentEntry.activeFocus ? 2 : 1
|
||||
|
||||
background: Rectangle {
|
||||
// Die Farbe des Hintergrunds im Normalzustand
|
||||
color: "#ffffff"
|
||||
|
||||
// Hier werden Rahmenfarbe und -breite definiert
|
||||
border.color: currentEntry.borderColor
|
||||
border.width: currentEntry.borderWidth
|
||||
|
||||
// Abgerundete Ecken für ein modernes Aussehen
|
||||
radius: 4
|
||||
|
||||
// Sanfter Übergang der Rahmenfarbe und -breite
|
||||
Behavior on border.color {
|
||||
ColorAnimation { duration: 150 }
|
||||
}
|
||||
Behavior on border.width {
|
||||
NumberAnimation { duration: 150 }
|
||||
}
|
||||
}
|
||||
|
||||
onEditingFinished:
|
||||
{
|
||||
console.log("Editing finished, new text is :"+ text + " at index :" + index)
|
||||
model.display = text //The roles here are defined in model class
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,7 @@ const QString c_ProjectID = "ProjectID";
|
||||
const QString c_ModelSheetFileName = "xml/modelsheets.xml";
|
||||
const QString c_ModelDummyFileName = "xml/saved_testfile.xtr";
|
||||
const QString c_DocumentDirectory = "xml/";
|
||||
|
||||
const QString c_DocumentFileName1 = "xml/modeldata1.xtr";
|
||||
const QString c_DocumentFileName2 = "xml/modeldata2.xtr";
|
||||
const QString c_DocumentFileName3 = "xml/modeldata3.xtr";
|
||||
|
@@ -36,10 +36,6 @@ XQChildModel::XQChildModel( QObject *parent )
|
||||
void XQChildModel::addModelData( const XQNodePtr& contentRoot )
|
||||
{
|
||||
|
||||
// __fix: set object name ??
|
||||
|
||||
qDebug() << " --- create Model Data: " << contentRoot->to_string();
|
||||
|
||||
// Die Datenbasis als shared_ptr sichern
|
||||
_contentRoot = contentRoot;
|
||||
|
||||
@@ -50,70 +46,81 @@ void XQChildModel::addModelData( const XQNodePtr& contentRoot )
|
||||
// Das ist hier der Typ des Eintrags: Panel, Battery ...
|
||||
QString key = contentEntry->tag_name();
|
||||
|
||||
|
||||
// 'silent failure' hier der Datenbaum kann auch Knoten enthalten
|
||||
// die nicht für uns gedacht sind.
|
||||
if (!_sections.hasValidSection(key))
|
||||
continue;
|
||||
|
||||
XQModelSection& section = _sections.at( key );
|
||||
// wir speichern das parent des datenknoten auch in der
|
||||
// section.
|
||||
// contentEntry->parent == _contentRoot, aber halt nur weil das model flach ist
|
||||
|
||||
//qDebug() << " --- add section ENTRY: " << key << " TagName: " << contentEntry->attribute("TagName");
|
||||
|
||||
const XQModelSection& section = _sections.sectionByKey( key );
|
||||
section.setContentRootNode( contentEntry->parent() );
|
||||
int newRow = _sections.lastRow(section);
|
||||
|
||||
XQNodePtr sheetNode = section.sheetRootNode();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, sheetNode, contentEntry );
|
||||
XQItemList list = _itemFactory.makeRow( sheetNode, contentEntry );
|
||||
|
||||
// als Baum?
|
||||
//section.headerItem().appendRow( list );
|
||||
insertRow( newRow, list);
|
||||
|
||||
// _hinter_ der letzen zeile einfügen
|
||||
insertRow( newRow+1, list);
|
||||
|
||||
if( contentEntry->has_children())
|
||||
{
|
||||
qDebug() << " --- AddModelData: CHILD Found for: :" << contentEntry->tag_name() << " sheet parent: " << sheetNode->tag_name();
|
||||
if( !sheetNode->has_children() )
|
||||
qDebug() << " --- AUA";
|
||||
//else
|
||||
}
|
||||
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Erzeugt eine model-section und fügt den zugehörigen header ein.
|
||||
|
||||
void XQChildModel::addSectionEntry( const QString& key, const XQNodePtr& contentEntry )
|
||||
{
|
||||
XQModelSection& section = _sections.at( key );
|
||||
const XQModelSection& section = _sections.sectionByKey( key );
|
||||
if(section.isValid() )
|
||||
{
|
||||
section.setContentRootNode( contentEntry->parent() );
|
||||
int newRow = _sections.lastRow(section);
|
||||
int newRow =_sections.lastRow(section);
|
||||
XQNodePtr sheetNode = section.sheetRootNode();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, sheetNode, contentEntry );
|
||||
XQItemList list = _itemFactory.makeRow( sheetNode, nullptr );
|
||||
insertRow( newRow, list);
|
||||
}
|
||||
}
|
||||
|
||||
//! erzeugt ein adhoc-contextmenu, je nachdem welche aktionen gerade möflich sind.
|
||||
|
||||
//! erzeugt ein adhoc-contextmenu, je nachdem welche aktionen gerade möglich sind.
|
||||
|
||||
void XQChildModel::initContextMenu()
|
||||
{
|
||||
|
||||
// __fixme! add a menu title
|
||||
_contextMenu->clear();
|
||||
|
||||
const QModelIndex& curIdx = _treeTable->currentIndex();
|
||||
bool hasSel = curIdx.isValid() && _treeTable->selectionModel()->hasSelection();
|
||||
bool canPaste = _clipBoard.canPaste( curIdx );
|
||||
|
||||
_contextMenu->addAction( "icn11Dummy", "Undo", XQCommand::cmdUndo, _undoStack->canUndo() );
|
||||
_contextMenu->addAction( "icn17Dummy", "Redo", XQCommand::cmdRedo, _undoStack->canRedo() );
|
||||
|
||||
_contextMenu->addAction( "icn58Dummy", "Cut", XQCommand::cmdCut, hasSel );
|
||||
_contextMenu->addAction( "icn61Dummy", "Paste", XQCommand::cmdPaste, canPaste );
|
||||
_contextMenu->addAction( "icn55Dummy", "Copy", XQCommand::cmdCopy, hasSel );
|
||||
//_contextMenu->addAction( "icn35Dummy", "Move", XQCommand::cmdMove, hasSel );
|
||||
_contextMenu->addAction( "icn70Dummy", "New", XQCommand::cmdNew, hasSel );
|
||||
_contextMenu->addAction( "icn50Dummy", "Delete", XQCommand::cmdDelete, hasSel );
|
||||
// editieren nur wenns kein header ist.
|
||||
if ( !xqItemFromIndex(curIdx).isHeaderStyle() )
|
||||
{
|
||||
bool hasSel = curIdx.isValid() && _treeTable->selectionModel()->hasSelection();
|
||||
bool canPaste = _clipBoard.canPaste( curIdx );
|
||||
|
||||
_contextMenu->addAction( "icn58Dummy", "Cut", XQCommand::cmdCut, hasSel );
|
||||
_contextMenu->addAction( "icn61Dummy", "Paste", XQCommand::cmdPaste, canPaste );
|
||||
_contextMenu->addAction( "icn55Dummy", "Copy", XQCommand::cmdCopy, hasSel );
|
||||
//_contextMenu->addAction( "icn35Dummy", "Move", XQCommand::cmdMove, hasSel );
|
||||
_contextMenu->addAction( "icn70Dummy", "New", XQCommand::cmdNew, hasSel );
|
||||
_contextMenu->addAction( "icn50Dummy", "Delete", XQCommand::cmdDelete, hasSel );
|
||||
}
|
||||
// __fixme! set 'toggle section <name>' entry
|
||||
//contextMenu.actions().first()->setText("<name>");
|
||||
_contextMenu->addAction( "icn29Dummy", "Toggle Section", XQCommand::cmdToggleSection, hasSel);
|
||||
_contextMenu->addAction( "icn29Dummy", "Hide Section", XQCommand::cmdToggleSection, true );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -18,8 +18,8 @@
|
||||
|
||||
//! erzeugt ein docukument
|
||||
|
||||
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView )
|
||||
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, modelView{ aModelView }
|
||||
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel )
|
||||
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, viewModel{ aViewModel }
|
||||
{
|
||||
|
||||
}
|
||||
@@ -44,9 +44,9 @@ XQDocumentStore::~XQDocumentStore()
|
||||
|
||||
//! erzeugt ein document eintrag
|
||||
|
||||
void XQDocumentStore::addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView )
|
||||
void XQDocumentStore::addDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel )
|
||||
{
|
||||
XQDocument newDocument( aFileName, aFriendlyName, aTreeItem, aModelView );
|
||||
XQDocument newDocument( aFileName, aFriendlyName, aTreeItem, aViewModel );
|
||||
addAtKey( aFileName, newDocument );
|
||||
// attention: this assumes the presence of the 'ProjectID' value
|
||||
//addAlias( aFileName, aTreeItem->attribute(c_ProjectID) );
|
||||
|
@@ -28,12 +28,10 @@ struct XQDocument
|
||||
XQDocument() = default;
|
||||
XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
|
||||
|
||||
virtual ~XQDocument() = default;
|
||||
|
||||
QString fileName; // also used as key
|
||||
QString friendlyName;
|
||||
XQItem* treeItem{};
|
||||
XQViewModel* modelView{};
|
||||
XQViewModel* viewModel{};
|
||||
|
||||
};
|
||||
|
||||
@@ -46,11 +44,7 @@ public:
|
||||
XQDocumentStore() = default;
|
||||
virtual ~ XQDocumentStore();
|
||||
|
||||
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
|
||||
|
||||
protected:
|
||||
|
||||
XQNode _treeRootNode{ "treeRootNode" };
|
||||
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel );
|
||||
|
||||
};
|
||||
|
||||
|
@@ -45,57 +45,36 @@ void XQMainModel::initContextMenu()
|
||||
|
||||
XQItem* XQMainModel::addProjectItem( XQNodePtr contentNode )
|
||||
{
|
||||
// wir durchsuchen alle unsere section nach dem passenden content-type,
|
||||
// hier: content-type beschreibt die
|
||||
// wir durchsuchen alle unsere sections nach dem passenden content-type,
|
||||
// hier: content-type beschreibt den projekt-status
|
||||
|
||||
|
||||
for(const auto& section : _sections )
|
||||
const QString& sectionKey = contentNode->attribute(c_ContentType);
|
||||
if( _sections.hasValidSection( sectionKey ) )
|
||||
{
|
||||
const XQModelSection& section = _sections.sectionByKey( sectionKey );
|
||||
// __fixme! das ist mist!
|
||||
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
|
||||
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") );
|
||||
|
||||
if( contentNode->attribute( c_ContentType) == section.contentType() )
|
||||
{
|
||||
|
||||
qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string();
|
||||
|
||||
// __fixme! das ist mist!
|
||||
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, contentNode, "ProjectName");
|
||||
|
||||
// den neuen eintrag in die passende section der übersicht eintragen ...
|
||||
section.headerItem().appendRow( list );
|
||||
// ... ausklappen...
|
||||
const QModelIndex index = section.headerItem().index();
|
||||
_treeTable->expand( index );
|
||||
// ... und markieren
|
||||
_treeTable->setCurrentIndex( index );
|
||||
// quellknoten auch speichern
|
||||
//newItem->setContentNode( contentNode );
|
||||
//emit itemCreated( newItem );
|
||||
|
||||
XQItem* newItem = dynamic_cast<XQItem*>(list[0]);
|
||||
// erzeuger sheet node speichern
|
||||
newItem->setSheetNode( sheetNode );
|
||||
return newItem;
|
||||
|
||||
}
|
||||
|
||||
// den neuen eintrag in die passende section der übersicht eintragen ...
|
||||
section.headerItem().appendRow( newItem );
|
||||
// erzeuger sheet node speichern
|
||||
newItem->setSheetNode( sheetNode );
|
||||
expandNewItem(section.headerItem().index() );
|
||||
return newItem;
|
||||
}
|
||||
|
||||
|
||||
throw XQException( "addProjectItem: main model should not be empty!" );
|
||||
}
|
||||
|
||||
|
||||
//! erzeugt einen einzelen baum-eintrag mit hilfe der section und den projekt-daten
|
||||
|
||||
void XQMainModel::addSectionItem( const XQModelSection& section, XQItem* projectItem )
|
||||
{
|
||||
return;
|
||||
|
||||
|
||||
// ich brauche _meine_ section für den sheetNode!
|
||||
|
||||
|
||||
XQNodePtr sheetNode = projectItem->sheetNode()->find_child_by_tag_name("CurrentSection");
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, nullptr, c_ContentType );
|
||||
projectItem->appendRow( list );
|
||||
_treeTable->expand( projectItem->index() );
|
||||
|
||||
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, section.contentType() );
|
||||
projectItem->appendRow( newItem );
|
||||
expandNewItem(projectItem->index() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
XQItem* addProjectItem( XQNodePtr contentNode );
|
||||
void addSectionItem( const XQModelSection& section, XQItem* projectItem );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void initContextMenu() override;
|
||||
|
@@ -88,36 +88,39 @@ void XQMainWindow::initMainWindow()
|
||||
connect( _actionExit, &QAction::triggered, this, &XQMainWindow::onExit );
|
||||
connect( _actionAbout, &QAction::triggered, this, &XQMainWindow::onAbout );
|
||||
|
||||
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onChildViewTabClicked(int)) );
|
||||
|
||||
//connect(&_mainModel, &QStandardItemModel::itemChanged, this, &XQMainWindow::onTreeItemChanged );
|
||||
//connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) );
|
||||
connect( _mainTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
|
||||
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
|
||||
//connect( _mainTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
|
||||
|
||||
connect(&_mainModel, &XQViewModel::xqItemChanged, this, &XQMainWindow::onTreeViewItemChanged );
|
||||
|
||||
|
||||
/*
|
||||
connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
|
||||
connect( _mainTreeView, &QTreeView::clicked, this, [&,this](const QModelIndex& index)
|
||||
{
|
||||
// when a new main tree item has been created ...
|
||||
QString pID = item->contentNode()->attribute(c_ProjectID);
|
||||
_mainTreeView->setCurrentIndex( item->index() );
|
||||
// ... we set the current view to this node
|
||||
if( _documentStore.contains( pID ) )
|
||||
_tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() );
|
||||
} );
|
||||
*/
|
||||
onTreeViewItemClicked( XQItem::xqItemFromIndex(index) );
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// hand over undostack
|
||||
_mainModelView.setUndoStack(&_undoStack);
|
||||
_mainModel.setUndoStack(&_undoStack);
|
||||
// hand over left side navigation tree
|
||||
_mainModelView.setTreeTable(_mainTreeView);
|
||||
_mainModel.setTreeTable(_mainTreeView);
|
||||
// #1. init the left side main tree view
|
||||
_mainModelView.initModel( c_MainModelName );
|
||||
_mainModel.initModel( c_MainModelName );
|
||||
|
||||
// 1: Wiebelbach
|
||||
// 2: Gerbrunn
|
||||
// 3: TBB
|
||||
|
||||
// #2. load demo data
|
||||
loadDocument( c_DocumentFileName1 );
|
||||
loadDocumentQML( c_DocumentFileName2 );
|
||||
loadDocument( c_DocumentFileName2, true );
|
||||
//loadDocument( c_DocumentFileName2 );
|
||||
//loadDocument( c_DocumentFileName3 );
|
||||
|
||||
|
||||
qDebug() << " --- all here: " << XQNode::s_Count;
|
||||
|
||||
@@ -131,9 +134,6 @@ void XQMainWindow::initMainWindow()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//! slot für zentrales undo
|
||||
|
||||
void XQMainWindow::onUndo()
|
||||
@@ -235,7 +235,7 @@ void XQMainWindow::onAbout()
|
||||
QMessageBox msgBox(QMessageBox::NoIcon, "About", "", QMessageBox::Ok);
|
||||
|
||||
QString text = "<b>xtree concept</b><br>";
|
||||
text += "2024 c.holzheuer<br><br>";
|
||||
text += "2024-2025 c.holzheuer<br><br>";
|
||||
text += "<a href=\"https://sourceworx.org/xtree\">sourceworx.org/xtree</a>";
|
||||
|
||||
msgBox.setTextFormat(Qt::RichText); // This allows you to click the link
|
||||
@@ -245,66 +245,190 @@ void XQMainWindow::onAbout()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! wenn ein item im navigations-baum geklickt wird, soll die document
|
||||
//! view rechts angepasst werden.
|
||||
|
||||
void XQMainWindow::onTreeItemClicked(const QModelIndex& index )
|
||||
void XQMainWindow::onTreeViewItemClicked( const XQItem& item )
|
||||
{
|
||||
|
||||
XQItem& entry = XQItem::xqItemFromIndex(index);
|
||||
|
||||
qDebug() << " --- XXX mainWindow onTreeItemClicked:" << entry.text();
|
||||
_mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
|
||||
|
||||
if( XQNodePtr contentNode = entry.contentNode() )
|
||||
//qDebug() << " --- Tree item CLICK:" << item.text() << " : " << item.itemType().text();
|
||||
if( item.itemType().text() == "TreeChildType" )
|
||||
{
|
||||
QString key = contentNode->attribute(c_ProjectID);
|
||||
qDebug() << " --- FIRZ: key: " << key;
|
||||
|
||||
bool isThere = _documentStore.contains(key);
|
||||
if( isThere)
|
||||
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() );
|
||||
setChildTabByName( item.text() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XQMainWindow::onTreeViewItemChanged(const XQItem& item )
|
||||
{
|
||||
qDebug() << " --- TREE VIEW itemChanged: text" << item.text() << " parent: " << item.parent()->text() << " type: " << item.itemType().text() << " : " << (void*)&_mainModel << " : " << (void*) sender();
|
||||
// hier müssen wir erst das projekt aktivieren
|
||||
XQItem* xqItem = static_cast<XQItem*>(item.parent());
|
||||
onTreeViewItemClicked( *xqItem );
|
||||
//if( item.itemType().text() == "TreeSectionType" )
|
||||
{
|
||||
int idx = _tabWidget->currentIndex();
|
||||
if(_documentStore.contains(idx) )
|
||||
{
|
||||
qDebug() << " --- Has Document and might toggle: " << item.text();
|
||||
XQViewModel& childModel = *_documentStore[idx].viewModel;
|
||||
childModel.onToggleSection(item.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst.
|
||||
|
||||
void XQMainWindow::onTabClicked( int index )
|
||||
void XQMainWindow::onChildViewTabClicked( int idx )
|
||||
{
|
||||
//const QString& key = _documentStore[index].treeItem->attribute( c_ProjectID );
|
||||
//qDebug() << " ---- tab clicked: " << index << " : " << _documentStore[index].friendlyName;// << ": " << key;
|
||||
//_mainTreeView->setCurrentIndex( _documentStore[index].treeItem->index() );
|
||||
}
|
||||
|
||||
void XQMainWindow::onSectionCreated( const XQModelSection& section )
|
||||
{
|
||||
qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
|
||||
if( _currentProjectItem )
|
||||
if(_documentStore.contains(idx) )
|
||||
{
|
||||
_mainModelView.addSectionItem( section, _currentProjectItem );
|
||||
QModelIndex treeIndex =_documentStore[idx].treeItem->index();
|
||||
_mainModel.expandNewItem( treeIndex );
|
||||
}
|
||||
}
|
||||
|
||||
void XQMainWindow::onSectionToggled( const XQModelSection& section )
|
||||
|
||||
//! SLOT, der aufgerufen wird, sobald eine section erzeugt worden ist.
|
||||
|
||||
void XQMainWindow::onSectionCreated( const XQModelSection& section )
|
||||
{
|
||||
//qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
|
||||
if( _currentProjectItem )
|
||||
{
|
||||
_mainModel.addSectionItem( section, _currentProjectItem );
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItemModel* createModel() {
|
||||
auto* model = new QStandardItemModel;
|
||||
model->setHorizontalHeaderLabels({ "Name" });
|
||||
|
||||
QStandardItem* parent = new QStandardItem("Tiere");
|
||||
parent->appendRow(new QStandardItem("Hund"));
|
||||
parent->appendRow(new QStandardItem("Katze"));
|
||||
model->appendRow(parent);
|
||||
//! SLOT, der aufgerufen wird, wenn eine section getoggelt wurde.
|
||||
|
||||
return model;
|
||||
void XQMainWindow::onSectionToggled( const XQModelSection& section )
|
||||
{
|
||||
for (int row = 0; row < _currentProjectItem->rowCount(); ++row)
|
||||
{
|
||||
QStandardItem* child = _currentProjectItem->child(row);
|
||||
if (child->text() == section.contentType() )
|
||||
{
|
||||
bool checked = (child->checkState() == Qt::Checked);
|
||||
child->setCheckState( checked ? Qt::Unchecked :Qt::Checked );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! aktiviert das tab, das zum dokument mit dem schlüssel 'key' gehört.
|
||||
|
||||
void XQMainWindow::setChildTabByName( const QString& key )
|
||||
{
|
||||
for( int i=0; i<_documentStore.size(); ++i )
|
||||
{
|
||||
if( key == _documentStore[i].friendlyName)
|
||||
{
|
||||
_tabWidget->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XQNodePtr XQMainWindow::createDataTree( const QString& fileName )
|
||||
{
|
||||
// gibts die Datei?
|
||||
if( !QFile::exists( fileName) )
|
||||
throw XQException( "no such file", fileName );
|
||||
|
||||
XQNodeFactory treeLoader;
|
||||
// xml daten laden
|
||||
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(fileName) );
|
||||
// versteckten root node ignorieren
|
||||
return rawTree->first_child();
|
||||
}
|
||||
|
||||
|
||||
XQChildModel* XQMainWindow::createChildModel( const XQNodePtr& contentRoot )
|
||||
{
|
||||
// Ein neues Child-Model erzeugen
|
||||
XQChildModel* childModel = new XQChildModel(this);
|
||||
|
||||
connect( childModel, SIGNAL(sectionCreated(XQModelSection)), this, SLOT(onSectionCreated(XQModelSection)) );
|
||||
connect( childModel, SIGNAL(sectionToggled(XQModelSection)), this, SLOT(onSectionToggled(XQModelSection)) );
|
||||
|
||||
// Den globalen undo-stack ...
|
||||
childModel->setUndoStack(&_undoStack);
|
||||
|
||||
// die Modelstruktur anlegen
|
||||
childModel->initModel( c_ChildModelName );
|
||||
|
||||
// model inhalte laden
|
||||
childModel->addModelData( contentRoot->first_child() );
|
||||
childModel->setObjectName( contentRoot->friendly_name() );
|
||||
|
||||
return childModel;
|
||||
|
||||
}
|
||||
|
||||
//! liest eine XML datei namens 'fileName'
|
||||
|
||||
void XQMainWindow::loadDocument( const QString& fileName, bool useQML )
|
||||
{
|
||||
|
||||
// Datenbaum laden
|
||||
XQNodePtr contentRoot = createDataTree( fileName );
|
||||
|
||||
// Falls schon vorhanden ...
|
||||
const QString& pID = contentRoot->attribute(c_ProjectID);
|
||||
int idx = _documentStore.indexOf( pID );
|
||||
if( idx > -1 )
|
||||
{
|
||||
const XQDocument& document = _documentStore.at(idx);
|
||||
QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) );
|
||||
_mainTreeView->setCurrentIndex( document.treeItem->index() );
|
||||
_tabWidget->setCurrentIndex( idx );
|
||||
// ... wird nichts wieter unternommen
|
||||
return;
|
||||
}
|
||||
|
||||
// 'friendly Name' ist ein Link auf ein anderes Attribute
|
||||
// das als Namen verwendet wird.
|
||||
const QString& fName = contentRoot->friendly_name();
|
||||
QString pTabTitle = QString("Project %1: %2").arg( pID, fName );
|
||||
|
||||
// neuen eintrag im übsichts-baum erzeugen
|
||||
_currentProjectItem = _mainModel.addProjectItem( contentRoot );
|
||||
// Kindmodel für den Datenbaum erzeugen.
|
||||
XQChildModel* childModel = createChildModel(contentRoot);
|
||||
|
||||
_documentStore.addDocument( fileName, fName, _currentProjectItem, childModel );
|
||||
|
||||
|
||||
QWidget* childView{};
|
||||
if(useQML)
|
||||
{
|
||||
XQQuickWidget* quickView = new XQQuickWidget(_tabWidget);
|
||||
//quickChild->setResizeMode(QQuickWidget::SizeViewToRootObject);
|
||||
|
||||
quickView->rootContext()->setContextProperty("xtrChildModel", childModel);
|
||||
quickView->setSource(QUrl("qrc:/xqtreeview.qml"));
|
||||
childView = quickView;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eine neue TreeView erzeugn und im TabWidget parken.
|
||||
XQTreeTable* treeTable = new XQTreeTable(_tabWidget);
|
||||
// und die TreeView übergeben
|
||||
childModel->setTreeTable(treeTable);
|
||||
childView = treeTable;
|
||||
}
|
||||
|
||||
_tabWidget->addTab( childView, pTabTitle );
|
||||
_tabWidget->setCurrentWidget( childView );
|
||||
setWindowTitle( pTabTitle );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void XQMainWindow::loadDocumentQML( const QString& fileName )
|
||||
{
|
||||
// gibts die Datei?
|
||||
@@ -332,75 +456,14 @@ void XQMainWindow::loadDocumentQML( const QString& fileName )
|
||||
XQQuickWidget* quickChild = new XQQuickWidget(_tabWidget);
|
||||
//quickChild->setResizeMode(QQuickWidget::SizeViewToRootObject);
|
||||
|
||||
quickChild->rootContext()->setContextProperty("myChildModel", childModel);
|
||||
quickChild->setSource(QUrl("qrc:/xqtableview.qml"));
|
||||
quickChild->rootContext()->setContextProperty("xtrChildModel", childModel);
|
||||
quickChild->setSource(QUrl("qrc:/xqtreeview.qml"));
|
||||
_tabWidget->addTab( quickChild, "QML:"+fName );
|
||||
_tabWidget->setCurrentWidget( quickChild );
|
||||
quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
}
|
||||
|
||||
//! liest eine XML datei namens 'fileName'
|
||||
|
||||
void XQMainWindow::loadDocument( const QString& fileName )
|
||||
{
|
||||
|
||||
// gibts die Datei?
|
||||
if( !QFile::exists( fileName) )
|
||||
throw XQException( "no such file", fileName );
|
||||
|
||||
XQNodeFactory treeLoader;
|
||||
// xml daten laden
|
||||
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(fileName) );
|
||||
// versteckten root node ignorieren
|
||||
XQNodePtr contentRoot = rawTree->first_child();
|
||||
// Project-ID behandeln
|
||||
const QString& pID = contentRoot->attribute(c_ProjectID);
|
||||
int idx = _documentStore.indexOf( pID );
|
||||
if( idx > -1 )
|
||||
{
|
||||
const XQDocument& document = _documentStore.at(idx);
|
||||
QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) );
|
||||
_mainTreeView->setCurrentIndex( document.treeItem->index() );
|
||||
_tabWidget->setCurrentIndex( idx );
|
||||
return;
|
||||
}
|
||||
|
||||
// 'friendly Name' ist ein Link auf ein anderes Attribute
|
||||
// das als Namen verwendet wird.
|
||||
const QString& fName = contentRoot->friendly_name();
|
||||
QString pTitle = QString("Project %1: %2").arg( pID, fName );
|
||||
|
||||
// Eine neue TreeView erzeugn und im TabWidget parken.
|
||||
XQTreeTable* childTreeView = new XQTreeTable(_tabWidget);
|
||||
_tabWidget->addTab( childTreeView, pTitle );
|
||||
_tabWidget->setCurrentWidget( childTreeView );
|
||||
setWindowTitle( pTitle );
|
||||
|
||||
// Ein neues Child-Model erzeugen
|
||||
XQChildModel* childModel = new XQChildModel(this);
|
||||
|
||||
connect( childModel, SIGNAL(sectionCreated(XQModelSection)), this, SLOT(onSectionCreated(XQModelSection)) );
|
||||
connect( childModel, SIGNAL(sectionToggled(XQModelSection)), this, SLOT(onSectionToggled(XQModelSection)) );
|
||||
|
||||
// Den globalen undo-stack ...
|
||||
childModel->setUndoStack(&_undoStack);
|
||||
|
||||
// und die TreeView übergeben
|
||||
childModel->setTreeTable(childTreeView);
|
||||
|
||||
// neuen eintrag im übsichts-baum erzeugen
|
||||
_currentProjectItem = _mainModelView.addProjectItem( contentRoot );
|
||||
_documentStore.addDocument( fileName, pTitle, _currentProjectItem, childModel );
|
||||
|
||||
// die Modelstruktur anlegen
|
||||
childModel->initModel( c_ChildModelName );
|
||||
|
||||
// model inhalte laden
|
||||
childModel->addModelData( contentRoot->first_child() );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! speichert ein XML unter dem 'filename'
|
||||
@@ -409,7 +472,9 @@ void XQMainWindow::saveDocument( const QString& fileName )
|
||||
{
|
||||
XQNodeWriter nodeWriter;
|
||||
int curIdx = _tabWidget->currentIndex();
|
||||
XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode();
|
||||
//XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode();
|
||||
XQNodePtr rootNode = _documentStore[curIdx].viewModel->contentRootNode();
|
||||
Q_ASSERT(rootNode);
|
||||
nodeWriter.dumpTree( rootNode, fileName );
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,11 @@ public:
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onMyFirz(XQItem& item)
|
||||
{
|
||||
qDebug() << " --- myFirz: " << item.text();
|
||||
}
|
||||
|
||||
void onUndo();
|
||||
void onRedo();
|
||||
|
||||
@@ -46,31 +51,38 @@ public slots:
|
||||
void onAbout();
|
||||
void onExit();
|
||||
|
||||
void onTreeItemClicked(const QModelIndex& index );
|
||||
void onTabClicked( int index );
|
||||
void onTreeViewItemClicked( const XQItem& item );
|
||||
void onTreeViewItemChanged( const XQItem& item );
|
||||
void onChildViewTabClicked( int index );
|
||||
|
||||
//void onItemCreated( XQItem* item );
|
||||
void onSectionCreated( const XQModelSection& section);
|
||||
void onSectionToggled( const XQModelSection& section );
|
||||
|
||||
void setChildTabByName( const QString& key );
|
||||
|
||||
// fixme implement
|
||||
//void showDocument( const QString& key ){}
|
||||
void loadDocument( const QString& fileName, bool useQML=false );
|
||||
void loadDocumentQML( const QString& fileName );
|
||||
void saveDocument( const QString& fileName );
|
||||
|
||||
static void setupWorkingDir();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
XQNodePtr createDataTree( const QString& fileName );
|
||||
XQChildModel* createChildModel( const XQNodePtr& contentRoot );
|
||||
|
||||
|
||||
// fixme implement
|
||||
void showDocumnet( const QString& key ){}
|
||||
void loadDocument( const QString& fileName );
|
||||
void loadDocumentQML( const QString& fileName );
|
||||
void saveDocument( const QString& fileName );
|
||||
|
||||
|
||||
QUndoStack _undoStack;
|
||||
XQDocumentStore _documentStore;
|
||||
|
||||
XQMainModel _mainModelView;
|
||||
XQMainModel _mainModel;
|
||||
XQItem* _currentProjectItem{};
|
||||
|
||||
//XQChildModel* _currentChildModel{};
|
||||
|
||||
};
|
||||
|
||||
|
@@ -64,7 +64,7 @@ XQItem::XQRenderStyleMap XQItem::s_RenderStyleMap
|
||||
{ "CustomRenderStyle", CustomRenderStyle },
|
||||
{ "PickerStyle", PickerStyle },
|
||||
{ "SpinBoxStyle", SpinBoxStyle },
|
||||
{ "ProgressBarStyle", ProgressBarStyle},
|
||||
{ "ColorBarStyle", ColorBarStyle},
|
||||
{ "FormattedStyle", FormattedStyle},
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ XQItem::XQEditorTypeMap XQItem::s_EditorTypeMap
|
||||
{ "LineEditType", LineEditType },
|
||||
{ "ComboBoxType", ComboBoxType },
|
||||
{ "PickerType", PickerType },
|
||||
{ "ProgressBarType", ProgressBarType },
|
||||
{ "ColorBarType", ColorBarType },
|
||||
{ "SpinBoxType", SpinBoxType},
|
||||
{ "CustomEditorType", CustomEditorType}
|
||||
};
|
||||
@@ -116,6 +116,8 @@ XQItem::XQPrefixExponentMap XQItem::s_PrefixExponentMap
|
||||
};
|
||||
|
||||
|
||||
//! Default konstruktor, setzt einen ungültigen (dummy)
|
||||
//! itemType.
|
||||
|
||||
XQItem::XQItem()
|
||||
: XQItem{XQItemType::staticItemType()}
|
||||
@@ -123,6 +125,9 @@ XQItem::XQItem()
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Default konstruktor mit einem vorhandenen itemType.
|
||||
|
||||
XQItem::XQItem( XQItemType* itemType )
|
||||
: QStandardItem{}
|
||||
{
|
||||
@@ -130,12 +135,21 @@ XQItem::XQItem( XQItemType* itemType )
|
||||
}
|
||||
|
||||
|
||||
XQItem::XQItem(XQItemType* itemType, const QString *content )
|
||||
//! konstruiert ein daten-item mit zeiger auf 'unser' attribut
|
||||
//! im übergeordneten content-node.
|
||||
|
||||
XQItem::XQItem(XQItemType* itemType, const QString* content )
|
||||
: XQItem{ itemType }
|
||||
{
|
||||
setContent(content);
|
||||
// hier setzen wir direkt ohne umwege den string pointer
|
||||
QStandardItem::setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
|
||||
}
|
||||
|
||||
XQItem::XQItem( XQItemType* itemType, const QString& content )
|
||||
: XQItem{ itemType }
|
||||
{
|
||||
setText(content);
|
||||
}
|
||||
//! ruft den copy-konstruktor auf.
|
||||
|
||||
XQItem* XQItem::clone() const
|
||||
@@ -147,21 +161,36 @@ XQItem* XQItem::clone() const
|
||||
//! false für ein ungültiges item. 'ungültig' heisst hier, dass nur ein
|
||||
//! mockup-itemtype gesetzt ist.
|
||||
|
||||
bool XQItem::isValid() const
|
||||
bool XQItem::isValidX() const
|
||||
{
|
||||
XQItemType* dummyType = XQItemType::staticItemType();
|
||||
return QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>() != dummyType;
|
||||
}
|
||||
|
||||
|
||||
bool XQItem::hasContentNode() const
|
||||
{
|
||||
if( column() == 0)
|
||||
{
|
||||
QVariant value = QStandardItem::data( XQItem::ContentNodeRole );
|
||||
return !value.isNull();
|
||||
}
|
||||
|
||||
// sonst: delegieren an den node-Besitzer
|
||||
QModelIndex pIndex = model()->index( row(), 0 );
|
||||
if( pIndex.isValid() )
|
||||
{
|
||||
XQItem& firstItem = xqItemFromIndex( pIndex );
|
||||
return firstItem.hasContentNode();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! gibt den content-node zurück.
|
||||
|
||||
XQNodePtr XQItem::contentNode() const
|
||||
{
|
||||
XQNodePtr node = data( ContentNodeRole ).value<XQNodePtr>();
|
||||
if( node )
|
||||
return node;
|
||||
throw XQException("XQItem::contentNode() nullptr");
|
||||
return data( ContentNodeRole ).value<XQNodePtr>();
|
||||
}
|
||||
|
||||
|
||||
@@ -319,37 +348,23 @@ QString XQItem::rawText() const
|
||||
|
||||
|
||||
//! Gibt den string-zeiger auf das attribut aus unseren XQNodePtr zurück.
|
||||
|
||||
/*
|
||||
QString* XQItem::content() const
|
||||
{
|
||||
// macht jetzt das, ws draufsteht: gibt einen string* zurück
|
||||
// macht jetzt das, was draufsteht: gibt einen string* zurück
|
||||
return data( XQItem::ContentRole ).value<QString*>();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//! set den content()-string pointer. (als leihgabe)
|
||||
|
||||
void XQItem::setContent( const QString* content )
|
||||
{
|
||||
setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
|
||||
}
|
||||
|
||||
|
||||
//! holt den schlüssel bzw. bezeicher des content() string aus 'unserem' content knoten.
|
||||
|
||||
QString XQItem::contentKey() const
|
||||
{
|
||||
return contentNode()->attributes().key_of( rawText() );
|
||||
}
|
||||
|
||||
//! gibt den content-format string zurück
|
||||
//! Gibt den content-format string zurück
|
||||
|
||||
QString XQItem::contentFormat() const
|
||||
{
|
||||
return data( XQItem::ContentFormatRole ).toString();
|
||||
}
|
||||
|
||||
//! setz den den content format-string. wird im itemType gespeichert.
|
||||
//! Setzt den den content format-string. wird im itemType gespeichert.
|
||||
|
||||
void XQItem::setContentFormat(const QString& contentFormat)
|
||||
{
|
||||
@@ -357,7 +372,7 @@ void XQItem::setContentFormat(const QString& contentFormat)
|
||||
}
|
||||
|
||||
|
||||
//! gibt das read-only auswahl-model zurück (wenn dieses item als
|
||||
//! Gibt das read-only auswahl-model zurück (wenn dieses item als
|
||||
//! combobox gerendert wird). wird im itemType gespeichert.
|
||||
|
||||
QStandardItemModel* XQItem::fixedChoices() const
|
||||
@@ -413,6 +428,30 @@ QString XQItem::dataRoleName(int role) const
|
||||
return XQItem::fetchItemDataRoleName(role);
|
||||
}
|
||||
|
||||
bool XQItem::hasContentPtr() const
|
||||
{
|
||||
return !QStandardItem::data( XQItem::ContentRole ).isNull();
|
||||
}
|
||||
|
||||
//! Gibt den content()-String zurück, sofern vorhanden.
|
||||
//! sonst: gibt der ihnalt der Qt::DisplayRole als fallback
|
||||
//! zurück.
|
||||
|
||||
QString XQItem::contentFallBackText() const
|
||||
{
|
||||
if( hasContentPtr() )
|
||||
{
|
||||
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
|
||||
if(contentPtr)
|
||||
return *contentPtr;
|
||||
}
|
||||
|
||||
// wenn wir keinen contentPtr haben, benutzen wir als fallback
|
||||
// die basis-text() role
|
||||
return QStandardItem::data( Qt::DisplayRole ).toString();
|
||||
|
||||
}
|
||||
|
||||
//! angespasste variante von qstandarditem::setData. geteilte attribute
|
||||
//! werden vom xqitemtype geholt
|
||||
|
||||
@@ -438,33 +477,35 @@ QVariant XQItem::data(int role ) const
|
||||
return itemType().data(role);
|
||||
}
|
||||
|
||||
// Zugriffe auf den sichtbaren inhalt geben den inhalt des string pointer
|
||||
// auf ein feld in content node wieder.
|
||||
|
||||
// DisplayRole gibt den formatieren inhalt wieder. die formatierung übernimmt
|
||||
// der item type
|
||||
// auf den original inhalt im content node zurückgeben.
|
||||
|
||||
case Qt::DisplayRole :
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
if( itemType().renderStyle() == XQItem::FormattedStyle)//return "display:"+content();
|
||||
return itemType().formatText( *this );
|
||||
[[fallthrough]];
|
||||
qDebug() << " --- data(XQItem::ContentRole) should NOT be called!";
|
||||
return *QStandardItem::data( XQItem::ContentRole ).value<QString*>();
|
||||
}
|
||||
|
||||
// EditRole & ContentRole sollen den 'rohen' inhalt unseres string-pointers
|
||||
// auf den original inhalt im content node zurückgeben.
|
||||
|
||||
case Qt::EditRole :
|
||||
case XQItem::ContentRole:
|
||||
case Qt::EditRole :
|
||||
{
|
||||
// Zugriffe auf den text-inhalt geben den inhalt des string pointer
|
||||
// auf ein feld in content-node wieder. Wenn kein content-node vorhanden
|
||||
// ist (single-items), wird Qt::DisplayRole zurückgeliefert.
|
||||
|
||||
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
|
||||
if(contentPtr)
|
||||
return *contentPtr;
|
||||
return contentFallBackText();
|
||||
//[[fallthrough]];
|
||||
}
|
||||
|
||||
static const QString s_dummyContent("-");
|
||||
return s_dummyContent;
|
||||
// DisplayRole gibt den formatierten inhalt wieder. die formatierung übernimmt
|
||||
// der item type
|
||||
|
||||
case Qt::DisplayRole :
|
||||
{
|
||||
QString plainText = contentFallBackText();
|
||||
//if( renderStyle() == XQItem::FormattedStyle)
|
||||
if( unitType() != XQItem::NoUnitType)
|
||||
return XQItemType::formatToSI( plainText, unitType() );
|
||||
return plainText;
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
@@ -479,16 +520,30 @@ QVariant XQItem::data(int role ) const
|
||||
|
||||
case ContentNodeRole:
|
||||
{
|
||||
// Das Node-Besitzer-Item wohnt in der ersten Spalte,
|
||||
// wenn wir also der Node-Besitzer item sind ...
|
||||
if( column() == 0)
|
||||
return QStandardItem::data( XQItem::ContentNodeRole );
|
||||
// Das Node-Besitzer-Item wohnt in der ersten Spalte,
|
||||
// wenn wir also der Node-Besitzer item sind ...
|
||||
if( column() == 0)
|
||||
{
|
||||
QVariant value = QStandardItem::data( XQItem::ContentNodeRole );
|
||||
if( !value.isNull() )
|
||||
return value;
|
||||
|
||||
// sonst: delegieren an den node-Besitzer
|
||||
QModelIndex pIndex = model()->index( row(), 0 );
|
||||
// das gibt immerhin was zurück, was auf nullptr getestet werden kann,
|
||||
return QVariant::fromValue<XQNodePtr>(nullptr);
|
||||
|
||||
// diese variante erzieht uns zur verwendung von 'hasContentNode()'
|
||||
// was ist besser ?
|
||||
throw XQException( "ContentNode is nullptr!");
|
||||
}
|
||||
|
||||
// sonst: delegieren an den node-Besitzer
|
||||
QModelIndex pIndex = model()->index( row(), 0 );
|
||||
if( pIndex.isValid())
|
||||
{
|
||||
XQItem& firstItem = xqItemFromIndex( pIndex );
|
||||
|
||||
return firstItem.data( XQItem::ContentNodeRole );
|
||||
}
|
||||
throw XQException( "Item has no valid index (yet)!");
|
||||
}
|
||||
|
||||
case Qt::StatusTipRole:
|
||||
@@ -537,7 +592,6 @@ void XQItem::setData(const QVariant& value, int role )
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
|
||||
case RenderStyleRole :
|
||||
case EditorTypeRole :
|
||||
case UnitTypeRole:
|
||||
@@ -557,30 +611,33 @@ void XQItem::setData(const QVariant& value, int role )
|
||||
return;
|
||||
}
|
||||
|
||||
// set the raw, unformatted data
|
||||
case ContentRole:
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
// string ptr setzen kann die basis.
|
||||
break;
|
||||
}
|
||||
QVariant newValue;
|
||||
|
||||
case Qt::EditRole :
|
||||
{
|
||||
qDebug() << " --- setting EDITrole: " << value.toString();
|
||||
break;
|
||||
}
|
||||
//if( itemType().renderStyle() == XQItem::FormattedStyle)
|
||||
if( unitType() != XQItem::NoUnitType)
|
||||
newValue = XQItemType::unFormatFromSI( value.toString() );
|
||||
else
|
||||
newValue = value;
|
||||
|
||||
case Qt::DisplayRole :
|
||||
{
|
||||
// what will happen? value is a string ptr ?!
|
||||
qDebug() << " --- setting DISPLAYrole: " << value.toString();
|
||||
break;
|
||||
// fallback: wenns keinen content node gibt, dann nehmen wir
|
||||
// das standardverfahren.
|
||||
if( !hasContentPtr() )
|
||||
return QStandardItem::setData( newValue, Qt::DisplayRole );
|
||||
|
||||
// wir nehmen den string pointer
|
||||
const QString* constContentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
|
||||
// aua, aua, muss aber sein, weil sonst alle anderen consts nicht durchgehalten werden könnten
|
||||
*const_cast<QString*>(constContentPtr) = newValue.toString();
|
||||
return;
|
||||
}
|
||||
|
||||
// alles andere wie gehabt
|
||||
case ContentNodeRole:
|
||||
case SheetNodeRole:
|
||||
|
||||
//case TypeKeyRole: not used
|
||||
default:
|
||||
break;
|
||||
@@ -591,6 +648,133 @@ void XQItem::setData(const QVariant& value, int role )
|
||||
|
||||
}
|
||||
|
||||
//! erzeugt eine QVariant zur gegebenen rolle aus dem gegebenen string.
|
||||
//! Hack: Das Item wird hier als zusätzliche datenquelle übergeben,
|
||||
//! um _vorher_ erzeugte eigenschaften des items als parameter für _jetzt_
|
||||
//! erzeugte eigenschaft verwenden zu können.
|
||||
//! Beispiel
|
||||
|
||||
QVariant XQItem::makeVariant( XQItem* item, int dataRole, const QString& source )
|
||||
{
|
||||
|
||||
QVariant value;
|
||||
|
||||
//qDebug() << " ----- makeVariant: " << XQItem::fetchItemDataRoleName( dataRole );
|
||||
|
||||
switch(dataRole)
|
||||
{
|
||||
// das ist ein pointer auf den original-string aus dem XML
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
// content() -> QString*
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case XQItem::ItemTypeRole:
|
||||
{
|
||||
// itemType() -> XQItemType*
|
||||
XQItemType* itemType = findItemTypeTemplate( source );
|
||||
value = QVariant::fromValue(itemType);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case XQItem::RenderStyleRole:
|
||||
{
|
||||
XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source );
|
||||
value = QVariant::fromValue(renderStyle);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::EditorTypeRole:
|
||||
{
|
||||
XQItem::EditorType editorType = XQItem::fetchEditorType( source );
|
||||
value = QVariant::fromValue(editorType);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::UnitTypeRole:
|
||||
{
|
||||
//qDebug() << " --- make unit type: " << source;
|
||||
XQItem::UnitType unitType = XQItem::fetchUnitType( source );
|
||||
value = QVariant::fromValue(unitType);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::ContentFormatRole:
|
||||
{
|
||||
// contentFormat() -> QString
|
||||
value = QVariant::fromValue(source);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::FlagsRole:
|
||||
{
|
||||
QFlags itemFlags = Qt::NoItemFlags;
|
||||
const QStringList flagKeys = source.split( '|' );
|
||||
for( const QString& flagKey : flagKeys )
|
||||
{
|
||||
Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey );
|
||||
itemFlags.setFlag( flag );
|
||||
}
|
||||
value = QVariant::fromValue(itemFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case XQItem::IconRole:
|
||||
{
|
||||
QIcon typeIcon = XQAppData::typeIcon(source);
|
||||
value = QVariant::fromValue(typeIcon);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case XQItem::FixedChoicesRole:
|
||||
{
|
||||
const QStringList choices = source.split( '|' );
|
||||
|
||||
QStandardItemModel* fixedChoices = new QStandardItemModel();
|
||||
for( const QString& entry : choices )
|
||||
{
|
||||
QString result = entry;
|
||||
if( item->unitType() != XQItem::NoUnitType )
|
||||
result = XQItemType::formatToSI( entry, item->unitType() );
|
||||
fixedChoices->appendRow( new QStandardItem( result ) );
|
||||
}
|
||||
value = QVariant::fromValue(fixedChoices);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case XQItem::ContentNodeRole:
|
||||
{
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::XQItem::SheetNodeRole:
|
||||
{
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
default:
|
||||
case XQItem::XQItem::NoRole:
|
||||
{
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
//if( !value.toString().isEmpty())
|
||||
// setData( value, dataRole);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
//! gibt ein statisches invalid-item zurück, anstelle von nullptr
|
||||
|
||||
@@ -694,13 +878,10 @@ XQItem::UnitType XQItem::fetchUnitType(const QString& unitTypeKey)
|
||||
return s_UnitTypeMap.key(unitTypeKey);
|
||||
}
|
||||
|
||||
|
||||
//! gibt die bezeichung für den gegebenen unitType aus.
|
||||
|
||||
QString XQItem::fetchUnitTypeToString( UnitType unitType)
|
||||
{
|
||||
return s_UnitTypeMap[unitType];
|
||||
}
|
||||
|
||||
/// ---
|
||||
/// ---
|
||||
/// ---
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#ifndef XQITEM_H
|
||||
#define XQITEM_H
|
||||
|
||||
#include <QtQmlIntegration>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QStandardItem>
|
||||
@@ -35,6 +36,8 @@ class XQItemType;
|
||||
class XQItem : public QStandardItem
|
||||
{
|
||||
|
||||
QML_ELEMENT
|
||||
|
||||
friend class XQItemFactory;
|
||||
|
||||
public:
|
||||
@@ -81,7 +84,7 @@ public:
|
||||
ComboBoxStyle,
|
||||
PickerStyle,
|
||||
SpinBoxStyle,
|
||||
ProgressBarStyle,
|
||||
ColorBarStyle,
|
||||
FormattedStyle,
|
||||
TreeHeaderStyle,
|
||||
CustomRenderStyle,
|
||||
@@ -96,7 +99,7 @@ public:
|
||||
LineEditType,
|
||||
ComboBoxType,
|
||||
PickerType,
|
||||
ProgressBarType,
|
||||
ColorBarType,
|
||||
SpinBoxType,
|
||||
CustomEditorType,
|
||||
EditorTypeEnd
|
||||
@@ -130,6 +133,7 @@ public:
|
||||
XQItem();
|
||||
XQItem( XQItemType* itemType );
|
||||
XQItem( XQItemType* itemType, const QString* content );
|
||||
XQItem( XQItemType* itemType, const QString& content );
|
||||
|
||||
virtual ~XQItem() = default;
|
||||
|
||||
@@ -137,14 +141,16 @@ public:
|
||||
//! -- not used at the moment --
|
||||
XQItem* clone() const override;
|
||||
|
||||
//!
|
||||
bool isValid() const;
|
||||
//! __fix Tested, ob ein itemtype vorhanden ist.
|
||||
bool isValidX() const;
|
||||
|
||||
//! gibt den zu diesem item gehörigen datenknoten zurück
|
||||
virtual XQNodePtr contentNode() const;
|
||||
bool hasContentNode() const;
|
||||
//! gibt den zu diesem item gehörigen datenknoten zurück
|
||||
XQNodePtr contentNode() const;
|
||||
|
||||
virtual XQNodePtr sheetNode() const;
|
||||
virtual void setSheetNode( const XQNodePtr& sheetNode );
|
||||
|
||||
XQNodePtr sheetNode() const;
|
||||
void setSheetNode( const XQNodePtr& sheetNode );
|
||||
|
||||
XQItemType& itemType() const;
|
||||
void setItemType( XQItemType* itemTypePtr );
|
||||
@@ -159,9 +165,8 @@ public:
|
||||
QString rawText() const;
|
||||
|
||||
// changed: gibt jetzt den pointer zurück.
|
||||
QString* content() const;
|
||||
QString contentKey() const;
|
||||
void setContent( const QString* content );
|
||||
//QString* content() const;
|
||||
//void setContent( const QString* content );
|
||||
|
||||
//
|
||||
// Convenience-Funktionen zum Memberzugriff, die Implementierung
|
||||
@@ -219,6 +224,8 @@ public:
|
||||
/// Static convenience methods
|
||||
///
|
||||
|
||||
static QVariant makeVariant( XQItem* item, int dataRole, const QString& source );
|
||||
|
||||
static XQItem& xqItemFromIndex( const QModelIndex& index );
|
||||
static XQItem& fallBackDummyItem();
|
||||
|
||||
@@ -238,6 +245,10 @@ protected:
|
||||
XQItem(const XQItem& other) = default;
|
||||
XQItem& operator=(const XQItem& other) = default;
|
||||
|
||||
bool hasContentPtr() const;
|
||||
QString contentFallBackText() const;
|
||||
|
||||
// das ist protected, weil damit der content()-zugriff demoliert werden kann
|
||||
void setContentNode(const XQNodePtr& contentNode );
|
||||
|
||||
using XQItemFlagMap = QMap<QString,int>;
|
||||
@@ -259,9 +270,7 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(XQItem);
|
||||
Q_DECLARE_METATYPE(XQItem::RenderStyle);
|
||||
Q_DECLARE_METATYPE(XQItem::EditorType);
|
||||
Q_DECLARE_METATYPE(XQItem::UnitType);
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <QComboBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QProgressBar>
|
||||
#include <QSlider>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QHeaderView>
|
||||
@@ -28,153 +29,167 @@
|
||||
#include <xqviewmodel.h>
|
||||
|
||||
|
||||
//! erzeugt eine editorfactory mit den hauseigenen editortypen.
|
||||
|
||||
class XQItemEditorFactory : public QItemEditorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
XQItemEditorFactory()
|
||||
{
|
||||
|
||||
registerEditor(XQItem::LineEditType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
registerEditor(XQItem::ComboBoxType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
registerEditor(XQItem::ComboBoxType, new QStandardItemEditorCreator<QComboBox>());
|
||||
registerEditor(XQItem::PickerType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
registerEditor(XQItem::ProgressBarType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
registerEditor(XQItem::SpinBoxType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
//registerEditor(XQItem::ColorBarType, new QStandardItemEditorCreator<QProgressBar>());
|
||||
registerEditor(XQItem::ColorBarType, new QStandardItemEditorCreator<QSlider>());
|
||||
registerEditor(XQItem::SpinBoxType, new QStandardItemEditorCreator<QSpinBox>());
|
||||
registerEditor(XQItem::CustomEditorType, new QStandardItemEditorCreator<QLineEdit>());
|
||||
|
||||
/*
|
||||
registerEditor(XQItem::LineEditStyle, new QStandardItemEditorCreator<QLineEdit>());
|
||||
registerEditor(XQItemType::ComboBoxStyle, new QStandardItemEditorCreator<QComboBox>());
|
||||
//registerEditor(XQItemType::ProgressBarStyle, new QStandardItemEditorCreator<QProgressBar>());
|
||||
registerEditor(XQItemType::SpinBoxStyle, new QStandardItemEditorCreator<QSpinBox>());
|
||||
*/
|
||||
/*
|
||||
registerEditor(XQItem::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
|
||||
registerEditor(XQItemItemTypes::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
|
||||
registerEditor(XQItemItemTypes::etIPAddressType, new QStandardItemEditorCreator<NTIpAddressEdit>());
|
||||
registerEditor(XQItemItemTypes::etLineEditBrowser, new QStandardItemEditorCreator<NTFileSelectLine>());
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! kontruktor mit dem zusändigen viewModel
|
||||
|
||||
XQItemDelegate::XQItemDelegate( XQViewModel& modelView)
|
||||
: _modelView{modelView}
|
||||
XQItemDelegate::XQItemDelegate( XQViewModel& viewModel)
|
||||
: QStyledItemDelegate(), _modelView{viewModel}
|
||||
{
|
||||
static XQItemEditorFactory s_EditorFactory;
|
||||
setItemEditorFactory(&s_EditorFactory);
|
||||
}
|
||||
|
||||
|
||||
//! gibt die interne tree table zurück
|
||||
|
||||
XQTreeTable* XQItemDelegate::treeTable() const
|
||||
{
|
||||
return _modelView.treeTable();
|
||||
}
|
||||
|
||||
|
||||
//! shortcut: gibt das XQItem für den gegebenen index zurück.
|
||||
|
||||
XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const
|
||||
{
|
||||
return _modelView.xqItemFromIndex( index );
|
||||
}
|
||||
|
||||
|
||||
//! überladene paint-methode: zeichnet das item je nach render-style.
|
||||
|
||||
void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
if( !index.isValid() )
|
||||
qDebug() << " index DEAD!";
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
if( item.isValid() )
|
||||
if( index.isValid() )
|
||||
{
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
switch( item.renderStyle() )
|
||||
{
|
||||
case XQItem::HeaderStyle :
|
||||
return drawHeaderStyle( painter, option, index );
|
||||
return drawHeaderStyle( painter, option, item );
|
||||
//return drawHeaderStyleX( painter, option, index );
|
||||
|
||||
case XQItem::ComboBoxStyle :
|
||||
return drawComboBoxStyle( painter, option, index );
|
||||
return drawComboBoxStyle( painter, option, item );
|
||||
|
||||
case XQItem::ColorBarStyle :
|
||||
return drawColorBarStyle( painter, option, item );
|
||||
|
||||
// das funktioniert nicht unter windows11
|
||||
//case XQItem::SpinBoxStyle :
|
||||
// return drawSpinBoxStyle( painter, option, item );
|
||||
|
||||
case XQItem::HiddenStyle :
|
||||
return;
|
||||
|
||||
//case XQItem::ProgressBarStyle :
|
||||
// return drawProgressBarStyle( painter, option, index );
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
qDebug() << " ---- paint: INDEX DEAD!" ;
|
||||
}
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! einen section header im header-style zeichnen
|
||||
|
||||
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const
|
||||
{
|
||||
QStyleOptionHeader headerOption;
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
|
||||
// use the header as "parent" for style init
|
||||
QWidget* srcWidget = treeTable();//->header();
|
||||
QWidget* srcWidget = treeTable();//->header();
|
||||
headerOption.initFrom(srcWidget);
|
||||
headerOption.text = index.data(Qt::DisplayRole).toString();
|
||||
headerOption.rect = option.rect.adjusted(0,0,0,3);
|
||||
headerOption.text = item.text();//index.data(Qt::DisplayRole).toString();
|
||||
headerOption.rect = option.rect;//.adjusted(0,0,0,3);
|
||||
headerOption.styleObject = option.styleObject;
|
||||
// __ch: reduce inner offset when painting
|
||||
headerOption.textAlignment |= Qt::AlignVCenter;
|
||||
headerOption.icon = item.icon();
|
||||
|
||||
if (srcWidget != nullptr)
|
||||
{
|
||||
// save painter
|
||||
painter->save();
|
||||
//value = index.data(Qt::ForegroundRole);
|
||||
//if (value.canConvert<QBrush>())
|
||||
//headerOption.palette.setBrush(QPalette::Text, Qt::red );
|
||||
//headerOption.palette.setBrush(QPalette::Window, Qt::red );
|
||||
QCommonStyle itemStyle;
|
||||
//headerOption.backgroundBrush()
|
||||
//srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
|
||||
itemStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
|
||||
// restore painter
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
// save painter
|
||||
painter->save();
|
||||
//value = index.data(Qt::ForegroundRole);
|
||||
//if (value.canConvert<QBrush>())
|
||||
//headerOption.palette.setBrush(QPalette::Text, Qt::red );
|
||||
//headerOption.palette.setBrush(QPalette::Window, Qt::red );
|
||||
//QCommonStyle itemStyle;
|
||||
|
||||
void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
//qApp->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
|
||||
//srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
|
||||
// warum das nur mit dem commonstyle, ist mir echt unklar.
|
||||
_commonStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
|
||||
// restore painter
|
||||
painter->restore();
|
||||
|
||||
int progress = index.data(XQItem::ContentRole ).toInt();
|
||||
|
||||
QStyleOptionProgressBar progressBarOption;
|
||||
progressBarOption.rect = option.rect;
|
||||
progressBarOption.minimum = 0;
|
||||
progressBarOption.maximum = 100;
|
||||
progressBarOption.progress = progress;
|
||||
progressBarOption.text = QString::number(progress) + "%";
|
||||
progressBarOption.textAlignment = Qt::AlignCenter;
|
||||
progressBarOption.textVisible = true;
|
||||
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, painter);
|
||||
|
||||
}
|
||||
|
||||
void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
|
||||
//! Zeichnet prozent-werte als balken
|
||||
|
||||
void XQItemDelegate::drawColorBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const
|
||||
{
|
||||
//QStyledItemDelegate::paint(painter, option, item);
|
||||
|
||||
// Wert aus dem Modell holen
|
||||
bool ok;
|
||||
int value = item.data(Qt::EditRole).toInt(&ok);
|
||||
if (!ok || value < 0 || value > 100)
|
||||
return;
|
||||
|
||||
// Balkenbereich berechnen
|
||||
QRect rect = option.rect.adjusted(2, 2, -2, -2); // etwas Padding
|
||||
int barWidth = static_cast<int>(rect.width() * (value / 100.0));
|
||||
|
||||
// Balken zeichnen
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QRect barRect(rect.left(), rect.top(), barWidth, rect.height());
|
||||
QColor barColor = QColor(100, 180, 255);
|
||||
painter->setBrush(barColor);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(barRect);
|
||||
|
||||
painter->setPen(Qt::black);
|
||||
painter->drawText(rect, Qt::AlignCenter, item.text() );
|
||||
|
||||
painter->restore();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Zeichnet das Item als combo box.
|
||||
|
||||
void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const
|
||||
{
|
||||
QStyleOptionComboBox comboOption;
|
||||
|
||||
QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject);
|
||||
QStyleOptionComboBox comboOption;
|
||||
QStyle* comboStyle = srcWidget->style();
|
||||
|
||||
comboOption.initFrom(srcWidget);
|
||||
|
||||
// set options
|
||||
@@ -182,68 +197,102 @@ void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionView
|
||||
comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled;
|
||||
// not editable => only visual, but painter needs to know it
|
||||
comboOption.editable = false;
|
||||
comboOption.currentText = index.data(Qt::DisplayRole).toString();
|
||||
comboOption.currentText = item.text();
|
||||
// decoration (if any)
|
||||
comboOption.currentIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
|
||||
comboOption.currentIcon = qvariant_cast<QIcon>(item.data(Qt::DecorationRole));
|
||||
comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3));
|
||||
|
||||
// save painter
|
||||
painter->save();
|
||||
|
||||
// hier wiederum funktioniert der '_commonStyle' nicht
|
||||
QStyle* widgetStyle = srcWidget->style();
|
||||
// draw combo
|
||||
comboStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget);
|
||||
widgetStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget);
|
||||
// and combobox label
|
||||
comboStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget);
|
||||
widgetStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget);
|
||||
// restore painter
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
|
||||
//! Zeichnet das Item als spin box.
|
||||
|
||||
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const
|
||||
{
|
||||
|
||||
// xx_fix!
|
||||
//int value = index.data(XQItem::ContentRole ).toInt();
|
||||
QStyleOptionSpinBox spinBoxOption;
|
||||
spinBoxOption.rect = option.rect;
|
||||
/*
|
||||
spinBoxOption.text = QString::number(value);
|
||||
spinBoxOption.textAlignment = Qt::AlignCenter;
|
||||
spinBoxOption.textVisible = true;
|
||||
*/
|
||||
qDebug() << " --- jawas +++? SPINBOX!";
|
||||
|
||||
QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject);
|
||||
QStyleOptionViewItem viewOption(option);
|
||||
QStyleOptionSpinBox spinBoxOption;
|
||||
spinBoxOption.initFrom(srcWidget);
|
||||
|
||||
initStyleOption(&viewOption, item.index());
|
||||
if (option.state & QStyle::State_HasFocus)
|
||||
{
|
||||
viewOption.state = viewOption.state ^ QStyle::State_HasFocus; // Fokus nicht auf dem Hintergrund malen
|
||||
}
|
||||
QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewOption, painter);
|
||||
|
||||
spinBoxOption.rect = option.rect;//.adjusted( 0,0,-40,0);
|
||||
spinBoxOption.state = option.state | QStyle::State_Sunken; // Sunken-State für den "LineEdit"-Look
|
||||
spinBoxOption.buttonSymbols = QAbstractSpinBox::UpDownArrows;
|
||||
spinBoxOption.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
|
||||
spinBoxOption.frame = true;
|
||||
|
||||
_commonStyle.drawComplexControl(QStyle::CC_SpinBox, &spinBoxOption, painter, nullptr);
|
||||
QRect editRect =_commonStyle.subControlRect(QStyle::CC_SpinBox, &spinBoxOption, QStyle::SC_SpinBoxEditField, nullptr);
|
||||
painter->drawText(spinBoxOption.rect, Qt::AlignCenter, item.text());
|
||||
|
||||
QApplication::style()->drawComplexControl(QStyle::CC_SpinBox,&spinBoxOption, painter);
|
||||
}
|
||||
|
||||
|
||||
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
//! Überschreibt QStyledItemDelegate::sizeHint(option, index);
|
||||
|
||||
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
|
||||
//! Erzeugt ein editor-widget, sofern ein gültiger content-Ptr vorhanden und ein editor-Type gesetzt ist.
|
||||
|
||||
QWidget* XQItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
Q_UNUSED(option);
|
||||
|
||||
return QStyledItemDelegate::createEditor( parent, option, index );
|
||||
|
||||
int editorType = XQItem::xqItemFromIndex(index).editorType();
|
||||
QWidget* editor = itemEditorFactory()->createEditor(editorType, parent);
|
||||
if( editor )
|
||||
XQItem& item = xqItemFromIndex(index);
|
||||
XQItem::EditorType edType = item.editorType();
|
||||
if( edType == XQItem::NoEditorType )
|
||||
{
|
||||
return editor;
|
||||
qDebug() << "---- NO Content or NO EditorType";
|
||||
return nullptr;
|
||||
}
|
||||
qDebug() << "---- ed type:" << XQItem::fetchEditorTypeToString( edType ) << ": " << edType;
|
||||
|
||||
QWidget* editor = itemEditorFactory()->createEditor(edType, parent);;
|
||||
//return QStyledItemDelegate::createEditor( parent, option, index );
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
//! Füttert einen editor mit den model-daten
|
||||
|
||||
void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
switch( item.editorType() )
|
||||
XQItem::EditorType edType = item.editorType();
|
||||
if( edType == XQItem::NoEditorType )
|
||||
return;
|
||||
|
||||
switch( edType )
|
||||
{
|
||||
case XQItemType::ComboBoxType :
|
||||
{
|
||||
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
|
||||
// wir erwarten hier ein gültiges model?
|
||||
comboBox->setModel( item.fixedChoices());
|
||||
comboBox->setCurrentText( item.data().toString() );
|
||||
comboBox->showPopup();
|
||||
@@ -251,24 +300,37 @@ void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) co
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
// wir benutzen hier die DisplayRole wenn der Inhalt schon formatiert ist.
|
||||
int role = item.renderStyle() == XQItem::FormattedStyle ? Qt::DisplayRole : Qt::EditRole;
|
||||
QVariant value = index.data(role);
|
||||
|
||||
QByteArray userProp = editor->metaObject()->userProperty().name();
|
||||
if (!userProp.isEmpty())
|
||||
{
|
||||
if (!value.isValid())
|
||||
value = QVariant(editor->property(userProp).metaType());
|
||||
editor->setProperty(userProp, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
|
||||
void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
|
||||
//! Schreibt die daten aus dem editor ins model zurück
|
||||
|
||||
void XQItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
|
||||
switch( item.editorType() )
|
||||
{
|
||||
|
||||
case XQItem::ComboBoxType :
|
||||
{
|
||||
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
|
||||
item.setData( comboBox->currentText(), Qt::DisplayRole );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -280,8 +342,12 @@ void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
|
||||
|
||||
//! Überschreibt QItemDelegate::updateEditorGeometry. Nicht implementiert.
|
||||
|
||||
void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
//qDebug() << " --- update Editor Geometry";
|
||||
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#define XQITEMDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QCommonStyle>
|
||||
#include <xqappdata.h>
|
||||
|
||||
class XQItem;
|
||||
@@ -32,26 +33,27 @@ class XQItemDelegate : public QStyledItemDelegate
|
||||
|
||||
public:
|
||||
|
||||
explicit XQItemDelegate(XQViewModel& modelView);
|
||||
explicit XQItemDelegate(XQViewModel& viewModel);
|
||||
|
||||
XQTreeTable* treeTable() const;
|
||||
XQItem& xqItemFromIndex( const QModelIndex& index ) const;
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor, QAbstractItemModel *model, const QModelIndex& index) const override;
|
||||
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
protected:
|
||||
|
||||
void drawHeaderStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawSpinBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item ) const;
|
||||
void drawColorBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const;
|
||||
void drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const;
|
||||
void drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const;
|
||||
|
||||
XQViewModel& _modelView;
|
||||
QCommonStyle _commonStyle;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -29,7 +29,7 @@ void XQItemFactory::initItemFactory( const QString& modelSheetFileName )
|
||||
for( const auto& [key,value] : sheetNode->attributes() )
|
||||
{
|
||||
//qDebug() << " --- conf item Type: " << key << " : " << value;
|
||||
setItemDataFromString( *itemType, key, value );
|
||||
setItemTypeDataFromString( *itemType, key, value );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +91,7 @@ XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry )
|
||||
// wenn ja, überschreiben
|
||||
if( role != XQItem::NoRole )
|
||||
{
|
||||
QVariant newValue = makeVariant(role, attrEntry.second );
|
||||
QVariant newValue = XQItem::makeVariant( itemType, role, attrEntry.second );
|
||||
itemType = itemType->replaceAttribute( newValue, role );
|
||||
}
|
||||
|
||||
@@ -99,12 +99,13 @@ XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry )
|
||||
return itemType;
|
||||
}
|
||||
|
||||
|
||||
//! sucht einen item typ aus der map mit 'vorgefertigen' itemtypen.
|
||||
|
||||
XQItemType* XQItemFactory::findItemTypeTemplate(const QString& key ) const
|
||||
{
|
||||
if( !key.isEmpty() && s_ItemTypeTemplates.contains(key))
|
||||
return s_ItemTypeTemplates[key];
|
||||
return s_ItemTypeTemplates[key];
|
||||
throw XQException( "itemfactory: findItemTypeTemplate: not found:", key );
|
||||
}
|
||||
|
||||
@@ -123,188 +124,21 @@ XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const
|
||||
|
||||
//! erzeugt eine QVariant aus dem gegebenen string und setzt diese dann via role im item.
|
||||
|
||||
void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const
|
||||
void XQItemFactory::setItemTypeDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const
|
||||
{
|
||||
int dataRole = XQItem::fetchItemDataRole( roleKey );
|
||||
if( dataRole != XQItem::NoRole)
|
||||
{
|
||||
QVariant variant = makeVariant( dataRole, source );
|
||||
QVariant variant = XQItem::makeVariant( &item, dataRole, source );
|
||||
if( !variant.isNull() && variant.isValid() )
|
||||
item.setData( variant, dataRole );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! erzeugt eine QVariant aus dem gegebenen string
|
||||
|
||||
QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
|
||||
{
|
||||
|
||||
QVariant value;
|
||||
|
||||
switch(dataRole)
|
||||
{
|
||||
// das ist ein pointer auf den original-string aus dem XML
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
// content() -> QString*
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::ItemTypeRole:
|
||||
{
|
||||
// itemType() -> XQItemType*
|
||||
//qDebug() << " --- makeVariant: make ItemType: " << source;
|
||||
XQItemType* itemType = findItemTypeTemplate( source );
|
||||
value = QVariant::fromValue(itemType);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::RenderStyleRole:
|
||||
{
|
||||
XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source );
|
||||
value = QVariant::fromValue(renderStyle);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::EditorTypeRole:
|
||||
{
|
||||
XQItem::EditorType editorType = XQItem::fetchEditorType( source );
|
||||
value = QVariant::fromValue(editorType);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::UnitTypeRole:
|
||||
{
|
||||
//qDebug() << " --- make unit type: " << source;
|
||||
XQItem::UnitType unitType = XQItem::fetchUnitType( source );
|
||||
value = QVariant::fromValue(unitType);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::ContentFormatRole:
|
||||
{
|
||||
// contentFormat() -> QString
|
||||
value = QVariant::fromValue(source);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::FlagsRole:
|
||||
{
|
||||
QFlags itemFlags = Qt::NoItemFlags;
|
||||
const QStringList flagKeys = source.split( '|' );
|
||||
for( const QString& flagKey : flagKeys )
|
||||
{
|
||||
Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey );
|
||||
itemFlags.setFlag( flag );
|
||||
}
|
||||
value = QVariant::fromValue(itemFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case XQItem::IconRole:
|
||||
{
|
||||
QIcon typeIcon = XQAppData::typeIcon(source);
|
||||
value = QVariant::fromValue(typeIcon);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case XQItem::FixedChoicesRole:
|
||||
{
|
||||
const QStringList choices = source.split( '|' );
|
||||
|
||||
QStandardItemModel* fixedChoices = new QStandardItemModel();
|
||||
for( const QString& entry : choices )
|
||||
fixedChoices->appendRow( new QStandardItem( entry ) );
|
||||
value = QVariant::fromValue(fixedChoices);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
case XQItem::ContentNodeRole:
|
||||
{
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
|
||||
case XQItem::XQItem::SheetNodeRole:
|
||||
{
|
||||
value = QVariant::fromValue(&source);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
default:
|
||||
case XQItem::XQItem::NoRole:
|
||||
{
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
//if( !value.toString().isEmpty())
|
||||
// setData( value, dataRole);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// ------------------------------------------------
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
|
||||
{
|
||||
Q_UNUSED(contentNode)
|
||||
|
||||
XQItemList list;
|
||||
|
||||
// create a data node for each sheet entry
|
||||
size_t max = sheetNode->children().size();
|
||||
for( size_t i=0; i<max; ++i )
|
||||
{
|
||||
// __fix
|
||||
//list.append( new XQItem( "", XQItemType::EmptyStyle ) );
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
XQItemList XQItemFactory::createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
|
||||
{
|
||||
|
||||
// we have a new empty contentNode, so we add attributes first.
|
||||
for( const auto& sheetEntry : sheetNode->children() )
|
||||
{
|
||||
QString value = "[" + sheetEntry->tag_name() + "]";
|
||||
if( sheetEntry->has_attribute("Unit") )
|
||||
value = "0";
|
||||
contentNode->set_attribute( sheetEntry->tag_name(), value );
|
||||
}
|
||||
|
||||
if( sheetNode->has_attribute( c_FriendlyName ) )
|
||||
contentNode->set_attribute( c_FriendlyName, sheetNode->friendly_name() );
|
||||
|
||||
// now, we can create a normal entry row
|
||||
return makeContentRow(contentNode, sheetNode );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//! erzeugt eine item-row.
|
||||
|
||||
XQItemList XQItemFactory::makeRow(CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey )
|
||||
XQItemList XQItemFactory::makeRow(const XQNodePtr& sheetNode, const XQNodePtr& contentNode )
|
||||
{
|
||||
|
||||
XQItemList list;
|
||||
@@ -320,24 +154,31 @@ XQItemList XQItemFactory::makeRow(CreationMode mode, const XQNodePtr& sheetNode,
|
||||
//
|
||||
|
||||
for( const auto& sheetEntry : sheetNode->children() )
|
||||
list.append( makeItem( mode, sheetEntry, contentNode, captionKey ) );
|
||||
list.append( makeItem( sheetEntry, contentNode ) );
|
||||
|
||||
Q_ASSERT(!list.empty());
|
||||
|
||||
// wir merken uns den original content node auch, aber
|
||||
// im ersten Item.
|
||||
// im ersten Item. Kann null sein, macht aber erstmal nix.
|
||||
dynamic_cast<XQItem*>(list[0])->setContentNode(contentNode);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
XQItemList XQItemFactory::makeChildRow( XQItem* parent, const XQNodePtr& sheetNode, const XQNodePtr& contentNode )
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
Q_UNUSED(sheetNode);
|
||||
Q_UNUSED(contentNode);
|
||||
|
||||
//! fixme! unsinn!
|
||||
//! erzeugt ein XQItem aus einer typ-beschreibung ('sheetNode') und einem daten-knoten ('contentNode').
|
||||
//! wenn der content node nicht gesetzt ist, wird stattdess das attribut 'Caption' aus der typ-beschreibung
|
||||
//! verwendet: es handelt sich dann um ein header item, das erzeugt wurde.
|
||||
return XQItemList();
|
||||
}
|
||||
|
||||
XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey )
|
||||
//! Erzeugt ein XQItem aus einer typ-beschreibung ('sheetNode') und einem daten-knoten ('contentNode').
|
||||
//! Wenn der content node nicht gesetzt ist, wird stattdess das attribut 'Caption' aus der typ-beschreibung
|
||||
//! verwendet: es handelt sich dann um ein header item
|
||||
|
||||
XQItem* XQItemFactory::makeItem(const XQNodePtr& sheetNode, const XQNodePtr& contentNode )
|
||||
{
|
||||
// den itemtype des neuen items rausfinden
|
||||
XQItemType* itemType = makeItemType(sheetNode); // throws
|
||||
@@ -347,19 +188,10 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
|
||||
// das ist Unterschied vom HeaderItem zum normalen Item: Der Titel kommt aus der Modelbeschreibung,
|
||||
// sonst wird der content indirekt über den tag-name des sheetnode geholt
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case mHeader:
|
||||
contentPtr = sheetNode->attribute_ptr(captionKey);
|
||||
break;
|
||||
|
||||
case mData:
|
||||
contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() );
|
||||
break;
|
||||
|
||||
case mSingle:
|
||||
contentPtr = contentNode->attribute_ptr( captionKey );
|
||||
}
|
||||
if( !contentNode )
|
||||
contentPtr = sheetNode->attribute_ptr(c_Caption);
|
||||
else
|
||||
contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() );
|
||||
|
||||
XQItem* newItem = new XQItem( itemType, contentPtr);
|
||||
|
||||
@@ -371,3 +203,18 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
|
||||
|
||||
return newItem;
|
||||
}
|
||||
|
||||
//! Erzeugt ein Item _ohne_ internen content node, sondern
|
||||
XQItem* XQItemFactory::makeSingleItem( const XQNodePtr& sheetNode, const QString& caption )
|
||||
{
|
||||
// den itemtype des neuen items rausfinden
|
||||
XQItemType* itemType = makeItemType(sheetNode); // throws
|
||||
XQItem* newItem = new XQItem( itemType, caption);
|
||||
// __fixme!
|
||||
if( newItem->isCheckable() )
|
||||
{
|
||||
newItem->setCheckState( Qt::Checked );
|
||||
}
|
||||
|
||||
return newItem;
|
||||
}
|
||||
|
@@ -28,35 +28,25 @@ class XQItemFactory : public xsingleton<XQItemFactory>
|
||||
|
||||
public:
|
||||
|
||||
enum CreationMode
|
||||
{
|
||||
mHeader,
|
||||
mData,
|
||||
mSingle
|
||||
};
|
||||
|
||||
void initItemFactory(const QString& modelSheetFileName );
|
||||
|
||||
XQNodePtr findModelSheet( const QString& modelName ) const;
|
||||
|
||||
//XQItemList makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
|
||||
XQItemList makeRow( const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
|
||||
XQItemList makeChildRow( XQItem* parent, const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
|
||||
XQItem* makeSingleItem( const XQNodePtr& sheetNode, const QString& caption );
|
||||
|
||||
XQItemList makeRow( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey=c_Caption );
|
||||
|
||||
// wozu ist das gut?
|
||||
//XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
|
||||
|
||||
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
|
||||
void setItemTypeDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
|
||||
|
||||
XQItemType* makeItemType(const XQNodePtr& sheetEntry );
|
||||
XQItemType* findItemTypeTemplate(const QString& key ) const;
|
||||
QVariant makeVariant(int dataRole, const QString &value ) const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool isValid();
|
||||
|
||||
XQItem* makeItem( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey );
|
||||
XQItem* makeItem(const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
|
||||
|
||||
// shortcuts
|
||||
using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>;
|
||||
|
@@ -113,6 +113,7 @@ XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role )
|
||||
// Gibt es den geänderten ItemType schon?
|
||||
QString newKey = myClone->makeItemTypeKey();
|
||||
// jawoll
|
||||
|
||||
if( s_ItemTypeMap.contains( newKey ) )
|
||||
{
|
||||
// abräumen ...
|
||||
@@ -134,22 +135,9 @@ XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role )
|
||||
}
|
||||
|
||||
|
||||
//! formatiert den content() string eines items.
|
||||
|
||||
QVariant XQItemType::formatText( const XQItem& item ) const
|
||||
{
|
||||
XQItem::UnitType uType = unitType();
|
||||
//qDebug() << " --- formatText: " << XQItem::fetchUnitTypeToString( uType);
|
||||
const QString& cont = item.rawText();
|
||||
if( uType != XQItem::NoUnitType )
|
||||
return formatToSI( cont, uType );
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
//! formatiert einen zahlenwert als string mit einheit.
|
||||
|
||||
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType ) const
|
||||
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType )
|
||||
{
|
||||
|
||||
if( valueTxt.isEmpty() )
|
||||
@@ -180,18 +168,18 @@ QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitTy
|
||||
strVal = sysLocale.toString(nVal, 'f', 2);
|
||||
strPrefix = s_PrefixExponentMap.key(exp);
|
||||
//qDebug() << " convert: " << dVal << " : " << valueTxt << ": " << strVal << ":" << exp << " : " << strPrefix << ": " << nVal;
|
||||
|
||||
return QString("%1 %2%3").arg( strVal, strPrefix, unitTypeToString() );
|
||||
QString unitStr = XQItem::fetchUnitTypeToString( unitType);
|
||||
return QString("%1 %2%3").arg( strVal, strPrefix, unitStr );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! entfernt die einheit aus einem formatierten string
|
||||
|
||||
QString XQItemType::unFormatFromSI(const QString& formText ) const
|
||||
QString XQItemType::unFormatFromSI(const QString& formText )
|
||||
{
|
||||
|
||||
QString input = formText.simplified();
|
||||
const QString input = formText.simplified();
|
||||
// #1: strip numeric part
|
||||
if( input.isEmpty() )
|
||||
return input;
|
||||
|
@@ -40,17 +40,14 @@ public:
|
||||
QVariant data( int role ) const override;
|
||||
void setData(const QVariant& value, int role ) override;
|
||||
|
||||
QVariant formatText( const XQItem& item ) const;
|
||||
|
||||
QString formatToSI(const QString& rawText, XQItem::UnitType unitType ) const;
|
||||
QString unFormatFromSI(const QString& valueText ) const;
|
||||
|
||||
int roleForAttributeKey( const QString& attrKey );
|
||||
XQItemType* replaceAttribute(const QVariant& newValue, int role );
|
||||
|
||||
QString makeItemTypeKey();
|
||||
|
||||
static XQItemType* staticItemType();
|
||||
static QString formatToSI(const QString& rawText, XQItem::UnitType unitType );
|
||||
static QString unFormatFromSI(const QString& valueText );
|
||||
|
||||
protected:
|
||||
|
||||
|
79
src/main.cpp
@@ -19,6 +19,7 @@
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QUrl>
|
||||
#include <QQmlContext>
|
||||
#include <QStyleFactory>
|
||||
|
||||
#include <xqchildmodel.h>
|
||||
#include <xqquickwidget.h>
|
||||
@@ -73,60 +74,67 @@ XQChildModel* createChildModel()
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
class DummyModel : public XQChildModel
|
||||
{
|
||||
|
||||
public:
|
||||
CONFIG += precompile_header
|
||||
PRECOMPILED_HEADER = pch.h
|
||||
|
||||
DummyModel()
|
||||
{
|
||||
// pch.h – Precompiled Header für Qt-Projekt
|
||||
|
||||
initModel( c_ChildModelName );
|
||||
XQNodeFactory treeLoader;
|
||||
// xml daten laden
|
||||
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(c_DocumentFileName1) );
|
||||
// versteckten root node ignorieren
|
||||
XQNodePtr contentRoot = rawTree->first_child();
|
||||
addModelData( contentRoot->first_child() );
|
||||
Stelle sicher, dass pch.h im Projektordner liegt und in den .cpp-Dateien eingebunden wird:
|
||||
|
||||
//XQTreeTable* treeTable = new XQTreeTable;
|
||||
//treeTable->setModel(this);
|
||||
//setTreeTable( treeTable );
|
||||
C++
|
||||
#include "pch.h"
|
||||
|
||||
//treeTable->show();
|
||||
}
|
||||
};
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// Qt Core
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
// Qt GUI
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QPixmap>
|
||||
|
||||
// Qt Widgets (falls verwendet)
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QLabel>
|
||||
|
||||
// STL
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#endif // PCH_H
|
||||
|
||||
*/
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
// Signal für einzelne QStandardItem-Änderungen
|
||||
connect(model, &QStandardItemModel::itemChanged,
|
||||
this, [](QStandardItem *changedItem){
|
||||
QVariant state = changedItem->data(Qt::CheckStateRole);
|
||||
qDebug() << "Neuer Check-State:" << state.toInt();
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
QApplication app(argc, argv);
|
||||
//app.setStyle("fusion");
|
||||
//qDebug() << QStyleFactory::keys();
|
||||
//QApplication::setStyle("fusion");
|
||||
//QApplication::setStyle("windowsvista");
|
||||
//QApplication::setStyle("windows");
|
||||
|
||||
XQMainWindow window;
|
||||
window.show();
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
QApplication app(argc, argv);
|
||||
|
||||
|
||||
XQMainWindow::setupWorkingDir();
|
||||
XQItemFactory::instance().initItemFactory( c_ModelSheetFileName );
|
||||
|
||||
@@ -152,6 +160,7 @@ connect(model, &QStandardItemModel::itemChanged,
|
||||
|
||||
qDebug() << " hhakl!";
|
||||
|
||||
*/
|
||||
return app.exec();
|
||||
|
||||
}
|
||||
|
@@ -28,10 +28,10 @@ void XQNodeStore::dumpList( const QString& title ) const
|
||||
}
|
||||
|
||||
|
||||
//! kostruktor. übergibt command-type und die aufrufende modelView.
|
||||
//! kostruktor. übergibt command-type und die aufrufende viewModel.
|
||||
|
||||
XQCommand::XQCommand(CmdType cmdType, XQViewModel* modelView )
|
||||
: _cmdType{ cmdType }, _viewModel(modelView)
|
||||
XQCommand::XQCommand(CmdType cmdType, XQViewModel* viewModel )
|
||||
: _cmdType{ cmdType }, _viewModel(viewModel)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -108,20 +108,22 @@ void XQCommand::setOriginIndex( const QModelIndex& origin )
|
||||
void XQCommand::saveNodes( const QModelIndexList& list )
|
||||
{
|
||||
clear();
|
||||
// über jede zeil
|
||||
// über jede zeile
|
||||
for( auto entry : list )
|
||||
{
|
||||
// knoten holen
|
||||
const XQNodePtr& contentNode = XQItem::xqItemFromIndex( entry ).contentNode();
|
||||
// hier speichern wir den original knoten, nicht einen clone, wie im clipboard.
|
||||
push_back( {entry.row(), contentNode->own_pos(), contentNode } );
|
||||
// obacht: bei einem Header is der content node null
|
||||
if(contentNode)
|
||||
push_back( {entry.row(), contentNode->own_pos(), contentNode } );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! erzeugt einen string aus dem command-type, fürs debuggen.
|
||||
|
||||
QString XQCommand::toString()
|
||||
QString XQCommand::toString() const
|
||||
{
|
||||
|
||||
static QMap<CmdType,QString> s_CmdTypeMap
|
||||
|
@@ -66,7 +66,7 @@ public:
|
||||
cmdExtern //??
|
||||
};
|
||||
|
||||
XQCommand(CmdType cmdType, XQViewModel* modelView );
|
||||
XQCommand(CmdType cmdType, XQViewModel* viewModel );
|
||||
virtual ~XQCommand();
|
||||
|
||||
CmdType commandType() const;
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
void redo() override;
|
||||
void undo() override;
|
||||
|
||||
QString toString();
|
||||
QString toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
@@ -1,206 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
source::worx xtree
|
||||
Copyright © 2024-2025 c.holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <xqmodelsectionlist.h>
|
||||
|
||||
|
||||
//! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung
|
||||
//! der datenknoten.
|
||||
|
||||
XQModelSection::XQModelSection(const QModelIndex& modelIndex, XQNodePtr sheetNode)
|
||||
: _modelIndex{ modelIndex }, _sectionRootNode{ sheetNode }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! elementvergleich.
|
||||
|
||||
bool XQModelSection::operator==(const XQModelSection& other) const
|
||||
{
|
||||
return _modelIndex == other._modelIndex && _sectionRootNode == other._sectionRootNode;
|
||||
}
|
||||
|
||||
|
||||
//! true wenn der start-index valide und ein model-knoten vorhanden.
|
||||
|
||||
bool XQModelSection::isValid() const
|
||||
{
|
||||
return _modelIndex.isValid() && _sectionRootNode;
|
||||
}
|
||||
|
||||
QModelIndex XQModelSection::persistentModelIndex() const
|
||||
{
|
||||
return _modelIndex.operator QModelIndex();
|
||||
}
|
||||
|
||||
XQNodePtr XQModelSection::sectionRootNode() const
|
||||
{
|
||||
return _sectionRootNode;
|
||||
}
|
||||
|
||||
//! Gibt den sheet-node zurück, das ist die model-beschreibung,
|
||||
//! siehe modelsheet.xml:
|
||||
//! <section>
|
||||
//! <header>
|
||||
//! <data> <- dort
|
||||
|
||||
//! __fix! das versteht doch kein mensch!
|
||||
|
||||
XQNodePtr XQModelSection::sheetRootNode() const
|
||||
{
|
||||
return _sectionRootNode->find_child_by_tag_name( c_ModelSheet );
|
||||
}
|
||||
|
||||
|
||||
//! Gibt den content root node zurück, das ist der
|
||||
//! zeiger auf die realen inhalte.
|
||||
|
||||
XQNodePtr XQModelSection::contentRootNode() const
|
||||
{
|
||||
return _contentRootNode;
|
||||
}
|
||||
|
||||
void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode )
|
||||
{
|
||||
_contentRootNode = contentRootNode;
|
||||
}
|
||||
|
||||
|
||||
//! gibt die zeile des start-index zurück.
|
||||
|
||||
int XQModelSection::XQModelSection::row() const
|
||||
{
|
||||
return _modelIndex.row();
|
||||
}
|
||||
|
||||
|
||||
//! gibt den 'content type' zurück.
|
||||
|
||||
const QString& XQModelSection::contentType() const
|
||||
{
|
||||
return _sectionRootNode->attribute( c_ContentType );
|
||||
}
|
||||
|
||||
|
||||
//! gibt das dieser section entsprechende header-item zurück.
|
||||
|
||||
XQItem& XQModelSection::XQModelSection::headerItem() const
|
||||
{
|
||||
return XQItem::xqItemFromIndex( _modelIndex );
|
||||
}
|
||||
|
||||
|
||||
//! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist.
|
||||
|
||||
bool XQModelSectionList::hasValidSection(const QString& sectionKey) const
|
||||
{
|
||||
if (!contains(sectionKey) )
|
||||
return false;
|
||||
return at(sectionKey).isValid();
|
||||
}
|
||||
|
||||
|
||||
//! gibt für einen model index die 'zuständige' section zurück.
|
||||
|
||||
const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const
|
||||
{
|
||||
return sectionFromRow( index.row() );
|
||||
}
|
||||
|
||||
|
||||
//! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird
|
||||
//! nach der passenden section durchsucht.
|
||||
|
||||
const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const
|
||||
{
|
||||
|
||||
int i = size() - 1;
|
||||
for (; i >= 0; --i)
|
||||
{
|
||||
if ( at(i).persistentModelIndex().row() < itemRow )
|
||||
return at(i);
|
||||
}
|
||||
|
||||
static XQModelSection s_DummySection;
|
||||
|
||||
return s_DummySection;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die erste zeile einer section.
|
||||
|
||||
int XQModelSectionList::firstRow(const QModelIndex& idx) const
|
||||
{
|
||||
return sectionFromRow(idx.row() ).row();
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die zeile unterhalb des gegebenen modelindex,
|
||||
//! zum einfügen neuer items ebendort.
|
||||
|
||||
int XQModelSectionList::lastRow(const QModelIndex& idx) const
|
||||
{
|
||||
return lastRow(sectionFromRow(idx.row()));
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die zeile unterhalb der gegebenen section,
|
||||
//! zum einfügen neuer items ebendort.
|
||||
|
||||
int XQModelSectionList::lastRow(const XQModelSection& section ) const
|
||||
{
|
||||
//qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row();
|
||||
// row() der section unterhalb dieser
|
||||
// __fix? index mit speichern?
|
||||
int index = indexOf(section);
|
||||
if (index > -1)
|
||||
{
|
||||
// last section? return last row of model
|
||||
if (index == size() - 1)
|
||||
return section.persistentModelIndex().model()->rowCount();// - 1;
|
||||
// return row above the row of the next section -> last row of given section
|
||||
return at(index+1).row();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//! gibt alle sections aus, zum ankucken.
|
||||
|
||||
void XQModelSectionList::dump() const
|
||||
{
|
||||
qDebug() << " --- sections dump(): " <<size() << " entries.";
|
||||
for( int i = 0; i<size(); ++i )
|
||||
{
|
||||
QModelIndex idx = at(i).persistentModelIndex();
|
||||
qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
207
src/model/xqsectionmanager.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/***************************************************************************
|
||||
|
||||
source::worx xtree
|
||||
Copyright © 2024-2025 c.holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <xqsectionmanager.h>
|
||||
|
||||
|
||||
//! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung
|
||||
//! der datenknoten.
|
||||
|
||||
XQModelSection::XQModelSection(const QModelIndex& modelIndex, XQNodePtr sheetNode)
|
||||
: _modelIndex{ modelIndex }, _sectionSheetRootNode{ sheetNode }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! elementvergleich.
|
||||
|
||||
bool XQModelSection::operator==(const XQModelSection& other) const
|
||||
{
|
||||
return _modelIndex == other._modelIndex && _sectionSheetRootNode == other._sectionSheetRootNode;
|
||||
}
|
||||
|
||||
|
||||
//! true wenn der start-index valide und ein model-knoten vorhanden.
|
||||
|
||||
bool XQModelSection::isValid() const
|
||||
{
|
||||
return _modelIndex.isValid() && _sectionSheetRootNode;
|
||||
}
|
||||
|
||||
QModelIndex XQModelSection::startIndex() const
|
||||
{
|
||||
return _modelIndex.operator QModelIndex();
|
||||
}
|
||||
|
||||
XQNodePtr XQModelSection::sectionRootNode() const
|
||||
{
|
||||
return _sectionSheetRootNode;
|
||||
}
|
||||
|
||||
//! Gibt den sheet-node zurück, das ist die model-beschreibung,
|
||||
//! siehe modelsheet.xml:
|
||||
//! <section>
|
||||
//! <header>
|
||||
//! <data> <- dort
|
||||
|
||||
//! __fix! das versteht doch kein mensch!
|
||||
|
||||
XQNodePtr XQModelSection::sheetRootNode() const
|
||||
{
|
||||
return _sectionSheetRootNode->find_child_by_tag_name( c_ModelSheet );
|
||||
}
|
||||
|
||||
|
||||
//! Gibt den content root node zurück, das ist der
|
||||
//! zeiger auf die realen inhalte.
|
||||
|
||||
XQNodePtr XQModelSection::contentRootNode() const
|
||||
{
|
||||
return _contentRootNode;
|
||||
}
|
||||
|
||||
void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) const
|
||||
{
|
||||
_contentRootNode = contentRootNode;
|
||||
}
|
||||
|
||||
|
||||
//! gibt die zeile des start-index zurück.
|
||||
|
||||
int XQModelSection::XQModelSection::firstRow() const
|
||||
{
|
||||
return _modelIndex.row();
|
||||
}
|
||||
|
||||
|
||||
//! gibt den 'content type' zurück.
|
||||
|
||||
const QString& XQModelSection::contentType() const
|
||||
{
|
||||
//qDebug() << " ---AUA & AUS!";
|
||||
return _sectionSheetRootNode->attribute( c_ContentType );
|
||||
}
|
||||
|
||||
|
||||
//! gibt das dieser section entsprechende header-item zurück.
|
||||
|
||||
XQItem& XQModelSection::XQModelSection::headerItem() const
|
||||
{
|
||||
return XQItem::xqItemFromIndex( _modelIndex );
|
||||
}
|
||||
|
||||
|
||||
//! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist.
|
||||
|
||||
bool XQSectionManager::hasValidSection(const QString& sectionKey) const
|
||||
{
|
||||
if (!_sections.contains(sectionKey) )
|
||||
return false;
|
||||
return _sections.at(sectionKey).isValid();
|
||||
}
|
||||
|
||||
const XQModelSection& XQSectionManager::sectionByKey( const QString& sectionKey ) const
|
||||
{
|
||||
if( hasValidSection( sectionKey ) )
|
||||
return _sections.at(sectionKey);
|
||||
|
||||
throw XQException( "No section for key", sectionKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird
|
||||
//! nach der passenden section durchsucht.
|
||||
|
||||
const XQModelSection& XQSectionManager::sectionByRow(int itemRow ) const
|
||||
{
|
||||
|
||||
|
||||
for (const auto& section : _sections)
|
||||
{
|
||||
qDebug() << " ---- SEC: " << itemRow << " -> " << section.firstRow() << " : " << lastRow( section );
|
||||
XQSectionRange range = sectionRange(section);
|
||||
if( itemRow >= range.firstRow && itemRow <= range.lastRow)
|
||||
return section;
|
||||
}
|
||||
|
||||
throw XQException( "No section for item row", QString::number(itemRow));
|
||||
|
||||
}
|
||||
|
||||
|
||||
const XQModelSection& XQSectionManager::createSection(const QModelIndex& modelIndex, XQNodePtr sheetNode)
|
||||
{
|
||||
const QString& sectionKey = sheetNode->attribute(c_ContentType);
|
||||
//qDebug() << " --- create Section: " << sectionKey << ": " << modelIndex.data().toString();
|
||||
XQModelSection section(modelIndex, sheetNode );
|
||||
_sections.addAtKey( sectionKey, section);
|
||||
return sectionByKey(sectionKey);
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die zeile unterhalb des gegebenen modelindex,
|
||||
//! zum einfügen neuer items ebendort.
|
||||
|
||||
int XQSectionManager::lastRow(const XQModelSection& section ) const
|
||||
{
|
||||
//qDebug() << " -- last row in section: " << section.startIndex().data().toString() << " --> " << section.startIndex().row();
|
||||
// row() der section unterhalb dieser
|
||||
// __fix? index mit speichern?
|
||||
int index = _sections.indexOf(section);
|
||||
if (index > -1)
|
||||
{
|
||||
// last section? return last row of model
|
||||
if (index == _sections.size() - 1)
|
||||
return section.startIndex().model()->rowCount() - 1;
|
||||
// return row above the row of the next section -> last row of given section
|
||||
return _sections.at(index+1).firstRow() - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
XQSectionRange XQSectionManager::sectionRange(const XQModelSection& section ) const
|
||||
{
|
||||
return XQSectionRange{ section.startIndex().row(), lastRow(section) };
|
||||
}
|
||||
|
||||
|
||||
//! gibt alle sections aus, zum ankucken.
|
||||
|
||||
void XQSectionManager::dump() const
|
||||
{
|
||||
qDebug() << " --- sections dump(): " <<_sections.size() << " entries.";
|
||||
for( int i = 0; i<_sections.size(); ++i )
|
||||
{
|
||||
QModelIndex idx = _sections.at(i).startIndex();
|
||||
qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << _sections.keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -12,17 +12,18 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef XQMODELSECTIONLIST_H
|
||||
#define XQMODELSECTIONLIST_H
|
||||
#ifndef XQSECTIONMANAGER_H
|
||||
#define XQSECTIONMANAGER_H
|
||||
|
||||
#include <QPersistentModelIndex>
|
||||
|
||||
#include <xqmaptor.h>
|
||||
#include <xqitem.h>
|
||||
|
||||
/**
|
||||
* @brief Struct containing data for a header section
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//! Daten zur beschreibung einer 'sektion' des models.
|
||||
|
||||
class XQModelSection
|
||||
{
|
||||
@@ -35,13 +36,13 @@ public:
|
||||
|
||||
bool operator==(const XQModelSection& other) const;
|
||||
bool isValid() const;
|
||||
int row() const;
|
||||
int firstRow() const;
|
||||
|
||||
QModelIndex persistentModelIndex() const;
|
||||
QModelIndex startIndex() const;
|
||||
XQNodePtr sectionRootNode() const;
|
||||
XQNodePtr sheetRootNode() const;
|
||||
XQNodePtr contentRootNode() const;
|
||||
void setContentRootNode( const XQNodePtr dataRootNode );
|
||||
void setContentRootNode( const XQNodePtr dataRootNode ) const;
|
||||
|
||||
const QString& contentType() const;
|
||||
XQItem& headerItem() const;
|
||||
@@ -50,32 +51,42 @@ protected:
|
||||
|
||||
QPersistentModelIndex _modelIndex;
|
||||
|
||||
XQNodePtr _sectionRootNode{};
|
||||
XQNodePtr _contentRootNode{};
|
||||
mutable XQNodePtr _sectionSheetRootNode{};
|
||||
mutable XQNodePtr _contentRootNode{};
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(XQModelSection)
|
||||
|
||||
/**
|
||||
* @brief Maptor containing all header sections.
|
||||
*/
|
||||
//! Erste und letzte ziele einer XQModelSection
|
||||
struct XQSectionRange
|
||||
{
|
||||
int firstRow{-1};
|
||||
int lastRow{-1};
|
||||
};
|
||||
|
||||
class XQModelSectionList : public XQMaptor<XQModelSection>
|
||||
|
||||
//! struktur, die alle sections enthält
|
||||
|
||||
class XQSectionManager
|
||||
{
|
||||
public:
|
||||
|
||||
bool hasValidSection(const QString& sectionKey) const;
|
||||
|
||||
const XQModelSection& sectionFromRow( int row ) const;
|
||||
const XQModelSection& sectionFromIndex( const QModelIndex& index ) const;
|
||||
const XQModelSection& sectionByKey( const QString& sectionKey ) const;
|
||||
const XQModelSection& sectionByRow( int row ) const;
|
||||
|
||||
int firstRow(const QModelIndex& idx) const;
|
||||
int lastRow(const QModelIndex& idx) const;
|
||||
int lastRow(const XQModelSection& section) const;
|
||||
const XQModelSection& createSection(const QModelIndex& modelIndex, XQNodePtr sheetNode);
|
||||
int lastRow(const XQModelSection& section ) const;
|
||||
XQSectionRange sectionRange(const XQModelSection §ion) const;
|
||||
|
||||
void dump()const override;
|
||||
void dump()const;
|
||||
|
||||
protected:
|
||||
|
||||
XQMaptor<XQModelSection> _sections;
|
||||
|
||||
};
|
||||
|
||||
#endif // XQMODELSECTIONLIST_H
|
||||
#endif // XQSECTIONMANAGER_H
|
@@ -35,28 +35,34 @@ XQSelectionModel::XQSelectionModel(QAbstractItemModel* model, QObject* parent)
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
//! jetzt die selektierten indices, wie die basisklasse, aber nur die innerhalt einer section.
|
||||
|
||||
void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
// step #0: fetch selected indices.
|
||||
// step #0: die ursprüngliche selection bestimmen
|
||||
const QModelIndexList list = selection.indexes();
|
||||
if (list.isEmpty() || selectedRows().isEmpty() )
|
||||
return QItemSelectionModel::select(selection, command);
|
||||
|
||||
// fetch first index
|
||||
// step 01: den ersten index bestimmen
|
||||
QModelIndex firstValid = list.first();
|
||||
if (hasSelection() )
|
||||
firstValid = selectedRows().first();
|
||||
|
||||
//XQItem& firstItem = XQItem::xqItemFromIndex(firstValid);
|
||||
//if( firstItem.isValid() )
|
||||
// step 02: finde das erste item gültigem content node.
|
||||
XQNodePtr firstNode = XQItem::xqItemFromIndex(firstValid).contentNode();
|
||||
while( !firstNode)
|
||||
{
|
||||
firstValid = firstValid.siblingAtRow( firstValid.row()+1);
|
||||
firstNode = XQItem::xqItemFromIndex(firstValid).contentNode();
|
||||
}
|
||||
|
||||
XQNodePtr firstNode = XQItem::xqItemFromIndex(firstValid).contentNode();
|
||||
// step 03: selektiere nur knoten, die den gleichen tag_name haben, sich also
|
||||
// in der selben section befinden
|
||||
|
||||
if( firstNode )
|
||||
{
|
||||
QItemSelection newSelection;
|
||||
// __fixme! das crasht!
|
||||
|
||||
for (const QModelIndex& idx : list)
|
||||
{
|
||||
XQNodePtr nextNode = XQItem::xqItemFromIndex(idx).contentNode();
|
||||
@@ -66,5 +72,7 @@ void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionMod
|
||||
}
|
||||
return QItemSelectionModel::select(newSelection, command);
|
||||
}
|
||||
|
||||
// fallback
|
||||
QItemSelectionModel::select(selection, command);
|
||||
}
|
||||
|
@@ -35,18 +35,34 @@
|
||||
void showItemList( const XQItemList& list)
|
||||
{
|
||||
for(const auto& entry : list )
|
||||
qDebug() << " --- itemList: " << ((XQItem*)entry)->content();
|
||||
qDebug() << " --- itemList: " << entry->text();
|
||||
qDebug();
|
||||
}
|
||||
|
||||
void showSelectionList( const QModelIndexList& list)
|
||||
{
|
||||
for(const auto& entry : list )
|
||||
qDebug() << " --- SelectionList: " << entry.data().toString();
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
//! Konstruktur mit parent.
|
||||
//! Konstruktor mit parent.
|
||||
|
||||
XQViewModel::XQViewModel( QObject* parent )
|
||||
: QStandardItemModel{ parent }, _itemFactory{ XQItemFactory::instance() }
|
||||
{
|
||||
invisibleRootItem()->setData( "[rootItem]", Qt::DisplayRole );
|
||||
setItemPrototype( new XQItem );
|
||||
|
||||
// auf änderungen kann in den unterklassen reagiert werden
|
||||
connect(this, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item)
|
||||
{
|
||||
XQItem* xqItem = static_cast<XQItem*>(item);
|
||||
emit xqItemChanged( *xqItem );
|
||||
});
|
||||
// not needed
|
||||
//qRegisterMetaType<XQItem>("XQItem");
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +75,14 @@ const XQItem& XQViewModel::xqRootItem()
|
||||
// dynamisch über den ItemData Mechanismus wie in QStandardItem
|
||||
|
||||
return *static_cast<XQItem*>(invisibleRootItem());
|
||||
}
|
||||
|
||||
|
||||
//! Gibt den daten root node des models zurück.
|
||||
|
||||
XQNodePtr XQViewModel::contentRootNode()
|
||||
{
|
||||
return _contentRoot;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +106,16 @@ XQItem& XQViewModel::xqFirstItem(int row) const
|
||||
return *static_cast<XQItem*>( QStandardItemModel::item(row) );
|
||||
}
|
||||
|
||||
void XQViewModel::expandNewItem(const QModelIndex& index)
|
||||
{
|
||||
if( _treeTable )
|
||||
{
|
||||
// ... ausklappen...
|
||||
_treeTable->expand( index );
|
||||
// ... und markieren
|
||||
_treeTable->setCurrentIndex( index );
|
||||
}
|
||||
}
|
||||
|
||||
//! initialisiert dieses model über den namen. Es wird hier
|
||||
//! nur die strukur erzeugt, keine inhalte.
|
||||
@@ -99,9 +132,7 @@ void XQViewModel::initModel(const QString& modelName)
|
||||
|
||||
*/
|
||||
setObjectName( modelName );
|
||||
qDebug() << " --- initModel: " << objectName();
|
||||
|
||||
// model rootnode finden -> <DocumentTreeModel>
|
||||
// model rootnode finden -> <DocumentTreeModel>
|
||||
XQNodePtr modelSheet = _itemFactory.findModelSheet( modelName ); // throws
|
||||
|
||||
// #1: über alle sections
|
||||
@@ -111,7 +142,7 @@ void XQViewModel::initModel(const QString& modelName)
|
||||
const XQNodePtr header = sectionNode->find_child_by_tag_name( c_Header );
|
||||
if( header )
|
||||
{
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, header, nullptr );
|
||||
XQItemList list = _itemFactory.makeRow( header, nullptr );
|
||||
addSection(list, sectionNode );
|
||||
}
|
||||
}
|
||||
@@ -122,25 +153,24 @@ void XQViewModel::initModel(const QString& modelName)
|
||||
//! die section kann erst gültig sein, wenn die items im model gelandet sind,
|
||||
//! deswegen ist das hier zusammengefasst.
|
||||
|
||||
//! Wrzeugt dann eine section aus einer frisch erzeugten itemlist. Der erste modelindex
|
||||
//! Erzeugt dann eine section aus einer frisch erzeugten itemlist. Der erste modelindex
|
||||
//! der liste und der root knoten der model-beschreibung werden gespeichert.
|
||||
|
||||
void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNode )
|
||||
void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sheetNode )
|
||||
{
|
||||
// 1. die liste darf nicht leer sein
|
||||
Q_ASSERT(!list.isEmpty());
|
||||
// 2. sectionNode muss da sein
|
||||
Q_ASSERT(sectionNode);
|
||||
// 2. sheetNode muss da sein
|
||||
Q_ASSERT(sheetNode);
|
||||
// 3. 'ContenType' muss vorhanden sein
|
||||
if( !sectionNode->has_attribute( c_ContentType) )
|
||||
if( !sheetNode->has_attribute( c_ContentType) )
|
||||
throw XQException( "section list: Section node needs attribute 'ContentType'!");
|
||||
|
||||
// 5. das erzeugt dann auch valide indices
|
||||
appendRow(list);
|
||||
|
||||
// 6. jetzt können wir auch die sction erzeugen
|
||||
XQModelSection section(list[0]->index(), sectionNode );
|
||||
_sections.addAtKey(sectionNode->attribute( c_ContentType), section);
|
||||
// 6. jetzt können wir auch die section erzeugen
|
||||
const XQModelSection& section = _sections.createSection( list[0]->index(), sheetNode );
|
||||
|
||||
// ... und es der welt mitteilen.
|
||||
emit sectionCreated( section );
|
||||
@@ -148,11 +178,46 @@ void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNod
|
||||
}
|
||||
|
||||
|
||||
//! SLOT, toggled die section mit dem 'sectionKey' (hier: contentType)
|
||||
|
||||
void XQViewModel::onToggleSection(const QString& sectionKey )
|
||||
{
|
||||
qDebug() << " --- Model: " << this->objectName() << " should toggle: " << sectionKey << ": " << _sections.hasValidSection( sectionKey );
|
||||
_sections.dump();
|
||||
if(_sections.hasValidSection( sectionKey ) )
|
||||
toggleSection( _sections.sectionByKey(sectionKey) );
|
||||
}
|
||||
|
||||
|
||||
//! toggled die gegebene model section.
|
||||
|
||||
void XQViewModel::toggleSection( const XQModelSection& section )
|
||||
{
|
||||
if( section.isValid() && _treeTable )
|
||||
{
|
||||
XQSectionRange pos = _sections.sectionRange(section);
|
||||
qDebug() << " --- Section RANGE: " << pos.firstRow << " -> " << pos.lastRow;
|
||||
|
||||
_treeTable->toggleRowsHidden(pos.firstRow, pos.lastRow );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! SLOT als weiterleitung vom SIGNAL itemchanged
|
||||
|
||||
void XQViewModel::onItemChanged(XQItem* item )
|
||||
{
|
||||
qDebug() << " --- BASE item changed: " << item->text();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
//! SLOT, der aufgerufen wird, wenn eine edit-action getriggert wurde.
|
||||
|
||||
void XQViewModel::onActionTriggered(QAction* action)
|
||||
{
|
||||
qDebug() << " --- onActionTriggered: count:" << XQNode::s_Count;
|
||||
qDebug() << " --- onActionTriggered: count:" << action->text() <<": " << XQNode::s_Count;
|
||||
|
||||
// all selected indices
|
||||
QModelIndexList selectionList = treeTable()->selectionModel()->selectedRows();
|
||||
@@ -161,6 +226,7 @@ void XQViewModel::onActionTriggered(QAction* action)
|
||||
|
||||
switch( cmdType )
|
||||
{
|
||||
|
||||
// just handle undo ...
|
||||
case XQCommand::cmdUndo :
|
||||
return _undoStack->undo();
|
||||
@@ -185,45 +251,22 @@ void XQViewModel::onActionTriggered(QAction* action)
|
||||
|
||||
// we create a command
|
||||
XQCommand* command = new XQCommand( cmdType, this );
|
||||
QModelIndex currentIndex = treeTable()->currentIndex();
|
||||
command->setOriginIndex(currentIndex);
|
||||
// store the row positions of the selected indices
|
||||
showSelectionList(selectionList);
|
||||
command->saveNodes( selectionList );
|
||||
command->setOriginIndex( treeTable()->currentIndex() );
|
||||
|
||||
|
||||
// execute command
|
||||
_undoStack->push( command );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
switch (command.commandType())
|
||||
{
|
||||
case XQCommand::cmdToggleSection:
|
||||
return cmdToggleSection( command.originIndex() );
|
||||
|
||||
case XQCommand::cmdCut:
|
||||
return cmdCut( command );
|
||||
|
||||
case XQCommand::cmdPaste:
|
||||
return cmdPaste( command );
|
||||
|
||||
case XQCommand::cmdNew:
|
||||
return cmdNew( command );
|
||||
|
||||
case XQCommand::cmdDelete:
|
||||
return cmdDelete( command );
|
||||
|
||||
case XQCommand::cmdMove:
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << " --- onCommandRedo: default: not handled: " << command.toString();
|
||||
}
|
||||
*/
|
||||
|
||||
//! führt die 'redo' action des gegebenen commnds aus.
|
||||
|
||||
void XQViewModel::onCommandRedo( XQCommand& command )
|
||||
void XQViewModel::onCommandRedo( const XQCommand& command )
|
||||
{
|
||||
static MemCallMap redoCalls
|
||||
{
|
||||
@@ -249,45 +292,10 @@ void XQViewModel::onCommandRedo( XQCommand& command )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
switch (command.commandType())
|
||||
{
|
||||
case XQCommand::cmdToggleSection:
|
||||
return cmdToggleSection( command.originIndex() );
|
||||
break;
|
||||
|
||||
// undo Cut -> perform undoCut
|
||||
case XQCommand::cmdCut:
|
||||
return cmdCutUndo( command );
|
||||
|
||||
// undo Paste -> perform Cut
|
||||
case XQCommand::cmdPaste:
|
||||
return cmdPasteUndo( command );
|
||||
|
||||
// undo Move -> perform move back
|
||||
case XQCommand::cmdMove:
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
// undo New -> perform Delete
|
||||
case XQCommand::cmdNew:
|
||||
cmdNewUndo( command );
|
||||
break;
|
||||
|
||||
// undo Delete -> perform New
|
||||
case XQCommand::cmdDelete:
|
||||
qDebug() << " --- onCommandUndo: delete: " << command.toString();
|
||||
return cmdDeleteUndo( command );
|
||||
|
||||
default:
|
||||
qDebug() << " --- onCommandUndo: default: not handled: " << command.toString();
|
||||
}
|
||||
*/
|
||||
//! führt die 'undo' action des gegebenen commnds aus.
|
||||
|
||||
void XQViewModel::onCommandUndo( XQCommand& command )
|
||||
void XQViewModel::onCommandUndo( const XQCommand& command )
|
||||
{
|
||||
qDebug() << " --- onCommandUndo: count: " << XQNode::s_Count;
|
||||
|
||||
@@ -319,18 +327,26 @@ void XQViewModel::onCommandUndo( XQCommand& command )
|
||||
|
||||
//! markierte knoten entfernen, 'command' enthält die liste
|
||||
|
||||
void XQViewModel::cmdCut( XQCommand& command )
|
||||
void XQViewModel::cmdCut( const XQCommand& command )
|
||||
{
|
||||
|
||||
int itmPos = command.first().itemPos;
|
||||
const XQModelSection& section = _sections.sectionByRow( itmPos );
|
||||
qDebug() << " --- HEADSHOT I: " << itmPos << "->" << section.contentType();
|
||||
|
||||
// wir gehen rückwärts über alle gemerkten knoten ...
|
||||
for (auto it = command.rbegin(); it != command.rend(); ++it)
|
||||
{
|
||||
|
||||
|
||||
// ... holen das erste item, das auch den content node enthält
|
||||
//const XQNodeBackup& entry = *it;
|
||||
// jetzt löschen, dabei wird die parent-verbindung entfernt
|
||||
const XQNodeBackup& entry = *it;
|
||||
|
||||
XQItem& firstItem = xqFirstItem( (*it).itemPos );
|
||||
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
|
||||
//qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
|
||||
qDebug() << " ---- command CUT: itemPos: " << entry.itemPos << " nodePos: "<< entry.nodePos << " is " << entry.contentNode->friendly_name();
|
||||
|
||||
entry.contentNode->unlink_self();
|
||||
removeRow(entry.itemPos );
|
||||
@@ -340,31 +356,37 @@ void XQViewModel::cmdCut( XQCommand& command )
|
||||
|
||||
//! entfernte knoten wieder einfügen , 'command' enthält die liste
|
||||
|
||||
void XQViewModel::cmdCutUndo( XQCommand& command )
|
||||
void XQViewModel::cmdCutUndo( const XQCommand& command )
|
||||
{
|
||||
|
||||
// die anfangsposition
|
||||
int itmPos = command.first().itemPos;
|
||||
// die 'zuständige' section rausfinden
|
||||
const XQModelSection& section = _sections.sectionFromRow( itmPos );
|
||||
const XQModelSection& section = _sections.sectionByRow( itmPos );
|
||||
|
||||
qDebug() << " --- HEADSHOT II: " << itmPos << "->" << section.contentType();
|
||||
|
||||
// über alle einträge ...
|
||||
for (auto& entry : command )
|
||||
{
|
||||
const XQNodePtr& savedNode = entry.contentNode;
|
||||
// __fix! should not be _contentRoot!
|
||||
savedNode->add_me_at( entry.nodePos, _contentRoot );
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, section.sheetRootNode(), savedNode );
|
||||
XQItemList list = _itemFactory.makeRow( section.sheetRootNode(), savedNode );
|
||||
insertRow( entry.itemPos, list );
|
||||
|
||||
XQItem& firstItem = *((XQItem*)list[0]);
|
||||
|
||||
qDebug() << " ---- command cut UNDO2: itemPos: " << entry.itemPos << " nodePos: "<< entry.nodePos << " is " << entry.contentNode->friendly_name();
|
||||
qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count();
|
||||
|
||||
insertRow( entry.itemPos, list );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! clipboard inhalte einfügen
|
||||
|
||||
void XQViewModel::cmdPaste( XQCommand& command )
|
||||
void XQViewModel::cmdPaste( const XQCommand& command )
|
||||
{
|
||||
// selection holen ...
|
||||
QItemSelectionModel* selectionModel = treeTable()->selectionModel();
|
||||
@@ -379,7 +401,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
int nodePos = item.contentNode()->own_pos()+1;
|
||||
|
||||
// die zugehörige section finden
|
||||
const XQModelSection& section = _sections.sectionFromRow( insRow-1 );
|
||||
const XQModelSection& section = _sections.sectionByRow( insRow-1 );
|
||||
// wir pasten das clipboard
|
||||
for (auto& entry : _clipBoard )
|
||||
{
|
||||
@@ -388,7 +410,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
// ... diesen einfügen ...
|
||||
newNode->add_me_at( nodePos );
|
||||
// ... und damit eine frische item-row erzeugen
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, section.sheetRootNode(), newNode );
|
||||
XQItemList list = _itemFactory.makeRow( section.sheetRootNode(), newNode );
|
||||
insertRow( insRow, list );
|
||||
// die neue item-row selektieren
|
||||
const QModelIndex& selIdx = list[0]->index();
|
||||
@@ -399,14 +421,16 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
}
|
||||
|
||||
// unsere änderungen merken fürs 'undo'
|
||||
command.saveNodes( selectionModel->selectedRows() );
|
||||
|
||||
/// fix_xx
|
||||
const_cast<XQCommand&>(command).saveNodes( selectionModel->selectedRows() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! einfügen aus dem clipboard wieder rückgängig machen
|
||||
|
||||
void XQViewModel::cmdPasteUndo( XQCommand& command )
|
||||
void XQViewModel::cmdPasteUndo( const XQCommand& command )
|
||||
{
|
||||
command.dumpList("Paste UNDO");
|
||||
// wir gehen rückwärts über alle markieren knoten ...
|
||||
@@ -427,7 +451,7 @@ void XQViewModel::cmdPasteUndo( XQCommand& command )
|
||||
|
||||
//! entfernen der selection ohne copy in clipboard.
|
||||
|
||||
void XQViewModel::cmdDelete( XQCommand& command )
|
||||
void XQViewModel::cmdDelete( const XQCommand& command )
|
||||
{
|
||||
// wir gehen rückwärts über alle markieren knoten ...
|
||||
for (auto it = command.rbegin(); it != command.rend(); ++it)
|
||||
@@ -435,83 +459,85 @@ void XQViewModel::cmdDelete( XQCommand& command )
|
||||
// ... holen das erste item, das auch den content node enthält
|
||||
const XQNodeBackup& entry = *it;
|
||||
XQItem& firstItem = xqFirstItem( (*it).itemPos );
|
||||
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row();
|
||||
qDebug() << " --- delete: " << firstItem.text() << " " << firstItem.row();
|
||||
// jetzt löschen
|
||||
entry.contentNode->unlink_self();
|
||||
removeRow(entry.itemPos );
|
||||
}
|
||||
}
|
||||
|
||||
//! macht 'delete' wirder rückgängig.
|
||||
//! macht 'delete' wieder rückgängig.
|
||||
|
||||
void XQViewModel::cmdDeleteUndo( XQCommand& command )
|
||||
void XQViewModel::cmdDeleteUndo( const XQCommand& command )
|
||||
{
|
||||
|
||||
for (const auto& entry : command)
|
||||
{
|
||||
qDebug() << " --- delete UNDo: " << entry.contentNode->friendly_name();
|
||||
}
|
||||
cmdCutUndo(command);
|
||||
}
|
||||
|
||||
|
||||
//! legt eine neue, leere zeile an.
|
||||
|
||||
void XQViewModel::cmdNew( XQCommand& command )
|
||||
void XQViewModel::cmdNew( const XQCommand& command )
|
||||
{
|
||||
|
||||
// __fix
|
||||
/*
|
||||
const QModelIndex& origin = command.originIndex();
|
||||
if( !origin.isValid() )
|
||||
throw XQException("cmdNewRow failed: index not valid ");
|
||||
|
||||
XQItem* target = xqItemFromIndex( origin );
|
||||
XQItem& target = xqItemFromIndex( origin );
|
||||
// current data node
|
||||
XQNodePtr node = target->contentNode();
|
||||
|
||||
// we create a new data node
|
||||
//XQNodePtr newNode = new XQNodePtr( node->tag_name(), node->parent() );
|
||||
XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value(), node->parent() );
|
||||
XQNodePtr node = target.contentNode();
|
||||
// we create a new data node
|
||||
XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value() );
|
||||
// store node in node->parent()
|
||||
//node->add_before_me( newNode );
|
||||
// store node also in 'command' to enable undo
|
||||
const XQModelSection& section = _sections.sectionFromIndex( origin );
|
||||
newNode->add_me_at( node->own_pos(), node->parent() );
|
||||
|
||||
// create new item row
|
||||
XQItemList list = _itemFactory.createGenericRow( newNode, section.sheetRootNode );
|
||||
|
||||
// add it to the treeview ...
|
||||
//...
|
||||
const XQModelSection& section = _sections.sectionByRow( origin.row() );
|
||||
|
||||
// neue, leere zeile erzeugen ...
|
||||
XQItemList list =_itemFactory.makeRow( section.sheetRootNode(), newNode );
|
||||
// ... zur treeview hinzufügen ...
|
||||
insertRow( origin.row(), list );
|
||||
// ... editierbar machen ...
|
||||
QModelIndex newIndex = list[0]->index();
|
||||
treeTable()->setCurrentIndex( newIndex );
|
||||
treeTable()->edit( newIndex );
|
||||
// ,,, und fürs undo speichern
|
||||
const_cast<XQCommand&>(command).saveNodes( {newIndex} );
|
||||
|
||||
// ... and make it ...
|
||||
treeTable()->setCurrentIndex( list[0]->index() );
|
||||
// ... editable
|
||||
treeTable()->edit( list[0]->index() );
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//! entfernt die neu angelegte zeile.
|
||||
|
||||
void XQViewModel::cmdNewUndo( XQCommand& command )
|
||||
void XQViewModel::cmdNewUndo( const XQCommand& command )
|
||||
{
|
||||
cmdDelete( command );
|
||||
}
|
||||
|
||||
|
||||
//! schaltet eine section sichtbar oder unsichtbar.
|
||||
|
||||
void XQViewModel::cmdToggleSection( XQCommand& command )
|
||||
void XQViewModel::cmdToggleSection( const XQCommand& command )
|
||||
{
|
||||
const QModelIndex& index = command.originIndex();
|
||||
Q_ASSERT(index.isValid());
|
||||
const XQModelSection& section = _sections.sectionByRow(index.row());
|
||||
|
||||
int fstRow = _sections.firstRow( index );
|
||||
int lstRow = _sections.lastRow( index );
|
||||
// Obacht! Das ist hier etwas unsauber, 'toogleSection'' ändert den check-State
|
||||
// im document-tree, was wiederum die 'toggleSection' auslöst, das gibt also
|
||||
// einen doppelten Aufruf und wir sind dann wieder im Anfangszustand.
|
||||
|
||||
bool hidden =_treeTable->isRowHidden( fstRow, _treeTable->rootIndex() );
|
||||
for (int row = fstRow; row < lstRow; ++row )
|
||||
_treeTable->setRowHidden( row, _treeTable->rootIndex(), !hidden );
|
||||
//toggleSection( section );
|
||||
|
||||
emit sectionToggled(section);
|
||||
|
||||
emit sectionToggled( _sections.sectionFromIndex(index) );
|
||||
}
|
||||
|
||||
|
||||
//! git die treetable zurück
|
||||
//! gibt die treetable zurück
|
||||
|
||||
XQTreeTable* XQViewModel::treeTable()
|
||||
{
|
||||
@@ -524,7 +550,7 @@ void XQViewModel::setTreeTable(XQTreeTable* mainView )
|
||||
{
|
||||
// store view for direct access: the maintree
|
||||
_treeTable = mainView;
|
||||
// connect myself as model to the mainview
|
||||
// set myself as model to the mainview
|
||||
_treeTable->setModel(this);
|
||||
XQItemDelegate* delegate = new XQItemDelegate( *this );
|
||||
_treeTable->setItemDelegate( delegate );
|
||||
|
@@ -22,7 +22,7 @@
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
#include <xqsimpleclipboard.h>
|
||||
#include <xqmodelsectionlist.h>
|
||||
#include <xqsectionmanager.h>
|
||||
#include <xqitemfactory.h>
|
||||
#include <xqcontextmenu.h>
|
||||
|
||||
@@ -37,7 +37,7 @@ class XQCommand;
|
||||
class XQViewModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
//QML_ELEMENT
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
|
||||
@@ -54,78 +54,65 @@ public:
|
||||
|
||||
virtual void initModel( const QString& modelName);
|
||||
|
||||
void expandNewItem(const QModelIndex& index);
|
||||
void toggleSection( const XQModelSection& section );
|
||||
|
||||
//little helpers
|
||||
const XQItem& xqRootItem();
|
||||
XQNodePtr contentRootNode();
|
||||
|
||||
XQItem& xqItemFromIndex(const QModelIndex& index) const;
|
||||
XQItem& xqFirstItem(int row) const;
|
||||
|
||||
// undo-/redo-able stuff
|
||||
|
||||
virtual void cmdToggleSection( XQCommand& command );
|
||||
virtual void cmdCut( XQCommand& command );
|
||||
virtual void cmdCutUndo( XQCommand& command );
|
||||
virtual void cmdPaste( XQCommand& command );
|
||||
virtual void cmdPasteUndo( XQCommand& command );
|
||||
virtual void cmdDelete( XQCommand& command );
|
||||
virtual void cmdDeleteUndo( XQCommand& command );
|
||||
virtual void cmdNew( XQCommand& command );
|
||||
virtual void cmdNewUndo( XQCommand& command );
|
||||
virtual void cmdToggleSection( const XQCommand& command );
|
||||
virtual void cmdCut( const XQCommand& command );
|
||||
virtual void cmdCutUndo( const XQCommand& command );
|
||||
virtual void cmdPaste( const XQCommand& command );
|
||||
virtual void cmdPasteUndo( const XQCommand& command );
|
||||
virtual void cmdDelete( const XQCommand& command );
|
||||
virtual void cmdDeleteUndo( const XQCommand& command );
|
||||
virtual void cmdNew( const XQCommand& command );
|
||||
virtual void cmdNewUndo( const XQCommand& command );
|
||||
|
||||
// Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
|
||||
// Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'
|
||||
|
||||
signals:
|
||||
|
||||
/*!
|
||||
|
||||
Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
|
||||
Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
return QStandardItemModel::data( index, role );
|
||||
}
|
||||
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
|
||||
{
|
||||
qDebug() << " --- setData: " << value.toString();
|
||||
return QStandardItemModel::setData( index, value, role );
|
||||
}
|
||||
|
||||
*/
|
||||
void xqItemChanged( const XQItem& item );
|
||||
void itemCreated( XQItem* newItem );
|
||||
void sectionCreated( const XQModelSection& section );
|
||||
void sectionToggled( const XQModelSection& section );
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onShowContextMenu(const QPoint& point);
|
||||
virtual void onActionTriggered(QAction* action);
|
||||
|
||||
virtual void onToggleSection(const QString& sectionKey );
|
||||
// handle XQCommands ( == UndoCommand )
|
||||
virtual void onCommandRedo( XQCommand& command );
|
||||
virtual void onCommandUndo( XQCommand& command );
|
||||
|
||||
signals:
|
||||
|
||||
void itemCreated( XQItem* newItem );
|
||||
void sectionCreated( const XQModelSection& section );
|
||||
void sectionToggled( const XQModelSection& section );
|
||||
virtual void onCommandRedo( const XQCommand& command );
|
||||
virtual void onCommandUndo( const XQCommand& command );
|
||||
|
||||
protected:
|
||||
|
||||
void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
|
||||
virtual void initContextMenu(){}
|
||||
|
||||
virtual void initContextMenu() = 0;
|
||||
// __fixme: should be created from xml
|
||||
virtual void setupViewProperties();
|
||||
|
||||
protected:
|
||||
|
||||
using MemCall = void (XQViewModel::*)(XQCommand&);
|
||||
using MemCall = void (XQViewModel::*)(const XQCommand&);
|
||||
using MemCallMap = QMap<XQCommand::CmdType,MemCall>;
|
||||
|
||||
// das eine reference auf ein globales singleton
|
||||
XQItemFactory& _itemFactory;
|
||||
XQSimpleClipBoard _clipBoard;
|
||||
XQModelSectionList _sections;
|
||||
XQItemFactory& _itemFactory;
|
||||
XQSimpleClipBoard _clipBoard;
|
||||
XQSectionManager _sections;
|
||||
|
||||
XQTreeTable* _treeTable{};
|
||||
XQTreeTable* _treeTable{};
|
||||
//QAbstractItemView* _treeTable{};
|
||||
QUndoStack* _undoStack{};
|
||||
XQContextMenu* _contextMenu{};
|
||||
|
@@ -53,6 +53,7 @@ namespace znode
|
||||
|
||||
//! einfache tree-klasse, besonderheit: der nutzlast-string-type ist templated.
|
||||
template<typename str_t>
|
||||
//class zbasic_node : public zid, public zpayload<str_t>, public std::enable_shared_from_this<zbasic_node<str_t>>
|
||||
class zbasic_node : public zid, public zpayload<str_t>, public std::enable_shared_from_this<zbasic_node<str_t>>
|
||||
{
|
||||
|
||||
@@ -78,6 +79,7 @@ namespace znode
|
||||
zweak_node _parent;
|
||||
znode_list _children;
|
||||
|
||||
// functor, der auf pointer gleichheit prüft.
|
||||
struct match_node
|
||||
{
|
||||
match_node( zbasic_node* match )
|
||||
@@ -95,9 +97,11 @@ namespace znode
|
||||
public:
|
||||
|
||||
//! shortcut auf std::make_shared...
|
||||
static zshared_node make_node( str_cref arg1, str_cref arg2 = "" , zshared_cref parent = nullptr )
|
||||
//! beachte: der eltern-knoten wird hier nicht gesetzt, der neue knoten
|
||||
//! wird nirgends eingefügt.
|
||||
static zshared_node make_node( str_cref arg1, str_cref arg2 = "" )
|
||||
{
|
||||
return std::make_shared<zbasic_node>( arg1, arg2, parent );
|
||||
return std::make_shared<zbasic_node>( arg1, arg2 );
|
||||
}
|
||||
|
||||
//! leerer konstruktor
|
||||
@@ -136,7 +140,7 @@ namespace znode
|
||||
zbasic_node(const zbasic_node&) = delete;
|
||||
zbasic_node& operator=(const zbasic_node&) = delete;
|
||||
|
||||
// 'move' geht (shared_from_this bleibt gültig)
|
||||
//! 'move' geht (shared_from_this bleibt gültig)
|
||||
zbasic_node(zbasic_node&&) noexcept = default;
|
||||
zbasic_node& operator=(zbasic_node&&) noexcept = default;
|
||||
|
||||
@@ -178,31 +182,31 @@ namespace znode
|
||||
return _parent.lock();
|
||||
}
|
||||
|
||||
//! gibt den nachfolge-knoten oder 'end()' zurück.
|
||||
zshared_node sibling()
|
||||
{
|
||||
if( !parent() )
|
||||
//return zshared_node( make_node("WTF1") );
|
||||
return zshared_node();
|
||||
|
||||
znode_list& childs = _parent->_children;
|
||||
auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() );
|
||||
if( ++it != childs.end())
|
||||
if( parent() )
|
||||
{
|
||||
znode_list& childs = _parent->_children;
|
||||
auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() );
|
||||
return *(it);
|
||||
|
||||
//return zshared_node( make_node("WTF?") );
|
||||
return zshared_node();
|
||||
}
|
||||
throw std::runtime_error("sibling(): no parent node");
|
||||
}
|
||||
|
||||
//! gibt den vector mit kind-knoten zurück
|
||||
inline const znode_list& children() const
|
||||
{
|
||||
return _children;
|
||||
}
|
||||
|
||||
//! testet, ob kinder vorhanden sind.
|
||||
bool has_children() const
|
||||
{
|
||||
return !children().empty();
|
||||
}
|
||||
|
||||
//! gibt das erste kind zurück
|
||||
zshared_node first_child()
|
||||
{
|
||||
if(!children().empty())
|
||||
@@ -210,6 +214,7 @@ namespace znode
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//! gibt das letzte kind oder nullptr zurück
|
||||
zshared_node last_child()
|
||||
{
|
||||
if(!children().empty())
|
||||
@@ -237,7 +242,6 @@ namespace znode
|
||||
int add_child_at( int idx, const zshared_node& node )
|
||||
{
|
||||
// _fixme! was ist, wenn da schon ein elternknoten ist?
|
||||
|
||||
_children.insert(children().begin() + idx, node );
|
||||
node->_parent = this->shared_from_this();
|
||||
return int(children().size() - 1);
|
||||
@@ -250,10 +254,9 @@ namespace znode
|
||||
parent()->add_child_at( offset, this->shared_from_this() );
|
||||
else
|
||||
throw std::runtime_error("add_me_at(offset): no parent node");
|
||||
|
||||
}
|
||||
|
||||
//! fügt einen shard_ptr von 'mir' in die kinderliste des übergebenen knotens ein
|
||||
//! fügt einen shared_ptr von 'mir' in die kinderliste des übergebenen knotens ein
|
||||
//! und macht diesen zu meinem elternknoten.
|
||||
void add_me_at( int offset, const zshared_node& parent_node )
|
||||
{
|
||||
@@ -266,18 +269,17 @@ namespace znode
|
||||
{
|
||||
throw std::runtime_error("add_me_at(offset,parent): no parent node");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//! findet die eigene position im eltern-knoten
|
||||
int own_pos()
|
||||
{
|
||||
if( parent())
|
||||
return parent()->child_pos( this->shared_from_this() );
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
//int child_pos(zbasic_node* child)
|
||||
//! findet die postion eines kind-knotens
|
||||
int child_pos(const zshared_node& child)
|
||||
{
|
||||
//auto pos = std::find_if(children().begin(), children().end(), match_node(child) );
|
||||
@@ -287,7 +289,7 @@ namespace znode
|
||||
return -1;
|
||||
}
|
||||
|
||||
//zshared_node unlink_child( zbasic_node* node )
|
||||
//! findet die postion eines kind-knotens
|
||||
zshared_node unlink_child( const zshared_node& node )
|
||||
{
|
||||
auto it = std::find(_children.begin(), _children.end(), node);
|
||||
@@ -315,11 +317,10 @@ namespace znode
|
||||
{
|
||||
for( auto child : _children )
|
||||
{
|
||||
qDebug() << " --#- " << child->name() << " : " << child->has_attribute( attrkey, attrvalue );
|
||||
if( child->has_attribute( attrkey, attrvalue ))
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -330,7 +331,7 @@ namespace znode
|
||||
if( child->tag_name() == tagname )
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
zshared_node find_child_by_id( int id )
|
||||
@@ -340,46 +341,7 @@ namespace znode
|
||||
if (child->_id == id)
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dump(int indent = 0) const
|
||||
{
|
||||
|
||||
// fix_me!
|
||||
qDebug() << std::string(indent * 2, ' ').c_str() << this->to_string();
|
||||
//qDebug() << to_string();
|
||||
//qDebug() << '\n';// std::endl;
|
||||
|
||||
if (!children().empty())
|
||||
{
|
||||
for (auto child : _children)
|
||||
{
|
||||
//qDebug() << " --- type: " << typeid(child).name();
|
||||
child.get()->dump( indent + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool for_each_x( T func, int depth = 0 )
|
||||
//bool for_each( auto func ) const
|
||||
{
|
||||
if( !apply( func, depth ) )
|
||||
return false;
|
||||
|
||||
if( !children().empty() )
|
||||
{
|
||||
for( auto child : _children )
|
||||
{
|
||||
if( !child->for_each( func, depth+1 ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// find ...
|
||||
@@ -392,22 +354,6 @@ namespace znode
|
||||
|
||||
};
|
||||
|
||||
|
||||
class zbasic_node_walker
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void begin()
|
||||
{}
|
||||
|
||||
template<typename str_t>
|
||||
void for_each_node( zbasic_node<str_t>* node );
|
||||
|
||||
virtual void end()
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
} //namespace znode
|
||||
|
||||
|
||||
|
@@ -100,7 +100,7 @@ namespace znode
|
||||
//parent->add_child( new_node );
|
||||
|
||||
//zbasic_node<str_t>* new_node = new zbasic_node<str_t>( node.name(), node.child_value(), parent );
|
||||
zshared_node new_node = zbasic_node<str_t>::make_node( xml_node.name(), xml_node.child_value(), parent );
|
||||
zshared_node new_node = zbasic_node<str_t>::make_node( xml_node.name(), xml_node.child_value() );
|
||||
parent->add_child( new_node );
|
||||
|
||||
if( !xml_node.attributes().empty() )
|
||||
|
@@ -4,9 +4,6 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
//#include <znode_stringmap.h>
|
||||
//#include <znode_attributes.h>
|
||||
|
||||
namespace znode
|
||||
{
|
||||
template<typename str_t>
|
||||
|
@@ -73,12 +73,23 @@ public:
|
||||
return _data.end();
|
||||
}
|
||||
|
||||
auto begin() const
|
||||
{
|
||||
return _data.begin();
|
||||
}
|
||||
|
||||
auto end() const
|
||||
{
|
||||
return _data.end();
|
||||
}
|
||||
|
||||
inline int size() const
|
||||
{
|
||||
return (int) _data.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool isEmpty() const
|
||||
{
|
||||
return (_data.size()==0);
|
||||
@@ -94,13 +105,11 @@ public:
|
||||
return mapIndex().contains(key);
|
||||
}
|
||||
|
||||
|
||||
inline const XQMapIndex& mapIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
|
||||
int indexOf( const QString& key ) const
|
||||
{
|
||||
return mapIndex().indexOf(key);
|
||||
@@ -121,7 +130,6 @@ public:
|
||||
return mapIndex().key( index );
|
||||
}
|
||||
|
||||
|
||||
T& operator[]( int index )
|
||||
{
|
||||
if( contains(index) )
|
||||
@@ -129,7 +137,6 @@ public:
|
||||
throw XQException("XQMaptor operator[ int index ]: out of range");
|
||||
}
|
||||
|
||||
|
||||
const T& operator[]( int index ) const
|
||||
{
|
||||
if ( contains(index) )
|
||||
@@ -150,19 +157,17 @@ public:
|
||||
T& operator[]( const QString& key )
|
||||
{
|
||||
if( key.isEmpty() || !contains(key) )
|
||||
throw XQException("maprow operator[]: key empty || not found: " + key);
|
||||
throw XQException("XQMaptor operator[]: key empty || not found: " + key);
|
||||
return _data[ _index[key] ];
|
||||
}
|
||||
|
||||
|
||||
const T& operator[]( const QString& key ) const
|
||||
{
|
||||
if (key.isEmpty() || !contains(key))
|
||||
throw XQException("maprow operator[]: key empty || not found: " + key);
|
||||
throw XQException("XQMaptor operator[]: key empty || not found: " + key);
|
||||
return _data[_index[key]];
|
||||
}
|
||||
|
||||
|
||||
T& at( const QString& key )
|
||||
{
|
||||
return (*this)[key];
|
||||
@@ -173,28 +178,54 @@ public:
|
||||
return (*this)[key];
|
||||
}
|
||||
|
||||
const T& last() const
|
||||
{
|
||||
if(_data.isEmpty())
|
||||
throw XQException( "XQMaptor last: is empty!" );
|
||||
return _data.last();
|
||||
}
|
||||
|
||||
const T& first() const
|
||||
{
|
||||
if(_data.isEmpty())
|
||||
throw XQException( "XQMaptor first: is empty!" );
|
||||
return _data.first();
|
||||
}
|
||||
|
||||
T& last()
|
||||
{
|
||||
if(_data.isEmpty())
|
||||
throw XQException( "XQMaptor last: is empty!" );
|
||||
return _data.last();
|
||||
}
|
||||
|
||||
T& first()
|
||||
{
|
||||
if(_data.isEmpty())
|
||||
throw XQException( "XQMaptor first: is empty!" );
|
||||
return _data.first();
|
||||
}
|
||||
|
||||
|
||||
virtual int add( const T& item )
|
||||
{
|
||||
_data.push_back( item );
|
||||
return _data.size()-1;
|
||||
}
|
||||
|
||||
|
||||
virtual void addAtIndex( int index, const T& item )
|
||||
{
|
||||
if(contains(index))
|
||||
throw XQException( "QStringrow::add: index out of range!" );
|
||||
throw XQException( "XQMaptor add at index: index out of range!" );
|
||||
_data[index] = item;
|
||||
}
|
||||
|
||||
|
||||
// convenience method to mimic QMap<T,QString>
|
||||
virtual void insert( const T& item, const QString& key )
|
||||
{
|
||||
addAtKey(key, item );
|
||||
}
|
||||
|
||||
|
||||
virtual void addAtKey( const QString& key, const T& item )
|
||||
{
|
||||
XQMapIndex::iterator pos = _index.find( key );
|
||||
@@ -209,7 +240,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool addAlias( const QString& key, const QString& alias )
|
||||
{
|
||||
// look for 'original' key
|
||||
@@ -227,20 +257,17 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void addKey( const QString& key, int index )
|
||||
{
|
||||
_index.addKey( key, index );
|
||||
}
|
||||
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
_data.clear();
|
||||
_index.clear();
|
||||
}
|
||||
|
||||
|
||||
virtual bool killEntry( const QString& key )
|
||||
{
|
||||
int idx = indexOf( key );
|
||||
@@ -249,7 +276,6 @@ public:
|
||||
return killEntry( (int) idx );
|
||||
}
|
||||
|
||||
|
||||
virtual bool killEntry( int index )
|
||||
{
|
||||
if( index >= this->_data.size() )
|
||||
@@ -261,19 +287,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual QString toString() const
|
||||
{
|
||||
return join( ";" );
|
||||
}
|
||||
|
||||
|
||||
virtual void dump() const
|
||||
{
|
||||
throw XQException("XQMaptor: dump not implemented!" );
|
||||
}
|
||||
|
||||
|
||||
virtual QString join( const QString& sep, int from=0, int to=-1) const
|
||||
{
|
||||
Q_UNUSED(sep)
|
||||
@@ -283,7 +306,6 @@ public:
|
||||
return "--";
|
||||
}
|
||||
|
||||
|
||||
int replaceKey( const QString& oldkey, const QString& newkey )
|
||||
{
|
||||
int idx = indexOf( oldkey );
|
||||
|
@@ -31,7 +31,7 @@ void XQContextMenu::addAction(const QString& text, XQCommand::CmdType commandTyp
|
||||
QAction* newAction = new QAction(text, this);
|
||||
newAction->setData(commandType);
|
||||
_actionMap[commandType] = newAction;
|
||||
QWidget::addAction(newAction);
|
||||
QMenu::addAction(newAction);
|
||||
setActionEnabled( commandType, enabled );
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void XQContextMenu::addAction(const QIcon& icon, const QString& text, XQCommand:
|
||||
QAction* newAction = new QAction(icon, text, this);
|
||||
newAction->setData(commandType);
|
||||
_actionMap[commandType] = newAction;
|
||||
QWidget::addAction(newAction);
|
||||
QMenu::addAction(newAction);
|
||||
setActionEnabled( commandType, enabled );
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <xqquickwidget.h>
|
||||
|
||||
XQQuickWidget::XQQuickWidget(QWidget *parent)
|
||||
XQQuickWidget::XQQuickWidget(QWidget* parent)
|
||||
: QQuickWidget(parent)
|
||||
{
|
||||
|
||||
|
@@ -23,7 +23,7 @@ class XQQuickWidget : public QQuickWidget
|
||||
|
||||
public:
|
||||
|
||||
XQQuickWidget(QWidget *parent = nullptr);
|
||||
XQQuickWidget(QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // XQQUICKWIDGET_H
|
||||
|
@@ -38,7 +38,7 @@ XQTreeTable::XQTreeTable(QWidget* parent)
|
||||
|
||||
//! gibt die verbundene modelview zurück, cast auf 'model()'
|
||||
|
||||
XQViewModel* XQTreeTable::modelView()
|
||||
XQViewModel* XQTreeTable::viewModel()
|
||||
{
|
||||
return static_cast<XQViewModel*>(model());
|
||||
}
|
||||
@@ -48,7 +48,18 @@ XQViewModel* XQTreeTable::modelView()
|
||||
|
||||
XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index )
|
||||
{
|
||||
return modelView()->xqItemFromIndex( index );
|
||||
return viewModel()->xqItemFromIndex( index );
|
||||
}
|
||||
|
||||
|
||||
//! rows sichtbar/unsichtbar schalten, von 'fstRow' bis _einschliesslich_
|
||||
//! 'lstRow'
|
||||
|
||||
void XQTreeTable::toggleRowsHidden( int fstRow, int lstRow )
|
||||
{
|
||||
bool hidden = isRowHidden( fstRow, rootIndex() );
|
||||
for (int row = fstRow; row <= lstRow; ++row )
|
||||
setRowHidden( row, rootIndex(), !hidden );
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +82,7 @@ void XQTreeTable::currentChanged(const QModelIndex& current, const QModelIndex&
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
//! ändert die breite eines header-feldes anhand der maus-position
|
||||
|
||||
void XQTreeTable::mouseResizeHeaderEntry(int xpos)
|
||||
{
|
||||
@@ -96,7 +107,7 @@ void XQTreeTable::mouseResizeHeaderEntry(int xpos)
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
//! behandelt den mouse-drag zur grössenänderung der header-felder.
|
||||
|
||||
void XQTreeTable::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
@@ -106,10 +117,9 @@ void XQTreeTable::mouseMoveEvent(QMouseEvent* event)
|
||||
bool leftBtn = (event->buttons() & Qt::LeftButton);
|
||||
QPoint eventPos = event->pos();
|
||||
|
||||
// splitcursor ist active
|
||||
// splitcursor ist gesetzt
|
||||
bool splitCursor = (cursor().shape() == Qt::SplitHCursor);
|
||||
|
||||
|
||||
// sind wir schon am 'draggen'?
|
||||
if (_indexToResize.isValid() && splitCursor && leftBtn)
|
||||
{
|
||||
|
@@ -38,9 +38,11 @@ public:
|
||||
XQTreeTable(QWidget* parent = nullptr );
|
||||
virtual ~XQTreeTable() = default;
|
||||
|
||||
XQViewModel* modelView();
|
||||
XQViewModel* viewModel();
|
||||
XQItem& xqItemFromIndex(const QModelIndex& index );
|
||||
|
||||
void toggleRowsHidden(int fstRow, int lstRow );
|
||||
|
||||
protected:
|
||||
|
||||
void currentChanged(const QModelIndex& current, const QModelIndex& previous) override;
|
||||
|
@@ -2,6 +2,7 @@ QT += core gui widgets quick quickwidgets
|
||||
# widgets-private
|
||||
|
||||
CONFIG += c++20 qmltypes
|
||||
CONFIG -= qml_debug
|
||||
|
||||
QML_IMPORT_NAME = org.sourceworx.qmlcomponents
|
||||
QML_IMPORT_MAJOR_VERSION = 1
|
||||
@@ -23,9 +24,9 @@ HEADERS += \
|
||||
items/xqitemtype.h \
|
||||
items/xqitemdelegate.h \
|
||||
model/xqcommand.h \
|
||||
model/xqmodelsectionlist.h \
|
||||
model/xqnode.h \
|
||||
model/xqnodewriter.h \
|
||||
model/xqsectionmanager.h \
|
||||
model/xqselectionmodel.h \
|
||||
model/xqsimpleclipboard.h \
|
||||
model/xqviewmodel.h \
|
||||
@@ -61,9 +62,9 @@ SOURCES += \
|
||||
items/xqitemdelegate.cpp \
|
||||
main.cpp \
|
||||
model/xqcommand.cpp \
|
||||
model/xqmodelsectionlist.cpp \
|
||||
model/xqnode.cpp \
|
||||
model/xqnodewriter.cpp \
|
||||
model/xqsectionmanager.cpp \
|
||||
model/xqselectionmodel.cpp \
|
||||
model/xqsimpleclipboard.cpp \
|
||||
model/xqviewmodel.cpp \
|
||||
|
@@ -1,13 +1,9 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="modeldata1.xtr">../xml/modeldata1.xtr</file>
|
||||
<file alias="modeldata2.xtr">../xml/modeldata2.xtr</file>
|
||||
<file alias="modeldata3.xtr">../xml/modeldata3.xtr</file>
|
||||
<file alias="modelsheet.xml">../xml/modelsheets.xml</file>
|
||||
<file alias="xqtableview.qml">../qml/xqtableview.qml</file>
|
||||
<file alias="HorizontalHeaderViewDelegate.qml">../qml/HorizontalHeaderViewDelegate.qml</file>
|
||||
<file alias="XMain.qml">../qml/XMain.qml</file>
|
||||
<file alias="VerticalHeaderViewDelegate.qml">../qml/VerticalHeaderViewDelegate.qml</file>
|
||||
<file alias="dummyview.qml">../qml/dummyview.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="modeldata1.xtr">../xml/modeldata1.xtr</file>
|
||||
<file alias="modeldata2.xtr">../xml/modeldata2.xtr</file>
|
||||
<file alias="modeldata3.xtr">../xml/modeldata3.xtr</file>
|
||||
<file alias="modelsheet.xml">../xml/modelsheets.xml</file>
|
||||
<file alias="xqtreeview.qml">../qml/xqtreeview.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -7,14 +7,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtree", "xtree.vcxproj", "{
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x86.Build.0 = Release|Win32
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x64.Build.0 = Debug|x64
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x64.ActiveCfg = Release|x64
|
||||
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@@ -5,16 +5,26 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}</ProjectGuid>
|
||||
<Keyword>QtVS_v304</Keyword>
|
||||
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)'=='Release|x64'">10.0</WindowsTargetPlatformVersion>
|
||||
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
@@ -24,6 +34,12 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
@@ -31,13 +47,25 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
|
||||
<Import Project="$(QtMsBuild)\qt_defaults.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'" Label="QtSettings">
|
||||
<QtInstall>qt691</QtInstall>
|
||||
<QtModules>core;gui;widgets</QtModules>
|
||||
<QtInstall>qt692</QtInstall>
|
||||
<QtModules>core;gui;quick;quickcontrols2;quickdialogs2;quicklayouts;widgets;quickwidgets</QtModules>
|
||||
<QtBuildConfig>debug</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="QtSettings">
|
||||
<QtInstall>qt692</QtInstall>
|
||||
<QtModules>core;gui;quick;widgets;quickwidgets</QtModules>
|
||||
<QtBuildConfig>debug</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="QtSettings">
|
||||
@@ -45,6 +73,11 @@
|
||||
<QtModules>core;gui;widgets</QtModules>
|
||||
<QtBuildConfig>release</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="QtSettings">
|
||||
<QtInstall>VS2017x86Default</QtInstall>
|
||||
<QtModules>core;gui;widgets</QtModules>
|
||||
<QtBuildConfig>release</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
|
||||
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
|
||||
</Target>
|
||||
@@ -54,13 +87,22 @@
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
@@ -69,6 +111,12 @@
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>items;model;application;widgets;util;nodes;pugixml;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'" Label="Configuration">
|
||||
<ClCompile>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -81,6 +129,18 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ClCompile>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="Configuration">
|
||||
<ClCompile>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -97,62 +157,70 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ClCompile>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<QtRcc Include="xtree.qrc" />
|
||||
<QtUic Include="application\xqmainwindow.ui" />
|
||||
<ClCompile Include="application\xqappdata.cpp" />
|
||||
<ClCompile Include="application\xqchildmodelview.cpp" />
|
||||
<ClCompile Include="application\xqchildmodel.cpp" />
|
||||
<ClCompile Include="application\xqdocumentstore.cpp" />
|
||||
<ClCompile Include="application\xqmainmodelview.cpp" />
|
||||
<ClCompile Include="application\xqmainmodel.cpp" />
|
||||
<ClCompile Include="application\xqmainwindow.cpp" />
|
||||
<ClCompile Include="items\xqgenericitem.cpp" />
|
||||
<ClCompile Include="items\xqitem.cpp" />
|
||||
<ClCompile Include="items\xqitemdelegate.cpp" />
|
||||
<ClCompile Include="items\xqitemfactory.cpp" />
|
||||
<ClCompile Include="items\xqitemtype.cpp" />
|
||||
<ClCompile Include="model\xqcommand.cpp" />
|
||||
<ClCompile Include="model\xqitemtype.cpp" />
|
||||
<ClCompile Include="model\xqitemtypefactory.cpp" />
|
||||
<ClCompile Include="model\xqnodewriter.cpp" />
|
||||
<ClCompile Include="model\xqsectionmanager.cpp" />
|
||||
<ClCompile Include="model\xqselectionmodel.cpp" />
|
||||
<ClCompile Include="model\xqitem.cpp" />
|
||||
<ClCompile Include="model\xqmodelview.cpp" />
|
||||
<ClCompile Include="model\xqmodelsections.cpp" />
|
||||
<ClCompile Include="model\xqsimpleclipboard.cpp" />
|
||||
<ClCompile Include="model\xqitemfactory.cpp" />
|
||||
<ClCompile Include="model\xqnode.cpp" />
|
||||
<ClCompile Include="model\xqviewmodel.cpp" />
|
||||
<ClCompile Include="nodes\znode.cpp" />
|
||||
<ClCompile Include="pugixml\pugixml.cpp" />
|
||||
<ClCompile Include="util\xqexception.cpp" />
|
||||
<ClCompile Include="widgets\xqitemdelegate.cpp" />
|
||||
<ClCompile Include="widgets\xqcontextmenu.cpp" />
|
||||
<ClCompile Include="widgets\xqtreeview.cpp" />
|
||||
<ClCompile Include="widgets\xqquickwidget.cpp" />
|
||||
<ClCompile Include="widgets\xqtreetable.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="application\xqchildmodelview.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="application\xqmainmodelview.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="application\xqmainwindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="widgets\xqtreetable.h" />
|
||||
<QtMoc Include="widgets\xqquickwidget.h" />
|
||||
<QtMoc Include="application\xqdocumentstore.h" />
|
||||
<ClInclude Include="application\xqappdata.h" />
|
||||
<ClInclude Include="items\xqgenericitem.h" />
|
||||
<QtMoc Include="application\xqchildmodel.h" />
|
||||
<QtMoc Include="application\xqmainmodel.h" />
|
||||
<ClInclude Include="items\xqitem.h" />
|
||||
<ClInclude Include="items\xqitemdelegate.h" />
|
||||
<ClInclude Include="items\xqitemfactory.h" />
|
||||
<ClInclude Include="items\xqitemtype.h" />
|
||||
<ClInclude Include="model\xqcommand.h" />
|
||||
<ClInclude Include="model\xqmodelsections.h" />
|
||||
<ClInclude Include="model\xqnodewriter.h" />
|
||||
<ClInclude Include="model\xqsectionmanager.h" />
|
||||
<ClInclude Include="model\xqsimpleclipboard.h" />
|
||||
<ClInclude Include="model\xqnode.h" />
|
||||
<QtMoc Include="model\xqviewmodel.h" />
|
||||
<ClInclude Include="nodes\znode.h" />
|
||||
<ClInclude Include="nodes\znode_attributes.h" />
|
||||
<ClInclude Include="nodes\znode_factory.h" />
|
||||
<ClInclude Include="nodes\znode_id.h" />
|
||||
<ClInclude Include="nodes\znode_iterator.h" />
|
||||
@@ -166,10 +234,7 @@
|
||||
<ClInclude Include="util\xqptrmaptor.h" />
|
||||
<ClInclude Include="util\xsingleton.h" />
|
||||
<ClInclude Include="util\xtreewalker.h" />
|
||||
<QtMoc Include="widgets\xqtreeview.h" />
|
||||
<QtMoc Include="widgets\xqcontextmenu.h" />
|
||||
<QtMoc Include="widgets\xqitemdelegate.h" />
|
||||
<QtMoc Include="model\xqmodelview.h" />
|
||||
<QtMoc Include="model\xqselectionmodel.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@@ -76,42 +76,21 @@
|
||||
<ClCompile Include="model\xqcommand.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqitem.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqmodelview.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqnode.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqmainmodelview.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqmainwindow.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="nodes\znode.cpp">
|
||||
<Filter>Source Files\nodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgets\xqitemdelegate.cpp">
|
||||
<Filter>Source Files\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgets\xqtreeview.cpp">
|
||||
<Filter>Source Files\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pugixml\pugixml.cpp">
|
||||
<Filter>Source Files\pugixml</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqmodelsections.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqselectionmodel.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqchildmodelview.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqsimpleclipboard.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
@@ -127,21 +106,9 @@
|
||||
<ClCompile Include="model\xqnodewriter.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqitemfactory.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqappdata.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqitemtypefactory.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqitemtype.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="items\xqgenericitem.cpp">
|
||||
<Filter>Source Files\Items</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="items\xqitem.cpp">
|
||||
<Filter>Source Files\Items</Filter>
|
||||
</ClCompile>
|
||||
@@ -154,6 +121,24 @@
|
||||
<ClCompile Include="items\xqitemtype.cpp">
|
||||
<Filter>Source Files\Items</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqsectionmanager.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="model\xqviewmodel.cpp">
|
||||
<Filter>Source Files\model</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgets\xqquickwidget.cpp">
|
||||
<Filter>Source Files\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgets\xqtreetable.cpp">
|
||||
<Filter>Source Files\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqchildmodel.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application\xqmainmodel.cpp">
|
||||
<Filter>Source Files\application</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="model\xqcommand.h">
|
||||
@@ -183,9 +168,6 @@
|
||||
<ClInclude Include="pugixml\pugixml.hpp">
|
||||
<Filter>Header Files\pugixml</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="model\xqmodelsections.h">
|
||||
<Filter>Header Files\model</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\xqmapindex.h">
|
||||
<Filter>Header Files\util</Filter>
|
||||
</ClInclude>
|
||||
@@ -216,12 +198,6 @@
|
||||
<ClInclude Include="nodes\znode_payload.h">
|
||||
<Filter>Header Files\nodes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nodes\znode_attributes.h">
|
||||
<Filter>Header Files\nodes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="items\xqgenericitem.h">
|
||||
<Filter>Header Files\items</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="items\xqitem.h">
|
||||
<Filter>Header Files\items</Filter>
|
||||
</ClInclude>
|
||||
@@ -234,33 +210,36 @@
|
||||
<ClInclude Include="items\xqitemtype.h">
|
||||
<Filter>Header Files\items</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="model\xqsectionmanager.h">
|
||||
<Filter>Header Files\model</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="model\xqmodelview.h">
|
||||
<Filter>Header Files\model</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqmainmodelview.h">
|
||||
<Filter>Header Files\application</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqmainwindow.h">
|
||||
<Filter>Header Files\application</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="widgets\xqitemdelegate.h">
|
||||
<Filter>Header Files\widgets</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="widgets\xqtreeview.h">
|
||||
<Filter>Header Files\widgets</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="widgets\xqcontextmenu.h">
|
||||
<Filter>Header Files\widgets</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="model\xqselectionmodel.h">
|
||||
<Filter>Header Files\model</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqchildmodelview.h">
|
||||
<QtMoc Include="application\xqdocumentstore.h">
|
||||
<Filter>Header Files\application</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqdocumentstore.h">
|
||||
<QtMoc Include="model\xqviewmodel.h">
|
||||
<Filter>Header Files\model</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="widgets\xqquickwidget.h">
|
||||
<Filter>Header Files\widgets</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="widgets\xqtreetable.h">
|
||||
<Filter>Header Files\widgets</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqchildmodel.h">
|
||||
<Filter>Header Files\application</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="application\xqmainmodel.h">
|
||||
<Filter>Header Files\application</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
|
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<QtTouchProperty>
|
||||
</QtTouchProperty>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<QtTouchProperty>
|
||||
</QtTouchProperty>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@@ -10,21 +10,20 @@
|
||||
<Panel PanelID="#4 JA 04" FriendlyName="@PanelName" PanelName="JA 04 Solar X58C" Manufacturer="JA Solar 4" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
|
||||
<Panel PanelID="#5 JA 05" FriendlyName="@PanelName" PanelName="JA 05 Solar X58C" Manufacturer="JA Solar 5" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
|
||||
<Panel PanelID="#6 JA 06" FriendlyName="@PanelName" PanelName="JA 06 Solar X58C" Manufacturer="JA Solar 6" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
|
||||
<Inverter InverterID="#1 HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter InverterID="#2 HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
|
||||
<Inverter InverterID="#3 HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="6000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
|
||||
<Inverter InverterID="#4 D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="12000,33" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter InverterID="#1 HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="3000,00" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter InverterID="#2 HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="4000;6000;8000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
|
||||
<Inverter InverterID="#3 HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="9000,00" MaxPowerInputChoice="6000;8000;10000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
|
||||
<Inverter InverterID="#4 D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="8000" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Battery BatteryID="#1 BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="90" MaxCurrent="120" MaxVolt="48">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
<Images FrontView="image.png" PackageView="package.png" InstalledView="installed.png"/>
|
||||
<Documents Manual="manual.docx" Certificate="certificate.pdf"/>
|
||||
</Battery>
|
||||
<Battery BatteryID="#2 BYD 02" FriendlyName="@BatteryName" BatteryName="02 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#3 BYD 03" FriendlyName="@BatteryName" BatteryName="03 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="86" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#4 BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="98" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#4 BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="91" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#5 GroWatt 05 G2K" FriendlyName="@BatteryName" BatteryName="05 BYD T01 Stackable" Manufacturer="GroWatt" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#6 GroWatt 06 G4K" FriendlyName="@BatteryName" BatteryName="06 BYD T02 Stackable" Manufacturer="GroWatt" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#7 Pyne 07 G4K" FriendlyName="@BatteryName" BatteryName="07 Pyne K7 Stackable" Manufacturer="PyNe" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>
|
||||
<Battery BatteryID="#7 Pyne 07 G4K" FriendlyName="@BatteryName" BatteryName="07 Pyne K7 Stackable" Manufacturer="PyNe" Capacity="9000" Yield="68" MaxCurrent="120" MaxVolt="48"/>
|
||||
|
||||
</Components>
|
||||
<IrgendWasAnderes>
|
||||
|
@@ -4,9 +4,9 @@
|
||||
<Project ProjectID="HA02" FriendlyName="@ProjectName" ProjectName="Gerbrunn Ost" Established="2006" WattPeak="9840" ContentType="planned">
|
||||
<Components>
|
||||
<Panel PanelID="Jingli 01" FriendlyName="@PanelName" PanelName="Jingli 01 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">
|
||||
<AdditionalData DataItem="Image" DataValue="image,png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual,docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate,pdf"/>
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</Panel>
|
||||
<Panel PanelID="Jingli 02" FriendlyName="@PanelName" PanelName="Jingli 02 Solar X58C" Manufacturer="Jingli Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
|
||||
<Panel PanelID="Jingli 03" FriendlyName="@PanelName" PanelName="Jingli 03 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<Project ProjectID="HA03" FriendlyName="@ProjectName" ProjectName="Neubrunn Süd" Established="2006" WattPeak="9840" ContentType="runnning">
|
||||
<Project ProjectID="HA03" FriendlyName="@ProjectName" ProjectName="Tauberbischoffsheim SÜD" Established="2006" WattPeak="9840" ContentType="runnning">
|
||||
<Components>
|
||||
<Panel PanelID="AIKO 01" FriendlyName="@PanelName" PanelName="AIKO 01 Solar T62B" Manufacturer="AIKO Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
|
@@ -6,28 +6,29 @@
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<ItemTypes>
|
||||
<TreeParentType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
|
||||
<TreeSectionType RenderStyle="PlainStyle" ItemFlags="IsEnabled" Icon="DesktopIcon"/>
|
||||
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsUserCheckable|IsEnabled" Icon="MediaPlay"/>
|
||||
<HeaderType RenderStyle="HeaderStyle" ItemFlags="IsEnabled"/>
|
||||
<TreeParentType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
|
||||
<TreeChildType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled" Icon="MediaPlay"/>
|
||||
<TreeSectionType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsUserCheckable|IsEnabled" Icon="DesktopIcon"/>
|
||||
<HeaderType RenderStyle="HeaderStyle" EditorType="LineEditType" ItemFlags="IsEnabled"/>
|
||||
<HiddenType RenderStyle="HiddenStyle"/>
|
||||
<StaticType RenderStyle="PlainStyle"/>
|
||||
<PlainType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
|
||||
<ValueType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/>
|
||||
<CheckableType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="###"/>
|
||||
<PercentageType RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
<ChoiceType RenderStyle="ComboBoxStyle" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
|
||||
<IntValueType RenderStyle="SpinBoxStyle" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
<PlainType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
|
||||
<ValueType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/>
|
||||
<CheckableType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" />
|
||||
<PercentageType RenderStyle="ColorBarStyle" EditorType="ColorBarType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="%"/>
|
||||
<ChoiceType RenderStyle="ComboBoxStyle" EditorType="ComboBoxType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="W" FixedChoices="2000|4000|6000|8000" />
|
||||
<IntValueType RenderStyle="SpinBoxStyle" EditorType="SpinBoxType" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
|
||||
</ItemTypes>
|
||||
|
||||
|
||||
<DocumentTreeModel>
|
||||
<Section ContentType="runnning">
|
||||
<Header>
|
||||
<Entry Caption="Active Projects" ItemType="TreeParentType"/>
|
||||
</Header>
|
||||
<ModelSheet firz="running">
|
||||
<ModelSheet>
|
||||
<Project Caption="@ProjectName" ItemType="TreeChildType">
|
||||
<CurrentSection ItemType="TreeSectionType"/>
|
||||
</Project>
|
||||
@@ -37,7 +38,7 @@
|
||||
<Header>
|
||||
<Entry Caption="Planned Projects" ItemType="TreeParentType"/>
|
||||
</Header>
|
||||
<ModelSheet firz="planned">
|
||||
<ModelSheet>
|
||||
<Project Caption="@ProjectName" ItemType="TreeChildType">
|
||||
<CurrentSection ItemType="TreeSectionType"/>
|
||||
</Project>
|
||||
@@ -47,7 +48,7 @@
|
||||
<Header>
|
||||
<Entry Caption="Finished Projects" ItemType="TreeParentType"/>
|
||||
</Header>
|
||||
<ModelSheet firz="finished">
|
||||
<ModelSheet>
|
||||
<Project Caption="@ProjectName" ItemType="TreeChildType">
|
||||
<CurrentSection ItemType="TreeSectionType"/>
|
||||
</Project>
|
||||
@@ -75,10 +76,10 @@
|
||||
<!-- 'Icon' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
|
||||
<PanelID ItemType="PlainType" Icon="DesktopIcon"/>
|
||||
<PanelName ItemType="PlainType" Icon="BrowserStop"/>
|
||||
<Manufacturer ItemType="ValueType"/>
|
||||
<Manufacturer ItemType="PlainType"/>
|
||||
<!-- 'UnitType' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
|
||||
<WattPeak ItemType="ValueType" UnitType="Wp"/>
|
||||
<Width ItemType="CheckableType" Icon="VistaShield" UnitType="m"/>
|
||||
<Width ItemType="ValueType" Icon="VistaShield" UnitType="m"/>
|
||||
<Height ItemType="ValueType" UnitType="m"/>
|
||||
<Weight ItemType="ValueType" UnitType="kg"/>
|
||||
<MaxVolt ItemType="ValueType" UnitType="V"/>
|
||||
@@ -86,8 +87,7 @@
|
||||
</ModelSheet>
|
||||
</Section>
|
||||
|
||||
|
||||
<Section ContentType="Inverter" >
|
||||
<Section ContentType="Inverter" >
|
||||
<Header >
|
||||
<InverterID Caption="Inverter" ItemType="HeaderType" />
|
||||
<InverterName Caption="Name" ItemType="HeaderType" />
|
||||
@@ -98,20 +98,20 @@
|
||||
<Weight Caption="Weight" ItemType="HeaderType" />
|
||||
</Header>
|
||||
<ModelSheet>
|
||||
<InverterID Caption="Inverter" ItemType="ValueType" />
|
||||
<InverterName Caption="Name" ItemType="ValueType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="ValueType" />
|
||||
<MaxPowerInput Caption="max. Input" ItemType="ValueType" ItemType="ChoiceType" ChoiceModelSheetSource="MaxPowerInputChoice" UnitType="W"/>
|
||||
<MaxPowerOutput Caption="max Output" ItemType="ValueType" UnitType="W"/>
|
||||
<NumStrings Caption="Strings" ItemType="ValueType" />
|
||||
<Weight Caption="Weight" ItemType="ValueType" UnitType="kg"/>
|
||||
<InverterID ItemType="PlainType" />
|
||||
<InverterName ItemType="PlainType" />
|
||||
<Manufacturer ItemType="PlainType" />
|
||||
<MaxPowerInput ItemType="ChoiceType" FixedChoices="2000|4000|6000|8000" UnitType="W"/>
|
||||
<MaxPowerOutput ItemType="ValueType" UnitType="W"/>
|
||||
<NumStrings ItemType="IntValueType" />
|
||||
<Weight ItemType="ValueType" UnitType="kg"/>
|
||||
</ModelSheet>
|
||||
</Section>
|
||||
|
||||
<Section ContentType="Battery" >
|
||||
<Header>
|
||||
<BatteryID Caption="Name" ItemType="HeaderType" />
|
||||
<BatteryName Caption="Battery" ItemType="HeaderType" />
|
||||
<BatteryID Caption="Battery" ItemType="HeaderType" />
|
||||
<BatteryName Caption="Name" ItemType="HeaderType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="HeaderType" />
|
||||
<Capacity Caption="Capacity" ItemType="HeaderType"/>
|
||||
<Yield Caption="Yield" ItemType="HeaderType" />
|
||||
@@ -119,14 +119,24 @@
|
||||
<MaxVolt Caption="max. Volt" ItemType="HeaderType" />
|
||||
</Header>
|
||||
<ModelSheet>
|
||||
<BatteryID Caption="Battery" ItemType="ValueType" />
|
||||
<BatteryName Caption="Name" ItemType="ValueType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="ValueType" />
|
||||
<Capacity Caption="Capacity" ItemType="ValueType" UnitType="Wh"/>
|
||||
<Yield Caption="Yield" ItemType="ValueType" ItemType="PercentageType" UnitType="%"/>
|
||||
<MaxCurrent Caption="max. Current" ItemType="ValueType" UnitType="A"/>
|
||||
<MaxVolt Caption="max. Volt" ItemType="ValueType" UnitType="V"/>
|
||||
<BatteryID ItemType="PlainType" />
|
||||
<BatteryName ItemType="PlainType" />
|
||||
<Manufacturer ItemType="PlainType" />
|
||||
<Capacity ItemType="ValueType" UnitType="Wh"/>
|
||||
<Yield ItemType="PercentageType" UnitType="%"/>
|
||||
<MaxCurrent ItemType="ValueType" UnitType="A">
|
||||
<SubType ItemType="PlainType"/>
|
||||
</MaxCurrent>
|
||||
<MaxVolt ItemType="ValueType" UnitType="V"/>
|
||||
|
||||
<firz ItemType="PlainType"/>
|
||||
|
||||
<Image DataValue="image.png" ItemType="PlainType"/>
|
||||
<Manual DataValue="manual.docx" ItemType="PlainType"/>
|
||||
<Certificate DataValue="certificate.pdf" ItemType="PlainType"/>
|
||||
|
||||
|
||||
</ModelSheet>
|
||||
</Section>
|
||||
|
||||
</DocumentDetailsModel>
|
||||
</DocumentDetailsModel>
|
||||
|
@@ -1,27 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project Established="2006" FriendlyName="@ProjectName" ProjectID="HA01" ProjectName="Wiebelbach West" State="runnning" WattPeak="84000">
|
||||
<Components>
|
||||
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 1 XX" MaxAmpere="11" MaxVolt="67" PanelID="#1 JA 01" PanelName="JA 01 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 2" MaxAmpere="11" MaxVolt="42" PanelID="#2 JA 02" PanelName="JA 02 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 3" MaxAmpere="11" MaxVolt="67" PanelID="#3 JA 03" PanelName="JA 03 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 4" MaxAmpere="11" MaxVolt="42" PanelID="#4 JA 04" PanelName="JA 04 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 5" MaxAmpere="11" MaxVolt="42" PanelID="#5 JA 05" PanelName="JA 05 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 6" MaxAmpere="11" MaxVolt="42" PanelID="#6 JA 06" PanelName="JA 06 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#1 HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#2 HM800 02" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#3 HM1600 03" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="6000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#4 D12K 04" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="12000,33" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Battery BatteryID="#1 BYD 01" BatteryName="01 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="90">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</Battery>
|
||||
<Battery BatteryID="#2 BYD 02" BatteryName="02 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="94"/>
|
||||
<Battery BatteryID="#3 BYD 03" BatteryName="03 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="86"/>
|
||||
<Battery BatteryID="#4 BYD 04" BatteryName="04 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="98"/>
|
||||
<Battery BatteryID="#5 GroWatt 05 G2K" BatteryName="05 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="94"/>
|
||||
<Battery BatteryID="#6 GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
<Battery BatteryID="#7 Pyne 07 G4K" BatteryName="07 Pyne K7 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PyNe" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
</Components>
|
||||
<IrgendWasAnderes/>
|
||||
</Project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Components>
|
||||
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="Jingli Solar" MaxAmpere="11" MaxVolt="67" PanelID="Jingli 01" PanelName="Jingli 01 Solar T62B" WattPeak="620" Weight="12" Width="1,10">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</Panel>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="Jingli Solar" MaxAmpere="11" MaxVolt="42" PanelID="Jingli 02" PanelName="Jingli 02 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="Jingli Solar" MaxAmpere="11" MaxVolt="67" PanelID="Jingli 03" PanelName="Jingli 03 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="HM800 02" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="HM1600 03" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="D12K 04" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Battery BatteryID="BYD 01" BatteryName="FIRZ!" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="88">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</Battery>
|
||||
<Battery BatteryID="BYD 04" BatteryName="04 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="32"/>
|
||||
<Battery BatteryID="GroWatt 05 G2K" BatteryName="05 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="PylonTech" MaxCurrent="120" MaxVolt="48" Yield="46"/>
|
||||
<Battery BatteryID="GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PylonTech" MaxCurrent="120" MaxVolt="48" Yield="94"/>
|
||||
</Components>
|
||||
|