diff --git a/README.md b/README.md index f6e99d6..ed5dad2 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,76 @@ # BareCode -**BareCode – Schlanker Code-Editor für Web-Entwickler** -Version 1.1.0 +**Schlanker, modularer Code-Editor für Web-Entwickler** +Version 1.1.0 — von **Dany Thinnes** | [Projekt Hirnfrei](https://www.projekt-hirnfrei.de) | [Discord](https://discord.projekt-hirnfrei.de) -Kompiliert sauber auf **Linux**, **Windows** und **Haiku**. +Entwickelt mit **C++17**, **Qt6** und **CMake**. +Kompiliert auf **Linux**, **Windows** und **Haiku**. + +--- + +## Installation + +### Arch Linux / Manjaro (AUR) + +```bash +# Mit yay +yay -S barecode + +# Mit paru +paru -S barecode + +# Immer aktuellster Git-Stand +yay -S barecode-git +``` + +### Aus dem Quellcode bauen + +Siehe Abschnitt **Bauen** weiter unten. --- ## Features +### Editor | Feature | Details | |---|---| -| Projektbaum | Linkes Panel — zeigt nur das gewählte Projektverzeichnis | +| Syntax-Highlighting | HTML, PHP, CSS, C/C++ — inkl. mehrzeiliger Kommentare | | Tabs | Mehrere Dateien gleichzeitig, verschiebbar und schließbar | | Änderungsindikator | ● im Tab-Titel bei ungespeicherten Änderungen | -| Syntax-Highlighting | HTML, PHP, CSS, C/C++ inkl. mehrzeiliger Kommentare | | Zeilennummern | Eigener Gutter, aktuelle Zeile hervorgehoben | | Einrück-Führungslinien | Vertikale Linien wie in VS Code | | Auto-Indent | Einrückungstiefe wird bei Enter übernommen | | Tab / Shift+Tab | Ein- und Ausrücken, auch für mehrere Zeilen gleichzeitig | | Smart Backspace | Springt zur vorherigen Tab-Stop-Position | +| Farbvorschau | CSS-Farbwerte (#hex, rgb, hsl) werden inline angezeigt | +| Farbauswahl | Klick auf das Farbquadrat öffnet einen Farbauswahl-Dialog | +| Funktionssignatur | Tooltip mit Parametern beim Tippen von PHP-Funktionen | + +### Navigation +| Feature | Details | +|---|---| +| Projektbaum | Linkes Panel — zeigt nur das gewählte Projektverzeichnis | +| Neue Datei / Ordner | Rechtsklick im Dateibaum | +| Doppelklick-Navigation | Doppelklick auf einen Funktionsnamen springt zur Definition | +| Suchen & Ersetzen | Einzeln, Alle, In Auswahl, Regex, Live-Hervorhebung (Strg+F) | +| In Dateien suchen | Rekursive Projektsuche mit Ergebnisliste (Strg+Shift+F) | + +### Projektanalyse +| Feature | Details | +|---|---| +| Projektfunktionen | Alle definierten Funktionen als durchsuchbare Liste (Strg+Shift+P) | +| Tote Funktionen | Analyse ungenutzter Funktionen mit Exclude-Verzeichnissen (Strg+Shift+T) | +| Export | Analyseergebnisse als TXT exportieren | + +### Allgemein +| Feature | Details | +|---|---| | Speichern | Speichern, Speichern unter, Alles speichern | -| Suchen & Ersetzen | Einzeln, Alle, In Auswahl, Regex, Live-Hervorhebung | -| In Dateien suchen | Rekursive Projektsuche mit Ergebnisliste, direkt zur Zeile | -| Dark / Light Mode | Umschaltbar, wird gespeichert | +| Dark / Light Mode | Umschaltbar (Strg+Shift+D), wird gespeichert | | Session | Geöffnete Dateien und aktiver Tab werden wiederhergestellt | --- -## Projektstruktur - -``` -BareCode/ -├── CMakeLists.txt -├── main.cpp -├── resources/ -│ ├── resources.qrc -│ └── icon_*.png -└── src/ - ├── core/ # MainWindow, ProjectManager, Settings, ThemeManager, IPlugin - ├── editor/ # EditorPanel, EditorTab, CodeEditor, SearchPanel, FileSearchPanel - ├── filetree/ # FileTreePanel - └── highlighter/ # SyntaxHighlighter, HighlighterFactory -``` - -Jedes Unterverzeichnis kompiliert als eigene statische Bibliothek. - ---- - -## Abhängigkeiten & Bauen - -### Linux - -**Abhängigkeiten (Beispiel Ubuntu/Debian):** -```bash -sudo apt install cmake qt6-base-dev qt6-base-dev-tools libqt6concurrent6 -``` - -**Abhängigkeiten (Arch/Manjaro):** -```bash -sudo pacman -S cmake qt6-base -``` - -**Bauen:** -```bash -cmake -B build -DCMAKE_BUILD_TYPE=Release -cmake --build build -j$(nproc) -./build/BareCode -``` - -**Installieren:** -```bash -sudo cmake --install build -``` - ---- - -### Windows (Visual Studio) - -**Abhängigkeiten:** -- [Qt6](https://www.qt.io/download) (Komponenten: Qt6 Base, Qt6 Concurrent) -- CMake ≥ 3.16 -- Visual Studio 2019 oder neuer - -```bat -cmake -B build -G "Visual Studio 17 2022" -A x64 -cmake --build build --config Release -build\Release\BareCode.exe -``` - -**Windows Installer erstellen** (mit [Inno Setup](https://jrsoftware.org/isinfo.php)): -```bat -windeployqt --release build\Release\BareCode.exe -``` -Danach das Inno Setup Skript ausführen. - ---- - -### Haiku - -**Abhängigkeiten:** -```bash -pkgman install qt6_base qt6_base_devel -``` - -> **Hinweis:** `qt6_base_devel` enthält auf Haiku sowohl die Header als auch -> die Build-Tools (`moc`, `rcc`, `qmake`). Getestet auf Haiku R1/beta5. - -**Bauen:** -```bash -cmake -B build -DCMAKE_BUILD_TYPE=Release -cmake --build build -j$(nproc) -./build/BareCode -``` - -**Installieren:** -```bash -cmake --install build -``` - -> Nach der Installation wird `mimeset` automatisch aufgerufen um den -> MIME-Typ zu registrieren, damit BareCode im Haiku Tracker korrekt -> als Anwendung erkannt wird. - ---- - ## Tastaturkürzel | Aktion | Kürzel | @@ -137,13 +83,105 @@ cmake --install build | Alles speichern | Strg+Shift+S | | Suchen / Ersetzen | Strg+F | | In Dateien suchen | Strg+Shift+F | +| Projektfunktionen | Strg+Shift+P | +| Tote Funktionen | Strg+Shift+T | | Dark Mode | Strg+Shift+D | --- -## Erweitern +## Projektstruktur -### Neuen Highlighter hinzufügen +``` +BareCode/ +├── CMakeLists.txt +├── main.cpp +├── LICENSE +├── PKGBUILD # Stabiles AUR-Paket +├── PKGBUILD-git # AUR-Paket (Git-Stand) +├── BareCode.desktop # Linux-Anwendungsmenü +├── resources/ +│ ├── resources.qrc +│ ├── icon_*.png +│ └── php_functions.json +└── src/ + ├── core/ # MainWindow, ProjectManager, Settings, + │ # ThemeManager, AboutDialog, IPlugin + ├── editor/ # EditorPanel, EditorTab, CodeEditor, + │ # SearchPanel, FileSearchPanel, + │ # ColorIndicator, SignatureHelper, + │ # FunctionScanner, FunctionIndex, + │ # FunctionListPanel, FunctionListDialog, + │ # DeadCodeAnalyzer, DeadCodeDialog + ├── filetree/ # FileTreePanel + └── highlighter/ # SyntaxHighlighter, HighlighterFactory +``` + +Jedes Unterverzeichnis kompiliert als eigene statische Bibliothek — Komponenten lassen sich unabhängig austauschen und erweitern. + +--- + +## Abhängigkeiten & Bauen + +### Linux + +**Ubuntu / Debian:** +```bash +sudo apt install cmake ninja-build qt6-base-dev qt6-base-dev-tools +``` + +**Arch / Manjaro:** +```bash +sudo pacman -S cmake ninja qt6-base +``` + +**Bauen:** +```bash +cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release +cmake --build build +./build/BareCode +``` + +**Installieren:** +```bash +sudo cmake --install build +``` + +--- + +### Windows + +**Abhängigkeiten:** +- [Qt6](https://www.qt.io/download) — Komponenten: Qt6 Base, Qt6 Concurrent +- CMake ≥ 3.16 +- Visual Studio 2019 oder neuer + +```bat +cmake -B build -G "Visual Studio 17 2022" -A x64 +cmake --build build --config Release +``` + +**Installer erstellen** (mit [Inno Setup](https://jrsoftware.org/isinfo.php)): +```bat +windeployqt --release build\Release\BareCode.exe +``` + +--- + +### Haiku + +```bash +pkgman install qt6_base qt6_base_devel +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j$(nproc) +./build/BareCode +``` + +> Getestet auf Haiku R1/beta5. `qt6_base_devel` enthält auf Haiku +> sowohl die Header als auch die Build-Tools. + +--- + +## Neue Sprache hinzufügen 1. Subklasse von `SyntaxHighlighter` in `src/highlighter/` erstellen 2. `m_rules` im Konstruktor befüllen (siehe `CppHighlighter` als Vorlage) @@ -151,17 +189,11 @@ cmake --install build Keine weiteren Dateien müssen geändert werden. -### Neues Panel / Plugin hinzufügen - -1. `IPlugin`-Interface aus `src/core/IPlugin.h` implementieren -2. `QWidget`-Subklasse für die UI erstellen -3. In `MainWindow` instanziieren und verdrahten - --- -## Code-Stil +## Lizenz -Allman-Klammerstil, C++17 durchgehend. +MIT License — Copyright (c) 2025 Dany Thinnes / Projekt Hirnfrei --- @@ -169,3 +201,5 @@ Allman-Klammerstil, C++17 durchgehend. - Website: [www.projekt-hirnfrei.de](https://www.projekt-hirnfrei.de) - Discord: [discord.projekt-hirnfrei.de](https://discord.projekt-hirnfrei.de) +- Quellcode: [git.projekt-hirnfrei.de/diabolus/BareCode](https://git.projekt-hirnfrei.de/diabolus/BareCode) +- AUR: [aur.archlinux.org/packages/barecode](https://aur.archlinux.org/packages/barecode) diff --git a/barecode-1.1.0.tar.gz b/barecode-1.1.0.tar.gz new file mode 100644 index 0000000..25212fe Binary files /dev/null and b/barecode-1.1.0.tar.gz differ diff --git a/src/barecode-1.1.0.tar.gz b/src/barecode-1.1.0.tar.gz new file mode 120000 index 0000000..5db912c --- /dev/null +++ b/src/barecode-1.1.0.tar.gz @@ -0,0 +1 @@ +/home/diabolus/Arbeit/Projekt-Hirnfrei/BareCode/barecode-1.1.0.tar.gz \ No newline at end of file diff --git a/src/barecode/.gitignore b/src/barecode/.gitignore new file mode 100644 index 0000000..20292e4 --- /dev/null +++ b/src/barecode/.gitignore @@ -0,0 +1,2 @@ +{src/ +build/ diff --git a/src/barecode/BareCode.desktop b/src/barecode/BareCode.desktop new file mode 100644 index 0000000..ade1b56 --- /dev/null +++ b/src/barecode/BareCode.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=BareCode +GenericName=Code Editor +Comment=Modularer Code-Editor für HTML, PHP, CSS und mehr +Exec=BareCode %F +Icon=barecode +Terminal=false +Categories=Development;TextEditor; +MimeType=text/plain;text/html;text/css;text/x-php;text/x-csrc;text/x-chdr;text/x-c++src;text/x-c++hdr; +Keywords=editor;code;html;php;css;c++; +StartupWMClass=BareCode diff --git a/src/barecode/BareCode.rc b/src/barecode/BareCode.rc new file mode 100644 index 0000000..8650ce3 --- /dev/null +++ b/src/barecode/BareCode.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON "resources/BareCode.ico" diff --git a/src/barecode/BareCodeAUR/PKGBUILD b/src/barecode/BareCodeAUR/PKGBUILD new file mode 100644 index 0000000..7e6cfef --- /dev/null +++ b/src/barecode/BareCodeAUR/PKGBUILD @@ -0,0 +1,47 @@ +# Maintainer: Dany Thinnes + +pkgname=barecode-git +pkgver=r5.cb66172 +pkgrel=1 +pkgdesc="Modularer Code-Editor, entwickelt von Projekt Hirnfrei (git)" +arch=('x86_64' 'aarch64') +url="https://git.projekt-hirnfrei.de/diabolus/BareCode" +license=('MIT') +depends=('qt6-base') +makedepends=('cmake' 'ninja' 'git') +provides=('barecode') +conflicts=('barecode') + +source=("$pkgname::git+$url.git") +sha256sums=('SKIP') + +pkgver() +{ + cd "$pkgname" + printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" +} + +build() +{ + cmake \ + -B build \ + -S "$pkgname" \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr + cmake --build build +} + +package() +{ + DESTDIR="$pkgdir" cmake --install build + + install -Dm644 "$pkgname/barecode.desktop" \ + "$pkgdir/usr/share/applications/barecode.desktop" + + # install -Dm644 "$pkgname/resources/barecode.png" \ + # "$pkgdir/usr/share/pixmaps/barecode.png" + + install -Dm644 "$pkgname/LICENSE" \ + "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/src/barecode/BareCodeAUR/PKGBUILD-git b/src/barecode/BareCodeAUR/PKGBUILD-git new file mode 100644 index 0000000..2c88cc8 --- /dev/null +++ b/src/barecode/BareCodeAUR/PKGBUILD-git @@ -0,0 +1,47 @@ +# Maintainer: Dany Thinnes + +pkgname=barecode-git +pkgver=r1.0.0 +pkgrel=1 +pkgdesc="Modularer Code-Editor, entwickelt von Projekt Hirnfrei (git)" +arch=('x86_64' 'aarch64') +url="https://git.projekt-hirnfrei.de/diabolus/BareCode" +license=('MIT') +depends=('qt6-base') +makedepends=('cmake' 'ninja' 'git') +provides=('barecode') +conflicts=('barecode') + +source=("$pkgname::git+$url.git") +sha256sums=('SKIP') + +pkgver() +{ + cd "$pkgname" + printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" +} + +build() +{ + cmake \ + -B build \ + -S "$pkgname" \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr + cmake --build build +} + +package() +{ + DESTDIR="$pkgdir" cmake --install build + + install -Dm644 "$pkgname/barecode.desktop" \ + "$pkgdir/usr/share/applications/barecode.desktop" + + # install -Dm644 "$pkgname/resources/barecode.png" \ + # "$pkgdir/usr/share/pixmaps/barecode.png" + + install -Dm644 "$pkgname/LICENSE" \ + "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/src/barecode/BareCodeAUR/PKGBUILD-stable b/src/barecode/BareCodeAUR/PKGBUILD-stable new file mode 100644 index 0000000..ce3f7af --- /dev/null +++ b/src/barecode/BareCodeAUR/PKGBUILD-stable @@ -0,0 +1,41 @@ +# Maintainer: Dany Thinnes + +pkgname=barecode +pkgver=1.0.0 +pkgrel=1 +pkgdesc="Modularer Code-Editor, entwickelt von Projekt Hirnfrei" +arch=('x86_64' 'aarch64') +url="https://git.projekt-hirnfrei.de/diabolus/BareCode" +license=('MIT') +depends=('qt6-base') +makedepends=('cmake' 'ninja' 'git') + +# Gitea erzeugt automatisch Tarballs unter: +# https://DEIN-GITEA-SERVER/DEINNAME/BareCode/archive/v1.0.0.tar.gz +# +# sha256sum nach dem Taggen ermitteln: +# curl -L https://DEIN-GITEA-SERVER/DEINNAME/BareCode/archive/v1.0.0.tar.gz | sha256sum +source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz") +sha256sums=('SKIP') # Ersetzen nach erstem Tag + +build() +{ + cmake \ + -B build \ + -S "BareCode-$pkgver" \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr + cmake --build build +} + +package() +{ + DESTDIR="$pkgdir" cmake --install build + + install -Dm644 "BareCode-$pkgver/barecode.desktop" \ + "$pkgdir/usr/share/applications/barecode.desktop" + + install -Dm644 "BareCode-$pkgver/LICENSE" \ + "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/src/barecode/BareCodeAUR/barecode-git-r5.cb66172-1-x86_64.pkg.tar.zst b/src/barecode/BareCodeAUR/barecode-git-r5.cb66172-1-x86_64.pkg.tar.zst new file mode 100644 index 0000000..f105603 Binary files /dev/null and b/src/barecode/BareCodeAUR/barecode-git-r5.cb66172-1-x86_64.pkg.tar.zst differ diff --git a/src/barecode/BareCodeAUR/barecode-git/HEAD b/src/barecode/BareCodeAUR/barecode-git/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/src/barecode/BareCodeAUR/barecode-git/config b/src/barecode/BareCodeAUR/barecode-git/config new file mode 100644 index 0000000..5bdc7ec --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/config @@ -0,0 +1,9 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true +[remote "origin"] + url = https://git.projekt-hirnfrei.de/diabolus/BareCode.git + tagOpt = --no-tags + fetch = +refs/*:refs/* + mirror = true diff --git a/src/barecode/BareCodeAUR/barecode-git/description b/src/barecode/BareCodeAUR/barecode-git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/applypatch-msg.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/applypatch-msg.sample new file mode 100755 index 0000000..a5d7b84 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/commit-msg.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/commit-msg.sample new file mode 100755 index 0000000..f7458ef --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/commit-msg.sample @@ -0,0 +1,74 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines and messages that +# would confuse 'git am'. + +ret=0 + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + ret=1 +} + +comment_re="$( + { + git config --get-regexp "^core\.comment(char|string)\$" || + echo '#' + } | sed -n -e ' + ${ + s/^[^ ]* // + s|[][*./\]|\\&|g + s/^auto$/[#;@!$%^&|:]/ + p + }' +)" +scissors_line="^${comment_re} -\{8,\} >8 -\{8,\}\$" +comment_line="^${comment_re}.*" +blank_line='^[ ]*$' +# Disallow lines starting with "diff -" or "Index: " in the body of the +# message. Stop looking if we see a scissors line. +line="$(sed -n -e " + # Skip comments and blank lines at the start of the file. + /${scissors_line}/q + /${comment_line}/d + /${blank_line}/d + # The first paragraph will become the subject header so + # does not need to be checked. + : subject + n + /${scissors_line}/q + /${blank_line}/!b subject + # Check the body of the message for problematic + # prefixes. + : body + n + /${scissors_line}/q + /${comment_line}/b body + /^diff -/{p;q;} + /^Index: /{p;q;} + b body + " "$1")" +if test -n "$line" +then + echo >&2 "Message contains a diff that will confuse 'git am'." + echo >&2 "To fix this indent the diff." + ret=1 +fi + +exit $ret diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/fsmonitor-watchman.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/fsmonitor-watchman.sample new file mode 100755 index 0000000..429e0a5 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/fsmonitor-watchman.sample @@ -0,0 +1,168 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $o->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/post-update.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/post-update.sample new file mode 100755 index 0000000..ec17ec1 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-applypatch.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-applypatch.sample new file mode 100755 index 0000000..4142082 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-commit.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-commit.sample new file mode 100755 index 0000000..29ed5ee --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-merge-commit.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-merge-commit.sample new file mode 100755 index 0000000..399eab1 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-push.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-push.sample new file mode 100755 index 0000000..4ce688d --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-rebase.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-rebase.sample new file mode 100755 index 0000000..6cbef5c --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/pre-receive.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-receive.sample new file mode 100755 index 0000000..a1fd29e --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/prepare-commit-msg.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/prepare-commit-msg.sample new file mode 100755 index 0000000..10fa14c --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/push-to-checkout.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/push-to-checkout.sample new file mode 100755 index 0000000..af5a0c0 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/src/barecode/BareCodeAUR/barecode-git/hooks/update.sample b/src/barecode/BareCodeAUR/barecode-git/hooks/update.sample new file mode 100755 index 0000000..c4d426b --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/src/barecode/BareCodeAUR/barecode-git/info/attributes b/src/barecode/BareCodeAUR/barecode-git/info/attributes new file mode 100644 index 0000000..1c897b7 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/info/attributes @@ -0,0 +1 @@ +* -export-subst -export-ignore diff --git a/src/barecode/BareCodeAUR/barecode-git/info/exclude b/src/barecode/BareCodeAUR/barecode-git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.idx b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.idx new file mode 100644 index 0000000..85361d9 Binary files /dev/null and b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.idx differ diff --git a/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.pack b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.pack new file mode 100644 index 0000000..8578d51 Binary files /dev/null and b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.pack differ diff --git a/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.rev b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.rev new file mode 100644 index 0000000..7891364 Binary files /dev/null and b/src/barecode/BareCodeAUR/barecode-git/objects/pack/pack-4853b9353e960d827cf8a26533fb09b06b4cfb2b.rev differ diff --git a/src/barecode/BareCodeAUR/barecode-git/packed-refs b/src/barecode/BareCodeAUR/barecode-git/packed-refs new file mode 100644 index 0000000..01fe6bb --- /dev/null +++ b/src/barecode/BareCodeAUR/barecode-git/packed-refs @@ -0,0 +1,4 @@ +# pack-refs with: peeled fully-peeled sorted +cb6617222dbcac30aaf15bf336b150fed440cc7f refs/heads/main +ca573209e715409e5989324aaeaa4efbd4da5642 refs/tags/v1.0.0 +^36e074f43d5b76d940d953956b0ed80899e71848 diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/.BUILDINFO b/src/barecode/BareCodeAUR/pkg/barecode-git/.BUILDINFO new file mode 100644 index 0000000..bbe4b8b --- /dev/null +++ b/src/barecode/BareCodeAUR/pkg/barecode-git/.BUILDINFO @@ -0,0 +1,3020 @@ +format = 2 +pkgname = barecode-git +pkgbase = barecode-git +pkgver = r5.cb66172-1 +pkgarch = x86_64 +pkgbuild_sha256sum = 3056388bf283742ba87373e135080d9a5b72c9f1364e8662380f8bc6f712d2f2 +packager = Unknown Packager +builddate = 1781069213 +builddir = /home/diabolus/Arbeit/Projekt-Hirnfrei/BareCode/BareCodeAUR +startdir = /home/diabolus/Arbeit/Projekt-Hirnfrei/BareCode/BareCodeAUR +buildtool = makepkg +buildtoolver = 7.1.0 +buildenv = !distcc +buildenv = color +buildenv = !ccache +buildenv = check +buildenv = !sign +options = strip +options = docs +options = !libtool +options = !staticlibs +options = emptydirs +options = zipman +options = purge +options = !debug +options = lto +installed = 7zip-26.01-1-x86_64 +installed = a52dec-0.8.0-3-x86_64 +installed = aalib-1.4rc5-19-x86_64 +installed = aarch64-linux-gnu-binutils-2.46-2-x86_64 +installed = aarch64-linux-gnu-gcc-15.2.0-1-x86_64 +installed = aarch64-linux-gnu-gdb-17.1-1-x86_64 +installed = aarch64-linux-gnu-glibc-2.43-1-any +installed = aarch64-linux-gnu-linux-api-headers-6.19-3-any +installed = aarch64-none-elf-gcc-bin-15.2.rel1-1-x86_64 +installed = abseil-cpp-20260107.1-1-x86_64 +installed = accounts-qml-module-0.7-8-x86_64 +installed = accountsservice-26.13.3-1-x86_64 +installed = acl-2.3.2-2-x86_64 +installed = acpid-2.0.34-2-x86_64 +installed = ada-3.4.4-1-x86_64 +installed = adobe-source-code-pro-fonts-2.042u+1.062i+1.026vf-2-any +installed = adwaita-cursors-50.0-1-any +installed = adwaita-fonts-50.0-1-any +installed = adwaita-icon-theme-50.0-1-any +installed = adwaita-icon-theme-legacy-46.2-3-any +installed = akonadi-26.04.2-1-x86_64 +installed = akonadi-calendar-26.04.2-1-x86_64 +installed = akonadi-contacts-26.04.2-1-x86_64 +installed = akonadi-import-wizard-26.04.2-1-x86_64 +installed = akonadi-mime-26.04.2-1-x86_64 +installed = akonadi-notes-24.08.3-2-x86_64 +installed = akonadi-notes-debug-24.08.3-2-x86_64 +installed = akonadi-search-26.04.2-1-x86_64 +installed = alembic-1.8.11-2-x86_64 +installed = alsa-card-profiles-1:1.6.6-1-x86_64 +installed = alsa-lib-1.2.16-1-x86_64 +installed = alsa-plugins-1:1.2.12-5-x86_64 +installed = alsa-topology-conf-1.2.5.1-4-any +installed = alsa-ucm-conf-1.2.16-2-any +installed = alsa-utils-1.2.16-1-x86_64 +installed = amitools-0.8.1-1-any +installed = android-armv7a-eabi-giflib-5.2.2-1-any +installed = android-armv7a-eabi-libjpeg-turbo-3.1.3-1-any +installed = android-armv7a-eabi-libpng-1.6.54-1-any +installed = android-armv7a-eabi-openssl-3.6.2-1-any +installed = android-armv7a-eabi-zlib-1.3.1-2-any +installed = android-cmake-2-1-any +installed = android-configure-2-3-any +installed = android-environment-7-5-any +installed = android-ndk-r29-3-x86_64 +installed = android-pkg-config-3-1-any +installed = android-sdk-26.1.1-2-x86_64 +installed = android-sdk-build-tools-r37.0.0-1-x86_64 +installed = android-sdk-platform-tools-37.0.0-1-x86_64 +installed = android-sdk-platform-tools-debug-36.0.0-1-x86_64 +installed = android-tools-35.0.2-26-x86_64 +installed = android-udev-20260423-1-any +installed = ant-1.10.17-1-any +installed = anydesk-bin-8.0.2-1-x86_64 +installed = aom-3.14.1-1-x86_64 +installed = apache-2.4.68-1-x86_64 +installed = apache-orc-2.3.0-4-x86_64 +installed = apparmor-4.1.7-1-x86_64 +installed = appstream-1.1.2-1-x86_64 +installed = appstream-glib-0.8.3-4-x86_64 +installed = appstream-qt-1.1.2-1-x86_64 +installed = apr-1.7.6-1-x86_64 +installed = apr-util-1.6.3-2-x86_64 +installed = arandr-0.1.11-6-any +installed = arch-install-scripts-31-1-any +installed = archlinux-appstream-data-20260606-1-any +installed = archlinux-keyring-20260420-1-any +installed = arduino-1:1.8.19-4-x86_64 +installed = arduino-avr-core-1.8.8-1-any +installed = arduino-builder-1.6.1-3-x86_64 +installed = arduino-ctags-5.8_arduino11-5-x86_64 +installed = argon2-20190702-6-x86_64 +installed = aria2-1.37.0-3-x86_64 +installed = aribb24-1.0.3-4-x86_64 +installed = arm-linux-gnueabihf-binutils-2.45+r8+g09be88bfb653-1-x86_64 +installed = arm-linux-gnueabihf-linux-api-headers-6.15.1-1-any +installed = arm-none-eabi-binutils-2.43-2-x86_64 +installed = arm-none-eabi-gcc-14.2.0-2-x86_64 +installed = arm-none-eabi-newlib-4.5.0.20241231-2-any +installed = arrow-24.0.0-2-x86_64 +installed = asar-4.2.0-1-any +installed = asciidoc-10.2.1-3-any +installed = asio-1.38.0-1-any +installed = aspell-0.60.8.2-2-x86_64 +installed = assimp-6.0.5-1-x86_64 +installed = at-spi2-core-2.60.4-1-x86_64 +installed = atkmm-2.28.5-2-x86_64 +installed = atril-1.28.3-1-x86_64 +installed = attica-6.26.0-1-x86_64 +installed = attr-2.5.2-2-x86_64 +installed = audacity-1:3.7.7-2-x86_64 +installed = audiofile-0.3.6-12-x86_64 +installed = audit-4.1.4-2-x86_64 +installed = aurorae-6.6.5-1-x86_64 +installed = autoconf-2.73-1-any +installed = autoconf-archive-1:2024.10.16-4-any +installed = automake-1.18.1-1-any +installed = autossh-1.4g-4-x86_64 +installed = avahi-1:0.9rc4-1-x86_64 +installed = avisynthplus-3.7.5-3-x86_64 +installed = avr-binutils-2.43-2-x86_64 +installed = avr-gcc-15.1.0-2-x86_64 +installed = avr-libc-2.3.2-1-any +installed = avrdude-1:8.1-1-x86_64 +installed = awesome-4.3-6-x86_64 +installed = aws-c-auth-0.10.1-1-x86_64 +installed = aws-c-cal-0.9.13-1-x86_64 +installed = aws-c-common-0.12.6-1-x86_64 +installed = aws-c-compression-0.3.2-1-x86_64 +installed = aws-c-event-stream-0.7.0-1-x86_64 +installed = aws-c-http-0.10.14-1-x86_64 +installed = aws-c-io-0.26.3-1-x86_64 +installed = aws-c-mqtt-0.15.2-1-x86_64 +installed = aws-c-s3-0.12.2-1-x86_64 +installed = aws-c-sdkutils-0.2.4-1-x86_64 +installed = aws-checksums-0.2.10-1-x86_64 +installed = aws-crt-cpp-0.38.5-1-x86_64 +installed = aws-sdk-cpp-core-1.11.792-1-x86_64 +installed = aws-sdk-cpp-iam-1.11.792-1-x86_64 +installed = aws-sdk-cpp-s3-1.11.792-1-x86_64 +installed = ayatana-ido-0.10.4-1-x86_64 +installed = babl-0.1.126-1-x86_64 +installed = baloo-6.26.0-1-x86_64 +installed = baloo-widgets-26.04.2-1-x86_64 +installed = baobab-50.0-1-x86_64 +installed = base-3-3-any +installed = base-devel-1-2-any +installed = bash-5.3.12-1-x86_64 +installed = bash-completion-2.17.0-3-any +installed = bc-1.08.2-1-x86_64 +installed = benchmark-1.9.5-2-x86_64 +installed = bigsh0t-2.7-2-x86_64 +installed = binutils-2.46+r70+g155188ea10a7-1-x86_64 +installed = bison-3.8.2-8-x86_64 +installed = blas-3.12.1-2-x86_64 +installed = blender-17:5.1.2-1-x86_64 +installed = blosc-1.21.6-2-x86_64 +installed = bluefish-2.2.19-2-x86_64 +installed = blueman-2.4.6-2-x86_64 +installed = blueprint-compiler-0.20.4-1-any +installed = bluez-5.86-6-x86_64 +installed = bluez-libs-5.86-6-x86_64 +installed = bluez-obex-5.86-6-x86_64 +installed = bluez-utils-5.86-6-x86_64 +installed = bogofilter-db-1.2.5-12-x86_64 +installed = bolt-0.9.11-1-x86_64 +installed = boost-1.91.0-1-x86_64 +installed = boost-libs-1.91.0-1-x86_64 +installed = brasero-3.12.3+r44+gdea4990b-1-x86_64 +installed = brave-bin-1:1.91.171-1-x86_64 +installed = breeze-6.6.5-1-x86_64 +installed = breeze-cursors-6.6.5-1-x86_64 +installed = breeze-icons-6.26.0-1-x86_64 +installed = breezy-3.3.21-2-x86_64 +installed = bridge-utils-1.7.1-5-x86_64 +installed = brltty-6.9.1-1-x86_64 +installed = brother-ql570-1.0.1r0-1-x86_64 +installed = brotli-1.2.0-1-x86_64 +installed = btop-1.4.7-1-x86_64 +installed = btrfs-progs-7.0-1-x86_64 +installed = bubblewrap-0.11.2-1-x86_64 +installed = bzip2-1.0.8-6-x86_64 +installed = c-ares-1.34.6-1-x86_64 +installed = ca-certificates-20240618-1-any +installed = ca-certificates-mozilla-3.124-1-x86_64 +installed = ca-certificates-utils-20240618-1-any +installed = cabextract-1.11-2-x86_64 +installed = cairo-1.18.4-1-x86_64 +installed = cairomm-1.14.6-1-x86_64 +installed = cairomm-1.16-1.18.1-1-x86_64 +installed = caja-1.28.0-4-x86_64 +installed = calendarsupport-26.04.2-1-x86_64 +installed = cantarell-fonts-1:0.311-1-any +installed = capstone-5.0.9-1-x86_64 +installed = cargo-c-0.10.23-1-x86_64 +installed = cauchy-0.9.0-5-x86_64 +installed = cblas-3.12.1-2-x86_64 +installed = ccache-4.13.6-1-x86_64 +installed = cccl-3.3.4-1-any +installed = cdparanoia-10.2-9-x86_64 +installed = cdrdao-1.2.6-3-x86_64 +installed = cdrtools-3.02a09-6-x86_64 +installed = cef-minimal-obs-bin-2:127.3.4+ga0ca18e+chromium_127.0.6533.100_6-1-x86_64 +installed = ceres-solver-2.2.0-5-x86_64 +installed = cfitsio-1:4.6.4-1-x86_64 +installed = chmlib-0.40-10-x86_64 +installed = chromaprint-1.6.0-3-x86_64 +installed = chromium-149.0.7827.53-1-x86_64 +installed = chrpath-0.18-1-x86_64 +installed = cifs-utils-7.5-1-x86_64 +installed = cinnamon-6.6.8-1-x86_64 +installed = cinnamon-control-center-6.6.0-3-x86_64 +installed = cinnamon-desktop-6.6.2-2-x86_64 +installed = cinnamon-menus-6.6.0-1-x86_64 +installed = cinnamon-screensaver-6.6.1-3-x86_64 +installed = cinnamon-session-6.6.3-2-x86_64 +installed = cinnamon-settings-daemon-6.6.4-1-x86_64 +installed = cinnamon-translations-6.6.2-1-any +installed = cjs-128.1-2-x86_64 +installed = cjson-1.7.19-1-x86_64 +installed = clang-22.1.6-1-x86_64 +installed = clang21-21.1.8-1-x86_64 +installed = clazy-1.17.1-1-x86_64 +installed = clucene-2.3.3.4-17-x86_64 +installed = clutter-1.26.4-4-x86_64 +installed = cmake-4.3.3-1-x86_64 +installed = cmark-0.31.2-1-x86_64 +installed = cogl-1.22.8-5-x86_64 +installed = colm-0.14.7-5-x86_64 +installed = colord-1.4.8-1-x86_64 +installed = colord-gtk-common-0.3.1-1-x86_64 +installed = colord-gtk4-0.3.1-1-x86_64 +installed = colord-sane-1.4.8-1-x86_64 +installed = compiler-rt-22.1.6-1-x86_64 +installed = compiler-rt20-20.1.8-1-x86_64 +installed = compiler-rt21-21.1.8-1-x86_64 +installed = composefs-1.0.8-1-x86_64 +installed = composer-2.10.1-1-any +installed = confuse-3.3-5-x86_64 +installed = containerd-2.3.1-1-x86_64 +installed = convertlit-1.8-13-x86_64 +installed = coqui-tts-0.27.5-1-any +installed = coreutils-9.11-1-x86_64 +installed = cpio-2.15-3-x86_64 +installed = cppdap-1.58.0-3-x86_64 +installed = cracklib-2.10.3-1-x86_64 +installed = cryptsetup-2.8.6-1-x86_64 +installed = ctpl-0.3.5-3-x86_64 +installed = cuda-13.3.0-1-x86_64 +installed = cups-2:2.4.19-1-x86_64 +installed = cups-filters-2.0.1-2-x86_64 +installed = cups-pk-helper-0.2.7-2-x86_64 +installed = cura-bin-5.13.0-1-x86_64 +installed = curl-8.20.0-7-x86_64 +installed = curlftpfs-0.9.2-10-x86_64 +installed = curseforge-1.308.1_34958-1-x86_64 +installed = cutecom-0.60.0_RC1-2-x86_64 +installed = cutecom-debug-0.60.0_RC1-1-x86_64 +installed = cython-3.2.5-1-x86_64 +installed = dav1d-1.5.3-1-x86_64 +installed = db-6.2.32-4-x86_64 +installed = db5.3-5.3.28-7-x86_64 +installed = dbus-1.16.2-1-x86_64 +installed = dbus-broker-37-3-x86_64 +installed = dbus-broker-units-37-3-x86_64 +installed = dbus-glib-0.114-1-x86_64 +installed = dconf-0.49.0-1-x86_64 +installed = dconf-editor-49.0-1-x86_64 +installed = ddcutil-2.2.7-1-x86_64 +installed = debhelper-13.31-1-any +installed = debtap-3.6.3-1-any +installed = debugedit-5.3-1-x86_64 +installed = debuginfod-0.195-1-x86_64 +installed = default-cursors-3-1-any +installed = dejagnu-1.6.3-17-any +installed = deno-2.8.2-1-x86_64 +installed = desktop-file-utils-0.28-1-x86_64 +installed = device-mapper-2.03.41-1-x86_64 +installed = devilspie-0.23-6-x86_64 +installed = dhcpcd-10.3.2-1-x86_64 +installed = dialog-1:1.3_20260107-1-x86_64 +installed = diffutils-3.12-2-x86_64 +installed = ding-libs-0.7.0-1-x86_64 +installed = discord-1:1.0.142-1-x86_64 +installed = discount-3.0.1.2-1-x86_64 +installed = djvulibre-3.5.30-1-x86_64 +installed = dkms-3.4.1-1-any +installed = dleyna-0.8.3-5-x86_64 +installed = dmidecode-3.7-1-x86_64 +installed = dnsmasq-2.93-1-x86_64 +installed = docbook-xml-4.5-11-any +installed = docbook-xsl-1.79.2-9-any +installed = docker-1:29.5.2-1-x86_64 +installed = docker-buildx-0.34.1-1-x86_64 +installed = docker-compose-5.1.4-1-x86_64 +installed = dolphin-26.04.2-1-x86_64 +installed = dos2unix-7.5.6-1-x86_64 +installed = dosbox-0.74.3-4-x86_64 +installed = dosfstools-4.2-5-x86_64 +installed = dotconf-1.4.1-1-x86_64 +installed = dotnet-host-10.0.8.sdk108-1-x86_64 +installed = dotnet-runtime-6.0-6.0.36.sdk136-2-x86_64 +installed = double-conversion-3.4.0-1-x86_64 +installed = doxygen-1.16.1-3-x86_64 +installed = dpkg-1.23.7-1-x86_64 +installed = draco-1.5.7-2-x86_64 +installed = droidcam-obs-plugin-2.4.3-1-x86_64 +installed = dtc-1:1.7.2-1-x86_64 +installed = duktape-2.7.0-7-x86_64 +installed = dvd+rw-tools-7.1-13-x86_64 +installed = dvgrab-3.5.2-1-x86_64 +installed = dvisvgm-3.6-2-x86_64 +installed = dvr-scan-1.8.2-1-any +installed = e2fsprogs-1.47.4-1-x86_64 +installed = easyeffects-8.2.4-1-x86_64 +installed = ebook-tools-0.2.2-9-x86_64 +installed = edex-ui-bin-2.2.8-1-x86_64 +installed = editorconfig-core-c-0.12.11-1-x86_64 +installed = edk2-aarch64-202605-1-any +installed = edk2-ovmf-202605-1-any +installed = edk2-riscv64-202605-1-any +installed = egl-gbm-1.1.3-1-x86_64 +installed = egl-wayland-4:1.1.21-1-x86_64 +installed = egl-wayland2-1.0.1-1-x86_64 +installed = egl-x11-1.0.5-1-x86_64 +installed = eglexternalplatform-1.2.1-1-any +installed = eigen-5.0.1-2-x86_64 +installed = electron-1:42-1-any +installed = electron42-42.3.0-1-x86_64 +installed = elementary-icon-theme-8.2.0-2-any +installed = elfutils-0.195-1-x86_64 +installed = embree-4.4.1-1-x86_64 +installed = enca-1.22-1-x86_64 +installed = enchant-2.8.15-2-x86_64 +installed = engrampa-1.28.3-1-x86_64 +installed = epiphany-50.4-2-x86_64 +installed = epson-inkjet-printer-escpr-1.8.8-1-x86_64 +installed = espeak-ng-1.52.0-1-x86_64 +installed = eventviews-26.04.2-1-x86_64 +installed = evince-1:48.4-1-x86_64 +installed = evolution-3.60.2-1-x86_64 +installed = evolution-bogofilter-3.60.2-1-x86_64 +installed = evolution-data-server-3.60.2-2-x86_64 +installed = evolution-ews-3.60.2-1-x86_64 +installed = evolution-on-3.24.2-3-x86_64 +installed = evolution-spamassassin-3.60.2-1-x86_64 +installed = ex-vi-compat-2-1-any +installed = exempi-2.6.6-3-x86_64 +installed = exfat-utils-1.4.0-4-x86_64 +installed = exiv2-0.28.8-2-x86_64 +installed = exo-4.20.0-2-x86_64 +installed = expat-2.8.1-1-x86_64 +installed = expect-5.45.4-5-x86_64 +installed = extra-cmake-modules-6.26.0-1-any +installed = eza-0.23.4-3-x86_64 +installed = f3-10.0-1-x86_64 +installed = f3-debug-9.0-1-x86_64 +installed = faac-1.50-1-x86_64 +installed = faad2-2.11.2-1-x86_64 +installed = fakeroot-1:1.37.2-1-x86_64 +installed = ffcall-2.5-1-x86_64 +installed = ffmpeg-2:8.1.1-2-x86_64 +installed = ffmpeg4.4-4.4.6-5-x86_64 +installed = ffmpegthumbs-26.04.2-1-x86_64 +installed = ffnvcodec-headers-13.0.19.0-1-any +installed = fftw-3.3.11-1-x86_64 +installed = fig2dev-3.2.9-1-x86_64 +installed = file-5.48-1-x86_64 +installed = file-roller-44.6-2-x86_64 +installed = filesystem-2025.10.12-1-any +installed = findutils-4.10.0-3-x86_64 +installed = fio-3.42-1-x86_64 +installed = firefox-151.0.3-1-x86_64 +installed = firestorm-bin-7.2.4.80712-1-x86_64 +installed = flac-1.5.0-1-x86_64 +installed = flameshot-13.3.0-2-x86_64 +installed = flashrom-1.7.0-1-x86_64 +installed = flat-remix-gnome-20250926-1-any +installed = flatpak-1:1.16.6-1-x86_64 +installed = flex-2.6.4-6-x86_64 +installed = fltk-1.4.5-1-x86_64 +installed = fltk1.3-1.3.11-4-x86_64 +installed = fluidsynth-2.5.4-1-x86_64 +installed = fmt-12.1.0-2-x86_64 +installed = fontconfig-2:2.18.1-1-x86_64 +installed = foomatic-db-engine-5:20200131-2-x86_64 +installed = fpc-3.2.2-11-x86_64 +installed = fpc-src-3.2.2-4-any +installed = frameworkintegration-6.26.0-1-x86_64 +installed = freealut-1.1.0-10-x86_64 +installed = freecol-1.2.0-2-any +installed = freeglut-3.8.0-1-x86_64 +installed = freeoffice-1234-1-x86_64 +installed = freerdp-2:3.26.0-1-x86_64 +installed = freetype2-2.14.3-1-x86_64 +installed = frei0r-plugins-3.2.1-1-x86_64 +installed = fribidi-1.0.16-2-x86_64 +installed = fritzing-1.0.7-2-x86_64 +installed = fs-uae-3.2.35-2-x86_64 +installed = fs-uae-launcher-3.2.35-2-any +installed = ftgl-2.4.0-3-x86_64 +installed = ftxui-6.1.9-1-x86_64 +installed = fuse-common-3.18.2-1-x86_64 +installed = fuse2-2.9.9-5-x86_64 +installed = fuse3-3.18.2-1-x86_64 +installed = fwupd-2.1.4-2-x86_64 +installed = fwupd-efi-1.8-2-any +installed = galculator-2.1.4-10-x86_64 +installed = gamemode-1.8.2-2-x86_64 +installed = gamescope-3.16.24-1-x86_64 +installed = garcon-4.20.0-2-x86_64 +installed = gavl-2.0.1-2-x86_64 +installed = gawk-5.4.0-1-x86_64 +installed = gc-8.2.12-1-x86_64 +installed = gcc-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = gcc-ada-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = gcc-d-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = gcc-fortran-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = gcc-libs-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = gcc14-14.3.1+r516+g5998566829ee-1-x86_64 +installed = gcc14-libs-14.3.1+r516+g5998566829ee-1-x86_64 +installed = gcc15-15.2.1+r934+gbcd3e3ff5aa7-1-x86_64 +installed = gcc15-libs-15.2.1+r934+gbcd3e3ff5aa7-1-x86_64 +installed = gconf-3.2.6+11+g07808097-15-x86_64 +installed = gconf-debug-3.2.6+11+g07808097-15-x86_64 +installed = gcr-3.41.2-2-x86_64 +installed = gcr-4-4.4.0.1-1-x86_64 +installed = gd-2.3.3-9-x86_64 +installed = gdb-17.2-1-x86_64 +installed = gdb-common-17.2-1-x86_64 +installed = gdbm-1.26-2-x86_64 +installed = gdk-pixbuf2-2.44.6-2-x86_64 +installed = gdm-50.1-1-x86_64 +installed = geany-2.1-2-x86_64 +installed = geany-plugins-2.1-3-x86_64 +installed = geekbench-6.7.1-1-x86_64 +installed = gef-git-0.0.0.2252.2b7f315-1-any +installed = gegl-0.4.70-2-x86_64 +installed = gendesk-1.0.15-1-x86_64 +installed = geoclue-2.8.1-1-x86_64 +installed = geocode-glib-3.26.4-6-x86_64 +installed = geoip-1.6.12-3-x86_64 +installed = geoip-database-20260204-1-any +installed = gettext-1.0-2-x86_64 +installed = gexiv2-0.16.0-2-x86_64 +installed = gflags-2.2.2-6-x86_64 +installed = gfxstream-0.1.2-2-x86_64 +installed = ghex-50.2-1-x86_64 +installed = ghostscript-10.07.1-1-x86_64 +installed = gi-docgen-2026.1-1-any +installed = giflib-6.1.3-1-x86_64 +installed = gimp-3.2.4-1-x86_64 +installed = git-2.54.0-1-x86_64 +installed = git-lfs-3.7.1-1-x86_64 +installed = gjs-2:1.88.0-1-x86_64 +installed = glabels-3.4.1-13-x86_64 +installed = glew-2.3.1-1-x86_64 +installed = glfw-1:3.4-1-x86_64 +installed = glib-1.2.10-19-x86_64 +installed = glib-debug-1.2.10-18-x86_64 +installed = glib-networking-1:2.80.1-1-x86_64 +installed = glib2-2.88.1-1-x86_64 +installed = glib2-devel-2.88.1-1-x86_64 +installed = glib2-docs-2.88.1-1-x86_64 +installed = glibc-2.43+r22+g8362e8ce10b2-2-x86_64 +installed = glibmm-2.66.8-2-x86_64 +installed = glibmm-2.68-2.88.0-2-x86_64 +installed = glm-1.0.3-1-x86_64 +installed = glslang-1:1.4.350.0-1-x86_64 +installed = glu-9.0.3-3-x86_64 +installed = glusterfs-1:11.2-2-x86_64 +installed = glycin-2.1.1-1-x86_64 +installed = glycin-gtk4-2.1.1-1-x86_64 +installed = gmp-6.3.0-3-x86_64 +installed = gnokii-0.6.31-21-x86_64 +installed = gnokii-debug-0.6.31-21-x86_64 +installed = gnome-app-list-3.0-1-any +installed = gnome-autoar-0.4.5-1-x86_64 +installed = gnome-backgrounds-50.0-1-any +installed = gnome-bluetooth-3.0-47.2-1-x86_64 +installed = gnome-calculator-50.0-1-x86_64 +installed = gnome-characters-50.0-1-x86_64 +installed = gnome-clocks-50.0-2-x86_64 +installed = gnome-color-manager-3.36.2-1-x86_64 +installed = gnome-common-3.18.0-5-any +installed = gnome-control-center-50.2-1-x86_64 +installed = gnome-desktop-1:44.5-1-x86_64 +installed = gnome-desktop-4-1:44.5-1-x86_64 +installed = gnome-desktop-common-1:44.5-1-x86_64 +installed = gnome-disk-utility-46.1-2-x86_64 +installed = gnome-font-viewer-50.0-1-x86_64 +installed = gnome-keybindings-50.2-1-x86_64 +installed = gnome-keyring-1:50.0-1-x86_64 +installed = gnome-logs-50.0-1-x86_64 +installed = gnome-menus-3.38.1-1-x86_64 +installed = gnome-music-1:49.1-2-any +installed = gnome-online-accounts-3.58.1-1-x86_64 +installed = gnome-online-accounts-gtk-3.50.10-1-x86_64 +installed = gnome-remote-desktop-50.1-1-x86_64 +installed = gnome-session-50.1-1-x86_64 +installed = gnome-settings-daemon-50.1-1-x86_64 +installed = gnome-shell-1:50.2-1-x86_64 +installed = gnome-shell-extension-appindicator-1:64-1-any +installed = gnome-shell-extensions-50.2-1-any +installed = gnome-software-50.2-1-x86_64 +installed = gnome-system-monitor-50.0-1-x86_64 +installed = gnome-text-editor-50.1-1-x86_64 +installed = gnome-themes-extra-1:3.28-1-any +installed = gnome-tweaks-49.0-2-any +installed = gnome-user-docs-50.2-1-any +installed = gnome-user-share-48.3-1-x86_64 +installed = gnome-weather-50.0-1-any +installed = gnu-free-fonts-20120503-9-any +installed = gnulib-l10n-20241231-1-any +installed = gnupg-2.4.9-1-x86_64 +installed = gnutls-3.8.13-2-x86_64 +installed = go-2:1.26.4-1-x86_64 +installed = go-tools-4:0.45.0-1-x86_64 +installed = gobject-introspection-1.86.0-2-x86_64 +installed = gobject-introspection-runtime-1.86.0-2-x86_64 +installed = gom-0.5.6-1-x86_64 +installed = google-chrome-149.0.7827.102-1-x86_64 +installed = google-earth-pro-7.3.7.1155-1-x86_64 +installed = google-glog-0.7.1-2-x86_64 +installed = goverlay-1.8.2-1-x86_64 +installed = gparted-1.8.1-2-x86_64 +installed = gperf-3.3-2-x86_64 +installed = gperftools-2.18.1-1-x86_64 +installed = gpgme-2.1.0-1-x86_64 +installed = gpgmepp-2.1.0-1-x86_64 +installed = gpm-1.20.7.r38.ge82d1a6-6-x86_64 +installed = gradle-9.5.1-1-any +installed = grantleetheme-26.04.2-1-x86_64 +installed = graphene-1.10.8-2-x86_64 +installed = graphicsmagick-1.3.47-1-x86_64 +installed = graphite-1:1.3.15-1-x86_64 +installed = graphviz-14.1.5-1-x86_64 +installed = grep-3.12-2-x86_64 +installed = grilo-0.3.19-2-x86_64 +installed = grilo-plugins-1:0.3.18-3-x86_64 +installed = groff-1.24.1-1-x86_64 +installed = grpc-1.80.0-2-x86_64 +installed = grub-2:2.14-1-x86_64 +installed = grub-customizer-5.2.5-2-x86_64 +installed = grub-customizer-debug-5.2.5-2-x86_64 +installed = gsettings-desktop-schemas-50.1-1-any +installed = gsettings-system-schemas-50.1-1-any +installed = gsfonts-20200910-6-any +installed = gsl-2.8-1-x86_64 +installed = gsm-1.0.24-1-x86_64 +installed = gsound-1.0.3-4-x86_64 +installed = gspell-1.14.3-1-x86_64 +installed = gssdp-1.6.5-1-x86_64 +installed = gssproxy-0.9.2-3-x86_64 +installed = gst-devtools-libs-1.28.3-1-x86_64 +installed = gst-editing-services-1.28.3-1-x86_64 +installed = gst-libav-1.28.3-1-x86_64 +installed = gst-plugin-gtk-1.28.3-1-x86_64 +installed = gst-plugins-bad-1.28.3-1-x86_64 +installed = gst-plugins-bad-libs-1.28.3-1-x86_64 +installed = gst-plugins-base-1.28.3-1-x86_64 +installed = gst-plugins-base-libs-1.28.3-1-x86_64 +installed = gst-plugins-good-1.28.3-1-x86_64 +installed = gst-python-1.28.3-1-x86_64 +installed = gstreamer-1.28.3-1-x86_64 +installed = gtest-1.17.0-2-x86_64 +installed = gtk-1.2.10-20-x86_64 +installed = gtk-debug-1.2.10-20-x86_64 +installed = gtk-doc-1.36.1-1-any +installed = gtk-engine-murrine-0.98.2-5-x86_64 +installed = gtk-engines-2.21.0-7-x86_64 +installed = gtk-layer-shell-0.10.1-1-x86_64 +installed = gtk-update-icon-cache-1:4.22.4-1-x86_64 +installed = gtk-vnc-1.5.0-1-x86_64 +installed = gtk2-2.24.33-5-x86_64 +installed = gtk3-1:3.24.52-1-x86_64 +installed = gtk4-1:4.22.4-1-x86_64 +installed = gtkd-3.11.0-4-x86_64 +installed = gtkd-debug-3.11.0-4-x86_64 +installed = gtkglext-1.2.0-20-x86_64 +installed = gtkmm-4.0-4.22.0-2-x86_64 +installed = gtkmm3-3.24.10-2-x86_64 +installed = gtksourceview4-4.8.4-2-x86_64 +installed = gtksourceview5-5.20.0-1-x86_64 +installed = gtkspell3-3.0.10-4-x86_64 +installed = gts-0.7.6.121130-5-x86_64 +installed = guake-3.10.1-1-any +installed = guile-3.0.11-1-x86_64 +installed = gulp-5.0.1-1-any +installed = gumbo-parser-0.13.2-1-x86_64 +installed = gupnp-1:1.6.10-1-x86_64 +installed = gupnp-av-0.14.5-1-x86_64 +installed = gupnp-dlna-0.12.0-5-x86_64 +installed = gupnp-igd-1.6.0-2-x86_64 +installed = guvcview-2.2.2-2-x86_64 +installed = guvcview-common-2.2.2-2-x86_64 +installed = gvfs-1.60.0-2-x86_64 +installed = gvfs-afc-1.60.0-2-x86_64 +installed = gvfs-goa-1.60.0-2-x86_64 +installed = gvfs-gphoto2-1.60.0-2-x86_64 +installed = gvfs-mtp-1.60.0-2-x86_64 +installed = gvfs-nfs-1.60.0-2-x86_64 +installed = gvfs-smb-1.60.0-2-x86_64 +installed = gweather-locations-2026.2-1-x86_64 +installed = gwenview-26.04.2-1-x86_64 +installed = gzip-1.14-2-x86_64 +installed = handbrake-1.11.2-1-x86_64 +installed = hardinfo2-2.2.16-2-x86_64 +installed = hardinfo2-debug-2.2.13-1-x86_64 +installed = harfbuzz-14.2.1-1-x86_64 +installed = harfbuzz-icu-14.2.1-1-x86_64 +installed = haveged-1.9.22-1-x86_64 +installed = hdf5-2.1.1-1-x86_64 +installed = heroic-games-launcher-bin-2.22.0-1-x86_64 +installed = hicolor-icon-theme-0.18-1-any +installed = hidapi-0.15.0-1-x86_64 +installed = highway-1.4.0-1-x86_64 +installed = hiredis-1.3.0-1-x86_64 +installed = hplip-1:3.26.4-1-x86_64 +installed = hspell-1.4-6-x86_64 +installed = htdig-3.2.0b6-11.1-x86_64 +installed = htop-3.5.1-1-x86_64 +installed = http-parser-2.9.4-2-x86_64 +installed = hunspell-1.7.3-1-x86_64 +installed = hwdata-0.408-1-any +installed = hwinfo-25.2-1-x86_64 +installed = hwloc-2.13.0-1-x86_64 +installed = hyphen-2.8.9-1-x86_64 +installed = i2c-tools-4.4-4-x86_64 +installed = iana-etc-20260530-1-any +installed = iat-0.1.7-4-x86_64 +installed = ibus-1.5.34-1-x86_64 +installed = icu-78.3-1-x86_64 +installed = icu69-69.1-1-x86_64 +installed = iec16022-0.3.1-3-x86_64 +installed = iio-sensor-proxy-3.9-1-x86_64 +installed = ijs-0.35-7-x86_64 +installed = imagemagick-7.1.2.25-1-x86_64 +installed = imake-1.0.11-1-x86_64 +installed = imath-3.2.2-6-x86_64 +installed = imlib-1.9.15-19-x86_64 +installed = imlib-debug-1.9.15-19-x86_64 +installed = imlib2-1.12.6-1-x86_64 +installed = incidenceeditor-26.04.2-1-x86_64 +installed = inetutils-2.8-1-x86_64 +installed = iniparser-4.2.6-2-x86_64 +installed = inkscape-1.4.4-2-x86_64 +installed = innoextract-1.9-16-x86_64 +installed = intel-oneapi-common-2026.0.0_235-1-any +installed = intel-oneapi-compiler-dpcpp-cpp-runtime-libs-2026.0.0_947-2-x86_64 +installed = intel-oneapi-compiler-shared-runtime-2026.0.0_947-1-x86_64 +installed = intel-oneapi-compiler-shared-runtime-libs-2026.0.0_947-1-x86_64 +installed = intel-oneapi-mkl-2026.0.0_908-1-x86_64 +installed = intel-oneapi-openmp-2026.0.0_947-1-x86_64 +installed = intel-oneapi-tbb-2023.0.0_724-1-x86_64 +installed = intel-oneapi-tcm-1.5.0_489-1-x86_64 +installed = intel-oneapi-umf-1.1.0_340-2-x86_64 +installed = intel-ucode-20260512-1-any +installed = intltool-0.51.0-6-any +installed = intltool-debian-1:0.35.0+20060710.6-1-any +installed = iperf3-3.21-1-x86_64 +installed = iproute2-7.0.0-1-x86_64 +installed = iptables-1:1.8.13-1-x86_64 +installed = iputils-20250605-1-x86_64 +installed = iso-codes-4.20.1-1-any +installed = itstool-1:2.0.7-3-any +installed = iw-6.17-1-x86_64 +installed = jansson-2.15.0-1-x86_64 +installed = jasper-4.2.9-1-x86_64 +installed = java-environment-common-3-6-any +installed = java-hamcrest-3.0-3-any +installed = java-runtime-common-3-6-any +installed = jbig2dec-0.20-2-x86_64 +installed = jbigkit-2.1-8-x86_64 +installed = jdk-openjdk-26.0.1.u8-1-x86_64 +installed = jdk11-openjdk-11.0.31.u11-1-x86_64 +installed = jdk17-openjdk-17.0.19.u10-1-x86_64 +installed = jdk8-openjdk-8.492.u09-1-x86_64 +installed = jemalloc-1:5.3.1-2-x86_64 +installed = joyutils-1.8.1-3-x86_64 +installed = jq-1.8.1-3-x86_64 +installed = jre-26.0.1-1-x86_64 +installed = jre8-openjdk-8.492.u09-1-x86_64 +installed = jre8-openjdk-headless-8.492.u09-1-x86_64 +installed = js115-115.31.0-1-x86_64 +installed = js128-128.14.0-1-x86_64 +installed = js140-140.11.0-1-x86_64 +installed = json-c-0.18-2-x86_64 +installed = json-glib-1.10.8-1-x86_64 +installed = jsoncpp-1.9.6-3-x86_64 +installed = jstest-gtk-git-0.1.0.r127.g92bdf8e-1-x86_64 +installed = jstest-gtk-git-debug-0.1.0.r127.g92bdf8e-1-x86_64 +installed = junit-4.13.2-2-any +installed = kaccounts-integration-26.04.2-1-x86_64 +installed = kactivitymanagerd-6.6.5-1-x86_64 +installed = karchive-6.26.0-1-x86_64 +installed = karchive5-5.116.0-3-x86_64 +installed = kate-26.04.2-1-x86_64 +installed = kauth-6.26.0-1-x86_64 +installed = kauth5-5.116.0-2-x86_64 +installed = kbd-2.10.0-1-x86_64 +installed = kbookmarks-6.26.0-1-x86_64 +installed = kbookmarks5-5.116.0-2-x86_64 +installed = kcalendarcore-6.26.0-3-x86_64 +installed = kcalutils-26.04.2-1-x86_64 +installed = kcmutils-6.26.0-1-x86_64 +installed = kcodecs-6.26.0-1-x86_64 +installed = kcodecs5-5.116.0-2-x86_64 +installed = kcolorpicker-0.3.1-6-x86_64 +installed = kcolorscheme-6.26.0-2-x86_64 +installed = kcompletion-6.26.0-1-x86_64 +installed = kcompletion5-5.116.0-2-x86_64 +installed = kconfig-6.26.0-1-x86_64 +installed = kconfig5-5.116.0-2-x86_64 +installed = kconfigwidgets-6.26.0-1-x86_64 +installed = kconfigwidgets5-5.116.0-3-x86_64 +installed = kcontacts-1:6.26.0-1-x86_64 +installed = kcoreaddons-6.26.0-1-x86_64 +installed = kcoreaddons5-5.116.0-2-x86_64 +installed = kcrash-6.26.0-1-x86_64 +installed = kcrash5-5.116.0-2-x86_64 +installed = kdbusaddons-6.26.0-1-x86_64 +installed = kdbusaddons5-5.116.0-2-x86_64 +installed = kddockwidgets-2.4.0-3-x86_64 +installed = kde-cli-tools-6.6.5-1-x86_64 +installed = kdeclarative-6.26.0-1-x86_64 +installed = kdeclarative5-5.116.0-2-x86_64 +installed = kdeconnect-26.04.2-1-x86_64 +installed = kdecoration-6.6.5-1-x86_64 +installed = kded-6.26.0-1-x86_64 +installed = kded5-5.116.0-2-x86_64 +installed = kdeedu-data-26.04.2-1-any +installed = kdegraphics-mobipocket-26.04.2-1-x86_64 +installed = kdegraphics-thumbnailers-26.04.2-1-x86_64 +installed = kdenetwork-filesharing-26.04.2-1-x86_64 +installed = kdenlive-26.04.2-1-x86_64 +installed = kdepim-addons-26.04.2-1-x86_64 +installed = kdesu-6.26.0-1-x86_64 +installed = kdiagram-3.0.1-5-x86_64 +installed = kdiskmark-3.2.0-2-x86_64 +installed = kdnssd-6.26.0-1-x86_64 +installed = kdoctools5-5.116.0-3-x86_64 +installed = kdsingleapplication-1.2.1-1-x86_64 +installed = kdsoap-2.3.0-1-x86_64 +installed = kdsoap-ws-discovery-client-0.4.0-3-x86_64 +installed = keyutils-1.6.3-4-x86_64 +installed = kfilemetadata-6.26.0-1-x86_64 +installed = kglobalaccel-6.26.0-1-x86_64 +installed = kglobalaccel5-5.116.0-2-x86_64 +installed = kglobalacceld-6.6.5-1-x86_64 +installed = kguiaddons-6.26.0-2-x86_64 +installed = kguiaddons5-5.116.0-2-x86_64 +installed = kholidays-1:6.26.0-1-x86_64 +installed = ki18n-6.26.0-1-x86_64 +installed = ki18n5-5.116.0-2-x86_64 +installed = kiconthemes-6.26.0-1-x86_64 +installed = kiconthemes5-5.116.0-2-x86_64 +installed = kidentitymanagement-26.04.2-1-x86_64 +installed = kidletime-6.26.0-2-x86_64 +installed = kimageannotator-0.7.2-2-x86_64 +installed = kimageformats-6.26.0-1-x86_64 +installed = kimap-26.04.2-1-x86_64 +installed = kio-6.26.0-1-x86_64 +installed = kio-admin-26.04.2-1-x86_64 +installed = kio-extras-26.04.2-1-x86_64 +installed = kio-fuse-5.1.1-2-x86_64 +installed = kio5-5.116.0-6-x86_64 +installed = kirigami-6.26.0-2-x86_64 +installed = kirigami-addons-1.12.1-1-x86_64 +installed = kirigami2-5.116.0-2-x86_64 +installed = kitemmodels-6.26.0-1-x86_64 +installed = kitemviews-6.26.0-1-x86_64 +installed = kitemviews5-5.116.0-2-x86_64 +installed = kitinerary-26.04.2-1-x86_64 +installed = kitty-0.47.1-1-x86_64 +installed = kitty-shell-integration-0.47.1-1-x86_64 +installed = kitty-terminfo-0.47.1-1-x86_64 +installed = kjobwidgets-6.26.0-1-x86_64 +installed = kjobwidgets5-5.116.0-2-x86_64 +installed = kldap-26.04.2-1-x86_64 +installed = kmailtransport-26.04.2-1-x86_64 +installed = kmbox-26.04.2-1-x86_64 +installed = kmenuedit-6.6.5-1-x86_64 +installed = kmime-26.04.2-1-x86_64 +installed = kmod-34.2-1-x86_64 +installed = knewstuff-6.26.0-1-x86_64 +installed = knighttime-6.6.5-1-x86_64 +installed = knotifications-6.26.0-1-x86_64 +installed = knotifications5-5.116.0-3-x86_64 +installed = knotifyconfig-6.26.0-1-x86_64 +installed = konsole-26.04.2-1-x86_64 +installed = kpackage-6.26.0-1-x86_64 +installed = kpackage5-5.116.0-3-x86_64 +installed = kparts-6.26.0-1-x86_64 +installed = kpeople-6.26.0-1-x86_64 +installed = kpimtextedit-26.04.2-1-x86_64 +installed = kpipewire-6.6.5-1-x86_64 +installed = kpkpass-26.04.2-1-x86_64 +installed = kpty-6.26.0-1-x86_64 +installed = kquickcharts-6.26.0-2-x86_64 +installed = kquickimageeditor-0.6.1-2-x86_64 +installed = krb5-1.22.2-1-x86_64 +installed = krunner-6.26.0-1-x86_64 +installed = ksanecore-26.04.2-1-x86_64 +installed = kscreenlocker-6.6.5-1-x86_64 +installed = kservice-6.26.0-1-x86_64 +installed = kservice5-5.116.0-3-x86_64 +installed = ksmtp-26.04.2-1-x86_64 +installed = kstatusnotifieritem-6.26.0-2-x86_64 +installed = ksvg-6.26.0-2-x86_64 +installed = ksystemstats-6.6.5-2-x86_64 +installed = ktextaddons-2.0.2-1-x86_64 +installed = ktexteditor-6.26.0-1-x86_64 +installed = ktexttemplate-6.26.0-2-x86_64 +installed = ktextwidgets-6.26.0-1-x86_64 +installed = ktextwidgets5-5.116.0-2-x86_64 +installed = ktnef-26.04.2-1-x86_64 +installed = kunitconversion-6.26.0-1-x86_64 +installed = kuserfeedback-6.26.0-2-x86_64 +installed = kwallet-6.26.0-1-x86_64 +installed = kwallet5-5.116.0-6-x86_64 +installed = kwayland-6.6.5-1-x86_64 +installed = kwayland5-5.116.0-2-x86_64 +installed = kwidgetsaddons-6.26.0-1-x86_64 +installed = kwidgetsaddons5-5.116.0-2-x86_64 +installed = kwin-6.6.5-4-x86_64 +installed = kwindowsystem-6.26.0-2-x86_64 +installed = kwindowsystem5-5.116.0-2-x86_64 +installed = kxmlgui-6.26.0-1-x86_64 +installed = kxmlgui5-5.116.0-2-x86_64 +installed = l-smash-2.14.5-4-x86_64 +installed = ladspa-1.17-7-x86_64 +installed = lame-3.101.r6531-1-x86_64 +installed = lapack-3.12.1-2-x86_64 +installed = layer-shell-qt-6.6.5-2-x86_64 +installed = lazarus-4.6-1-x86_64 +installed = lcms-1.19-7.1-x86_64 +installed = lcms2-2.19.1-1-x86_64 +installed = ldb-2:4.24.3-1-x86_64 +installed = ldc-3:1.42.0-1-x86_64 +installed = leancrypto-1.7.2-1-x86_64 +installed = lensfun-1:0.3.4-6-x86_64 +installed = leptonica-1.87.0-1-x86_64 +installed = less-1:704-1-x86_64 +installed = level-zero-loader-1.28.2-1-x86_64 +installed = lhasa-0.5.0-1-x86_64 +installed = lib2geom-1.4-3-x86_64 +installed = lib32-aalib-1.4rc5-5-x86_64 +installed = lib32-acl-2.3.2-2-x86_64 +installed = lib32-alsa-lib-1.2.16-1-x86_64 +installed = lib32-alsa-plugins-1.2.12-1-x86_64 +installed = lib32-at-spi2-core-2.60.4-1-x86_64 +installed = lib32-audit-4.1.4-1-x86_64 +installed = lib32-brotli-1.1.0-1-x86_64 +installed = lib32-bzip2-1.0.8-4-x86_64 +installed = lib32-cairo-1.18.4-1-x86_64 +installed = lib32-cdparanoia-10.2-5-x86_64 +installed = lib32-colord-1.4.8-1-x86_64 +installed = lib32-curl-8.20.0-7-x86_64 +installed = lib32-dbus-1.16.2-1-x86_64 +installed = lib32-duktape-2.7.0-7-x86_64 +installed = lib32-e2fsprogs-1.47.4-1-x86_64 +installed = lib32-expat-2.8.1-1-x86_64 +installed = lib32-flac-1.5.0-1-x86_64 +installed = lib32-fontconfig-2:2.18.1-1-x86_64 +installed = lib32-freetype2-2.14.3-1-x86_64 +installed = lib32-fribidi-1.0.16-2-x86_64 +installed = lib32-gcc-libs-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = lib32-gdk-pixbuf2-2.44.6-2-x86_64 +installed = lib32-gettext-1.0-1-x86_64 +installed = lib32-giflib-6.1.3-1-x86_64 +installed = lib32-glib-networking-1:2.80.1-1-x86_64 +installed = lib32-glib2-2.88.1-1-x86_64 +installed = lib32-glibc-2.43+r22+g8362e8ce10b2-2-x86_64 +installed = lib32-gmp-6.3.0-2-x86_64 +installed = lib32-gnutls-3.8.13-3-x86_64 +installed = lib32-gpm-1.20.7.r38.ge82d1a6-2-x86_64 +installed = lib32-gst-plugins-base-libs-1.28.1-3-x86_64 +installed = lib32-gstreamer-1.28.1-3-x86_64 +installed = lib32-gtk3-1:3.24.52-1-x86_64 +installed = lib32-harfbuzz-14.2.1-1-x86_64 +installed = lib32-icu-78.3-1-x86_64 +installed = lib32-imlib2-1.12.6-1-x86_64 +installed = lib32-json-c-0.18-2-x86_64 +installed = lib32-keyutils-1.6.3-4-x86_64 +installed = lib32-krb5-1.22.2-1-x86_64 +installed = lib32-lcms2-2.17-1-x86_64 +installed = lib32-libasyncns-1:0.8+r3+g68cd5af-3-x86_64 +installed = lib32-libavc1394-0.5.4-5-x86_64 +installed = lib32-libcaca-0.99.beta20-2-x86_64 +installed = lib32-libcap-2.78-1-x86_64 +installed = lib32-libcups-2.4.19-1-x86_64 +installed = lib32-libdatrie-0.2.13-3-x86_64 +installed = lib32-libdrm-2.4.134-1-x86_64 +installed = lib32-libdv-1.0.0-9-x86_64 +installed = lib32-libelf-0.195-1-x86_64 +installed = lib32-libepoxy-1.5.10-2-x86_64 +installed = lib32-libffi-3.5.2-1-x86_64 +installed = lib32-libgcrypt-1.12.2-1-x86_64 +installed = lib32-libglvnd-1.7.0-1-x86_64 +installed = lib32-libgpg-error-1.61-1-x86_64 +installed = lib32-libgudev-238-3-x86_64 +installed = lib32-libidn-1.43-1-x86_64 +installed = lib32-libidn11-1.33-3-x86_64 +installed = lib32-libidn2-2.3.8-1-x86_64 +installed = lib32-libiec61883-1.2.0-5-x86_64 +installed = lib32-libjpeg-turbo-3.1.4.1-1-x86_64 +installed = lib32-libjpeg6-turbo-1.5.3-4-x86_64 +installed = lib32-libldap-2.6.13-1-x86_64 +installed = lib32-libnghttp2-1.69.0-1-x86_64 +installed = lib32-libnghttp3-1.16.0-1-x86_64 +installed = lib32-libngtcp2-1.23.0-1-x86_64 +installed = lib32-libnl-3.12.0-1-x86_64 +installed = lib32-libnm-1.56.1-1-x86_64 +installed = lib32-libnsl-2.0.1-2-x86_64 +installed = lib32-libogg-1.3.6-1-x86_64 +installed = lib32-libpcap-1.10.6-1-x86_64 +installed = lib32-libpciaccess-0.19-1-x86_64 +installed = lib32-libpipewire-1:1.6.6-1-x86_64 +installed = lib32-libpng-1.6.58-1-x86_64 +installed = lib32-libproxy-0.5.12-1-x86_64 +installed = lib32-libpsl-0.21.5-1-x86_64 +installed = lib32-libpulse-17.0+r98+gb096704c0-1-x86_64 +installed = lib32-libraw1394-2.1.2-5-x86_64 +installed = lib32-librsvg-2:2.62.3-1-x86_64 +installed = lib32-libshout-1:2.4.6-4-x86_64 +installed = lib32-libsndfile-1.2.2-3-x86_64 +installed = lib32-libsoup3-3.6.6-2-x86_64 +installed = lib32-libssh2-1.11.1-1-x86_64 +installed = lib32-libtasn1-4.21.0-1-x86_64 +installed = lib32-libthai-0.1.29-3-x86_64 +installed = lib32-libtheora-1.2.0-1-x86_64 +installed = lib32-libtiff-4.7.1-1-x86_64 +installed = lib32-libtirpc-1.3.7-1-x86_64 +installed = lib32-libunistring-1.4.2-1-x86_64 +installed = lib32-libunwind-1.8.2-1-x86_64 +installed = lib32-libusb-1.0.30-1-x86_64 +installed = lib32-libva-2.22.0-1-x86_64 +installed = lib32-libvdpau-1.5-3-x86_64 +installed = lib32-libvorbis-1.3.7-4-x86_64 +installed = lib32-libvpx-1.16.0-2-x86_64 +installed = lib32-libwebp-1.6.0-1-x86_64 +installed = lib32-libx11-1.8.13-1-x86_64 +installed = lib32-libxau-1.0.12-1-x86_64 +installed = lib32-libxcb-1.17.0-1-x86_64 +installed = lib32-libxcomposite-0.4.7-1-x86_64 +installed = lib32-libxcrypt-4.5.2-1-x86_64 +installed = lib32-libxcrypt-compat-4.5.2-1-x86_64 +installed = lib32-libxcursor-1.2.3-1-x86_64 +installed = lib32-libxdamage-1.1.7-1-x86_64 +installed = lib32-libxdmcp-1.1.5-1-x86_64 +installed = lib32-libxext-1.3.7-1-x86_64 +installed = lib32-libxfixes-6.0.1-2-x86_64 +installed = lib32-libxft-2.3.9-1-x86_64 +installed = lib32-libxi-1.8.3-1-x86_64 +installed = lib32-libxinerama-1.1.6-1-x86_64 +installed = lib32-libxkbcommon-1.13.2-1-x86_64 +installed = lib32-libxml2-2.15.3-1-x86_64 +installed = lib32-libxrandr-1.5.5-1-x86_64 +installed = lib32-libxrender-0.9.11-2-x86_64 +installed = lib32-libxshmfence-1.3.3-1-x86_64 +installed = lib32-libxss-1.2.5-1-x86_64 +installed = lib32-libxtst-1.2.5-2-x86_64 +installed = lib32-libxv-1.0.12-2-x86_64 +installed = lib32-libxxf86vm-1.1.5-2-x86_64 +installed = lib32-llvm-libs-1:22.1.6-1-x86_64 +installed = lib32-lm_sensors-1:3.6.2-2-x86_64 +installed = lib32-mesa-1:26.1.2-1-x86_64 +installed = lib32-mpg123-1.33.5-1-x86_64 +installed = lib32-ncurses-6.6-2-x86_64 +installed = lib32-nettle-4.0-2-x86_64 +installed = lib32-nspr-4.39-1-x86_64 +installed = lib32-nss-3.124-1-x86_64 +installed = lib32-nvidia-utils-610.43.02-1-x86_64 +installed = lib32-openal-1.25.2-1-x86_64 +installed = lib32-openssl-1:3.6.3-1-x86_64 +installed = lib32-openssl-1.1-1.1.1.w-5-x86_64 +installed = lib32-opus-1.6.1-1-x86_64 +installed = lib32-orc-0.4.42-1-x86_64 +installed = lib32-p11-kit-0.26.2-1-x86_64 +installed = lib32-pam-1.7.1-1-x86_64 +installed = lib32-pango-1:1.57.1-1-x86_64 +installed = lib32-pcre2-10.47-1-x86_64 +installed = lib32-pipewire-1:1.6.6-1-x86_64 +installed = lib32-pipewire-jack-1:1.6.6-1-x86_64 +installed = lib32-pixman-0.46.4-1-x86_64 +installed = lib32-popt-1.19-2-x86_64 +installed = lib32-rust-libs-1:1.96.0-1-x86_64 +installed = lib32-sdl2-compat-2.32.70-1-x86_64 +installed = lib32-sdl3-3.4.10-1-x86_64 +installed = lib32-speex-1.2.1-2-x86_64 +installed = lib32-spirv-tools-1:1.4.350.0-1-x86_64 +installed = lib32-sqlite-3.53.2-1-x86_64 +installed = lib32-systemd-260.2-1-x86_64 +installed = lib32-taglib-2.3-1-x86_64 +installed = lib32-twolame-0.4.0-3-x86_64 +installed = lib32-util-linux-2.42.1-1-x86_64 +installed = lib32-v4l-utils-1.32.0-1-x86_64 +installed = lib32-vkd3d-1.19-1-x86_64 +installed = lib32-vulkan-icd-loader-1.4.350.0-1-x86_64 +installed = lib32-wavpack-5.9.0-1-x86_64 +installed = lib32-wayland-1.25.0-1-x86_64 +installed = lib32-xz-5.8.3-1-x86_64 +installed = lib32-zlib-1.3.2-1-x86_64 +installed = lib32-zstd-1.5.7-2-x86_64 +installed = libaccounts-glib-1.27-3-x86_64 +installed = libaccounts-qt-1.17-2-x86_64 +installed = libadwaita-1:1.9.1-1-x86_64 +installed = libaec-1.1.6-1-x86_64 +installed = libaemu-0.1.2-5-x86_64 +installed = libaio-0.3.113-4-x86_64 +installed = libajantv2-1:17.5.0-1-x86_64 +installed = libajantv2-debug-1:17.5.0-1-x86_64 +installed = libao-1.2.2-7-x86_64 +installed = libappindicator-12.10.1-1-x86_64 +installed = libarchive-3.8.7-1-x86_64 +installed = libasan-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libass-0.17.4-2-x86_64 +installed = libassuan-3.0.0-1-x86_64 +installed = libasyncns-1:0.8+r3+g68cd5af-3-x86_64 +installed = libatasmart-0.19-8-x86_64 +installed = libatomic-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libavc1394-0.5.4-7-x86_64 +installed = libavif-1.4.2-1-x86_64 +installed = libavtp-0.2.0-3-x86_64 +installed = libayatana-indicator-0.9.4-2-x86_64 +installed = libb2-0.98.1-3-x86_64 +installed = libb64-1.2.1-5-x86_64 +installed = libblake3-1.8.4-1-x86_64 +installed = libblockdev-3.5.0-2-x86_64 +installed = libblockdev-crypto-3.5.0-2-x86_64 +installed = libblockdev-fs-3.5.0-2-x86_64 +installed = libblockdev-loop-3.5.0-2-x86_64 +installed = libblockdev-mdraid-3.5.0-2-x86_64 +installed = libblockdev-nvme-3.5.0-2-x86_64 +installed = libblockdev-part-3.5.0-2-x86_64 +installed = libblockdev-smart-3.5.0-2-x86_64 +installed = libblockdev-swap-3.5.0-2-x86_64 +installed = libbluray-1.4.1-1-x86_64 +installed = libbpf-1.7.0-1-x86_64 +installed = libbs2b-3.1.0-10-x86_64 +installed = libbsd-0.12.2-2-x86_64 +installed = libburn-1.5.8-1-x86_64 +installed = libbytesize-2.12-3-x86_64 +installed = libc++-22.1.6-1-x86_64 +installed = libc++abi-22.1.6-1-x86_64 +installed = libcaca-0.99.beta20-7-x86_64 +installed = libcacard-2.8.1-1-x86_64 +installed = libcamera-0.7.1-1-x86_64 +installed = libcamera-ipa-0.7.1-1-x86_64 +installed = libcanberra-1:0.30+r2+gc0620e4-6-x86_64 +installed = libcap-2.78-1-x86_64 +installed = libcap-ng-0.9.3-1-x86_64 +installed = libcbor-0.14.0-1-x86_64 +installed = libcddb-1.3.2-9-x86_64 +installed = libcdio-2.3.0-1-x86_64 +installed = libcdio-paranoia-10.2+2.0.2-2-x86_64 +installed = libcdr-0.1.9-1-x86_64 +installed = libcloudproviders-0.4.0-1-x86_64 +installed = libcolord-1.4.8-1-x86_64 +installed = libcue-2.3.0-2-x86_64 +installed = libcups-2:2.4.19-1-x86_64 +installed = libcupsfilters-2.1.1-4-x86_64 +installed = libdaemon-0.14-6-x86_64 +installed = libdatachannel-0.24.3-2-x86_64 +installed = libdatrie-0.2.14-1-x86_64 +installed = libdbusmenu-glib-18.10.20180917-1-x86_64 +installed = libdbusmenu-gtk3-18.10.20180917-1-x86_64 +installed = libdbusmenu-lxqt-0.4.0-1-x86_64 +installed = libdbusmenu-qt5-0.9.3+16.04.20160218-8-x86_64 +installed = libdc1394-2.2.7-2-x86_64 +installed = libdca-0.0.7-3-x86_64 +installed = libde265-1.1.1-1-x86_64 +installed = libdecor-0.2.5-1-x86_64 +installed = libdeflate-1.25-1-x86_64 +installed = libdisplay-info-0.3.0-1-x86_64 +installed = libdmapsharing-3.9.14-1-x86_64 +installed = libdmtx-0.7.8-1-x86_64 +installed = libdovi-3.3.2-1-x86_64 +installed = libdrm-2.4.134-1-x86_64 +installed = libdv-1.0.0-12-x86_64 +installed = libdvbpsi-1:1.3.3-4-x86_64 +installed = libdvdcss-1.5.0-1-x86_64 +installed = libdvdnav-7.0.0-1-x86_64 +installed = libdvdread-7.0.1-1-x86_64 +installed = libebml-1.4.5-2-x86_64 +installed = libebur128-1.2.6-2-x86_64 +installed = libedit-20260512_3.1-1-x86_64 +installed = libei-1.6.0-1-x86_64 +installed = libelf-0.195-1-x86_64 +installed = libepoxy-1.5.10-3-x86_64 +installed = libev-4.33-5-x86_64 +installed = libevdev-1.13.6-1-x86_64 +installed = libevent-2.1.12-5-x86_64 +installed = libexif-0.6.26-1-x86_64 +installed = libfabric-2.5.1-1-x86_64 +installed = libfakekey-0.3-4-x86_64 +installed = libfdk-aac-2.0.3-2-x86_64 +installed = libffi-3.5.2-1-x86_64 +installed = libfido2-1.17.0-1-x86_64 +installed = libfm-1.4.1-1-x86_64 +installed = libfm-extra-1.4.1-1-x86_64 +installed = libfm-gtk3-1.4.1-1-x86_64 +installed = libfm-qt-2.4.0-2-x86_64 +installed = libfontenc-1.1.9-1-x86_64 +installed = libfreeaptx-0.2.2-1-x86_64 +installed = libftdi-1.5-10-x86_64 +installed = libfyaml-0.9.6-2-x86_64 +installed = libgadu-1.12.2-14-x86_64 +installed = libgbinder-1.1.47-1-x86_64 +installed = libgcc-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libgcrypt-1.12.2-1-x86_64 +installed = libgdata-0.18.1-5-x86_64 +installed = libgdiplus-6.2-1-x86_64 +installed = libgdm-50.1-1-x86_64 +installed = libgee-0.20.8-1-x86_64 +installed = libgexiv2-0.14.6-2-x86_64 +installed = libgfortran-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libgirepository-1.86.0-2-x86_64 +installed = libgit2-1:1.9.4-1-x86_64 +installed = libglade-2.6.4-9-x86_64 +installed = libglibutil-1.0.82-1-x86_64 +installed = libglibutil-debug-1.0.80-1-x86_64 +installed = libglvnd-1.7.0-3-x86_64 +installed = libgme-0.6.5-1-x86_64 +installed = libgnome-keyring-1:3.12.0+r14+g23438cc-1-x86_64 +installed = libgnomekbd-1:3.28.1-2-x86_64 +installed = libgoa-3.58.1-1-x86_64 +installed = libgomp-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libgovirt-2:0.3.11-1-x86_64 +installed = libgpg-error-1.61-1-x86_64 +installed = libgphobos-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libgphoto2-2.5.34-1-x86_64 +installed = libgpod-0.8.3-20-x86_64 +installed = libgravatar-26.04.2-1-x86_64 +installed = libgsf-1.14.58-1-x86_64 +installed = libgtop-2.41.3-2-x86_64 +installed = libgudev-238-3-x86_64 +installed = libgusb-0.4.9-2-x86_64 +installed = libgweather-4-4.6.0-1-x86_64 +installed = libgxps-0.3.2-5-x86_64 +installed = libhandy-1.8.3-2-x86_64 +installed = libharu-2.4.6-1-x86_64 +installed = libheif-1.23.0-1-x86_64 +installed = libibus-1.5.34-1-x86_64 +installed = libical-4.0.2-1-x86_64 +installed = libice-1.1.2-1-x86_64 +installed = libiconv-1.19-1-x86_64 +installed = libid3tag-0.16.4-1-x86_64 +installed = libidn-1.43-1-x86_64 +installed = libidn2-2.3.8-1-x86_64 +installed = libiec61883-1.2.0-9-x86_64 +installed = libieee1284-0.2.11-19-x86_64 +installed = libimagequant-4.4.1-2-x86_64 +installed = libimobiledevice-1.4.0-2-x86_64 +installed = libimobiledevice-glue-1.3.2-1-x86_64 +installed = libindicator-12.10.1-11-x86_64 +installed = libinih-62-2-x86_64 +installed = libinput-1.31.3-1-x86_64 +installed = libinstpatch-1.1.7-2-x86_64 +installed = libiptcdata-1.0.5-5-x86_64 +installed = libiscsi-1.20.3-1-x86_64 +installed = libisl-0.27-1-x86_64 +installed = libisoburn-1.5.8.2-1-x86_64 +installed = libisofs-1.5.8.2-1-x86_64 +installed = libjcat-0.2.6-1-x86_64 +installed = libjpeg-turbo-3.1.4.1-1-x86_64 +installed = libjpeg6-turbo-1.5.3-3-x86_64 +installed = libjuice-1.7.2-1-x86_64 +installed = libjxl-0.11.2-2-x86_64 +installed = libkate-0.4.3-4-x86_64 +installed = libkdcraw-26.04.2-1-x86_64 +installed = libkdepim-26.04.2-1-x86_64 +installed = libkexiv2-26.04.2-1-x86_64 +installed = libkeybinder3-0.3.2-5-x86_64 +installed = libkgapi-26.04.2-1-x86_64 +installed = libkleo-26.04.2-1-x86_64 +installed = libksba-1.8.0-1-x86_64 +installed = libkscreen-6.6.5-1-x86_64 +installed = libksieve-26.04.2-1-x86_64 +installed = libksysguard-6.6.5-2-x86_64 +installed = liblc3-1.1.3-2-x86_64 +installed = libldac-2.0.2.3-3-x86_64 +installed = libldap-2.6.13-1-x86_64 +installed = liblouis-3.38.0-1-x86_64 +installed = liblphobos-3:1.42.0-1-x86_64 +installed = liblqr-0.4.3-1-x86_64 +installed = liblrdf-0.6.1-5-x86_64 +installed = liblsan-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libltc-1.3.2-2-x86_64 +installed = liblxqt-2.4.0-1-x86_64 +installed = liblzf-3.6-5-x86_64 +installed = libmad-0.15.1b-10-x86_64 +installed = libmakepkg-dropins-20-1-any +installed = libmalcontent-0.14.0-4-x86_64 +installed = libmanette-0.2.13-2-x86_64 +installed = libmatroska-1.7.1-2-x86_64 +installed = libmbim-1.34.0-1-x86_64 +installed = libmd-1.2.0-1-x86_64 +installed = libmediaart-1.9.7-2-x86_64 +installed = libmediainfo-26.05-1-x86_64 +installed = libmfx-23.2.2-6-x86_64 +installed = libmicrodns-0.2.0-2-x86_64 +installed = libmicrohttpd-1.0.5-1-x86_64 +installed = libmikmod-3.3.13-1-x86_64 +installed = libmm-glib-1.24.2-1-x86_64 +installed = libmms-0.6.4-6-x86_64 +installed = libmng-2.0.3-4-x86_64 +installed = libmnl-1.0.5-2-x86_64 +installed = libmodplug-0.8.9.0-7-x86_64 +installed = libmp3splt-0.9.3.1519+r5+g4b48268-4-x86_64 +installed = libmp3splt-debug-0.9.3.1519+r5+g4b48268-4-x86_64 +installed = libmpc-1.4.1-1-x86_64 +installed = libmpcdec-1:0.1+r475-6-x86_64 +installed = libmpeg2-0.5.1-11-x86_64 +installed = libmspack-1:1.11-2-x86_64 +installed = libmtp-1.1.23-1-x86_64 +installed = libmypaint-1.6.1-2-x86_64 +installed = libmysofa-1.3.4-1-x86_64 +installed = libnatpmp-20230423-3-x86_64 +installed = libnautilus-extension-50.2.2-1-x86_64 +installed = libnbd-1.24.2-2-x86_64 +installed = libndp-1.9-1-x86_64 +installed = libnet-2:1.3-2-x86_64 +installed = libnetfilter_conntrack-1.1.1-1-x86_64 +installed = libnewt-0.52.25-2-x86_64 +installed = libnfnetlink-1.0.2-2-x86_64 +installed = libnfs-6.0.2-5-x86_64 +installed = libnftnl-1.3.1-1-x86_64 +installed = libnghttp2-1.69.0-1-x86_64 +installed = libnghttp3-1.16.0-1-x86_64 +installed = libngtcp2-1.23.0-1-x86_64 +installed = libnice-0.1.23-1-x86_64 +installed = libnl-3.12.0-1-x86_64 +installed = libnm-1.56.1-1-x86_64 +installed = libnma-1.10.6-3-x86_64 +installed = libnma-common-1.10.6-3-x86_64 +installed = libnma-gtk4-1.10.6-3-x86_64 +installed = libnotify-0.8.8-1-x86_64 +installed = libnsl-2.0.1-2-x86_64 +installed = libnss_nis-3.4-1-x86_64 +installed = libntfs-3g-2026.2.25-1-x86_64 +installed = libnvidia-container-1.19.1-1-x86_64 +installed = libnvme-1.16.1-3-x86_64 +installed = liboauth-1:1.0.3+r16+gc26f038-2-x86_64 +installed = libobjc-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libodfgen-0.1.8-5-x86_64 +installed = libofx-0.10.9-2-x86_64 +installed = libogg-1.3.6-1-x86_64 +installed = liboggz-1.1.3-1-x86_64 +installed = libomxil-bellagio-0.9.3-5-x86_64 +installed = libopenmpt-0.8.7-1-x86_64 +installed = libosinfo-1.12.0-3-x86_64 +installed = libp11-0.4.18-1-x86_64 +installed = libp11-kit-0.26.2-1-x86_64 +installed = libpackagekit-glib-1.3.5-1-x86_64 +installed = libpamac-full-1:11.7.4.3.gc7efe92-1-x86_64 +installed = libpaper-2.2.8-1-x86_64 +installed = libpcap-1.10.6-1-x86_64 +installed = libpciaccess-0.19-1-x86_64 +installed = libpeas-1.38.1-1-x86_64 +installed = libpgm-5.3.128-4-x86_64 +installed = libphobos-1:2.112.1-2-x86_64 +installed = libphonenumber-1:9.0.32-1-x86_64 +installed = libpipeline-1.5.8-1-x86_64 +installed = libpipewire-1:1.6.6-1-x86_64 +installed = libplacebo-7.360.1-2-x86_64 +installed = libplasma-6.6.5-1-x86_64 +installed = libplist-2.7.0-3-x86_64 +installed = libpng-1.6.58-1-x86_64 +installed = libportal-0.9.1-3-x86_64 +installed = libportal-gtk3-0.9.1-3-x86_64 +installed = libportal-gtk4-0.9.1-3-x86_64 +installed = libportal-qt6-0.9.1-3-x86_64 +installed = libppd-2.1.1-2-x86_64 +installed = libproxy-0.5.12-1-x86_64 +installed = libpsl-0.21.5-2-x86_64 +installed = libpst-0.6.76-10-x86_64 +installed = libpulse-17.0+r98+gb096704c0-1-x86_64 +installed = libpwquality-1.4.5-7-x86_64 +installed = libqaccessibilityclient-qt6-0.6.0-4-x86_64 +installed = libqalculate-5.11.0-1-x86_64 +installed = libqmi-1.38.0-1-x86_64 +installed = libqrtr-glib-1.4.0-1-x86_64 +installed = libqtxdg-4.4.0-2-x86_64 +installed = libquadmath-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libquicktime-1.2.4-34-x86_64 +installed = libraqm-0.10.5-1-x86_64 +installed = libraw-0.22.1-1-x86_64 +installed = libraw1394-2.1.2-4-x86_64 +installed = librest-0.10.2-1-x86_64 +installed = librevenge-0.0.5-4-x86_64 +installed = librist-0.2.17-1-x86_64 +installed = librsvg-2:2.62.3-1-x86_64 +installed = librsync-1:2.3.4-2-x86_64 +installed = libsamplerate-0.2.2-3-x86_64 +installed = libsasl-2.1.28-5-x86_64 +installed = libsass-3.6.6-2-x86_64 +installed = libsbsms-2.3.0-6-x86_64 +installed = libseccomp-2.6.0-1-x86_64 +installed = libsecret-0.21.7-1-x86_64 +installed = libshout-1:2.4.6-5-x86_64 +installed = libsigc++-2.12.2-1-x86_64 +installed = libsigc++-3.0-3.8.1-1-x86_64 +installed = libsigsegv-2.15-1-x86_64 +installed = libsixel-1.10.5-1-x86_64 +installed = libslirp-4.9.3-1-x86_64 +installed = libsm-1.2.6-1-x86_64 +installed = libsndfile-1.2.2-4-x86_64 +installed = libsodium-1.0.22-1-x86_64 +installed = libsonic-0.2.0-2-x86_64 +installed = libsoup-2.74.3-4-x86_64 +installed = libsoup3-3.6.6-2-x86_64 +installed = libsoxr-0.1.3-4-x86_64 +installed = libspatialindex-2.1.0-1-x86_64 +installed = libspectre-0.2.12-2-x86_64 +installed = libspeechd-0.12.1-3-x86_64 +installed = libspelling-0.4.10-1-x86_64 +installed = libspiro-1:20240903-1-x86_64 +installed = libspnav-1.2-1-x86_64 +installed = libsrtp-1:2.8.0-1-x86_64 +installed = libssc-0.4.3-1-x86_64 +installed = libssh-0.12.0-1-x86_64 +installed = libssh2-1.11.1-1-x86_64 +installed = libstdc++-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libstemmer-3.1.1-1-x86_64 +installed = libsynctex-2026.0-2-x86_64 +installed = libsysprof-capture-50.0-2-x86_64 +installed = libtar-1.2.20-8-x86_64 +installed = libtasn1-4.21.0-1-x86_64 +installed = libtatsu-1.0.5-1-x86_64 +installed = libteam-1.32-3-x86_64 +installed = libthai-0.1.30-1-x86_64 +installed = libtheora-1.2.0-1-x86_64 +installed = libtiff-4.7.1-2-x86_64 +installed = libtiff5-4.4.0-2-x86_64 +installed = libtirpc-1.3.7-1-x86_64 +installed = libtommath-1.3.0-2-x86_64 +installed = libtool-2.6.1-1-x86_64 +installed = libtpms-0.10.2-1-x86_64 +installed = libtraceevent-1:1.9.0-1-x86_64 +installed = libtracefs-1.8.3-1-x86_64 +installed = libtsan-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libubsan-16.1.1+r12+g301eb08fa2c5-1-x86_64 +installed = libunibreak-7.0-1-x86_64 +installed = libunistring-1.4.2-1-x86_64 +installed = libunwind-1.8.2-1-x86_64 +installed = libupnp-1.14.31-1-x86_64 +installed = liburcu-0.15.6-1-x86_64 +installed = liburing-2.14-1-x86_64 +installed = libusb-1.0.30-1-x86_64 +installed = libusb-compat-0.1.9-1-x86_64 +installed = libusbmuxd-2.1.1-2-x86_64 +installed = libutempter-1.2.3-1-x86_64 +installed = libutf8proc-2.11.3-1-x86_64 +installed = libuv-1.52.1-1-x86_64 +installed = libva-2.23.0-1-x86_64 +installed = libva-intel-driver-2.4.1-7-x86_64 +installed = libva-utils-2.23.0-1-x86_64 +installed = libvdpau-1.5-4-x86_64 +installed = libverto-0.3.2-6-x86_64 +installed = libvirt-1:12.4.0-1-x86_64 +installed = libvirt-glib-5.0.0-3-x86_64 +installed = libvirt-python-1:12.4.0-1-x86_64 +installed = libvisio-0.1.11-1-x86_64 +installed = libvlc-3.0.23_2-6-x86_64 +installed = libvncserver-0.9.15-1-x86_64 +installed = libvoikko-4.3.3-3-x86_64 +installed = libvorbis-1.3.7-4-x86_64 +installed = libvpl-2.16.0-2-x86_64 +installed = libvpx-1.16.0-3-x86_64 +installed = libwacom-2.19.0-1-x86_64 +installed = libwbclient-2:4.24.3-1-x86_64 +installed = libwebp-1.6.0-2-x86_64 +installed = libwireplumber-0.5.14-1-x86_64 +installed = libwireplumber-4.0-compat-0.4.17-2-x86_64 +installed = libwireplumber-4.0-compat-debug-0.4.17-2-x86_64 +installed = libwmf-0.2.15-1-x86_64 +installed = libwnck3-43.3-1-x86_64 +installed = libwpd-0.10.3-6-x86_64 +installed = libwpg-0.3.4-3-x86_64 +installed = libx11-1.8.13-1-x86_64 +installed = libx86-1.1.1-1-x86_64 +installed = libx86emu-3.7-2-x86_64 +installed = libxau-1.0.12-1-x86_64 +installed = libxaw-1.0.16-2-x86_64 +installed = libxcb-1.17.0-1-x86_64 +installed = libxcomposite-0.4.7-1-x86_64 +installed = libxcrypt-4.5.2-1-x86_64 +installed = libxcrypt-compat-4.5.2-1-x86_64 +installed = libxcursor-1.2.3-1-x86_64 +installed = libxcvt-0.1.3-1-x86_64 +installed = libxdamage-1.1.7-1-x86_64 +installed = libxdg-basedir-1.2.3-3-x86_64 +installed = libxdmcp-1.1.5-2-x86_64 +installed = libxdp-1.6.3-1-x86_64 +installed = libxext-1.3.7-1-x86_64 +installed = libxfce4ui-4.20.2-1-x86_64 +installed = libxfce4util-4.20.1-1-x86_64 +installed = libxfce4windowing-4.20.6-1-x86_64 +installed = libxfixes-6.0.2-1-x86_64 +installed = libxfont2-2.0.7-1-x86_64 +installed = libxft-2.3.9-1-x86_64 +installed = libxi-1.8.3-1-x86_64 +installed = libxinerama-1.1.6-1-x86_64 +installed = libxkbcommon-1.13.2-1-x86_64 +installed = libxkbcommon-x11-1.13.2-1-x86_64 +installed = libxkbfile-1.2.0-1-x86_64 +installed = libxklavier-5.4-7-x86_64 +installed = libxml++2.6-2.42.4-1-x86_64 +installed = libxml2-2.15.3-1-x86_64 +installed = libxml2-legacy-2.13.9-2-x86_64 +installed = libxmlb-0.3.27-1-x86_64 +installed = libxmp-4.7.0-1-x86_64 +installed = libxmu-1.3.1-1-x86_64 +installed = libxnvctrl-610.43.02-1-x86_64 +installed = libxpm-3.5.19-1-x86_64 +installed = libxpresent-1.0.2-1-x86_64 +installed = libxrandr-1.5.5-1-x86_64 +installed = libxrender-0.9.12-1-x86_64 +installed = libxres-1.2.3-1-x86_64 +installed = libxshmfence-1.3.3-1-x86_64 +installed = libxslt-1.1.45-2-x86_64 +installed = libxss-1.2.5-1-x86_64 +installed = libxt-1.3.1-1-x86_64 +installed = libxtst-1.2.5-1-x86_64 +installed = libxv-1.0.13-1-x86_64 +installed = libxvmc-1.0.15-1-x86_64 +installed = libxxf86vm-1.1.7-1-x86_64 +installed = libyaml-0.2.5-3-x86_64 +installed = libytnef-1:2.1.2-2-x86_64 +installed = libyuv-r2426+464c51a03-1-x86_64 +installed = libzen-0.4.41-3-x86_64 +installed = libzip-1.11.4-1-x86_64 +installed = licenses-20240728-1-any +installed = lightdm-1:1.32.0-6-x86_64 +installed = lightdm-gtk-greeter-1:2.0.9-2-x86_64 +installed = lightdm-gtk-greeter-settings-1.2.3-4-any +installed = lightdm-settings-2.1.1-1-any +installed = lightdm-slick-greeter-2.2.6-1-x86_64 +installed = lilv-0.26.4-1-x86_64 +installed = linphone-desktop-appimage-6.1.2-1-x86_64 +installed = linux-7.0.11.arch1-1-x86_64 +installed = linux-api-headers-7.0-1-x86_64 +installed = linux-firmware-20260519-1-any +installed = linux-firmware-amdgpu-20260519-1-any +installed = linux-firmware-atheros-20260519-1-any +installed = linux-firmware-broadcom-20260519-1-any +installed = linux-firmware-cirrus-20260519-1-any +installed = linux-firmware-intel-20260519-1-any +installed = linux-firmware-mediatek-20260519-1-any +installed = linux-firmware-nvidia-20260519-1-any +installed = linux-firmware-other-20260519-1-any +installed = linux-firmware-radeon-20260519-1-any +installed = linux-firmware-realtek-20260519-1-any +installed = linux-firmware-whence-20260519-1-any +installed = linux-headers-7.0.11.arch1-1-x86_64 +installed = linux-zen-7.0.11.zen1-1-x86_64 +installed = linux-zen-headers-7.0.11.zen1-1-x86_64 +installed = lirc-1:0.10.2-6-x86_64 +installed = litehtml-0.9-3-x86_64 +installed = lksctp-tools-1.0.21-1-x86_64 +installed = lld-22.1.6-1-x86_64 +installed = llhttp-9.3.1-1-x86_64 +installed = llvm-22.1.6-1-x86_64 +installed = llvm-libs-22.1.6-1-x86_64 +installed = llvm15-libs-15.0.7-3-x86_64 +installed = llvm20-libs-20.1.8-1-x86_64 +installed = llvm21-21.1.8-1-x86_64 +installed = llvm21-libs-21.1.8-1-x86_64 +installed = lm_sensors-1:3.6.2-1-x86_64 +installed = lmdb-0.9.35-1-x86_64 +installed = localsearch-3.11.1-1-x86_64 +installed = log4cplus-2.1.2-1-x86_64 +installed = lsb-release-2.0.r55.a25a4fc-1-any +installed = lshw-B.02.20-3-x86_64 +installed = lsof-4.99.6-1-x86_64 +installed = lua-5.5.0-2-x86_64 +installed = lua51-5.1.5-13-x86_64 +installed = lua53-5.3.6-4-x86_64 +installed = lua53-lgi-0.9.2-14-x86_64 +installed = lua54-5.4.8-6-x86_64 +installed = luajit-2.1.1780076327+b925b3e-1-x86_64 +installed = luanti-5.15.1-1-x86_64 +installed = luanti-common-5.15.1-1-x86_64 +installed = luit-20250912-1-x86_64 +installed = lutris-0.5.22-1-any +installed = lv2-1.18.10-2-x86_64 +installed = lvm2-2.03.41-1-x86_64 +installed = lxc-1:7.0.0-1-x86_64 +installed = lximage-qt-2.4.0-1-x86_64 +installed = lxmenu-data-0.1.7-1-any +installed = lxqt-about-2.4.0-1-x86_64 +installed = lxqt-admin-2.4.0-1-x86_64 +installed = lxqt-archiver-1.4.0-1-x86_64 +installed = lxqt-config-2.4.0-1-x86_64 +installed = lxqt-globalkeys-2.4.0-1-x86_64 +installed = lxqt-menu-data-2.4.0-1-any +installed = lxqt-notificationd-2.4.0-1-x86_64 +installed = lxqt-openssh-askpass-2.4.0-1-x86_64 +installed = lxqt-panel-2.4.1-1-x86_64 +installed = lxqt-policykit-2.4.0-1-x86_64 +installed = lxqt-powermanagement-2.4.0-1-x86_64 +installed = lxqt-qtplugin-2.4.0-2-x86_64 +installed = lxqt-runner-2.4.0-1-x86_64 +installed = lxqt-session-2.4.0-2-x86_64 +installed = lxqt-sudo-2.4.0-1-x86_64 +installed = lxqt-themes-2.4.0-1-any +installed = lz4-1:1.10.0-2-x86_64 +installed = lzo-2.10-5-x86_64 +installed = m4-1.4.21-2-x86_64 +installed = m68k-elf-binutils-2.45-1-x86_64 +installed = mailcap-2.1.54-2-any +installed = mailcommon-26.04.2-1-x86_64 +installed = mailimporter-26.04.2-1-x86_64 +installed = make-4.4.1-3-x86_64 +installed = mallard-ducktype-1.0.2-13-any +installed = man-db-2.13.1-1-x86_64 +installed = man2html-3.0.1-10-any +installed = mangohud-0.8.4-1-x86_64 +installed = manifold-3.4.1-1-x86_64 +installed = mariadb-12.3.2-2-x86_64 +installed = mariadb-clients-12.3.2-2-x86_64 +installed = mariadb-libs-12.3.2-2-x86_64 +installed = masterpdfeditor-5.9.98-2-x86_64 +installed = masterpdfeditor-debug-5.9.94-1-x86_64 +installed = masterpdfeditor-free-4.3.89-1-x86_64 +installed = mate-desktop-1.28.2-2-x86_64 +installed = mate-system-monitor-1.28.1-3-x86_64 +installed = materialx-1.39.4-5-x86_64 +installed = mathjax2-2.7.9-2-any +installed = maturin-1.13.3-1-x86_64 +installed = mbedtls-3.6.5-1-x86_64 +installed = mbedtls2-2.28.10-1-x86_64 +installed = md4c-0.5.3-1-x86_64 +installed = mdadm-4.6-2-x86_64 +installed = media-player-info-26-1-any +installed = mediainfo-26.05-1-x86_64 +installed = menu-cache-1.1.1-2-x86_64 +installed = mercurial-7.2.2-1-x86_64 +installed = mesa-1:26.1.2-1-x86_64 +installed = mesa-utils-9.0.0-7-x86_64 +installed = meson-1.11.1-3-any +installed = messagelib-26.04.2-1-x86_64 +installed = micromamba-bin-2.8.0.0-1-x86_64 +installed = micropolis-git-r113.f46cb0f-1-x86_64 +installed = milou-6.6.5-1-x86_64 +installed = mingw-w64-binutils-2.46.0-1-x86_64 +installed = mingw-w64-crt-14.0.0-1-any +installed = mingw-w64-gcc-16.1.0-1-x86_64 +installed = mingw-w64-headers-14.0.0-1-any +installed = mingw-w64-winpthreads-14.0.0-1-any +installed = minicom-2.11.1-3-x86_64 +installed = miniupnpc-2.3.3-3-x86_64 +installed = minizip-1:1.3.2-3-x86_64 +installed = minizip-ng-4.2.1-1-x86_64 +installed = mjpegtools-2.2.1-4-x86_64 +installed = mkinitcpio-41-4-any +installed = mkinitcpio-busybox-1.36.1-1-x86_64 +installed = mlt-7.38.0-1-x86_64 +installed = mobile-broadband-provider-info-20251101-1-any +installed = mod_dnssd-0.6-10-x86_64 +installed = modemmanager-1.24.2-1-x86_64 +installed = modemmanager-qt-6.26.0-1-x86_64 +installed = mono-6.12.0.206-1-x86_64 +installed = mousepad-0.7.0-1-x86_64 +installed = movit-1.7.2-2-x86_64 +installed = mp3splt-2.6.3.1519+r2+g4b48268-3-x86_64 +installed = mp3wrap-0.5-7-x86_64 +installed = mpdecimal-4.0.1-3-x86_64 +installed = mpfr-4.2.2-1-x86_64 +installed = mpg123-1.33.5-1-x86_64 +installed = mplayer-38542-6-x86_64 +installed = mpv-1:0.41.0-3-x86_64 +installed = ms-sys-1:2.8.0-1-x86_64 +installed = mtdev-1.1.7-1-x86_64 +installed = mtools-1:4.0.49-1-x86_64 +installed = mtr-0.96-1-x86_64 +installed = muffin-6.6.3-1-x86_64 +installed = mujs-1.3.9-1-x86_64 +installed = multipath-tools-0.14.3-1-x86_64 +installed = muparser-2.3.5-2-x86_64 +installed = mutter-50.2-2-x86_64 +installed = mypaint-brushes-2.0.2-2-any +installed = mypaint-brushes1-1.3.1-2-any +installed = namcap-3.6.0-3-any +installed = nanobind-2.12.0-3-any +installed = nasm-3.01-1-x86_64 +installed = nautilus-50.2.2-1-x86_64 +installed = nautilus-python-4.1.0-3-x86_64 +installed = ncurses-6.6-2-x86_64 +installed = ndctl-84-1-x86_64 +installed = nemo-6.6.4-1-x86_64 +installed = nemo-python-6.6.0-4-x86_64 +installed = nemo-terminal-6.6.0-4-x86_64 +installed = neofetch-7.1.0-2-any +installed = neon-0.37.1-1-x86_64 +installed = net-snmp-5.9.5.2-1-x86_64 +installed = net-tools-2.10-3-x86_64 +installed = netctl-1.29-2-any +installed = netpbm-10.86.49-3-x86_64 +installed = nettle-4.0-1-x86_64 +installed = network-manager-applet-1.36.0-2-x86_64 +installed = networkmanager-1.56.1-1-x86_64 +installed = networktablet-1.5-3-x86_64 +installed = nextcloud-33.0.5-1-any +installed = nextcloud-app-spreed-1:23.0.6-1-any +installed = nextcloud-app-talk_matterbridge-1.33.1026000-1-any +installed = nextcloud-client-2:33.0.5-1-x86_64 +installed = nfs-utils-2.9.1-1-x86_64 +installed = nfsidmap-2.9.1-1-x86_64 +installed = nftables-1:1.1.6-3-x86_64 +installed = ngspice-46-2-x86_64 +installed = ninja-1.13.2-3-x86_64 +installed = nlohmann-json-3.12.0-2-any +installed = nm-connection-editor-1.36.0-2-x86_64 +installed = node-gyp-12.4.0-1-any +installed = nodejs-26.2.0-1-x86_64 +installed = nodejs-nopt-10.0.1-1-any +installed = noise-suppression-for-voice-1.21-1-x86_64 +installed = nordic-theme-2.2.0-1-any +installed = noto-fonts-1:2026.06.01-1-any +installed = noto-fonts-emoji-1:2.051-1-any +installed = notparadoxlauncher-1.3.1-4-x86_64 +installed = notparadoxlauncher-debug-1.3.1-4-x86_64 +installed = npm-11.16.0-1-any +installed = npth-1.8-1-x86_64 +installed = nrg2iso-0.4.1-3-x86_64 +installed = nspr-4.39-1-x86_64 +installed = nss-3.124-1-x86_64 +installed = nss-mdns-0.15.1-2-x86_64 +installed = ntfs-3g-2026.2.25-1-x86_64 +installed = ntp-4.2.8.p18-6-x86_64 +installed = numactl-2.0.19-1-x86_64 +installed = nvidia-container-toolkit-1.19.1-1-x86_64 +installed = nvidia-open-dkms-610.43.02-2-x86_64 +installed = nvidia-settings-610.43.02-1-x86_64 +installed = nvidia-utils-610.43.02-2-x86_64 +installed = nvm-0.40.4-1-any +installed = obconf-qt-0.16.6-1-x86_64 +installed = obs-studio-git-32.1.0.r13.g1159bc8-1-x86_64 +installed = obs-teleport-0.7.5-1-x86_64 +installed = obs-teleport-debug-0.7.5-1-x86_64 +installed = obs-vkcapture-1.5.6-1-x86_64 +installed = obs-vkcapture-debug-1.5.3-1-x86_64 +installed = ocean-sound-theme-6.6.5-1-any +installed = ocl-icd-2.3.4-1-x86_64 +installed = ocs-url-3.1.0-7-x86_64 +installed = onetbb-2023.0.0-1-x86_64 +installed = oniguruma-6.9.10-1-x86_64 +installed = openal-1.25.2-1-x86_64 +installed = openblas-0.3.33-1-x86_64 +installed = openbox-3.6.1-14-x86_64 +installed = opencamlib-2023.01.11-4-x86_64 +installed = opencascade-1:7.9.3-3-x86_64 +installed = opencl-headers-2:2025.07.22-1-any +installed = opencl-nvidia-610.43.02-2-x86_64 +installed = opencolorio-2.5.1-1-x86_64 +installed = opencore-amr-0.1.6-2-x86_64 +installed = opencv-4.13.0-9-x86_64 +installed = openexr-3.4.12-1-x86_64 +installed = openh264-2.6.0-2-x86_64 +installed = openimagedenoise-2.4.1-2-x86_64 +installed = openimageio-3.1.12.1-1-x86_64 +installed = openjpeg2-2.5.4-1-x86_64 +installed = openjph-0.27.4-1-x86_64 +installed = openmp-22.1.6-1-x86_64 +installed = openmpi-5.0.10-2-x86_64 +installed = openpace-1.1.4-2-x86_64 +installed = openpgl-0.7.1-1-x86_64 +installed = openpmix-5.0.10-2-x86_64 +installed = openresolv-3.17.4-1-any +installed = opensc-0.27.1-2-x86_64 +installed = openshadinglanguage-1.15.3.0-1-x86_64 +installed = opensp-1.5.2-11-x86_64 +installed = openssh-10.3p1-1-x86_64 +installed = openssl-3.6.3-1-x86_64 +installed = openssl-1.1-1.1.1.w-10-x86_64 +installed = opensubdiv-3.7.0-1-x86_64 +installed = opentimelineio-0.18.1-3-x86_64 +installed = opentrack-git-1:2024.1.1+r6883.20250506.6aae7665-1-x86_64 +installed = openucx-1.20.1-1-x86_64 +installed = openvdb-13.0.0-1-x86_64 +installed = openvpn-2.7.4-1-x86_64 +installed = openvr-2.15.6-1-x86_64 +installed = openxr-1.1.60-1-x86_64 +installed = optipng-7.9.1-1-x86_64 +installed = opus-1.6.1-1-x86_64 +installed = opusfile-0.12-4-x86_64 +installed = orc-0.4.42-1-x86_64 +installed = orca-50.2-1-any +installed = os-prober-1.84-1-x86_64 +installed = osinfo-db-20251212-1-any +installed = ostree-2025.7-3-x86_64 +installed = p11-kit-0.26.2-1-x86_64 +installed = packagekit-1.3.5-1-x86_64 +installed = packagekit-qt5-1.1.3-1-x86_64 +installed = pacman-7.1.0.r9.g54d9411-2-x86_64 +installed = pacman-mirrorlist-20260406-1-any +installed = pahole-1:1.31-2-x86_64 +installed = pam-1.7.2-2-x86_64 +installed = pamac-all-11.7.5-1-x86_64 +installed = pamac-all-git-debug-1:1.7.1.r1.g61b7570-1-x86_64 +installed = pamac-cli-11.7.4-1-x86_64 +installed = pambase-20250719-1-any +installed = pango-1:1.57.1-1-x86_64 +installed = pangomm-2.46.4-3-x86_64 +installed = pangomm-2.48-2.56.1-2-x86_64 +installed = papirus-icon-theme-20250501-1-any +installed = paprefs-1.2-3-x86_64 +installed = parted-3.7-1-x86_64 +installed = passim-0.1.11-1-x86_64 +installed = patch-2.8-1-x86_64 +installed = patchelf-0.18.0-4-x86_64 +installed = pavucontrol-1:6.2-1-x86_64 +installed = pavucontrol-qt-2.4.0-1-x86_64 +installed = pcaudiolib-1.3-1-x86_64 +installed = pciutils-3.15.0-1-x86_64 +installed = pcmanfm-1.4.0-2-x86_64 +installed = pcmanfm-qt-2.4.0-1-x86_64 +installed = pcre-8.45-4-x86_64 +installed = pcre2-10.47-1-x86_64 +installed = pcsclite-2.5.0-1-x86_64 +installed = perl-5.42.2-1-x86_64 +installed = perl-alien-build-2.84-4-any +installed = perl-alien-libxml2-0.20-5-any +installed = perl-archive-cpio-0.10-12-any +installed = perl-archive-zip-1.68-12-any +installed = perl-bytes-random-secure-0.29-15-any +installed = perl-capture-tiny-0.50-4-any +installed = perl-class-inspector-1.36-10-any +installed = perl-clone-0.50-1-x86_64 +installed = perl-crypt-openssl-bignum-0.09-12-x86_64 +installed = perl-crypt-openssl-random-0.17-3-x86_64 +installed = perl-crypt-openssl-rsa-0.41-1-x86_64 +installed = perl-crypt-random-seed-0.03-13-any +installed = perl-crypt-ssleay-0.73_06-7-x86_64 +installed = perl-cryptx-0.089-1-x86_64 +installed = perl-data-optlist-0.114-7-any +installed = perl-dbi-1.647-2-x86_64 +installed = perl-digest-hmac-1.05-3-any +installed = perl-digest-sha1-2.13-22-x86_64 +installed = perl-encode-locale-1.05-15-any +installed = perl-error-0.17030-3-any +installed = perl-ffi-checklib-0.31-8-any +installed = perl-file-chdir-0.1011-6-any +installed = perl-file-listing-6.16-6-any +installed = perl-file-sharedir-1.118-8-any +installed = perl-file-which-1.27-8-any +installed = perl-html-parser-3.85-1-x86_64 +installed = perl-html-tagset-3.24-4-any +installed = perl-http-cookiejar-0.014-5-any +installed = perl-http-cookies-6.11-4-any +installed = perl-http-daemon-6.17-1-any +installed = perl-http-date-6.06-5-any +installed = perl-http-message-7.02-1-any +installed = perl-http-negotiate-6.01-16-any +installed = perl-io-html-1.004-8-any +installed = perl-io-socket-inet6-2.73-7-any +installed = perl-io-socket-ssl-2.098-1-any +installed = perl-json-4.11-1-any +installed = perl-libintl-perl-1.37-1-x86_64 +installed = perl-libwww-6.83-1-any +installed = perl-locale-gettext-1.07-16-x86_64 +installed = perl-lwp-mediatypes-6.04-8-any +installed = perl-lwp-protocol-https-6.15-1-any +installed = perl-mail-authenticationresults-2.20260216-1-any +installed = perl-mail-dkim-1.20240923-3-any +installed = perl-mail-spf-3.20260331-1-any +installed = perl-mailtools-2.22-3-any +installed = perl-math-random-isaac-1.004-14-any +installed = perl-mime-charset-1.013.1-6-any +installed = perl-net-dns-1.54-1-any +installed = perl-net-http-6.24-2-any +installed = perl-net-ip-1.26-16-any +installed = perl-net-ssleay-1.96-1-x86_64 +installed = perl-netaddr-ip-4.079-17-x86_64 +installed = perl-params-util-1.102-7-x86_64 +installed = perl-path-class-0.37-13-any +installed = perl-path-tiny-0.150-2-any +installed = perl-pod-parser-1.67-4-any +installed = perl-socket6-0.29-11-x86_64 +installed = perl-sub-exporter-0.991-4-any +installed = perl-sub-install-0.929-4-any +installed = perl-sub-override-0.12-3-any +installed = perl-sub-prototype-0.03-3-x86_64 +installed = perl-term-readkey-2.38-11-x86_64 +installed = perl-text-bibtex-0.91-2-x86_64 +installed = perl-timedate-2.35-1-any +installed = perl-try-tiny-0.32-4-any +installed = perl-unicode-linebreak-2019.001-9-x86_64 +installed = perl-uri-5.34-2-any +installed = perl-www-robotrules-6.03-1-any +installed = perl-xml-libxml-2.0213-1-x86_64 +installed = perl-xml-namespacesupport-1.12-6-any +installed = perl-xml-parser-2.59-1-x86_64 +installed = perl-xml-sax-1.02-2-any +installed = perl-xml-sax-base-1.09-6-any +installed = perl-xml-writer-0.900-6-any +installed = perl-yaml-tiny-1.76-3-any +installed = persepolis-5.2.0-3-any +installed = phodav-3.0-4-x86_64 +installed = phonon-qt6-4.12.0-6-x86_64 +installed = phonon-qt6-vlc-0.12.0-6-x86_64 +installed = php-8.5.7-1-x86_64 +installed = php-apache-8.5.7-1-x86_64 +installed = php-gd-8.5.7-1-x86_64 +installed = php-legacy-8.3.31-1-x86_64 +installed = php-legacy-gd-8.3.31-1-x86_64 +installed = php-sqlite-8.5.7-1-x86_64 +installed = pico-sdk-2.2.0-3-any +installed = picocom-3.1-3-x86_64 +installed = pimcommon-26.04.2-1-x86_64 +installed = pinentry-1.3.2-2-x86_64 +installed = piper-tts-bin-2023.11.14-1-x86_64 +installed = pipewire-1:1.6.6-1-x86_64 +installed = pipewire-alsa-1:1.6.6-1-x86_64 +installed = pipewire-audio-1:1.6.6-1-x86_64 +installed = pipewire-jack-1:1.6.6-1-x86_64 +installed = pipewire-pulse-1:1.6.6-1-x86_64 +installed = pipewire-session-manager-1:1.6.6-1-x86_64 +installed = pixman-0.46.4-1-x86_64 +installed = pkcs11-helper-1.31.0-1-x86_64 +installed = pkgconf-2.5.1-1-x86_64 +installed = pkgfile-25-2-x86_64 +installed = plasma-activities-6.6.5-1-x86_64 +installed = plasma-activities-stats-6.6.5-1-x86_64 +installed = plasma-desktop-6.6.5-1-x86_64 +installed = plasma-integration-6.6.5-2-x86_64 +installed = plasma-workspace-6.6.5-2-x86_64 +installed = plasma5support-6.6.5-1-x86_64 +installed = plotutils-2.6-12-x86_64 +installed = plymouth-26.134.222-2-x86_64 +installed = pngcheck-4.0.0-3-x86_64 +installed = po-debconf-1.0.22-2-any +installed = po4a-0.74-1-any +installed = polkit-127-3-x86_64 +installed = polkit-gnome-0.105-12-x86_64 +installed = polkit-kde-agent-6.6.5-1-x86_64 +installed = polkit-qt5-0.201.1-1-x86_64 +installed = polkit-qt6-0.201.1-1-x86_64 +installed = polyclipping-6.4.2-6-x86_64 +installed = polyclipping-debug-6.4.2-5-x86_64 +installed = poppler-26.05.0-1-x86_64 +installed = poppler-data-0.4.12-2-any +installed = poppler-glib-26.05.0-1-x86_64 +installed = poppler-qt6-26.05.0-1-x86_64 +installed = popt-1.19-2-x86_64 +installed = portaudio-1:19.7.0-4-x86_64 +installed = portmidi-1:2.0.8-1-x86_64 +installed = portsmf-234-3-x86_64 +installed = postgresql-18.4-1-x86_64 +installed = postgresql-libs-18.4-1-x86_64 +installed = potrace-1.16-5-x86_64 +installed = power-profiles-daemon-0.30-1-x86_64 +installed = powerdevil-6.6.5-1-x86_64 +installed = ppp-2.5.2-1-x86_64 +installed = prison-6.26.0-1-x86_64 +installed = procps-ng-4.0.6-1-x86_64 +installed = projectm-3.1.12-5-x86_64 +installed = protobuf-35.0-1-x86_64 +installed = protobuf-c-1.5.2-10-x86_64 +installed = proton-ge-custom-bin-1:GE_Proton10_34-1-x86_64 +installed = protontricks-1.14.1-1-any +installed = prrte-3.0.13-1-x86_64 +installed = psensor-1.2.1-4-x86_64 +installed = psmisc-23.7-2-x86_64 +installed = pstoedit-4.3-1-x86_64 +installed = ptex-2.5.2-1-x86_64 +installed = pugixml-1.15-3-x86_64 +installed = pulseaudio-alsa-1:1.2.12-5-x86_64 +installed = pulseaudio-qt-1.8.1-1-x86_64 +installed = purpose-6.26.0-2-x86_64 +installed = pv-1.10.5-1-x86_64 +installed = pwvucontrol-0.5.2-1-x86_64 +installed = pwvucontrol-debug-0.5.1-1-x86_64 +installed = pyalpm-0.11.1-1-x86_64 +installed = pybind11-3.0.4-1-any +installed = pyside6-6.11.1-1-x86_64 +installed = pystring-1.1.5-1-x86_64 +installed = python-3.14.5-1-x86_64 +installed = python-aaf2-1.7.1-4-any +installed = python-aiohappyeyeballs-2.6.1-4-any +installed = python-aiohttp-3.13.5-1-x86_64 +installed = python-aiosignal-1.4.0-3-any +installed = python-annotated-doc-0.0.4-2-any +installed = python-annotated-types-0.7.0-3-any +installed = python-anyascii-0.3.3-1-any +installed = python-anyio-4.13.0-1-any +installed = python-appdirs-1.4.4-12-any +installed = python-argcomplete-3.6.3-1-any +installed = python-asgiref-3.11.1-1-any +installed = python-async-timeout-5.0.1-2-any +installed = python-atspi-2.58.2-1-any +installed = python-attrs-26.1.0-1-any +installed = python-audioop-lts-0.2.2-2-x86_64 +installed = python-audioread-3.1.0-3-any +installed = python-autocommand-2.2.2-9-any +installed = python-babel-2.17.0-3-any +installed = python-beaker-1.14.1-1-any +installed = python-beautifulsoup4-4.15.0-1-any +installed = python-black-26.5.1-1-any +installed = python-blinker-1.9.0-4-any +installed = python-boolean.py-5.0-2-any +installed = python-boto3-1.42.91-1-any +installed = python-botocore-1.42.91-1-any +installed = python-breathe-5.0.0a5-3-any +installed = python-brltty-6.9.1-1-x86_64 +installed = python-brotli-1.2.0-1-x86_64 +installed = python-build-1.4.3-1-any +installed = python-cachecontrol-1:0.14.4-3-any +installed = python-cairo-1.29.0-2-x86_64 +installed = python-cairocffi-1.7.1-2-any +installed = python-caja-1.28.0-4-x86_64 +installed = python-certifi-2026.05.20-1-any +installed = python-cffi-2.0.0-2-x86_64 +installed = python-chardet-6.0.0.post1-1-any +installed = python-charset-normalizer-3.4.7-1-x86_64 +installed = python-click-8.3.3-1-any +installed = python-colorama-0.4.6-6-any +installed = python-configobj-5.0.9-6-any +installed = python-contourpy-1.3.3-4-x86_64 +installed = python-coqpit-config-0.2.0-1-any +installed = python-coqui-trainer-0.3.2-1-any +installed = python-coverage-7.13.5-1-x86_64 +installed = python-cryptography-48.0.0-1-x86_64 +installed = python-cssselect-1.4.0-1-any +installed = python-cycler-0.12.1-4-any +installed = python-dasbus-1.7-5-any +installed = python-datasets-5.0.0-1-any +installed = python-dateutil-2.9.0-8-any +installed = python-dbus-1.4.0-2-x86_64 +installed = python-decorator-5.3.1-1-any +installed = python-defusedxml-0.7.1-8-any +installed = python-dill-0.4.1-1-any +installed = python-distlib-0.4.2-1-any +installed = python-distro-1.9.0-4-any +installed = python-distutils-extra-2.39-15-any +installed = python-django-5.2.13-1-any +installed = python-django-celery-results-2.6.0-2-any +installed = python-dnspython-1:2.8.0-3-any +installed = python-docopt-0.6.2-15-any +installed = python-docstring-to-markdown-0.17-2-any +installed = python-docutils-1:0.22.4-1-any +installed = python-dulwich-1.1.0-1-x86_64 +installed = python-edge-tts-7.2.8-1-any +installed = python-editables-0.6-1-any +installed = python-einops-0.8.2-1-any +installed = python-evdev-1.9.3-1-x86_64 +installed = python-eventlet-0.41.0-1-any +installed = python-fastbencode-0.3.10-1-x86_64 +installed = python-fastjsonschema-2.21.2-2-any +installed = python-filelock-3.29.0-1-any +installed = python-flask-3.1.3-1-any +installed = python-flit-core-4.0.0-1-any +installed = python-fonttools-4.63.0-1-x86_64 +installed = python-freezegun-1.5.5-2-any +installed = python-frozenlist-1.8.0-2-x86_64 +installed = python-fsspec-2026.4.0-1-any +installed = python-gbinder-1.3.1-1-x86_64 +installed = python-gevent-26.5.0-1-x86_64 +installed = python-gmpy2-2.3.0-1-x86_64 +installed = python-gobject-3.56.3-1-x86_64 +installed = python-greenlet-3.5.1-1-x86_64 +installed = python-grpcio-1.80.0-2-x86_64 +installed = python-grpcio-tools-1.80.0-2-x86_64 +installed = python-h11-0.16.0-2-any +installed = python-h5py-3.16.0-1-x86_64 +installed = python-hatchling-1.29.0-1-any +installed = python-hf-xet-1.5.0-1-x86_64 +installed = python-html2text-2025.4.15-2-any +installed = python-html5lib-1.1-17-any +installed = python-httpcore-1.0.9-3-any +installed = python-httpx-0.28.1-7-any +installed = python-huggingface-hub-1:1.16.0-1-any +installed = python-hypothesis-6.155.1-1-any +installed = python-idna-3.18-1-any +installed = python-imagesize-2.0.0-1-any +installed = python-importlib-metadata-9.0.0-1-any +installed = python-inflect-7.5.0-2-any +installed = python-iniconfig-2.3.0-1-any +installed = python-installer-1.0.0-1-any +installed = python-isodate-0.7.2-3-any +installed = python-itsdangerous-2.2.0-2-any +installed = python-jaraco.collections-5.1.0-3-any +installed = python-jaraco.context-6.1.2-1-any +installed = python-jaraco.functools-4.1.0-3-any +installed = python-jaraco.text-4.0.0-4-any +installed = python-jedi-0.19.2-4-any +installed = python-jinja-1:3.1.6-3-any +installed = python-jmespath-1.1.0-1-any +installed = python-joblib-1.5.3-1-any +installed = python-kiwisolver-1.5.0-1-x86_64 +installed = python-ko-speech-tools-0.1.0-1-any +installed = python-ladybug-core-0.44.48-1-any +installed = python-ladybug-geometry-1.34.26-1-any +installed = python-lark-parser-1.3.1-2-any +installed = python-lazy-loader-0.5-1-any +installed = python-legacy-cgi-2.6.4-2-any +installed = python-lhafile-0.3.1-2-x86_64 +installed = python-librosa-0.11.0-2-any +installed = python-license-expression-30.4.4-2-any +installed = python-llvmlite-0.47.0-1-x86_64 +installed = python-lockfile-0.12.2-15-any +installed = python-lsp-jsonrpc-1.1.2-6-any +installed = python-lsp-server-1.14.0-2-any +installed = python-lxml-6.1.1-1-x86_64 +installed = python-magic-1:0.4.27-6-any +installed = python-mako-1.3.11-1-any +installed = python-markdown-3.10.2-1-any +installed = python-markdown-it-py-4.0.0-2-any +installed = python-markupsafe-3.0.3-1-x86_64 +installed = python-matplotlib-3.10.9-1-x86_64 +installed = python-maturin-1.13.3-1-x86_64 +installed = python-mdurl-0.1.2-9-any +installed = python-merge3-0.0.16-2-any +installed = python-moddb-0.14.0-2-any +installed = python-monotonic-alignment-search-0.2.1-1-x86_64 +installed = python-more-itertools-11.1.0-1-any +installed = python-moto-5.1.22-1-any +installed = python-mpmath-1.4.1-1-any +installed = python-msgpack-1.1.2-2-x86_64 +installed = python-multidict-6.7.1-1-x86_64 +installed = python-multiprocess-0.70.19-1-any +installed = python-mypy_extensions-1.1.0-2-any +installed = python-networkx-3.6.1-1-any +installed = python-nose-1.3.7-19-any +installed = python-num2words-0.5.14-3-any +installed = python-numba-0.65.1-1-x86_64 +installed = python-numpy-2.4.6-1-x86_64 +installed = python-opencv-4.13.0-9-x86_64 +installed = python-opengl-3.1.10-3-any +installed = python-outcome-1.3.0.post0-7-any +installed = python-packaging-26.2-1-any +installed = python-pam-2.0.2-6-any +installed = python-pandas-2.3.3-2-x86_64 +installed = python-parso-1:0.8.6-1-any +installed = python-pathspec-1.1.1-1-any +installed = python-patiencediff-0.2.18-2-x86_64 +installed = python-pbr-7.0.3-3-any +installed = python-pexpect-4.9.0-7-any +installed = python-pillow-12.2.0-1-x86_64 +installed = python-pip-26.1.2-1-any +installed = python-pipx-1.14.0-1-any +installed = python-pkg_resources-81.0.0-1-any +installed = python-platformdirs-4.10.0-1-any +installed = python-pluggy-1.6.0-3-any +installed = python-poetry-core-2.4.1-1-any +installed = python-pooch-1.9.0-1-any +installed = python-prettytable-3.17.0-2-any +installed = python-propcache-0.4.1-2-x86_64 +installed = python-protobuf-35.0-1-x86_64 +installed = python-psutil-7.2.2-1-x86_64 +installed = python-ptyprocess-0.7.0-9-any +installed = python-pyarrow-24.0.0-1-x86_64 +installed = python-pycountry-24.6.1-5-any +installed = python-pycparser-3.00-1-any +installed = python-pycryptodome-3.23.0-2-x86_64 +installed = python-pycups-2.0.4-4-x86_64 +installed = python-pycurl-7.46.0-1-x86_64 +installed = python-pydantic-2.13.4-1-any +installed = python-pydantic-core-3:2.46.4-1-x86_64 +installed = python-pyelftools-0.33-1-any +installed = python-pygments-2.20.0-1-any +installed = python-pyinotify-0.9.6-16-any +installed = python-pymongo-4.16.0-2-x86_64 +installed = python-pyparsing-3.3.2-1-any +installed = python-pyproject-hooks-1.2.0-6-any +installed = python-pyqt5-5.15.11-7-x86_64 +installed = python-pyqt5-sip-12.18.0-1-x86_64 +installed = python-pyqt6-6.11.0-2-x86_64 +installed = python-pyqt6-sip-13.11.1-1-x86_64 +installed = python-pyro-4.82-6-any +installed = python-pysbd-0.3.4-00-any +installed = python-pyserial-3.5-8-any +installed = python-pysocks-1.7.1-12-any +installed = python-pytest-1:9.0.3-1-any +installed = python-pytest-asyncio-1.3.0-1-any +installed = python-pytest-click-1.1.0-6-any +installed = python-pytest-cov-7.1.0-1-any +installed = python-pytest-freezer-0.4.9-2-any +installed = python-pytest-subtests-0.15.0-2-any +installed = python-pytest-sugar-1.1.1-2-any +installed = python-pytest-timeout-2.4.0-2-any +installed = python-python-discovery-1.4.0-1-any +installed = python-pytokens-0.4.1-1-any +installed = python-pytorch-2.12.0-3-x86_64 +installed = python-pytz-2026.1-1-any +installed = python-pyudev-0.24.4-1-any +installed = python-pyxdg-0.28-7-any +installed = python-pyzmq-27.1.0-2-x86_64 +installed = python-redis-8.0.0-1-any +installed = python-regex-2026.5.9-1-x86_64 +installed = python-requests-2.34.2-1-any +installed = python-requests-file-2.1.0-3-any +installed = python-resampy-0.4.3-4-any +installed = python-responses-0.26.1-1-any +installed = python-rich-15.0.0-1-any +installed = python-roman-numerals-py-3.1.0-2-any +installed = python-s3transfer-0.16.0-2-any +installed = python-safetensors-0.7.0-2-x86_64 +installed = python-scenedetect-0.6.5-1-any +installed = python-scikit-learn-1.9.0-1-x86_64 +installed = python-scipy-1.17.1-2-x86_64 +installed = python-semantic-version-2.10.0-9-any +installed = python-sentry_sdk-2.62.0-1-any +installed = python-serpent-1.43-1-any +installed = python-setproctitle-1.3.7-2-x86_64 +installed = python-setuptools-1:82.0.1-1-any +installed = python-setuptools-rust-1.12.1-1-any +installed = python-setuptools-scm-10.0.5-1-any +installed = python-shellingham-1.5.4-4-any +installed = python-six-1.17.0-3-any +installed = python-smartypants-2.0.2-2-any +installed = python-sniffio-1.3.1-5-any +installed = python-snowballstemmer-3.1.1-1-any +installed = python-sortedcontainers-2.4.0-8-any +installed = python-soundfile-0.14.0-1-any +installed = python-soupsieve-2.8.4-1-any +installed = python-soxr-1.1.0-2-x86_64 +installed = python-sphinx-9.1.0-1-any +installed = python-sphinx-alabaster-theme-1.0.0-6-any +installed = python-sphinx_rtd_theme-3.0.0-1-any +installed = python-sphinxcontrib-applehelp-2.0.0-5-any +installed = python-sphinxcontrib-devhelp-2.0.0-6-any +installed = python-sphinxcontrib-htmlhelp-2.1.0-5-any +installed = python-sphinxcontrib-jquery-4.1-5-any +installed = python-sphinxcontrib-jsmath-1.0.1-21-any +installed = python-sphinxcontrib-qthelp-2.0.0-5-any +installed = python-sphinxcontrib-serializinghtml-2.0.0-5-any +installed = python-sqlalchemy-2.0.50-1-x86_64 +installed = python-sqlparse-0.5.3-2-any +installed = python-srt-3.5.3-3-any +installed = python-standard-aifc-3.13.0-4-any +installed = python-standard-chunk-3.13.0-4-any +installed = python-standard-sunau-3.13.0-4-any +installed = python-sympy-1.14.0-6-any +installed = python-tabulate-0.10.0-1-any +installed = python-tensorboardx-2.6.5-1-any +installed = python-termcolor-3.3.0-1-any +installed = python-threadpoolctl-3.5.0-3-any +installed = python-tinycss2-1.5.1-2-any +installed = python-tldextract-5.3.1-2-any +installed = python-tokenizers-0.23.1-1-x86_64 +installed = python-torchaudio-2.10.0-1-x86_64 +installed = python-torchcodec-0.14.0-1-x86_64 +installed = python-tqdm-4.68.1-1-any +installed = python-transformers-5.7.0-1-any +installed = python-trio-0.33.0-1-any +installed = python-trio-websocket-0.12.2-4-any +installed = python-trove-classifiers-2026.6.1.19-1-any +installed = python-typeguard-4.5.2-1-any +installed = python-typer-0.26.7-2-any +installed = python-typing-inspection-0.4.2-2-any +installed = python-typing_extensions-4.15.0-3-any +installed = python-typogrify-2.1.0-2-any +installed = python-tzlocal-1:5.3.1-2-any +installed = python-uc-micro-py-2.0.0-1-any +installed = python-ujson-5.12.1-1-x86_64 +installed = python-urllib3-2.7.0-1-any +installed = python-userpath-1.9.2-4-any +installed = python-uv-build-0.11.19-1-x86_64 +installed = python-vcs-versioning-1.1.1-1-any +installed = python-vdf-4.0-5-any +installed = python-virtualenv-21.4.2-1-any +installed = python-wcwidth-0.8.1-1-any +installed = python-webencodings-0.5.1-13-any +installed = python-websocket-client-1.9.0-3-any +installed = python-websockets-16.0-1-x86_64 +installed = python-werkzeug-3.1.8-1-any +installed = python-wheel-0.47.0-1-any +installed = python-wsproto-1.3.2-1-any +installed = python-wxpython-1:4.2.5-1-x86_64 +installed = python-xapp-3.0.3-1-any +installed = python-xmltodict-1.0.4-1-any +installed = python-xxhash-3.7.0-1-x86_64 +installed = python-yaml-6.0.3-2-x86_64 +installed = python-yarl-1.23.0-1-x86_64 +installed = python-zipp-3.21.0-4-any +installed = python-zope-event-6.2-1-any +installed = python-zope-interface-8.4-1-x86_64 +installed = python-zstandard-0.25.0-2-x86_64 +installed = python310-3.10.19-1-x86_64 +installed = python311-3.11.14-1-x86_64 +installed = qca-qt5-2.3.10-7-x86_64 +installed = qca-qt6-2.3.10-7-x86_64 +installed = qcoro-0.13.0-2-x86_64 +installed = qcustomplot-2.1.1-2-x86_64 +installed = qemu-audio-alsa-11.0.1-1-x86_64 +installed = qemu-audio-dbus-11.0.1-1-x86_64 +installed = qemu-audio-jack-11.0.1-1-x86_64 +installed = qemu-audio-oss-11.0.1-1-x86_64 +installed = qemu-audio-pa-11.0.1-1-x86_64 +installed = qemu-audio-pipewire-11.0.1-1-x86_64 +installed = qemu-audio-sdl-11.0.1-1-x86_64 +installed = qemu-audio-spice-11.0.1-1-x86_64 +installed = qemu-base-11.0.1-1-x86_64 +installed = qemu-block-curl-11.0.1-1-x86_64 +installed = qemu-block-dmg-11.0.1-1-x86_64 +installed = qemu-block-gluster-11.0.1-1-x86_64 +installed = qemu-block-iscsi-11.0.1-1-x86_64 +installed = qemu-block-nfs-11.0.1-1-x86_64 +installed = qemu-block-ssh-11.0.1-1-x86_64 +installed = qemu-chardev-baum-11.0.1-1-x86_64 +installed = qemu-chardev-spice-11.0.1-1-x86_64 +installed = qemu-common-11.0.1-1-x86_64 +installed = qemu-desktop-11.0.1-1-x86_64 +installed = qemu-docs-11.0.1-1-x86_64 +installed = qemu-emulators-full-11.0.1-1-x86_64 +installed = qemu-full-11.0.1-1-x86_64 +installed = qemu-hw-display-qxl-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-gl-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-gl-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-rutabaga-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-gpu-rutabaga-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-vga-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-vga-gl-11.0.1-1-x86_64 +installed = qemu-hw-display-virtio-vga-rutabaga-11.0.1-1-x86_64 +installed = qemu-hw-s390x-virtio-gpu-ccw-11.0.1-1-x86_64 +installed = qemu-hw-uefi-vars-11.0.1-1-x86_64 +installed = qemu-hw-usb-host-11.0.1-1-x86_64 +installed = qemu-hw-usb-redirect-11.0.1-1-x86_64 +installed = qemu-hw-usb-smartcard-11.0.1-1-x86_64 +installed = qemu-img-11.0.1-1-x86_64 +installed = qemu-pr-helper-11.0.1-1-x86_64 +installed = qemu-system-aarch64-11.0.1-1-x86_64 +installed = qemu-system-alpha-11.0.1-1-x86_64 +installed = qemu-system-alpha-firmware-11.0.1-1-x86_64 +installed = qemu-system-arm-11.0.1-1-x86_64 +installed = qemu-system-arm-firmware-11.0.1-1-x86_64 +installed = qemu-system-avr-11.0.1-1-x86_64 +installed = qemu-system-hppa-11.0.1-1-x86_64 +installed = qemu-system-hppa-firmware-11.0.1-1-x86_64 +installed = qemu-system-loongarch64-11.0.1-1-x86_64 +installed = qemu-system-m68k-11.0.1-1-x86_64 +installed = qemu-system-microblaze-11.0.1-1-x86_64 +installed = qemu-system-microblaze-firmware-11.0.1-1-x86_64 +installed = qemu-system-mips-11.0.1-1-x86_64 +installed = qemu-system-or1k-11.0.1-1-x86_64 +installed = qemu-system-ppc-11.0.1-1-x86_64 +installed = qemu-system-ppc-firmware-11.0.1-1-x86_64 +installed = qemu-system-riscv-11.0.1-1-x86_64 +installed = qemu-system-riscv-firmware-11.0.1-1-x86_64 +installed = qemu-system-rx-11.0.1-1-x86_64 +installed = qemu-system-s390x-11.0.1-1-x86_64 +installed = qemu-system-s390x-firmware-11.0.1-1-x86_64 +installed = qemu-system-sh4-11.0.1-1-x86_64 +installed = qemu-system-sparc-11.0.1-1-x86_64 +installed = qemu-system-sparc-firmware-11.0.1-1-x86_64 +installed = qemu-system-tricore-11.0.1-1-x86_64 +installed = qemu-system-x86-11.0.1-1-x86_64 +installed = qemu-system-x86-firmware-11.0.1-1-x86_64 +installed = qemu-system-xtensa-11.0.1-1-x86_64 +installed = qemu-tests-11.0.1-1-x86_64 +installed = qemu-tools-11.0.1-1-x86_64 +installed = qemu-ui-curses-11.0.1-1-x86_64 +installed = qemu-ui-dbus-11.0.1-1-x86_64 +installed = qemu-ui-egl-headless-11.0.1-1-x86_64 +installed = qemu-ui-gtk-11.0.1-1-x86_64 +installed = qemu-ui-opengl-11.0.1-1-x86_64 +installed = qemu-ui-sdl-11.0.1-1-x86_64 +installed = qemu-ui-spice-app-11.0.1-1-x86_64 +installed = qemu-ui-spice-core-11.0.1-1-x86_64 +installed = qemu-user-11.0.1-1-x86_64 +installed = qemu-vhost-user-gpu-11.0.1-1-x86_64 +installed = qemu-vmsr-helper-11.0.1-1-x86_64 +installed = qgpgme-2.1.0-1-x86_64 +installed = qhexedit2-0.8.9-2-x86_64 +installed = qhull-2020.2-5-x86_64 +installed = qmmp-2.3.2-1-x86_64 +installed = qogir-gtk-theme-2025.08.17-1-any +installed = qpdf-12.3.2-2-x86_64 +installed = qpwgraph-1.0.2-1-x86_64 +installed = qqc2-breeze-style-6.6.5-1-x86_64 +installed = qqc2-desktop-style-6.26.0-1-x86_64 +installed = qrcodegencpp-cmake-1.8.0-4-x86_64 +installed = qrencode-4.1.1-4-x86_64 +installed = qscintilla-qt5-2.14.1-6-x86_64 +installed = qt5-base-5.15.19+kde+r96-1-x86_64 +installed = qt5-declarative-5.15.19+kde+r23-1-x86_64 +installed = qt5-graphicaleffects-5.15.19-1-x86_64 +installed = qt5-location-5.15.19+kde+r7-1-x86_64 +installed = qt5-multimedia-5.15.19+kde+r2-1-x86_64 +installed = qt5-quick3d-5.15.19+kde+r1-1-x86_64 +installed = qt5-quickcontrols-5.15.19-1-x86_64 +installed = qt5-quickcontrols2-5.15.19+kde+r5-1-x86_64 +installed = qt5-remoteobjects-5.15.19-1-x86_64 +installed = qt5-sensors-5.15.19-2-x86_64 +installed = qt5-serialport-5.15.19-1-x86_64 +installed = qt5-speech-5.15.19+kde+r1-1-x86_64 +installed = qt5-svg-5.15.19+kde+r5-1-x86_64 +installed = qt5-tools-5.15.19+kde+r3-1-x86_64 +installed = qt5-translations-5.15.19-1-any +installed = qt5-wayland-5.15.19+kde+r55-1-x86_64 +installed = qt5-webchannel-5.15.19-1-x86_64 +installed = qt5-webengine-5.15.19-4-x86_64 +installed = qt5-websockets-5.15.19+kde+r2-1-x86_64 +installed = qt5-x11extras-5.15.19-1-x86_64 +installed = qt5-xmlpatterns-5.15.19-1-x86_64 +installed = qt6-5compat-6.11.1-1-x86_64 +installed = qt6-base-6.11.1-1-x86_64 +installed = qt6-charts-6.11.1-1-x86_64 +installed = qt6-connectivity-6.11.1-1-x86_64 +installed = qt6-declarative-6.11.1-3-x86_64 +installed = qt6-doc-6.11.1-1-any +installed = qt6-graphs-6.11.1-1-x86_64 +installed = qt6-imageformats-6.11.1-1-x86_64 +installed = qt6-location-6.11.1-1-x86_64 +installed = qt6-multimedia-6.11.1-1-x86_64 +installed = qt6-multimedia-ffmpeg-6.11.1-1-x86_64 +installed = qt6-networkauth-6.11.1-1-x86_64 +installed = qt6-positioning-6.11.1-1-x86_64 +installed = qt6-quick3d-6.11.1-1-x86_64 +installed = qt6-quicktimeline-6.11.1-1-x86_64 +installed = qt6-scxml-6.11.1-1-x86_64 +installed = qt6-sensors-6.11.1-1-x86_64 +installed = qt6-serialport-6.11.1-1-x86_64 +installed = qt6-shadertools-6.11.1-1-x86_64 +installed = qt6-speech-6.11.1-1-x86_64 +installed = qt6-svg-6.11.1-1-x86_64 +installed = qt6-tools-6.11.1-1-x86_64 +installed = qt6-translations-6.11.1-1-any +installed = qt6-virtualkeyboard-6.11.1-1-x86_64 +installed = qt6-wayland-6.11.1-1-x86_64 +installed = qt6-webchannel-6.11.1-1-x86_64 +installed = qt6-webengine-6.11.1-3-x86_64 +installed = qt6-websockets-6.11.1-1-x86_64 +installed = qt6pas-6.2.10-3-x86_64 +installed = qtcreator-19.0.2-2-x86_64 +installed = qterminal-2.4.0-1-x86_64 +installed = qtermwidget-2.4.0-1-x86_64 +installed = qtkeychain-qt6-0.16.0-1-x86_64 +installed = qtxdg-tools-4.4.0-1-x86_64 +installed = quazip-qt6-1.7.1-1-x86_64 +installed = r8168-dkms-8.056.02-1-x86_64 +installed = ragel-7.0.4-1-x86_64 +installed = rapidjson-1.1.0-6-any +installed = raptor-2.0.16-9-x86_64 +installed = rav1e-0.8.1-2-x86_64 +installed = rclone-1.74.3-1-x86_64 +installed = rconc-0.1.3-1-x86_64 +installed = rdma-core-63.0-1-x86_64 +installed = re2-2:2025.11.05-4-x86_64 +installed = re2c-4.5.1-1-x86_64 +installed = read-edid-3.0.2-5-x86_64 +installed = readline-8.3.003-1-x86_64 +installed = recode-3.7.15-1-x86_64 +installed = recordmydesktop-0.4.0-4-x86_64 +installed = reflector-2023-5-any +installed = remarkable-cups-1-1-any +installed = rhash-1.4.6-1-x86_64 +installed = ripgrep-15.1.0-3-x86_64 +installed = ripgrep-all-0.10.10-1-x86_64 +installed = rmapi-0.0.34-2-x86_64 +installed = rnnoise-1:0.2-1-x86_64 +installed = robin-map-1.4.1-1-x86_64 +installed = rpcbind-1.2.9-1-x86_64 +installed = rpi-imager-2.0.9-1-x86_64 +installed = rsync-3.4.4-1-x86_64 +installed = rtkit-0.14-1-x86_64 +installed = rtmpdump-1:2.6-2-x86_64 +installed = rubberband-4.0.0-2-x86_64 +installed = ruby-3.4.8-2-x86_64 +installed = ruby-abbrev-0.1.2-1-any +installed = ruby-base64-0.3.0-1-any +installed = ruby-bigdecimal-3.3.1-2-x86_64 +installed = ruby-bundled-gems-3.4.8-2-x86_64 +installed = ruby-bundler-4.0.3-1-any +installed = ruby-csv-3.3.5-1-any +installed = ruby-debug-1.11.1-1-x86_64 +installed = ruby-default-gems-3.4.8-2-x86_64 +installed = ruby-drb-2.2.3-1-any +installed = ruby-erb-4.0.4-9-x86_64 +installed = ruby-ffi-1.17.4-1-x86_64 +installed = ruby-getoptlong-0.2.1-1-any +installed = ruby-irb-1.15.0-1-any +installed = ruby-maruku-0.7.3-10-any +installed = ruby-matrix-0.4.3-1-any +installed = ruby-minitest-5.26.1-1-any +installed = ruby-mutex_m-0.3.0-2-any +installed = ruby-net-ftp-0.3.9-1-any +installed = ruby-net-imap-0.5.12-1-any +installed = ruby-net-pop-0.1.2-5-any +installed = ruby-net-smtp-0.5.1-1-any +installed = ruby-nkf-0.2.0-3-x86_64 +installed = ruby-observer-0.1.2-3-any +installed = ruby-power_assert-2.0.5-4-any +installed = ruby-prime-0.1.4-1-any +installed = ruby-racc-1.8.1-2-x86_64 +installed = ruby-rake-13.3.1-1-any +installed = ruby-rb-fsevent-0.11.2-5-any +installed = ruby-rb-inotify-0.10.1-6-any +installed = ruby-rbs-3.8.0-2-any +installed = ruby-rdoc-6.14.0-1-any +installed = ruby-repl_type_completor-0.1.15-1-any +installed = ruby-resolv-replace-0.2.0-1-any +installed = ruby-rexml-3.4.4-1-any +installed = ruby-rinda-0.2.0-2-any +installed = ruby-rss-0.3.2-1-any +installed = ruby-sass-3.7.4-7-any +installed = ruby-sass-listen-4.0.0-13-any +installed = ruby-stdlib-3.4.8-2-x86_64 +installed = ruby-syslog-0.4.0-1-any +installed = ruby-test-unit-3.7.7-1-any +installed = ruby-typeprof-0.30.1-2-any +installed = ruby-webrick-1.9.2-1-any +installed = ruby-yard-0.9.35-1-any +installed = rubygems-3.6.9-1-any +installed = runc-1.4.2-1-x86_64 +installed = rust-bindgen-0.72.1-2-x86_64 +installed = rustup-1.29.0-2-x86_64 +installed = rutabaga-ffi-0.1.75-1-x86_64 +installed = rygel-1:45.2-1-x86_64 +installed = s2n-tls-1.7.2-1-x86_64 +installed = safecopy-1.7-1-x86_64 +installed = samba-2:4.24.3-1-x86_64 +installed = sane-1.4.0-4-x86_64 +installed = sassc-3.6.2-5-x86_64 +installed = sbc-2.2-1-x86_64 +installed = schroedinger-1.0.11-7-x86_64 +installed = scour-0.38.2-6-any +installed = screengrab-3.2.0-1-x86_64 +installed = scummvm-2026.2.0-1-x86_64 +installed = sddm-0.21.0-7-x86_64 +installed = sddm-sugar-candy-git-1.6r42.d31dbf5-1-any +installed = sdl12-compat-1.2.68-2-x86_64 +installed = sdl2-compat-2.32.70-1-x86_64 +installed = sdl2_image-2.8.12-1-x86_64 +installed = sdl2_mixer-2.8.2-1-x86_64 +installed = sdl2_net-2:2.4.0-1-x86_64 +installed = sdl2_ttf-2.24.0-2-x86_64 +installed = sdl3-3.4.10-1-x86_64 +installed = sdl3_image-3.4.4-1-x86_64 +installed = sdl3_image-debug-3.2.4-1-x86_64 +installed = sdl3_ttf-3.2.2-3-x86_64 +installed = sdl_image-1.2.12-9-x86_64 +installed = sdl_mixer-1.2.12-13-x86_64 +installed = sdl_net-1.2.8-6-x86_64 +installed = sdl_sound-1.0.3-13-x86_64 +installed = seabios-1.17.0-2-any +installed = seahorse-1:47.0.1-6-x86_64 +installed = seatd-0.9.3-1-x86_64 +installed = sed-4.10-1-x86_64 +installed = semver-7.8.1-1-any +installed = serd-0.32.10-1-x86_64 +installed = serf-1.3.10-2-x86_64 +installed = sg3_utils-1.48-1-x86_64 +installed = sgml-common-0.6.3-9-any +installed = shaderc-2026.2-1-x86_64 +installed = shadow-4.18.0-1-x86_64 +installed = shared-mime-info-2.4-3-x86_64 +installed = shiboken6-6.11.1-1-x86_64 +installed = signon-kwallet-extension-26.04.2-1-x86_64 +installed = signon-plugin-oauth2-0.25-4-x86_64 +installed = signon-ui-0.17+20231016-4-x86_64 +installed = signond-8.61-4-x86_64 +installed = simde-0.8.2-1-any +installed = simdjson-1:4.6.4-1-x86_64 +installed = simple-scan-50.0-1-x86_64 +installed = sip4-4.19.25-7-x86_64 +installed = skanpage-26.04.2-1-x86_64 +installed = slang-2.3.3-4-x86_64 +installed = smartmontools-7.5-1-x86_64 +installed = smbclient-2:4.24.3-1-x86_64 +installed = snapd-2.75.2-1-x86_64 +installed = snapd-glib-1.72-1-x86_64 +installed = snapd-glib-debug-1.70-1-x86_64 +installed = snappy-1.2.2-3-x86_64 +installed = sndio-1.10.0-1-x86_64 +installed = socat-1.8.1.1-1-x86_64 +installed = solid-6.26.0-1-x86_64 +installed = solid5-5.116.0-2-x86_64 +installed = sonnet-6.26.0-1-x86_64 +installed = sonnet5-5.116.0-2-x86_64 +installed = sord-0.16.22-1-x86_64 +installed = sound-theme-freedesktop-0.8-6-any +installed = soundtouch-2.4.1-1-x86_64 +installed = source-highlight-3.1.9-18-x86_64 +installed = sox-14.8.0.1-1-x86_64 +installed = spamassassin-4.0.2-1-x86_64 +installed = spandsp-0.0.6-7-x86_64 +installed = spdlog-1.17.0-2-x86_64 +installed = speech-dispatcher-0.12.1-3-x86_64 +installed = speedtest-cli-2.1.3-10-any +installed = speex-1.2.1-2-x86_64 +installed = speexdsp-1.2.1-2-x86_64 +installed = spice-0.16.0-2-x86_64 +installed = spice-gtk-0.42-5-x86_64 +installed = spice-protocol-0.14.5-1-any +installed = spirv-tools-1:1.4.350.0-1-x86_64 +installed = sqlcipher-4.14.0-1-x86_64 +installed = sqlite-3.53.2-1-x86_64 +installed = sqlitebrowser-3.13.1-3-x86_64 +installed = squashfs-tools-4.7.5-1-x86_64 +installed = sratom-0.6.22-1-x86_64 +installed = srt-1.5.5-1-x86_64 +installed = sshfs-3.7.6-1-x86_64 +installed = sslscan-2.2.2-1-x86_64 +installed = stable-diffusion-ui-3.0.2-4-x86_64 +installed = startup-notification-0.12-9-x86_64 +installed = steam-1.0.0.85-7-x86_64 +installed = steam-devices-1.0.0.85-7-x86_64 +installed = steamcmd-latest-7-x86_64 +installed = strace-7.0-1-x86_64 +installed = strip-nondeterminism-1.15.1-1-any +installed = subversion-1.14.5-5-x86_64 +installed = sudo-1.9.17.p2-2-x86_64 +installed = suil-0.10.26-1-x86_64 +installed = suitesparse-7.12.2-2-x86_64 +installed = supertuxkart-1.5-1-x86_64 +installed = sushi-50.0-1-x86_64 +installed = svt-av1-4.1.0-1-x86_64 +installed = svt-hevc-1.5.1-4-x86_64 +installed = swig-4.4.1-1-x86_64 +installed = sword-1.9.0-18-x86_64 +installed = swtpm-0.10.1-2-x86_64 +installed = syndication-6.26.0-1-x86_64 +installed = syntax-highlighting-6.26.0-1-x86_64 +installed = sysbench-1.0.20-2-x86_64 +installed = system-config-printer-1.5.18-6-x86_64 +installed = systemd-260.2-2-x86_64 +installed = systemd-libs-260.2-2-x86_64 +installed = systemd-sysvcompat-260.2-2-x86_64 +installed = systemdgenie-0.99.0-8-x86_64 +installed = systemsettings-6.6.5-1-x86_64 +installed = taglib-2.3-1-x86_64 +installed = talloc-2.4.4-1-x86_64 +installed = tar-1.35-2-x86_64 +installed = tcl-8.6.16-1-x86_64 +installed = tdb-1.4.15-1-x86_64 +installed = tde-abakus-14.1.6-1-x86_64 +installed = tde-akode-14.1.6-1-x86_64 +installed = tde-amarok-14.1.6-1-x86_64 +installed = tde-arts-14.1.6-1-x86_64 +installed = tde-avahi-tqt-14.1.6-1-x86_64 +installed = tde-basket-14.1.6-1-x86_64 +installed = tde-bibletime-14.1.6-1-x86_64 +installed = tde-cmake-trinity-14.1.6-1-any +installed = tde-dbus-1-tqt-14.1.6-1-x86_64 +installed = tde-dbus-tqt-14.1.6-1-x86_64 +installed = tde-digikam-14.1.6-1-x86_64 +installed = tde-dolphin-14.1.6-1-x86_64 +installed = tde-ebook-reader-14.1.6-1-x86_64 +installed = tde-filelight-14.1.6-1-x86_64 +installed = tde-gtk-qt-engine-14.1.6-1-x86_64 +installed = tde-gtk3-tqt-engine-14.1.6-1-x86_64 +installed = tde-gwenview-14.1.6-1-x86_64 +installed = tde-gwenview-i18n-14.1.6-1-any +installed = tde-i18n-14.1.6-1-any +installed = tde-i18n-af-14.1.6-1-any +installed = tde-i18n-ar-14.1.6-1-any +installed = tde-i18n-az-14.1.6-1-any +installed = tde-i18n-be-14.1.6-1-any +installed = tde-i18n-bg-14.1.6-1-any +installed = tde-i18n-bn-14.1.6-1-any +installed = tde-i18n-br-14.1.6-1-any +installed = tde-i18n-bs-14.1.6-1-any +installed = tde-i18n-ca-14.1.6-1-any +installed = tde-i18n-cs-14.1.6-1-any +installed = tde-i18n-csb-14.1.6-1-any +installed = tde-i18n-cy-14.1.6-1-any +installed = tde-i18n-da-14.1.6-1-any +installed = tde-i18n-de-14.1.6-1-any +installed = tde-i18n-el-14.1.6-1-any +installed = tde-i18n-engb-14.1.6-1-any +installed = tde-i18n-eo-14.1.6-1-any +installed = tde-i18n-es-14.1.6-1-any +installed = tde-i18n-esar-14.1.6-1-any +installed = tde-i18n-et-14.1.6-1-any +installed = tde-i18n-eu-14.1.6-1-any +installed = tde-i18n-fa-14.1.6-1-any +installed = tde-i18n-fi-14.1.6-1-any +installed = tde-i18n-fr-14.1.6-1-any +installed = tde-i18n-fy-14.1.6-1-any +installed = tde-i18n-ga-14.1.6-1-any +installed = tde-i18n-gl-14.1.6-1-any +installed = tde-i18n-he-14.1.6-1-any +installed = tde-i18n-hi-14.1.6-1-any +installed = tde-i18n-hr-14.1.6-1-any +installed = tde-i18n-hu-14.1.6-1-any +installed = tde-i18n-ia-14.1.6-1-any +installed = tde-i18n-is-14.1.6-1-any +installed = tde-i18n-it-14.1.6-1-any +installed = tde-i18n-ja-14.1.6-1-any +installed = tde-i18n-kk-14.1.6-1-any +installed = tde-i18n-km-14.1.6-1-any +installed = tde-i18n-ko-14.1.6-1-any +installed = tde-i18n-lt-14.1.6-1-any +installed = tde-i18n-lv-14.1.6-1-any +installed = tde-i18n-mk-14.1.6-1-any +installed = tde-i18n-mn-14.1.6-1-any +installed = tde-i18n-ms-14.1.6-1-any +installed = tde-i18n-nb-14.1.6-1-any +installed = tde-i18n-nds-14.1.6-1-any +installed = tde-i18n-nl-14.1.6-1-any +installed = tde-i18n-nn-14.1.6-1-any +installed = tde-i18n-pa-14.1.6-1-any +installed = tde-i18n-pl-14.1.6-1-any +installed = tde-i18n-pt-14.1.6-1-any +installed = tde-i18n-ptbr-14.1.6-1-any +installed = tde-i18n-ro-14.1.6-1-any +installed = tde-i18n-ru-14.1.6-1-any +installed = tde-i18n-rw-14.1.6-1-any +installed = tde-i18n-se-14.1.6-1-any +installed = tde-i18n-sk-14.1.6-1-any +installed = tde-i18n-sl-14.1.6-1-any +installed = tde-i18n-sr-14.1.6-1-any +installed = tde-i18n-srlatin-14.1.6-1-any +installed = tde-i18n-ss-14.1.6-1-any +installed = tde-i18n-sv-14.1.6-1-any +installed = tde-i18n-ta-14.1.6-1-any +installed = tde-i18n-te-14.1.6-1-any +installed = tde-i18n-tg-14.1.6-1-any +installed = tde-i18n-th-14.1.6-1-any +installed = tde-i18n-tr-14.1.6-1-any +installed = tde-i18n-uk-14.1.6-1-any +installed = tde-i18n-uz-14.1.6-1-any +installed = tde-i18n-uzcyrillic-14.1.6-1-any +installed = tde-i18n-vi-14.1.6-1-any +installed = tde-i18n-wa-14.1.6-1-any +installed = tde-i18n-zhcn-14.1.6-1-any +installed = tde-i18n-zhtw-14.1.6-1-any +installed = tde-k3b-14.1.6-1-x86_64 +installed = tde-k3b-i18n-14.1.6-1-any +installed = tde-kaffeine-14.1.6-1-x86_64 +installed = tde-kbarcode-14.1.6-1-x86_64 +installed = tde-kbiff-14.1.6-1-x86_64 +installed = tde-kchmviewer-14.1.6-1-x86_64 +installed = tde-kcpuload-14.1.6-1-x86_64 +installed = tde-kdbg-14.1.6-1-x86_64 +installed = tde-kdiff3-14.1.6-1-x86_64 +installed = tde-kile-14.1.6-1-x86_64 +installed = tde-kipi-plugins-14.1.6-1-x86_64 +installed = tde-kmplayer-14.1.6-1-x86_64 +installed = tde-kmyfirewall-14.1.6-1-x86_64 +installed = tde-kmymoney-14.1.6-1-x86_64 +installed = tde-knights-14.1.6-1-x86_64 +installed = tde-kommando-14.1.6-1-x86_64 +installed = tde-kompose-14.1.6-1-x86_64 +installed = tde-konversation-14.1.6-1-x86_64 +installed = tde-kooldock-14.1.6-1-x86_64 +installed = tde-krecipes-14.1.6-1-x86_64 +installed = tde-krename-14.1.6-1-x86_64 +installed = tde-krusader-14.1.6-1-x86_64 +installed = tde-kscope-14.1.6-1-x86_64 +installed = tde-kshutdown-14.1.6-1-x86_64 +installed = tde-ksplash-engine-moodin-14.1.6-1-x86_64 +installed = tde-ksquirrel-14.1.6-1-x86_64 +installed = tde-ktorrent-14.1.6-1-x86_64 +installed = tde-kvkbd-14.1.6-1-x86_64 +installed = tde-kxmleditor-14.1.6-1-x86_64 +installed = tde-libart-lgpl-14.1.6-1-x86_64 +installed = tde-libcaldav-14.1.6-1-x86_64 +installed = tde-libcarddav-14.1.6-1-x86_64 +installed = tde-libkdcraw-14.1.6-1-x86_64 +installed = tde-libkexiv2-14.1.6-1-x86_64 +installed = tde-libkipi-14.1.6-1-x86_64 +installed = tde-libksquirrel-14.1.6-1-x86_64 +installed = tde-meta-14.1.6-1-any +installed = tde-piklab-14.1.6-1-x86_64 +installed = tde-polkit-agent-tde-14.1.6-1-x86_64 +installed = tde-polkit-tqt-14.1.6-1-x86_64 +installed = tde-potracegui-14.1.6-1-x86_64 +installed = tde-style-baghira-14.1.6-1-x86_64 +installed = tde-style-domino-14.1.6-1-x86_64 +installed = tde-style-ia-ora-14.1.6-1-x86_64 +installed = tde-style-lipstik-14.1.6-1-x86_64 +installed = tde-style-polyester-14.1.6-1-x86_64 +installed = tde-style-qtcurve-14.1.6-1-x86_64 +installed = tde-systemsettings-14.1.6-1-x86_64 +installed = tde-tdeaccessibility-14.1.6-1-x86_64 +installed = tde-tdeaddons-14.1.6-1-x86_64 +installed = tde-tdeadmin-14.1.6-1-x86_64 +installed = tde-tdeartwork-14.1.6-1-x86_64 +installed = tde-tdebase-14.1.6-1-x86_64 +installed = tde-tdebindings-14.1.6-1-x86_64 +installed = tde-tdebluez-14.1.6-1-x86_64 +installed = tde-tdeedu-14.1.6-1-x86_64 +installed = tde-tdegames-14.1.6-1-x86_64 +installed = tde-tdegraphics-14.1.6-1-x86_64 +installed = tde-tdeio-appinfo-14.1.6-1-x86_64 +installed = tde-tdeio-ftps-14.1.6-1-x86_64 +installed = tde-tdeio-gopher-14.1.6-1-x86_64 +installed = tde-tdeio-locate-14.1.6-1-x86_64 +installed = tde-tdeio-sword-14.1.6-1-x86_64 +installed = tde-tdeknighttour-14.1.6-1-x86_64 +installed = tde-tdelibs-14.1.6-1-x86_64 +installed = tde-tdemultimedia-14.1.6-1-x86_64 +installed = tde-tdenetwork-14.1.6-1-x86_64 +installed = tde-tdenetworkmanager-14.1.6-1-x86_64 +installed = tde-tdepacman-14.1.6-1-x86_64 +installed = tde-tdepim-14.1.6-1-x86_64 +installed = tde-tdepowersave-14.1.6-1-x86_64 +installed = tde-tdesdk-14.1.6-1-x86_64 +installed = tde-tdesudo-14.1.6-1-x86_64 +installed = tde-tdetoys-14.1.6-1-x86_64 +installed = tde-tdeutils-14.1.6-1-x86_64 +installed = tde-tdevelop-14.1.6-1-x86_64 +installed = tde-tdewebdev-14.1.6-1-x86_64 +installed = tde-tdmtheme-14.1.6-1-x86_64 +installed = tde-tellico-14.1.6-1-x86_64 +installed = tde-tork-14.1.6-1-x86_64 +installed = tde-tqca-14.1.6-1-x86_64 +installed = tde-tqca-tls-14.1.6-1-x86_64 +installed = tde-tqscintilla-14.1.6-1-x86_64 +installed = tde-tqt3-14.1.6-1-x86_64 +installed = tde-tqt3-docs-14.1.6-1-x86_64 +installed = tde-tqtinterface-14.1.6-1-x86_64 +installed = tde-twin-style-crystal-14.1.6-1-x86_64 +installed = tde-twin-style-dekorator-14.1.6-1-x86_64 +installed = tde-twin-style-fahrenheit-14.1.6-1-x86_64 +installed = tde-twin-style-machbunt-14.1.6-1-x86_64 +installed = tde-twin-style-mallory-14.1.6-1-x86_64 +installed = tde-twin-style-suse2-14.1.6-1-x86_64 +installed = tde-universal-indent-gui-tqt-14.1.6-1-x86_64 +installed = tde-xdg-desktop-portal-tde-14.1.6-1-x86_64 +installed = tde-yakuake-14.1.6-1-x86_64 +installed = teams-for-linux-2.10.0-2-x86_64 +installed = tecla-50.0-1-x86_64 +installed = terminator-2.1.5-2-any +installed = terminus-font-4.49.1-8-any +installed = tesseract-5.5.2-1-x86_64 +installed = tesseract-data-afr-2:4.1.0-5-any +installed = tesseract-data-eng-2:4.1.0-5-any +installed = tesseract-data-osd-2:4.1.0-5-any +installed = tevent-1:0.17.1-2-x86_64 +installed = texinfo-7.3-1-x86_64 +installed = texlab-5.25.1-2-x86_64 +installed = texlive-basic-2026.1-1-any +installed = texlive-bibtexextra-2026.1-1-any +installed = texlive-bin-2026.0-2-x86_64 +installed = texlive-fontsextra-2026.1-1-any +installed = texlive-fontsrecommended-2026.1-1-any +installed = texlive-formatsextra-2026.1-1-any +installed = texlive-games-2026.1-1-any +installed = texlive-humanities-2026.1-1-any +installed = texlive-latex-2026.1-1-any +installed = texlive-latexextra-2026.1-1-any +installed = texlive-latexrecommended-2026.1-1-any +installed = texlive-music-2026.1-1-any +installed = texlive-pictures-2026.1-1-any +installed = texlive-plaingeneric-2026.1-1-any +installed = texlive-pstricks-2026.1-1-any +installed = texlive-publishers-2026.1-1-any +installed = theme-windows-3.11-1.1-1-any +installed = thin-provisioning-tools-1.3.2-1-x86_64 +installed = threadweaver-6.26.0-1-x86_64 +installed = thrift-0.22.0-6-x86_64 +installed = thunar-4.20.8-3-x86_64 +installed = thunar-volman-4.20.0-2-x86_64 +installed = tig-2.6.0-1-x86_64 +installed = tigervnc-1.16.2-2-x86_64 +installed = tilix-1.9.6-9-x86_64 +installed = tilix-debug-1.9.6-9-x86_64 +installed = timezonemap-0.4.5.4-1-x86_64 +installed = tinc-1.0.36-4-x86_64 +installed = tinysparql-3.11.1-1-x86_64 +installed = tinyxml-2.6.2-13-x86_64 +installed = tinyxml2-11.0.0-2-x86_64 +installed = tk-8.6.16-1-x86_64 +installed = tmux-3.6_b-2-x86_64 +installed = topgrade-17.5.1-1-x86_64 +installed = tor-0.4.9.9-1-x86_64 +installed = torsocks-2.5.0-1-x86_64 +installed = totem-43.2-5-x86_64 +installed = totem-pl-parser-3.26.7-1-x86_64 +installed = tpm2-tss-4.1.3-1-x86_64 +installed = transcode-1.1.7-49-x86_64 +installed = transmission-gtk-4.1.1-1-x86_64 +installed = tree-2.3.2-1-x86_64 +installed = tslib-1.24-1-x86_64 +installed = ttf-bitstream-vera-1.10-16-any +installed = ttf-dejavu-2.37+18+g9b5d1b2f-8-any +installed = ttf-hack-3.003-7-any +installed = ttf-inconsolata-1:3.000-5-any +installed = ttf-indic-otf-0.2-12-any +installed = ttf-liberation-2.1.5-2-any +installed = ttf-ms-fonts-2.0-13-any +installed = ttf-segoe-fluent-icons-1.0-3-any +installed = ttf-segoe-ui-variable-1.0-1-any +installed = ttf-ubuntu-font-family-1:0.83-2-any +installed = tumbler-4.20.1-1-x86_64 +installed = twolame-0.4.0-4-x86_64 +installed = tzdata-2026b-1-x86_64 +installed = uartscope-1.0.0.r2.g92168ee-1-x86_64 +installed = uchardet-0.0.8-4-x86_64 +installed = udisks2-2.11.1-2-x86_64 +installed = unifdef-2.12-4-x86_64 +installed = unigine-valley-1.0-1-x86_64 +installed = unixodbc-2.3.14-1-x86_64 +installed = unrar-1:7.2.6-1-x86_64 +installed = unshield-1.6.2-1-x86_64 +installed = unzip-6.0-23-x86_64 +installed = upower-1.91.2-1-x86_64 +installed = usbmuxd-1.1.1-4-x86_64 +installed = usbredir-0.15.0-1-x86_64 +installed = usbutils-019-1-x86_64 +installed = usd-26.05-3-x86_64 +installed = uthash-2.3.0-3-any +installed = util-linux-2.42.1-1-x86_64 +installed = util-linux-libs-2.42.1-1-x86_64 +installed = v4l-utils-1.32.0-2-x86_64 +installed = v4l2loopback-dkms-0.15.3-1-any +installed = vala-0.56.19-1-x86_64 +installed = valgrind-3.25.1-5-x86_64 +installed = vamp-plugin-sdk-1:2.10-1-x86_64 +installed = vapoursynth-76-1-x86_64 +installed = vde2-2.3.3-8-x86_64 +installed = ventoy-bin-1.1.12-1-x86_64 +installed = verdict-1.4.5-2-x86_64 +installed = vice-3.10-2-x86_64 +installed = vid.stab-1.1.1-2-x86_64 +installed = vim-9.2.0600-1-x86_64 +installed = vim-runtime-9.2.0600-1-x86_64 +installed = virglrenderer-1.3.0-2-x86_64 +installed = virt-install-5.1.0-3-any +installed = virt-manager-5.1.0-3-any +installed = virt-viewer-11.0-4-x86_64 +installed = virtiofsd-1.13.3-1-x86_64 +installed = virtualbox-7.2.8-2-x86_64 +installed = virtualbox-guest-iso-7.2.8-1-any +installed = virtualbox-host-dkms-7.2.8-2-x86_64 +installed = virtualgl-3.1.4-1-x86_64 +installed = visual-studio-code-bin-1.123.0-6-x86_64 +installed = vivaldi-8.0.4033.44-1-x86_64 +installed = vivaldi-ffmpeg-codecs-148.0.7778.256-1-x86_64 +installed = vlc-3.0.23_2-6-x86_64 +installed = vlc-cli-3.0.23_2-6-x86_64 +installed = vlc-gui-qt-3.0.23_2-6-x86_64 +installed = vlc-plugin-a52dec-3.0.23_2-6-x86_64 +installed = vlc-plugin-alsa-3.0.23_2-6-x86_64 +installed = vlc-plugin-archive-3.0.23_2-6-x86_64 +installed = vlc-plugin-dav1d-3.0.23_2-6-x86_64 +installed = vlc-plugin-dbus-3.0.23_2-6-x86_64 +installed = vlc-plugin-dbus-screensaver-3.0.23_2-6-x86_64 +installed = vlc-plugin-faad2-3.0.23_2-6-x86_64 +installed = vlc-plugin-flac-3.0.23_2-6-x86_64 +installed = vlc-plugin-gnutls-3.0.23_2-6-x86_64 +installed = vlc-plugin-inflate-3.0.23_2-6-x86_64 +installed = vlc-plugin-journal-3.0.23_2-6-x86_64 +installed = vlc-plugin-jpeg-3.0.23_2-6-x86_64 +installed = vlc-plugin-lua-3.0.23_2-6-x86_64 +installed = vlc-plugin-matroska-3.0.23_2-6-x86_64 +installed = vlc-plugin-mpg123-3.0.23_2-6-x86_64 +installed = vlc-plugin-ogg-3.0.23_2-6-x86_64 +installed = vlc-plugin-opus-3.0.23_2-6-x86_64 +installed = vlc-plugin-png-3.0.23_2-6-x86_64 +installed = vlc-plugin-pulse-3.0.23_2-6-x86_64 +installed = vlc-plugin-shout-3.0.23_2-6-x86_64 +installed = vlc-plugin-speex-3.0.23_2-6-x86_64 +installed = vlc-plugin-tag-3.0.23_2-6-x86_64 +installed = vlc-plugin-theora-3.0.23_2-6-x86_64 +installed = vlc-plugin-twolame-3.0.23_2-6-x86_64 +installed = vlc-plugin-vorbis-3.0.23_2-6-x86_64 +installed = vlc-plugin-vpx-3.0.23_2-6-x86_64 +installed = vlc-plugin-xml-3.0.23_2-6-x86_64 +installed = vlc-plugins-base-3.0.23_2-6-x86_64 +installed = vlc-plugins-video-output-3.0.23_2-6-x86_64 +installed = vmaf-3.1.0-1-x86_64 +installed = volume_key-0.3.12-12-x86_64 +installed = vscodium-bin-1.121.03429-1-x86_64 +installed = vte-common-0.84.0-1-x86_64 +installed = vte3-0.84.0-1-x86_64 +installed = vtk-9.6.2-1-x86_64 +installed = vulkan-headers-1:1.4.350.0-1-any +installed = vulkan-icd-loader-1.4.350.0-1-x86_64 +installed = vulkan-tools-1.4.350.0-1-x86_64 +installed = w3m-0.5.6-1-x86_64 +installed = wavpack-5.9.0-1-x86_64 +installed = wayland-1.25.0-1-x86_64 +installed = wayland-protocols-1.49-1-any +installed = webapp-manager-git-1.4.4.r0.gd8ef0df-1-any +installed = webkit2gtk-2.50.6-7-x86_64 +installed = webkit2gtk-4.1-2.52.4-1-x86_64 +installed = webkitgtk-6.0-2.52.4-1-x86_64 +installed = webp-pixbuf-loader-0.2.7-2-x86_64 +installed = webrtc-audio-processing-2.1-7-x86_64 +installed = webrtc-audio-processing-1-1.3-5-x86_64 +installed = websocketpp-0.8.2-4-any +installed = wget-1.25.0-5-x86_64 +installed = which-2.25-1-x86_64 +installed = widelands-1:1.3.1-3-x86_64 +installed = wildmidi-0.4.6-1-x86_64 +installed = wine-11.10-1-x86_64 +installed = wine-gecko-2.47.4-2-x86_64 +installed = wine-mono-11.1.0-1-x86_64 +installed = winetricks-20260125-2-any +installed = wireguard-tools-1.0.20260223-1-x86_64 +installed = wireless-regdb-2026.05.30-1-any +installed = wireless_tools-30.pre9-5-x86_64 +installed = wireplumber-0.5.14-1-x86_64 +installed = wmctrl-1.07-6-x86_64 +installed = woff2-1.0.2-6-x86_64 +installed = wolfssl-5.9.1-1-x86_64 +installed = wpa_supplicant-2:2.11-5-x86_64 +installed = wps-office-all-dicts-win-languages-11.1.0.11704-0-any +installed = wps-office-bin-12.1.2.22571-1-x86_64 +installed = wps-office-mui-de-de-11.1.0.11704-1-any +installed = wscat-6.1.0-1-x86_64 +installed = wxwidgets-common-3.2.10-2-x86_64 +installed = wxwidgets-gtk3-3.2.10-2-x86_64 +installed = x264-3:0.165.r3222.b35605a-2-x86_64 +installed = x265-4.1-1-x86_64 +installed = xapian-core-1:2.0.0-2-x86_64 +installed = xapp-3.2.2-1-x86_64 +installed = xapp-symbolic-icons-1.1.0-1-any +installed = xawtv-3.107-3-x86_64 +installed = xbindkeys-1.8.7-5-x86_64 +installed = xbitmaps-1.1.4-1-any +installed = xcb-proto-1.17.0-4-any +installed = xcb-util-0.4.1-2-x86_64 +installed = xcb-util-cursor-0.1.6-1-x86_64 +installed = xcb-util-errors-1.0.1-2-x86_64 +installed = xcb-util-image-0.4.1-3-x86_64 +installed = xcb-util-keysyms-0.4.1-5-x86_64 +installed = xcb-util-renderutil-0.3.10-2-x86_64 +installed = xcb-util-wm-0.4.2-2-x86_64 +installed = xcb-util-xrm-1.3-4-x86_64 +installed = xdg-dbus-proxy-0.1.7-1-x86_64 +installed = xdg-desktop-portal-1.20.4-1-x86_64 +installed = xdg-desktop-portal-gnome-50.0-1-x86_64 +installed = xdg-desktop-portal-gtk-1.15.3-1-x86_64 +installed = xdg-desktop-portal-kde-6.6.5-1-x86_64 +installed = xdg-desktop-portal-lxqt-1.4.0-1-x86_64 +installed = xdg-desktop-portal-xapp-1.1.3-2-x86_64 +installed = xdg-user-dirs-0.20-1-x86_64 +installed = xdg-user-dirs-gtk-0.16-1-x86_64 +installed = xdg-utils-1.2.1-2-any +installed = xdotool-4.20260303.1-1-x86_64 +installed = xerces-c-3.3.0-4-x86_64 +installed = xf86-input-libinput-1.5.0-1-x86_64 +installed = xf86-video-fbdev-0.5.1-1-x86_64 +installed = xf86-video-intel-1:2.99.917+939+g4a64400e-1-x86_64 +installed = xf86-video-vesa-2.6.0-3-x86_64 +installed = xfce4-appfinder-4.20.0-2-x86_64 +installed = xfce4-panel-4.20.7-1-x86_64 +installed = xfce4-screensaver-4.20.2-1-x86_64 +installed = xfce4-session-4.20.4-1-x86_64 +installed = xfce4-settings-4.20.4-1-x86_64 +installed = xfconf-4.20.0-2-x86_64 +installed = xfdesktop-4.20.2-1-x86_64 +installed = xfsprogs-7.0.1-1-x86_64 +installed = xfwm4-4.20.0-2-x86_64 +installed = xfwm4-themes-4.10.0-6-any +installed = xine-lib-1.2.13-16-x86_64 +installed = xkeyboard-config-2.47-1-any +installed = xorg-appres-1.0.7-1-x86_64 +installed = xorg-fonts-alias-misc-1.0.6-1-any +installed = xorg-fonts-encodings-1.1.0-2-any +installed = xorg-fonts-misc-1.0.4-2-any +installed = xorg-iceauth-1.0.11-1-x86_64 +installed = xorg-mkfontscale-1.2.4-1-x86_64 +installed = xorg-server-21.1.23-1-x86_64 +installed = xorg-server-common-21.1.23-1-x86_64 +installed = xorg-server-xvfb-21.1.23-1-x86_64 +installed = xorg-setxkbmap-1.3.5-1-x86_64 +installed = xorg-xauth-1.1.5-1-x86_64 +installed = xorg-xdpyinfo-1.4.0-1-x86_64 +installed = xorg-xhost-1.0.10-1-x86_64 +installed = xorg-xinit-1.4.4-1-x86_64 +installed = xorg-xinput-1.6.4-2-x86_64 +installed = xorg-xkbcomp-1.5.0-1-x86_64 +installed = xorg-xmessage-1.0.7-2-x86_64 +installed = xorg-xmodmap-1.0.11-2-x86_64 +installed = xorg-xprop-1.2.8-1-x86_64 +installed = xorg-xrandr-1.5.4-1-x86_64 +installed = xorg-xrdb-1.2.2-2-x86_64 +installed = xorg-xset-1.2.5-2-x86_64 +installed = xorg-xsetroot-1.1.3-2-x86_64 +installed = xorg-xwayland-24.1.12-1-x86_64 +installed = xorg-xwininfo-1.1.6-2-x86_64 +installed = xorgproto-2025.1-1-any +installed = xplane-sdk-devel-4.3.0-1-any +installed = xsane-0.999-8-x86_64 +installed = xsane-gimp-0.999-8-x86_64 +installed = xsane2tess-1.0-12-any +installed = xscreensaver-6.15-1-x86_64 +installed = xterm-410-1-x86_64 +installed = xvidcore-1.3.7-3-x86_64 +installed = xxhash-0.8.3-1-x86_64 +installed = xz-5.8.3-1-x86_64 +installed = yakuake-26.04.2-1-x86_64 +installed = yaml-cpp-0.9.0-1-x86_64 +installed = yarn-1.22.22-2-any +installed = yasm-1.3.0-9-x86_64 +installed = yay-git-12.6.0.r2.g4c5fda79-1-x86_64 +installed = yaz-5.35.1-1-x86_64 +installed = yelp-49.1-1-x86_64 +installed = yelp-tools-42.1-2-any +installed = yelp-xsl-49.0-1-any +installed = youtube-dl-2021.12.17-5-any +installed = yp-tools-4.2.3-6-x86_64 +installed = yp-tools-debug-4.2.3-6-x86_64 +installed = yt-dlp-2026.03.17-1-any +installed = yt-dlp-ejs-0.8.0-1-any +installed = zbar-0.23.93-5-x86_64 +installed = zenity-4.2.2-1-x86_64 +installed = zeromq-4.3.5-3-x86_64 +installed = zimg-3.0.6-1-x86_64 +installed = zint-2.16.0-2-x86_64 +installed = zip-3.0-13-x86_64 +installed = zita-convolver-4.0.3-5-x86_64 +installed = zix-0.8.0-1-x86_64 +installed = zlib-1:1.3.2-3-x86_64 +installed = zlib-ng-2.3.3-1-x86_64 +installed = zsh-5.9.1-1-x86_64 +installed = zsh-completions-0.36.0-1-any +installed = zsh-syntax-highlighting-0.8.0-2-any +installed = zstd-1.5.7-3-x86_64 +installed = zvbi-0.2.44-1-x86_64 +installed = zxing-cpp-3.0.2-1-x86_64 +installed = zziplib-0.13.80-1-x86_64 diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/.MTREE b/src/barecode/BareCodeAUR/pkg/barecode-git/.MTREE new file mode 100644 index 0000000..e5d07aa Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/.MTREE differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/.PKGINFO b/src/barecode/BareCodeAUR/pkg/barecode-git/.PKGINFO new file mode 100644 index 0000000..5d82b3f --- /dev/null +++ b/src/barecode/BareCodeAUR/pkg/barecode-git/.PKGINFO @@ -0,0 +1,19 @@ +# Generated by makepkg 7.1.0 +# using fakeroot version 1.37.2 +pkgname = barecode-git +pkgbase = barecode-git +xdata = pkgtype=pkg +pkgver = r5.cb66172-1 +pkgdesc = Modularer Code-Editor, entwickelt von Projekt Hirnfrei (git) +url = https://git.projekt-hirnfrei.de/diabolus/BareCode +builddate = 1781069213 +packager = Unknown Packager +size = 1191503 +arch = x86_64 +license = MIT +conflict = barecode +provides = barecode +depend = qt6-base +makedepend = cmake +makedepend = ninja +makedepend = git diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/bin/BareCode b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/bin/BareCode new file mode 100755 index 0000000..c9950bf Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/bin/BareCode differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/BareCode.desktop b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/BareCode.desktop new file mode 100644 index 0000000..ade1b56 --- /dev/null +++ b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/BareCode.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=BareCode +GenericName=Code Editor +Comment=Modularer Code-Editor für HTML, PHP, CSS und mehr +Exec=BareCode %F +Icon=barecode +Terminal=false +Categories=Development;TextEditor; +MimeType=text/plain;text/html;text/css;text/x-php;text/x-csrc;text/x-chdr;text/x-c++src;text/x-c++hdr; +Keywords=editor;code;html;php;css;c++; +StartupWMClass=BareCode diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/barecode.desktop b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/barecode.desktop new file mode 100644 index 0000000..e6b348c --- /dev/null +++ b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/applications/barecode.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Type=Application +Name=BareCode +GenericName=Code-Editor +Comment=Modularer Code-Editor von Projekt Hirnfrei +Exec=BareCode %F +Icon=barecode +Terminal=false +Categories=Development;TextEditor;IDE; +MimeType=text/plain;text/x-csrc;text/x-chdr;text/x-c++src;text/x-c++hdr; +Keywords=editor;code;programmierung;entwicklung; +StartupNotify=true +StartupWMClass=BareCode diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/128x128/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/128x128/apps/barecode.png new file mode 100644 index 0000000..bb49b56 Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/128x128/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/16x16/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/16x16/apps/barecode.png new file mode 100644 index 0000000..7cba1e4 Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/16x16/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/256x256/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/256x256/apps/barecode.png new file mode 100644 index 0000000..f18f69f Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/256x256/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/32x32/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/32x32/apps/barecode.png new file mode 100644 index 0000000..5982252 Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/32x32/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/48x48/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/48x48/apps/barecode.png new file mode 100644 index 0000000..b792afe Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/48x48/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/512x512/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/512x512/apps/barecode.png new file mode 100644 index 0000000..5b843e5 Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/512x512/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/64x64/apps/barecode.png b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/64x64/apps/barecode.png new file mode 100644 index 0000000..1025e84 Binary files /dev/null and b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/icons/hicolor/64x64/apps/barecode.png differ diff --git a/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/licenses/barecode-git/LICENSE b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/licenses/barecode-git/LICENSE new file mode 100644 index 0000000..f657ddf --- /dev/null +++ b/src/barecode/BareCodeAUR/pkg/barecode-git/usr/share/licenses/barecode-git/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Dany Thinnes – Projekt Hirnfrei + +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. diff --git a/src/barecode/CMakeLists.txt b/src/barecode/CMakeLists.txt new file mode 100644 index 0000000..eb10c64 --- /dev/null +++ b/src/barecode/CMakeLists.txt @@ -0,0 +1,143 @@ +cmake_minimum_required(VERSION 3.16) + +project(BareCode + VERSION 1.1.0 + DESCRIPTION "A modular code editor built with Qt6" + LANGUAGES CXX +) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +# --------------------------------------------------------------------------- +# Plattform-Erkennung +# Haiku definiert kein eigenes CMake-Flag — wir erkennen es über den +# Systemnamen. CMAKE_SYSTEM_NAME ist "Haiku" auf Haiku OS. +# --------------------------------------------------------------------------- +if(WIN32) + set(PLATFORM_WINDOWS TRUE) + add_compile_definitions(PLATFORM_WINDOWS) + set(CMAKE_WIN32_EXECUTABLE ON) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Haiku") + set(PLATFORM_HAIKU TRUE) + add_compile_definitions(PLATFORM_HAIKU) +elseif(APPLE) + set(PLATFORM_MACOS TRUE) + add_compile_definitions(PLATFORM_MACOS) +elseif(UNIX) + set(PLATFORM_LINUX TRUE) + add_compile_definitions(PLATFORM_LINUX) +endif() + +# --------------------------------------------------------------------------- +# Qt6 +# --------------------------------------------------------------------------- +find_package(Qt6 REQUIRED COMPONENTS + Core + Gui + Widgets + Concurrent +) + +qt_standard_project_setup() + +# Include cmake modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +# Collect sources +add_subdirectory(src) + +# Resources +qt_add_resources(BARECODE_RESOURCES resources/resources.qrc) + +# --------------------------------------------------------------------------- +# Executable +# Unter Windows: .rc-Datei für EXE-Icon einbinden +# --------------------------------------------------------------------------- +if(PLATFORM_WINDOWS) + qt_add_executable(BareCode + main.cpp + BareCode.rc + ${BARECODE_RESOURCES} + ) +else() + qt_add_executable(BareCode + main.cpp + ${BARECODE_RESOURCES} + ) +endif() + +target_link_libraries(BareCode PRIVATE + BareCode_Core + BareCode_Editor + BareCode_FileTree + BareCode_Highlighter + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +target_include_directories(BareCode PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# --------------------------------------------------------------------------- +# Installation +# --------------------------------------------------------------------------- +include(GNUInstallDirs) + +install(TARGETS BareCode + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# ---- Linux (FreeDesktop) -------------------------------------------------- +if(PLATFORM_LINUX) + foreach(SIZE 16 32 48 64 128 256 512) + install(FILES resources/icon_${SIZE}.png + DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${SIZE}x${SIZE}/apps + RENAME barecode.png + ) + endforeach() + + install(FILES BareCode.desktop + DESTINATION ${CMAKE_INSTALL_DATADIR}/applications + ) +endif() + +# ---- Haiku ---------------------------------------------------------------- +# Haiku verwendet kein FreeDesktop-System. Icons und MIME-Typen werden +# nativ über 'mimeset' gesetzt. Die PNG-Icons legen wir in den +# Haiku-typischen Pfad, ein post-install Skript ruft mimeset auf. +if(PLATFORM_HAIKU) + install(FILES resources/icon_256.png + DESTINATION ${CMAKE_INSTALL_DATADIR}/BareCode + RENAME BareCode.png + ) + + # mimeset nach der Installation ausführen um MIME-Typ zu registrieren + install(CODE " + execute_process( + COMMAND mimeset -f \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/BareCode\" + RESULT_VARIABLE _mimeset_result + ) + if(NOT _mimeset_result EQUAL 0) + message(WARNING \"mimeset konnte nicht ausgeführt werden – MIME-Typ muss manuell gesetzt werden.\") + endif() + ") +endif() + +# ---- macOS ---------------------------------------------------------------- +if(PLATFORM_MACOS) + set_target_properties(BareCode PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_BUNDLE_NAME "BareCode" + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} + ) +endif() + diff --git a/src/barecode/LICENSE b/src/barecode/LICENSE new file mode 100644 index 0000000..f657ddf --- /dev/null +++ b/src/barecode/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Dany Thinnes – Projekt Hirnfrei + +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. diff --git a/src/barecode/README.md b/src/barecode/README.md new file mode 100644 index 0000000..f6e99d6 --- /dev/null +++ b/src/barecode/README.md @@ -0,0 +1,171 @@ +# BareCode + +**BareCode – Schlanker Code-Editor für Web-Entwickler** +Version 1.1.0 + +Kompiliert sauber auf **Linux**, **Windows** und **Haiku**. + +--- + +## Features + +| Feature | Details | +|---|---| +| Projektbaum | Linkes Panel — zeigt nur das gewählte Projektverzeichnis | +| Tabs | Mehrere Dateien gleichzeitig, verschiebbar und schließbar | +| Änderungsindikator | ● im Tab-Titel bei ungespeicherten Änderungen | +| Syntax-Highlighting | HTML, PHP, CSS, C/C++ inkl. mehrzeiliger Kommentare | +| Zeilennummern | Eigener Gutter, aktuelle Zeile hervorgehoben | +| Einrück-Führungslinien | Vertikale Linien wie in VS Code | +| Auto-Indent | Einrückungstiefe wird bei Enter übernommen | +| Tab / Shift+Tab | Ein- und Ausrücken, auch für mehrere Zeilen gleichzeitig | +| Smart Backspace | Springt zur vorherigen Tab-Stop-Position | +| Speichern | Speichern, Speichern unter, Alles speichern | +| Suchen & Ersetzen | Einzeln, Alle, In Auswahl, Regex, Live-Hervorhebung | +| In Dateien suchen | Rekursive Projektsuche mit Ergebnisliste, direkt zur Zeile | +| Dark / Light Mode | Umschaltbar, wird gespeichert | +| Session | Geöffnete Dateien und aktiver Tab werden wiederhergestellt | + +--- + +## Projektstruktur + +``` +BareCode/ +├── CMakeLists.txt +├── main.cpp +├── resources/ +│ ├── resources.qrc +│ └── icon_*.png +└── src/ + ├── core/ # MainWindow, ProjectManager, Settings, ThemeManager, IPlugin + ├── editor/ # EditorPanel, EditorTab, CodeEditor, SearchPanel, FileSearchPanel + ├── filetree/ # FileTreePanel + └── highlighter/ # SyntaxHighlighter, HighlighterFactory +``` + +Jedes Unterverzeichnis kompiliert als eigene statische Bibliothek. + +--- + +## Abhängigkeiten & Bauen + +### Linux + +**Abhängigkeiten (Beispiel Ubuntu/Debian):** +```bash +sudo apt install cmake qt6-base-dev qt6-base-dev-tools libqt6concurrent6 +``` + +**Abhängigkeiten (Arch/Manjaro):** +```bash +sudo pacman -S cmake qt6-base +``` + +**Bauen:** +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j$(nproc) +./build/BareCode +``` + +**Installieren:** +```bash +sudo cmake --install build +``` + +--- + +### Windows (Visual Studio) + +**Abhängigkeiten:** +- [Qt6](https://www.qt.io/download) (Komponenten: Qt6 Base, Qt6 Concurrent) +- CMake ≥ 3.16 +- Visual Studio 2019 oder neuer + +```bat +cmake -B build -G "Visual Studio 17 2022" -A x64 +cmake --build build --config Release +build\Release\BareCode.exe +``` + +**Windows Installer erstellen** (mit [Inno Setup](https://jrsoftware.org/isinfo.php)): +```bat +windeployqt --release build\Release\BareCode.exe +``` +Danach das Inno Setup Skript ausführen. + +--- + +### Haiku + +**Abhängigkeiten:** +```bash +pkgman install qt6_base qt6_base_devel +``` + +> **Hinweis:** `qt6_base_devel` enthält auf Haiku sowohl die Header als auch +> die Build-Tools (`moc`, `rcc`, `qmake`). Getestet auf Haiku R1/beta5. + +**Bauen:** +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j$(nproc) +./build/BareCode +``` + +**Installieren:** +```bash +cmake --install build +``` + +> Nach der Installation wird `mimeset` automatisch aufgerufen um den +> MIME-Typ zu registrieren, damit BareCode im Haiku Tracker korrekt +> als Anwendung erkannt wird. + +--- + +## Tastaturkürzel + +| Aktion | Kürzel | +|---|---| +| Datei öffnen | Strg+O | +| Neue Datei | Strg+N | +| Projekt öffnen | Strg+Shift+O | +| Speichern | Strg+S | +| Speichern unter | Strg+Shift+A | +| Alles speichern | Strg+Shift+S | +| Suchen / Ersetzen | Strg+F | +| In Dateien suchen | Strg+Shift+F | +| Dark Mode | Strg+Shift+D | + +--- + +## Erweitern + +### Neuen Highlighter hinzufügen + +1. Subklasse von `SyntaxHighlighter` in `src/highlighter/` erstellen +2. `m_rules` im Konstruktor befüllen (siehe `CppHighlighter` als Vorlage) +3. Dateiendung in `HighlighterFactory.cpp` registrieren + +Keine weiteren Dateien müssen geändert werden. + +### Neues Panel / Plugin hinzufügen + +1. `IPlugin`-Interface aus `src/core/IPlugin.h` implementieren +2. `QWidget`-Subklasse für die UI erstellen +3. In `MainWindow` instanziieren und verdrahten + +--- + +## Code-Stil + +Allman-Klammerstil, C++17 durchgehend. + +--- + +## Links + +- Website: [www.projekt-hirnfrei.de](https://www.projekt-hirnfrei.de) +- Discord: [discord.projekt-hirnfrei.de](https://discord.projekt-hirnfrei.de) diff --git a/src/barecode/barecode.desktop b/src/barecode/barecode.desktop new file mode 100644 index 0000000..e6b348c --- /dev/null +++ b/src/barecode/barecode.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Type=Application +Name=BareCode +GenericName=Code-Editor +Comment=Modularer Code-Editor von Projekt Hirnfrei +Exec=BareCode %F +Icon=barecode +Terminal=false +Categories=Development;TextEditor;IDE; +MimeType=text/plain;text/x-csrc;text/x-chdr;text/x-c++src;text/x-c++hdr; +Keywords=editor;code;programmierung;entwicklung; +StartupNotify=true +StartupWMClass=BareCode diff --git a/src/barecode/main.cpp b/src/barecode/main.cpp new file mode 100644 index 0000000..babe9b5 --- /dev/null +++ b/src/barecode/main.cpp @@ -0,0 +1,28 @@ +#include +#include +#include "core/MainWindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + app.setApplicationName("BareCode"); + app.setApplicationVersion("1.1.0"); + app.setOrganizationName("BareCode"); + + // Icon in allen verfügbaren Größen setzen + QIcon appIcon; + appIcon.addFile(":/icon_16.png", QSize(16, 16)); + appIcon.addFile(":/icon_32.png", QSize(32, 32)); + appIcon.addFile(":/icon_48.png", QSize(48, 48)); + appIcon.addFile(":/icon_64.png", QSize(64, 64)); + appIcon.addFile(":/icon_128.png", QSize(128, 128)); + appIcon.addFile(":/icon_256.png", QSize(256, 256)); + appIcon.addFile(":/icon_512.png", QSize(512, 512)); + app.setWindowIcon(appIcon); + + MainWindow window; + window.show(); + + return app.exec(); +} diff --git a/src/barecode/resources/BareCode.ico b/src/barecode/resources/BareCode.ico new file mode 100644 index 0000000..10ecf22 Binary files /dev/null and b/src/barecode/resources/BareCode.ico differ diff --git a/src/barecode/resources/icon_128.png b/src/barecode/resources/icon_128.png new file mode 100644 index 0000000..bb49b56 Binary files /dev/null and b/src/barecode/resources/icon_128.png differ diff --git a/src/barecode/resources/icon_16.png b/src/barecode/resources/icon_16.png new file mode 100644 index 0000000..7cba1e4 Binary files /dev/null and b/src/barecode/resources/icon_16.png differ diff --git a/src/barecode/resources/icon_24.png b/src/barecode/resources/icon_24.png new file mode 100644 index 0000000..67356ff Binary files /dev/null and b/src/barecode/resources/icon_24.png differ diff --git a/src/barecode/resources/icon_256.png b/src/barecode/resources/icon_256.png new file mode 100644 index 0000000..f18f69f Binary files /dev/null and b/src/barecode/resources/icon_256.png differ diff --git a/src/barecode/resources/icon_32.png b/src/barecode/resources/icon_32.png new file mode 100644 index 0000000..5982252 Binary files /dev/null and b/src/barecode/resources/icon_32.png differ diff --git a/src/barecode/resources/icon_48.png b/src/barecode/resources/icon_48.png new file mode 100644 index 0000000..b792afe Binary files /dev/null and b/src/barecode/resources/icon_48.png differ diff --git a/src/barecode/resources/icon_512.png b/src/barecode/resources/icon_512.png new file mode 100644 index 0000000..5b843e5 Binary files /dev/null and b/src/barecode/resources/icon_512.png differ diff --git a/src/barecode/resources/icon_64.png b/src/barecode/resources/icon_64.png new file mode 100644 index 0000000..1025e84 Binary files /dev/null and b/src/barecode/resources/icon_64.png differ diff --git a/src/barecode/resources/php_functions.json b/src/barecode/resources/php_functions.json new file mode 100644 index 0000000..1e81c97 --- /dev/null +++ b/src/barecode/resources/php_functions.json @@ -0,0 +1,1197 @@ +[ + { + "name": "abs", + "signature": "abs(int|float $num): int|float", + "desc": "Absolutwert" + }, + { + "name": "addslashes", + "signature": "addslashes(string $string): string", + "desc": "Sonderzeichen mit Backslash escapen" + }, + { + "name": "array_chunk", + "signature": "array_chunk(array $array, int $length, bool $preserve_keys = false): array", + "desc": "Array in Stücke aufteilen" + }, + { + "name": "array_column", + "signature": "array_column(array $array, int|string|null $column_key, int|string|null $index_key = null): array", + "desc": "Spalte aus mehrdimensionalem Array" + }, + { + "name": "array_combine", + "signature": "array_combine(array $keys, array $values): array", + "desc": "Array aus Schlüsseln und Werten erstellen" + }, + { + "name": "array_diff", + "signature": "array_diff(array $array, array ...$arrays): array", + "desc": "Differenz zweier Arrays" + }, + { + "name": "array_fill", + "signature": "array_fill(int $start_index, int $count, mixed $value): array", + "desc": "Array mit Werten füllen" + }, + { + "name": "array_fill_keys", + "signature": "array_fill_keys(array $keys, mixed $value): array", + "desc": "Array mit Schlüsseln und Wert füllen" + }, + { + "name": "array_filter", + "signature": "array_filter(array $array, callable $callback = null, int $mode = 0): array", + "desc": "Array filtern" + }, + { + "name": "array_flip", + "signature": "array_flip(array $array): array", + "desc": "Schlüssel und Werte tauschen" + }, + { + "name": "array_intersect", + "signature": "array_intersect(array $array, array ...$arrays): array", + "desc": "Schnittmenge zweier Arrays" + }, + { + "name": "array_key_exists", + "signature": "array_key_exists(string|int $key, array $array): bool", + "desc": "Prüft ob Schlüssel existiert" + }, + { + "name": "array_key_first", + "signature": "array_key_first(array $array): int|string|null", + "desc": "Ersten Schlüssel eines Arrays" + }, + { + "name": "array_key_last", + "signature": "array_key_last(array $array): int|string|null", + "desc": "Letzten Schlüssel eines Arrays" + }, + { + "name": "array_keys", + "signature": "array_keys(array $array, mixed $filter_value = null, bool $strict = false): array", + "desc": "Alle Schlüssel zurückgeben" + }, + { + "name": "array_map", + "signature": "array_map(callable|null $callback, array $array, array ...$arrays): array", + "desc": "Funktion auf alle Elemente anwenden" + }, + { + "name": "array_merge", + "signature": "array_merge(array ...$arrays): array", + "desc": "Arrays zusammenführen" + }, + { + "name": "array_merge_recursive", + "signature": "array_merge_recursive(array ...$arrays): array", + "desc": "Arrays rekursiv zusammenführen" + }, + { + "name": "array_pop", + "signature": "array_pop(array &$array): mixed", + "desc": "Letztes Element entfernen und zurückgeben" + }, + { + "name": "array_push", + "signature": "array_push(array &$array, mixed ...$values): int", + "desc": "Elemente ans Ende anhängen" + }, + { + "name": "array_reduce", + "signature": "array_reduce(array $array, callable $callback, mixed $initial = null): mixed", + "desc": "Array auf einen Wert reduzieren" + }, + { + "name": "array_reverse", + "signature": "array_reverse(array $array, bool $preserve_keys = false): array", + "desc": "Array umkehren" + }, + { + "name": "array_search", + "signature": "array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false", + "desc": "Wert im Array suchen" + }, + { + "name": "array_shift", + "signature": "array_shift(array &$array): mixed", + "desc": "Erstes Element entfernen und zurückgeben" + }, + { + "name": "array_slice", + "signature": "array_slice(array $array, int $offset, int $length = null, bool $preserve_keys = false): array", + "desc": "Teilarray zurückgeben" + }, + { + "name": "array_splice", + "signature": "array_splice(array &$array, int $offset, int $length = null, mixed $replacement = []): array", + "desc": "Array-Elemente entfernen und ersetzen" + }, + { + "name": "array_unique", + "signature": "array_unique(array $array, int $flags = SORT_STRING): array", + "desc": "Doppelte Werte entfernen" + }, + { + "name": "array_unshift", + "signature": "array_unshift(array &$array, mixed ...$values): int", + "desc": "Elemente am Anfang einfügen" + }, + { + "name": "array_values", + "signature": "array_values(array $array): array", + "desc": "Alle Werte neu indiziert zurückgeben" + }, + { + "name": "array_walk", + "signature": "array_walk(array|object &$array, callable $callback, mixed $arg = null): bool", + "desc": "Funktion auf jedes Element anwenden" + }, + { + "name": "arsort", + "signature": "arsort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array absteigend sortieren, Schlüssel beibehalten" + }, + { + "name": "asort", + "signature": "asort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array aufsteigend sortieren, Schlüssel beibehalten" + }, + { + "name": "base64_decode", + "signature": "base64_decode(string $string, bool $strict = false): string|false", + "desc": "Base64 dekodieren" + }, + { + "name": "base64_encode", + "signature": "base64_encode(string $string): string", + "desc": "Base64 kodieren" + }, + { + "name": "basename", + "signature": "basename(string $path, string $suffix = ''): string", + "desc": "Dateinamen aus Pfad" + }, + { + "name": "boolval", + "signature": "boolval(mixed $value): bool", + "desc": "In Boolean umwandeln" + }, + { + "name": "call_user_func", + "signature": "call_user_func(callable $callback, mixed ...$args): mixed", + "desc": "Funktion aufrufen" + }, + { + "name": "call_user_func_array", + "signature": "call_user_func_array(callable $callback, array $args): mixed", + "desc": "Funktion mit Array-Parametern aufrufen" + }, + { + "name": "ceil", + "signature": "ceil(int|float $num): float", + "desc": "Aufrunden" + }, + { + "name": "checkdate", + "signature": "checkdate(int $month, int $day, int $year): bool", + "desc": "Datum auf Gültigkeit prüfen" + }, + { + "name": "chunk_split", + "signature": "chunk_split(string $string, int $length = 76, string $separator = \"\\r\\n\"): string", + "desc": "String in Stücke aufteilen" + }, + { + "name": "class_exists", + "signature": "class_exists(string $class, bool $autoload = true): bool", + "desc": "Prüft ob Klasse existiert" + }, + { + "name": "compact", + "signature": "compact(array|string $var_names, mixed ...$vars): array", + "desc": "Array aus Variablen erstellen" + }, + { + "name": "constant", + "signature": "constant(string $name): mixed", + "desc": "Wert einer Konstante" + }, + { + "name": "copy", + "signature": "copy(string $from, string $to, resource $context = null): bool", + "desc": "Datei kopieren" + }, + { + "name": "count", + "signature": "count(Countable|array $array, int $mode = COUNT_NORMAL): int", + "desc": "Anzahl der Elemente" + }, + { + "name": "date", + "signature": "date(string $format, int $timestamp = time()): string", + "desc": "Datum formatieren" + }, + { + "name": "date_add", + "signature": "date_add(DateTime $object, DateInterval $interval): DateTime|false", + "desc": "Interval zu Datum addieren" + }, + { + "name": "date_create", + "signature": "date_create(string $datetime = 'now', DateTimeZone $timezone = null): DateTime|false", + "desc": "DateTime-Objekt erstellen" + }, + { + "name": "date_diff", + "signature": "date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute = false): DateInterval", + "desc": "Differenz zweier Datumswerte" + }, + { + "name": "date_format", + "signature": "date_format(DateTimeInterface $object, string $format): string", + "desc": "DateTime formatieren" + }, + { + "name": "date_sub", + "signature": "date_sub(DateTime $object, DateInterval $interval): DateTime|false", + "desc": "Interval von Datum subtrahieren" + }, + { + "name": "define", + "signature": "define(string $constant_name, mixed $value, bool $case_insensitive = false): bool", + "desc": "Konstante definieren" + }, + { + "name": "defined", + "signature": "defined(string $constant_name): bool", + "desc": "Prüft ob Konstante definiert ist" + }, + { + "name": "die", + "signature": "die(int|string $status = 0): never", + "desc": "Skript beenden (Alias exit)" + }, + { + "name": "dirname", + "signature": "dirname(string $path, int $levels = 1): string", + "desc": "Verzeichnisteil eines Pfades" + }, + { + "name": "echo", + "signature": "echo(string ...$expressions): void", + "desc": "Strings ausgeben" + }, + { + "name": "empty", + "signature": "empty(mixed $var): bool", + "desc": "Prüft ob Variable leer ist" + }, + { + "name": "error_reporting", + "signature": "error_reporting(int $error_level = null): int", + "desc": "Fehler-Reporting-Level setzen" + }, + { + "name": "exit", + "signature": "exit(int|string $status = 0): never", + "desc": "Skript beenden" + }, + { + "name": "exp", + "signature": "exp(float $num): float", + "desc": "e hoch x" + }, + { + "name": "explode", + "signature": "explode(string $separator, string $string, int $limit = PHP_INT_MAX): array", + "desc": "String aufteilen" + }, + { + "name": "extract", + "signature": "extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = ''): int", + "desc": "Variablen aus Array importieren" + }, + { + "name": "fclose", + "signature": "fclose(resource $handle): bool", + "desc": "Datei schließen" + }, + { + "name": "feof", + "signature": "feof(resource $handle): bool", + "desc": "Prüft ob Dateiende erreicht" + }, + { + "name": "fgets", + "signature": "fgets(resource $handle, int $length = null): string|false", + "desc": "Zeile aus Datei lesen" + }, + { + "name": "file", + "signature": "file(string $filename, int $flags = 0, resource $context = null): array|false", + "desc": "Datei als Array von Zeilen" + }, + { + "name": "file_exists", + "signature": "file_exists(string $filename): bool", + "desc": "Prüft ob Datei existiert" + }, + { + "name": "file_get_contents", + "signature": "file_get_contents(string $filename, bool $use_include_path = false, resource $context = null, int $offset = 0, int $length = null): string|false", + "desc": "Dateiinhalt als String" + }, + { + "name": "file_put_contents", + "signature": "file_put_contents(string $filename, mixed $data, int $flags = 0, resource $context = null): int|false", + "desc": "String in Datei schreiben" + }, + { + "name": "filectime", + "signature": "filectime(string $filename): int|false", + "desc": "Zeitpunkt der letzten Statusänderung" + }, + { + "name": "filemtime", + "signature": "filemtime(string $filename): int|false", + "desc": "Zeitpunkt der letzten Änderung" + }, + { + "name": "filesize", + "signature": "filesize(string $filename): int|false", + "desc": "Dateigröße in Bytes" + }, + { + "name": "floatval", + "signature": "floatval(mixed $value): float", + "desc": "In Float umwandeln" + }, + { + "name": "floor", + "signature": "floor(int|float $num): float", + "desc": "Abrunden" + }, + { + "name": "fmod", + "signature": "fmod(float $num1, float $num2): float", + "desc": "Modulo für Floats" + }, + { + "name": "fopen", + "signature": "fopen(string $filename, string $mode, bool $use_include_path = false, resource $context = null): resource|false", + "desc": "Datei öffnen" + }, + { + "name": "fread", + "signature": "fread(resource $handle, int $length): string|false", + "desc": "Aus Datei lesen" + }, + { + "name": "fseek", + "signature": "fseek(resource $handle, int $offset, int $whence = SEEK_SET): int", + "desc": "Dateizeiger setzen" + }, + { + "name": "ftell", + "signature": "ftell(resource $handle): int|false", + "desc": "Aktuelle Position des Dateizeigers" + }, + { + "name": "function_exists", + "signature": "function_exists(string $function): bool", + "desc": "Prüft ob Funktion existiert" + }, + { + "name": "fwrite", + "signature": "fwrite(resource $handle, string $string, int $length = null): int|false", + "desc": "In Datei schreiben" + }, + { + "name": "get_class", + "signature": "get_class(object $object = null): string|false", + "desc": "Klassenname eines Objekts" + }, + { + "name": "get_parent_class", + "signature": "get_parent_class(object|string $object_or_class): string|false", + "desc": "Elternklasse ermitteln" + }, + { + "name": "gettype", + "signature": "gettype(mixed $value): string", + "desc": "Typ einer Variable" + }, + { + "name": "glob", + "signature": "glob(string $pattern, int $flags = 0): array|false", + "desc": "Dateien per Muster suchen" + }, + { + "name": "hash", + "signature": "hash(string $algo, string $data, bool $binary = false, array $options = []): string", + "desc": "Hash mit beliebigem Algorithmus" + }, + { + "name": "header", + "signature": "header(string $header, bool $replace = true, int $response_code = 0): void", + "desc": "HTTP-Header senden" + }, + { + "name": "headers_sent", + "signature": "headers_sent(string &$filename = null, int &$line = null): bool", + "desc": "Prüft ob Header bereits gesendet" + }, + { + "name": "htmlentities", + "signature": "htmlentities(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, string $encoding = 'UTF-8', bool $double_encode = true): string", + "desc": "Alle Sonderzeichen in HTML-Entities" + }, + { + "name": "htmlspecialchars", + "signature": "htmlspecialchars(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, string $encoding = 'UTF-8', bool $double_encode = true): string", + "desc": "Sonderzeichen in HTML-Entities umwandeln" + }, + { + "name": "htmlspecialchars_decode", + "signature": "htmlspecialchars_decode(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE): string", + "desc": "HTML-Entities zurückumwandeln" + }, + { + "name": "http_build_query", + "signature": "http_build_query(array|object $data, string $numeric_prefix = '', string $arg_separator = null, int $encoding_type = PHP_QUERY_RFC1738): string", + "desc": "Query-String aufbauen" + }, + { + "name": "implode", + "signature": "implode(string $separator, array $array): string", + "desc": "Array zu String verbinden" + }, + { + "name": "in_array", + "signature": "in_array(mixed $needle, array $haystack, bool $strict = false): bool", + "desc": "Prüft ob Wert im Array vorhanden" + }, + { + "name": "include", + "signature": "include(string $filename): mixed", + "desc": "Datei einbinden" + }, + { + "name": "include_once", + "signature": "include_once(string $filename): mixed", + "desc": "Datei einmalig einbinden" + }, + { + "name": "ini_get", + "signature": "ini_get(string $option): string|false", + "desc": "PHP-Konfigurationswert holen" + }, + { + "name": "ini_set", + "signature": "ini_set(string $option, string $value): string|false", + "desc": "PHP-Konfigurationswert setzen" + }, + { + "name": "instanceof", + "signature": "instanceof", + "desc": "Prüft ob Objekt eine Instanz ist" + }, + { + "name": "intdiv", + "signature": "intdiv(int $num1, int $num2): int", + "desc": "Ganzzahlige Division" + }, + { + "name": "intval", + "signature": "intval(mixed $value, int $base = 10): int", + "desc": "In Integer umwandeln" + }, + { + "name": "is_array", + "signature": "is_array(mixed $value): bool", + "desc": "Prüft ob Array" + }, + { + "name": "is_bool", + "signature": "is_bool(mixed $value): bool", + "desc": "Prüft ob Boolean" + }, + { + "name": "is_callable", + "signature": "is_callable(mixed $value, bool $syntax_only = false, string &$callable_name = null): bool", + "desc": "Prüft ob aufrufbar" + }, + { + "name": "is_dir", + "signature": "is_dir(string $filename): bool", + "desc": "Prüft ob Pfad ein Verzeichnis ist" + }, + { + "name": "is_file", + "signature": "is_file(string $filename): bool", + "desc": "Prüft ob Pfad eine Datei ist" + }, + { + "name": "is_float", + "signature": "is_float(mixed $value): bool", + "desc": "Prüft ob Float" + }, + { + "name": "is_int", + "signature": "is_int(mixed $value): bool", + "desc": "Prüft ob Integer" + }, + { + "name": "is_null", + "signature": "is_null(mixed $value): bool", + "desc": "Prüft ob Wert null ist" + }, + { + "name": "is_numeric", + "signature": "is_numeric(mixed $value): bool", + "desc": "Prüft ob numerisch" + }, + { + "name": "is_object", + "signature": "is_object(mixed $value): bool", + "desc": "Prüft ob Objekt" + }, + { + "name": "is_readable", + "signature": "is_readable(string $filename): bool", + "desc": "Prüft ob Datei lesbar ist" + }, + { + "name": "is_string", + "signature": "is_string(mixed $value): bool", + "desc": "Prüft ob String" + }, + { + "name": "is_writable", + "signature": "is_writable(string $filename): bool", + "desc": "Prüft ob Datei schreibbar ist" + }, + { + "name": "isset", + "signature": "isset(mixed $var, mixed ...$vars): bool", + "desc": "Prüft ob Variable gesetzt und nicht null" + }, + { + "name": "join", + "signature": "join(string $separator, array $array): string", + "desc": "Array zu String verbinden (Alias implode)" + }, + { + "name": "json_decode", + "signature": "json_decode(string $json, bool $associative = null, int $depth = 512, int $flags = 0): mixed", + "desc": "JSON parsen" + }, + { + "name": "json_encode", + "signature": "json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false", + "desc": "In JSON umwandeln" + }, + { + "name": "json_last_error", + "signature": "json_last_error(): int", + "desc": "Letzten JSON-Fehler abrufen" + }, + { + "name": "json_last_error_msg", + "signature": "json_last_error_msg(): string", + "desc": "Letzten JSON-Fehler als Text" + }, + { + "name": "krsort", + "signature": "krsort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array nach Schlüsseln absteigend sortieren" + }, + { + "name": "ksort", + "signature": "ksort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array nach Schlüsseln sortieren" + }, + { + "name": "lcfirst", + "signature": "lcfirst(string $string): string", + "desc": "Ersten Buchstaben klein" + }, + { + "name": "list", + "signature": "list(mixed ...$vars): array", + "desc": "Variablen wie ein Array zuweisen" + }, + { + "name": "log", + "signature": "log(float $num, float $base = M_E): float", + "desc": "Logarithmus" + }, + { + "name": "ltrim", + "signature": "ltrim(string $string, string $characters = \" \\n\\r\\t\\v\\0\"): string", + "desc": "Leerzeichen links entfernen" + }, + { + "name": "max", + "signature": "max(mixed $value, mixed ...$values): mixed", + "desc": "Größten Wert ermitteln" + }, + { + "name": "md5", + "signature": "md5(string $string, bool $binary = false): string", + "desc": "MD5-Hash berechnen" + }, + { + "name": "method_exists", + "signature": "method_exists(object|string $object_or_class, string $method): bool", + "desc": "Prüft ob Methode existiert" + }, + { + "name": "microtime", + "signature": "microtime(bool $as_float = false): string|float", + "desc": "Aktuellen Timestamp mit Mikrosekunden" + }, + { + "name": "min", + "signature": "min(mixed $value, mixed ...$values): mixed", + "desc": "Kleinsten Wert ermitteln" + }, + { + "name": "mkdir", + "signature": "mkdir(string $directory, int $permissions = 0777, bool $recursive = false, resource $context = null): bool", + "desc": "Verzeichnis erstellen" + }, + { + "name": "mktime", + "signature": "mktime(int $hour, int $minute = null, int $second = null, int $month = null, int $day = null, int $year = null): int|false", + "desc": "Unix-Timestamp erstellen" + }, + { + "name": "mt_rand", + "signature": "mt_rand(int $min = 0, int $max = MT_RAND_MAX): int", + "desc": "Bessere Zufallszahl" + }, + { + "name": "nl2br", + "signature": "nl2br(string $string, bool $use_xhtml = true): string", + "desc": "Zeilenumbrüche in
umwandeln" + }, + { + "name": "number_format", + "signature": "number_format(float $num, int $decimals = 0, string $decimal_separator = '.', string $thousands_separator = ','): string", + "desc": "Zahl formatieren" + }, + { + "name": "ob_end_clean", + "signature": "ob_end_clean(): bool", + "desc": "Buffer leeren und beenden" + }, + { + "name": "ob_get_clean", + "signature": "ob_get_clean(): string|false", + "desc": "Buffer-Inhalt holen und beenden" + }, + { + "name": "ob_get_contents", + "signature": "ob_get_contents(): string|false", + "desc": "Buffer-Inhalt holen" + }, + { + "name": "ob_start", + "signature": "ob_start(callable $callback = null, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): bool", + "desc": "Output-Buffering starten" + }, + { + "name": "parse_str", + "signature": "parse_str(string $string, array &$result): void", + "desc": "Query-String parsen" + }, + { + "name": "pathinfo", + "signature": "pathinfo(string $path, int $options = PATHINFO_ALL): array|string", + "desc": "Informationen über einen Pfad" + }, + { + "name": "PDO::__construct", + "signature": "PDO::__construct(string $dsn, string $username = null, string $password = null, array $options = null)", + "desc": "PDO-Verbindung herstellen" + }, + { + "name": "PDO::beginTransaction", + "signature": "PDO::beginTransaction(): bool", + "desc": "Transaktion starten" + }, + { + "name": "PDO::commit", + "signature": "PDO::commit(): bool", + "desc": "Transaktion bestätigen" + }, + { + "name": "PDO::exec", + "signature": "PDO::exec(string $statement): int|false", + "desc": "SQL ausführen, Anzahl betroffener Zeilen" + }, + { + "name": "PDO::lastInsertId", + "signature": "PDO::lastInsertId(string $name = null): string|false", + "desc": "Letzte eingefügte ID" + }, + { + "name": "PDO::prepare", + "signature": "PDO::prepare(string $query, array $options = []): PDOStatement|false", + "desc": "SQL-Statement vorbereiten" + }, + { + "name": "PDO::query", + "signature": "PDO::query(string $query, int $fetchMode = null, mixed ...$fetchModeArgs): PDOStatement|false", + "desc": "SQL direkt ausführen" + }, + { + "name": "PDO::rollBack", + "signature": "PDO::rollBack(): bool", + "desc": "Transaktion zurückrollen" + }, + { + "name": "PDOStatement::bindParam", + "signature": "PDOStatement::bindParam(string|int $param, mixed &$var, int $type = PDO::PARAM_STR, int $maxLength = 0, mixed $driverOptions = null): bool", + "desc": "Parameter binden" + }, + { + "name": "PDOStatement::bindValue", + "signature": "PDOStatement::bindValue(string|int $param, mixed $value, int $type = PDO::PARAM_STR): bool", + "desc": "Wert binden" + }, + { + "name": "PDOStatement::execute", + "signature": "PDOStatement::execute(array $params = null): bool", + "desc": "Vorbereitetes Statement ausführen" + }, + { + "name": "PDOStatement::fetch", + "signature": "PDOStatement::fetch(int $mode = PDO::FETCH_DEFAULT, int $cursorOrientation = PDO::FETCH_ORI_NEXT, int $cursorOffset = 0): mixed", + "desc": "Nächste Zeile holen" + }, + { + "name": "PDOStatement::fetchAll", + "signature": "PDOStatement::fetchAll(int $mode = PDO::FETCH_DEFAULT, mixed ...$args): array", + "desc": "Alle Zeilen holen" + }, + { + "name": "PDOStatement::fetchColumn", + "signature": "PDOStatement::fetchColumn(int $column = 0): mixed", + "desc": "Einzelne Spalte holen" + }, + { + "name": "PDOStatement::rowCount", + "signature": "PDOStatement::rowCount(): int", + "desc": "Anzahl betroffener Zeilen" + }, + { + "name": "php_uname", + "signature": "php_uname(string $mode = 'a'): string", + "desc": "Systeminformationen" + }, + { + "name": "phpinfo", + "signature": "phpinfo(int $flags = INFO_ALL): bool", + "desc": "PHP-Konfiguration ausgeben" + }, + { + "name": "phpversion", + "signature": "phpversion(string $extension = null): string|false", + "desc": "PHP-Version" + }, + { + "name": "pi", + "signature": "pi(): float", + "desc": "Wert von Pi" + }, + { + "name": "pow", + "signature": "pow(mixed $base, mixed $exp): int|float", + "desc": "Potenz berechnen" + }, + { + "name": "preg_match", + "signature": "preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int|false", + "desc": "Regulären Ausdruck prüfen" + }, + { + "name": "preg_match_all", + "signature": "preg_match_all(string $pattern, string $subject, array &$matches = null, int $flags = PREG_PATTERN_ORDER, int $offset = 0): int|false", + "desc": "Alle Treffer eines Regex finden" + }, + { + "name": "preg_quote", + "signature": "preg_quote(string $string, string $delimiter = null): string", + "desc": "Regex-Sonderzeichen escapen" + }, + { + "name": "preg_replace", + "signature": "preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, int &$count = null): string|array|null", + "desc": "Regex-Suchen und -Ersetzen" + }, + { + "name": "preg_split", + "signature": "preg_split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array|false", + "desc": "String per Regex aufteilen" + }, + { + "name": "print", + "signature": "print(string $expression): int", + "desc": "String ausgeben" + }, + { + "name": "print_r", + "signature": "print_r(mixed $value, bool $return = false): string|bool", + "desc": "Variable lesbar ausgeben" + }, + { + "name": "printf", + "signature": "printf(string $format, mixed ...$values): int", + "desc": "Formatierten String ausgeben" + }, + { + "name": "property_exists", + "signature": "property_exists(object|string $object_or_class, string $property): bool", + "desc": "Prüft ob Eigenschaft existiert" + }, + { + "name": "rand", + "signature": "rand(int $min = 0, int $max = getrandmax()): int", + "desc": "Zufallszahl" + }, + { + "name": "random_int", + "signature": "random_int(int $min, int $max): int", + "desc": "Kryptografisch sichere Zufallszahl" + }, + { + "name": "range", + "signature": "range(string|int|float $start, string|int|float $end, int|float $step = 1): array", + "desc": "Array mit Wertebereich erstellen" + }, + { + "name": "rawurldecode", + "signature": "rawurldecode(string $string): string", + "desc": "URL-dekodieren nach RFC 3986" + }, + { + "name": "rawurlencode", + "signature": "rawurlencode(string $string): string", + "desc": "URL-kodieren nach RFC 3986" + }, + { + "name": "realpath", + "signature": "realpath(string $path): string|false", + "desc": "Absoluten Pfad auflösen" + }, + { + "name": "rename", + "signature": "rename(string $from, string $to, resource $context = null): bool", + "desc": "Datei umbenennen oder verschieben" + }, + { + "name": "require", + "signature": "require(string $filename): mixed", + "desc": "Datei einbinden (Fehler bei Misserfolg)" + }, + { + "name": "require_once", + "signature": "require_once(string $filename): mixed", + "desc": "Datei einmalig einbinden (Fehler bei Misserfolg)" + }, + { + "name": "restore_error_handler", + "signature": "restore_error_handler(): bool", + "desc": "Fehler-Handler zurücksetzen" + }, + { + "name": "rewind", + "signature": "rewind(resource $handle): bool", + "desc": "Dateizeiger zurücksetzen" + }, + { + "name": "rmdir", + "signature": "rmdir(string $directory, resource $context = null): bool", + "desc": "Verzeichnis löschen" + }, + { + "name": "round", + "signature": "round(int|float $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP): float", + "desc": "Runden" + }, + { + "name": "rsort", + "signature": "rsort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array absteigend sortieren" + }, + { + "name": "rtrim", + "signature": "rtrim(string $string, string $characters = \" \\n\\r\\t\\v\\0\"): string", + "desc": "Leerzeichen rechts entfernen" + }, + { + "name": "scandir", + "signature": "scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, resource $context = null): array|false", + "desc": "Verzeichnisinhalt auflisten" + }, + { + "name": "session_destroy", + "signature": "session_destroy(): bool", + "desc": "Session beenden" + }, + { + "name": "session_id", + "signature": "session_id(string $id = null): string|false", + "desc": "Session-ID holen oder setzen" + }, + { + "name": "session_regenerate_id", + "signature": "session_regenerate_id(bool $delete_old_session = false): bool", + "desc": "Session-ID erneuern" + }, + { + "name": "session_start", + "signature": "session_start(array $options = []): bool", + "desc": "Session starten" + }, + { + "name": "set_error_handler", + "signature": "set_error_handler(callable|null $callback, int $error_levels = E_ALL): callable|null", + "desc": "Eigenen Fehler-Handler setzen" + }, + { + "name": "set_exception_handler", + "signature": "set_exception_handler(callable|null $callback): callable|null", + "desc": "Eigenen Exception-Handler setzen" + }, + { + "name": "setcookie", + "signature": "setcookie(string $name, string $value = '', int $expires_or_options = 0, string $path = '', string $domain = '', bool $secure = false, bool $httponly = false): bool", + "desc": "Cookie setzen" + }, + { + "name": "settype", + "signature": "settype(mixed &$var, string $type): bool", + "desc": "Typ einer Variable setzen" + }, + { + "name": "sha1", + "signature": "sha1(string $string, bool $binary = false): string", + "desc": "SHA1-Hash berechnen" + }, + { + "name": "shuffle", + "signature": "shuffle(array &$array): bool", + "desc": "Array zufällig mischen" + }, + { + "name": "sleep", + "signature": "sleep(int $seconds): int|false", + "desc": "Ausführung anhalten" + }, + { + "name": "sort", + "signature": "sort(array &$array, int $flags = SORT_REGULAR): bool", + "desc": "Array aufsteigend sortieren" + }, + { + "name": "sprintf", + "signature": "sprintf(string $format, mixed ...$values): string", + "desc": "Formatierten String zurückgeben" + }, + { + "name": "sqrt", + "signature": "sqrt(float $num): float", + "desc": "Quadratwurzel" + }, + { + "name": "str_contains", + "signature": "str_contains(string $haystack, string $needle): bool", + "desc": "Prüft ob String enthalten ist" + }, + { + "name": "str_ends_with", + "signature": "str_ends_with(string $haystack, string $needle): bool", + "desc": "Prüft ob String mit needle endet" + }, + { + "name": "str_pad", + "signature": "str_pad(string $input, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT): string", + "desc": "String auf Länge auffüllen" + }, + { + "name": "str_repeat", + "signature": "str_repeat(string $string, int $times): string", + "desc": "String wiederholen" + }, + { + "name": "str_replace", + "signature": "str_replace(array|string $search, array|string $replace, string|array $subject, int &$count = null): string|array", + "desc": "Suchen und Ersetzen in einem String" + }, + { + "name": "str_split", + "signature": "str_split(string $string, int $length = 1): array", + "desc": "String in Array aufteilen" + }, + { + "name": "str_starts_with", + "signature": "str_starts_with(string $haystack, string $needle): bool", + "desc": "Prüft ob String mit needle beginnt" + }, + { + "name": "str_word_count", + "signature": "str_word_count(string $string, int $format = 0, string $characters = null): array|int", + "desc": "Wörter zählen" + }, + { + "name": "strcasecmp", + "signature": "strcasecmp(string $string1, string $string2): int", + "desc": "Strings ohne Groß-/Kleinschreibung vergleichen" + }, + { + "name": "strcmp", + "signature": "strcmp(string $string1, string $string2): int", + "desc": "Strings vergleichen" + }, + { + "name": "strip_tags", + "signature": "strip_tags(string $string, array|string $allowed_tags = null): string", + "desc": "HTML-Tags entfernen" + }, + { + "name": "stripslashes", + "signature": "stripslashes(string $string): string", + "desc": "Backslashes entfernen" + }, + { + "name": "strlen", + "signature": "strlen(string $string): int", + "desc": "Länge eines Strings" + }, + { + "name": "strpos", + "signature": "strpos(string $haystack, string $needle, int $offset = 0): int|false", + "desc": "Position des ersten Vorkommens" + }, + { + "name": "strrpos", + "signature": "strrpos(string $haystack, string $needle, int $offset = 0): int|false", + "desc": "Position des letzten Vorkommens" + }, + { + "name": "strtolower", + "signature": "strtolower(string $string): string", + "desc": "In Kleinbuchstaben umwandeln" + }, + { + "name": "strtotime", + "signature": "strtotime(string $datetime, int $baseTimestamp = time()): int|false", + "desc": "Datum-String in Timestamp umwandeln" + }, + { + "name": "strtoupper", + "signature": "strtoupper(string $string): string", + "desc": "In Großbuchstaben umwandeln" + }, + { + "name": "strval", + "signature": "strval(mixed $value): string", + "desc": "In String umwandeln" + }, + { + "name": "substr", + "signature": "substr(string $string, int $offset, int $length = null): string", + "desc": "Teilstring zurückgeben" + }, + { + "name": "sys_get_temp_dir", + "signature": "sys_get_temp_dir(): string", + "desc": "Temp-Verzeichnis des Systems" + }, + { + "name": "tempnam", + "signature": "tempnam(string $directory, string $prefix): string|false", + "desc": "Temporäre Datei erstellen" + }, + { + "name": "time", + "signature": "time(): int", + "desc": "Aktuellen Unix-Timestamp" + }, + { + "name": "trigger_error", + "signature": "trigger_error(string $message, int $error_level = E_USER_NOTICE): bool", + "desc": "Fehler auslösen" + }, + { + "name": "trim", + "signature": "trim(string $string, string $characters = \" \\n\\r\\t\\v\\0\"): string", + "desc": "Leerzeichen am Rand entfernen" + }, + { + "name": "uasort", + "signature": "uasort(array &$array, callable $callback): bool", + "desc": "Array mit eigener Funktion sortieren, Schlüssel beibehalten" + }, + { + "name": "ucfirst", + "signature": "ucfirst(string $string): string", + "desc": "Ersten Buchstaben groß" + }, + { + "name": "ucwords", + "signature": "ucwords(string $string, string $separators = \" \\t\\r\\n\\f\\v\"): string", + "desc": "Jeden Wortanfang groß" + }, + { + "name": "uksort", + "signature": "uksort(array &$array, callable $callback): bool", + "desc": "Array nach Schlüsseln mit eigener Funktion sortieren" + }, + { + "name": "unlink", + "signature": "unlink(string $filename, resource $context = null): bool", + "desc": "Datei löschen" + }, + { + "name": "urldecode", + "signature": "urldecode(string $string): string", + "desc": "URL-dekodieren" + }, + { + "name": "urlencode", + "signature": "urlencode(string $string): string", + "desc": "URL-kodieren" + }, + { + "name": "usleep", + "signature": "usleep(int $microseconds): void", + "desc": "Ausführung in Mikrosekunden anhalten" + }, + { + "name": "usort", + "signature": "usort(array &$array, callable $callback): bool", + "desc": "Array mit eigener Funktion sortieren" + }, + { + "name": "var_dump", + "signature": "var_dump(mixed $value, mixed ...$values): void", + "desc": "Variable ausgeben mit Typ-Info" + }, + { + "name": "var_export", + "signature": "var_export(mixed $value, bool $return = false): string|null", + "desc": "Variable als PHP-Code ausgeben" + }, + { + "name": "wordwrap", + "signature": "wordwrap(string $string, int $width = 75, string $break = \"\\n\", bool $cut_long_words = false): string", + "desc": "String umbrechen" + } +] \ No newline at end of file diff --git a/src/barecode/resources/resources.qrc b/src/barecode/resources/resources.qrc new file mode 100644 index 0000000..f3b588a --- /dev/null +++ b/src/barecode/resources/resources.qrc @@ -0,0 +1,12 @@ + + + icon_512.png + icon_256.png + icon_128.png + icon_64.png + icon_48.png + icon_32.png + icon_16.png + php_functions.json + + diff --git a/src/barecode/src/CMakeLists.txt b/src/barecode/src/CMakeLists.txt new file mode 100644 index 0000000..bb9abf8 --- /dev/null +++ b/src/barecode/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(core) +add_subdirectory(editor) +add_subdirectory(filetree) +add_subdirectory(highlighter) diff --git a/src/barecode/src/core/AboutDialog.cpp b/src/barecode/src/core/AboutDialog.cpp new file mode 100644 index 0000000..9feeca1 --- /dev/null +++ b/src/barecode/src/core/AboutDialog.cpp @@ -0,0 +1,105 @@ +#include "AboutDialog.h" + +#include +#include +#include +#include +#include +#include +#include + +AboutDialog::AboutDialog(QWidget *parent) + : QDialog(parent) +{ + setWindowTitle(tr("Über BareCode")); + setFixedSize(440, 310); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + QVBoxLayout *root = new QVBoxLayout(this); + root->setContentsMargins(0, 0, 0, 0); + root->setSpacing(0); + + // ----------------------------------------------------------------------- + // Header-Banner + // ----------------------------------------------------------------------- + QFrame *banner = new QFrame(this); + banner->setFixedHeight(88); + banner->setStyleSheet( + "background: qlineargradient(x1:0, y1:0, x2:1, y2:0," + " stop:0 #1a1a2e, stop:1 #16213e);" + ); + + QVBoxLayout *bannerLayout = new QVBoxLayout(banner); + bannerLayout->setContentsMargins(24, 10, 24, 10); + bannerLayout->setSpacing(2); + + QLabel *appName = new QLabel("BareCode", banner); + QFont nameFont = appName->font(); + nameFont.setPointSize(22); + nameFont.setBold(true); + appName->setFont(nameFont); + appName->setStyleSheet("color: #e0e0ff; background: transparent;"); + + QLabel *tagline = new QLabel(tr("Modularer Code-Editor"), banner); + tagline->setStyleSheet("color: #8888bb; background: transparent;"); + + bannerLayout->addWidget(appName); + bannerLayout->addWidget(tagline); + root->addWidget(banner); + + // ----------------------------------------------------------------------- + // Info-Tabelle + // ----------------------------------------------------------------------- + QVBoxLayout *info = new QVBoxLayout(); + info->setContentsMargins(28, 20, 28, 8); + info->setSpacing(10); + + auto makeRow = [&](const QString &label, const QString &value) + { + QHBoxLayout *row = new QHBoxLayout(); + row->setSpacing(12); + + QLabel *lbl = new QLabel(label, this); + QFont boldFont = lbl->font(); + boldFont.setBold(true); + lbl->setFont(boldFont); + lbl->setFixedWidth(100); + lbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + + QLabel *val = new QLabel(value, this); + val->setTextInteractionFlags(Qt::TextSelectableByMouse); + + row->addWidget(lbl); + row->addWidget(val, 1); + info->addLayout(row); + }; + + makeRow(tr("Version"), "1.1.0"); + makeRow(tr("Entwickler"), "Dany Thinnes"); + makeRow(tr("Projekt"), "Projekt Hirnfrei"); + makeRow(tr("Framework"), QString("Qt %1").arg(qVersion())); + makeRow(tr("Sprache"), "C++17"); + + root->addLayout(info); + root->addStretch(); + + // ----------------------------------------------------------------------- + // Trennlinie + Schließen-Button + // ----------------------------------------------------------------------- + QFrame *line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + root->addWidget(line); + + QHBoxLayout *btnRow = new QHBoxLayout(); + btnRow->setContentsMargins(12, 8, 12, 12); + btnRow->addStretch(); + + QPushButton *btnClose = new QPushButton(tr("Schließen"), this); + btnClose->setDefault(true); + btnClose->setFixedWidth(110); + connect(btnClose, &QPushButton::clicked, this, &QDialog::accept); + btnRow->addWidget(btnClose); + + root->addLayout(btnRow); +} diff --git a/src/barecode/src/core/AboutDialog.h b/src/barecode/src/core/AboutDialog.h new file mode 100644 index 0000000..d90939a --- /dev/null +++ b/src/barecode/src/core/AboutDialog.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +// --------------------------------------------------------------------------- +// AboutDialog – Zeigt Versionsinformationen und Entwicklerangaben. +// --------------------------------------------------------------------------- +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AboutDialog(QWidget *parent = nullptr); +}; diff --git a/src/barecode/src/core/CMakeLists.txt b/src/barecode/src/core/CMakeLists.txt new file mode 100644 index 0000000..e3b822e --- /dev/null +++ b/src/barecode/src/core/CMakeLists.txt @@ -0,0 +1,28 @@ +set(CORE_SOURCES + MainWindow.cpp + MainWindow.h + IPlugin.h + ProjectManager.cpp + ProjectManager.h + Settings.cpp + Settings.h + ThemeManager.cpp + ThemeManager.h + AboutDialog.cpp + AboutDialog.h +) + +add_library(BareCode_Core STATIC ${CORE_SOURCES}) + +target_link_libraries(BareCode_Core PUBLIC + Qt6::Core + Qt6::Gui + Qt6::Widgets + BareCode_Editor + BareCode_FileTree +) + +target_include_directories(BareCode_Core PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) diff --git a/src/barecode/src/core/IPlugin.h b/src/barecode/src/core/IPlugin.h new file mode 100644 index 0000000..c7c3571 --- /dev/null +++ b/src/barecode/src/core/IPlugin.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +// --------------------------------------------------------------------------- +// IPlugin – Interface that every BareCode module / plugin must implement. +// This allows components to be swapped or extended without touching the core. +// --------------------------------------------------------------------------- +class IPlugin +{ +public: + virtual ~IPlugin() = default; + + // Human-readable name of the plugin + virtual QString pluginName() const = 0; + + // Version string, e.g. "1.0.0" + virtual QString pluginVersion() const = 0; + + // Called once after all plugins are loaded so plugins can cross-reference + virtual void initialize() {} + + // Called before the application shuts down + virtual void shutdown() {} +}; diff --git a/src/barecode/src/core/MainWindow.cpp b/src/barecode/src/core/MainWindow.cpp new file mode 100644 index 0000000..37d588f --- /dev/null +++ b/src/barecode/src/core/MainWindow.cpp @@ -0,0 +1,336 @@ +#include "MainWindow.h" + +#include +#include +#include +#include +#include + +#include "AboutDialog.h" +#include "filetree/FileTreePanel.h" +#include "editor/EditorPanel.h" + +// --------------------------------------------------------------------------- +// Konstruktor +// --------------------------------------------------------------------------- +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , m_projectManager(std::make_unique()) + , m_settings(std::make_unique()) + , m_themeManager(std::make_unique()) +{ + setWindowTitle("BareCode"); + setMinimumSize(900, 600); + + setupUi(); + setupMenuBar(); + setupStatusBar(); + connectSignals(); + restoreWindowState(); + applyInitialTheme(); + + // Letztes Projekt wieder öffnen + const QString lastPath = m_settings->lastProjectPath(); + if (!lastPath.isEmpty()) + { + m_projectManager->openProject(lastPath); + } + + // Letzte Session wiederherstellen (geöffnete Dateien + aktiver Tab) + m_editor->restoreSession( + m_settings->lastOpenFiles(), + m_settings->lastActiveFile() + ); +} + +MainWindow::~MainWindow() = default; + +// --------------------------------------------------------------------------- +// UI aufbauen +// --------------------------------------------------------------------------- +void MainWindow::setupUi() +{ + m_splitter = new QSplitter(Qt::Horizontal, this); + setCentralWidget(m_splitter); + + m_fileTree = new FileTreePanel(m_splitter); + m_editor = new EditorPanel(m_settings.get(), m_splitter); + + m_splitter->addWidget(m_fileTree); + m_splitter->addWidget(m_editor); + + const int treeWidth = m_settings->fileTreeWidth(); + m_splitter->setSizes({treeWidth, width() - treeWidth}); + m_splitter->setStretchFactor(0, 0); + m_splitter->setStretchFactor(1, 1); +} + +// --------------------------------------------------------------------------- +// Menüleiste +// --------------------------------------------------------------------------- +void MainWindow::setupMenuBar() +{ + // ---- Datei ---- + QMenu *mDatei = menuBar()->addMenu(tr("&Datei")); + + m_actNewFile = mDatei->addAction(tr("&Neue Datei…"), this, &MainWindow::onNewFile); + m_actNewFile->setShortcut(QKeySequence::New); + + mDatei->addSeparator(); + + m_actOpenFile = mDatei->addAction(tr("Datei &öffnen…"), this, &MainWindow::onOpenFile); + m_actOpenFile->setShortcut(QKeySequence::Open); + + m_actOpenProject = mDatei->addAction(tr("&Projekt öffnen…"), this, &MainWindow::onOpenProject); + m_actOpenProject->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_O); + + m_actClose = mDatei->addAction(tr("Projekt &schließen"), this, &MainWindow::onCloseProject); + + mDatei->addSeparator(); + + m_actSave = mDatei->addAction(tr("&Speichern"), this, &MainWindow::onSave); + m_actSave->setShortcut(QKeySequence::Save); + + m_actSaveAs = mDatei->addAction(tr("Speichern &unter…"), this, &MainWindow::onSaveAs); + m_actSaveAs->setShortcut(QKeySequence::SaveAs); + + m_actSaveAll = mDatei->addAction(tr("&Alles speichern"), this, &MainWindow::onSaveAll); + m_actSaveAll->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_S); + + mDatei->addSeparator(); + + m_actQuit = mDatei->addAction(tr("&Beenden"), qApp, &QApplication::quit); + m_actQuit->setShortcut(QKeySequence::Quit); + + // ---- Bearbeiten ---- + QMenu *mBearbeiten = menuBar()->addMenu(tr("&Bearbeiten")); + + m_actUndo = mBearbeiten->addAction(tr("&Rückgängig"), this, &MainWindow::onUndo); + m_actUndo->setShortcut(QKeySequence::Undo); + + m_actRedo = mBearbeiten->addAction(tr("&Wiederholen"), this, &MainWindow::onRedo); + m_actRedo->setShortcut(QKeySequence::Redo); + + mBearbeiten->addSeparator(); + + m_actSearch = mBearbeiten->addAction(tr("&Suchen / Ersetzen…"), this, &MainWindow::onShowSearch); + m_actSearch->setShortcut(QKeySequence::Find); + + m_actFileSearch = mBearbeiten->addAction(tr("In &Dateien suchen…"), this, &MainWindow::onShowFileSearch); + m_actFileSearch->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_F); + + // ---- Ansicht ---- + QMenu *mAnsicht = menuBar()->addMenu(tr("&Ansicht")); + + m_actDarkMode = mAnsicht->addAction(tr("&Dark Mode")); + m_actDarkMode->setCheckable(true); + m_actDarkMode->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_D); + connect(m_actDarkMode, &QAction::toggled, this, &MainWindow::onToggleDarkMode); + + // ---- Hilfe ---- + QMenu *mHilfe = menuBar()->addMenu(tr("&Hilfe")); + m_actAbout = mHilfe->addAction(tr("&Über BareCode…"), this, &MainWindow::onAbout); +} + +void MainWindow::setupStatusBar() +{ + statusBar()->showMessage(tr("Bereit")); +} + +// --------------------------------------------------------------------------- +// Signale verbinden +// --------------------------------------------------------------------------- +void MainWindow::connectSignals() +{ + connect(m_projectManager.get(), &ProjectManager::projectOpened, + this, &MainWindow::onProjectOpened); + + connect(m_projectManager.get(), &ProjectManager::projectClosed, + this, &MainWindow::onProjectClosed); + + // Dateibaum → Editor + connect(m_fileTree, &FileTreePanel::fileActivated, + m_editor, &EditorPanel::openFile); + + connect(m_fileTree, &FileTreePanel::fileCreated, + m_editor, &EditorPanel::openFile); + + // Gespeichert → Statusleiste + connect(m_editor, &EditorPanel::currentFileSaved, this, [this](const QString &path) + { + statusBar()->showMessage(tr("Gespeichert: %1").arg(path), 3000); + }); + + // Splitter-Breite merken + connect(m_splitter, &QSplitter::splitterMoved, this, [this](int pos, int) + { + m_settings->setFileTreeWidth(pos); + }); +} + +// --------------------------------------------------------------------------- +// Theme beim Start +// --------------------------------------------------------------------------- +void MainWindow::applyInitialTheme() +{ + const bool dark = m_settings->darkMode(); + // Block damit toggled-Signal nicht doppelt feuert + m_actDarkMode->blockSignals(true); + m_actDarkMode->setChecked(dark); + m_actDarkMode->blockSignals(false); + + m_themeManager->applyTheme(dark ? ThemeManager::Theme::Dark + : ThemeManager::Theme::Light); +} + +// --------------------------------------------------------------------------- +// Slots – Datei +// --------------------------------------------------------------------------- +void MainWindow::onNewFile() +{ + m_fileTree->triggerNewFile(); +} + +void MainWindow::onOpenFile() +{ + const QString path = QFileDialog::getOpenFileName( + this, + tr("Datei öffnen"), + m_settings->lastProjectPath() + ); + + if (!path.isEmpty()) + { + m_editor->openFile(path); + } +} + +void MainWindow::onOpenProject() +{ + const QString path = QFileDialog::getExistingDirectory( + this, + tr("Projektverzeichnis öffnen"), + m_settings->lastProjectPath() + ); + + if (!path.isEmpty()) + { + m_projectManager->openProject(path); + m_settings->setLastProjectPath(path); + } +} + +void MainWindow::onCloseProject() +{ + m_projectManager->closeProject(); +} + +void MainWindow::onSave() +{ + m_editor->saveCurrentFile(); +} + +void MainWindow::onSaveAs() +{ + m_editor->saveCurrentFileAs(); +} + +void MainWindow::onSaveAll() +{ + m_editor->saveAllFiles(); + statusBar()->showMessage(tr("Alle Dateien gespeichert"), 3000); +} + +// --------------------------------------------------------------------------- +// Slots – Bearbeiten +// --------------------------------------------------------------------------- +void MainWindow::onUndo() +{ + m_editor->undo(); +} + +void MainWindow::onRedo() +{ + m_editor->redo(); +} + +void MainWindow::onShowSearch() +{ + m_editor->showSearchPanel(); +} + +// --------------------------------------------------------------------------- +// Slots – Ansicht +// --------------------------------------------------------------------------- +void MainWindow::onToggleDarkMode(bool checked) +{ + m_themeManager->applyTheme(checked ? ThemeManager::Theme::Dark + : ThemeManager::Theme::Light); + m_settings->setDarkMode(checked); +} + +// --------------------------------------------------------------------------- +// Slots – Hilfe +// --------------------------------------------------------------------------- +void MainWindow::onAbout() +{ + AboutDialog dlg(this); + dlg.exec(); +} + +// --------------------------------------------------------------------------- +// Slots – Projekt +// --------------------------------------------------------------------------- +void MainWindow::onShowFileSearch() +{ + m_editor->showFileSearchPanel(); +} + +void MainWindow::onProjectOpened(const QString &path) +{ + setWindowTitle(QString("BareCode – %1").arg(path)); + m_fileTree->setRootPath(path); + m_editor->setSearchRoot(path); + statusBar()->showMessage(tr("Projekt geöffnet: %1").arg(path), 4000); +} + +void MainWindow::onProjectClosed() +{ + setWindowTitle("BareCode"); + m_fileTree->clearRoot(); + m_editor->setSearchRoot(QString()); + statusBar()->showMessage(tr("Projekt geschlossen"), 3000); +} + +// --------------------------------------------------------------------------- +// Fenster-Zustand +// --------------------------------------------------------------------------- +void MainWindow::saveWindowState() +{ + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + s.setValue("window/geometry", saveGeometry()); + s.setValue("window/state", saveState()); + + // Session speichern + m_settings->setLastOpenFiles(m_editor->openFilePaths()); + m_settings->setLastActiveFile(m_editor->activeFilePath()); +} + +void MainWindow::restoreWindowState() +{ + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + if (s.contains("window/geometry")) + { + restoreGeometry(s.value("window/geometry").toByteArray()); + } + if (s.contains("window/state")) + { + restoreState(s.value("window/state").toByteArray()); + } +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + saveWindowState(); + event->accept(); +} diff --git a/src/barecode/src/core/MainWindow.h b/src/barecode/src/core/MainWindow.h new file mode 100644 index 0000000..3ae9b17 --- /dev/null +++ b/src/barecode/src/core/MainWindow.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "ProjectManager.h" +#include "Settings.h" +#include "ThemeManager.h" + +class FileTreePanel; +class EditorPanel; + +// --------------------------------------------------------------------------- +// MainWindow – Hauptfenster. Besitzt alle zentralen Dienste und das Layout. +// --------------------------------------------------------------------------- +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + +protected: + void closeEvent(QCloseEvent *event) override; + +private slots: + // Datei + void onNewFile(); + void onOpenFile(); + void onOpenProject(); + void onCloseProject(); + void onSave(); + void onSaveAs(); + void onSaveAll(); + // Bearbeiten + void onUndo(); + void onRedo(); + void onShowSearch(); + void onShowFileSearch(); + // Ansicht + void onToggleDarkMode(bool checked); + // Hilfe + void onAbout(); + // Intern + void onProjectOpened(const QString &path); + void onProjectClosed(); + +private: + void setupUi(); + void setupMenuBar(); + void setupStatusBar(); + void connectSignals(); + void applyInitialTheme(); + void saveWindowState(); + void restoreWindowState(); + + // Dienste + std::unique_ptr m_projectManager; + std::unique_ptr m_settings; + std::unique_ptr m_themeManager; + + // Layout + QSplitter *m_splitter = nullptr; + FileTreePanel *m_fileTree = nullptr; + EditorPanel *m_editor = nullptr; + + // Aktionen + QAction *m_actNewFile = nullptr; + QAction *m_actOpenFile = nullptr; + QAction *m_actOpenProject = nullptr; + QAction *m_actClose = nullptr; + QAction *m_actSave = nullptr; + QAction *m_actSaveAs = nullptr; + QAction *m_actSaveAll = nullptr; + QAction *m_actQuit = nullptr; + QAction *m_actUndo = nullptr; + QAction *m_actRedo = nullptr; + QAction *m_actSearch = nullptr; + QAction *m_actFileSearch = nullptr; + QAction *m_actDarkMode = nullptr; + QAction *m_actAbout = nullptr; +}; diff --git a/src/barecode/src/core/ProjectManager.cpp b/src/barecode/src/core/ProjectManager.cpp new file mode 100644 index 0000000..c4ee879 --- /dev/null +++ b/src/barecode/src/core/ProjectManager.cpp @@ -0,0 +1,33 @@ +#include "ProjectManager.h" + +ProjectManager::ProjectManager(QObject *parent) + : QObject(parent) +{ +} + +QString ProjectManager::currentProjectPath() const +{ + return m_projectPath; +} + +void ProjectManager::openProject(const QString &path) +{ + if (m_projectPath == path) + { + return; + } + + m_projectPath = path; + emit projectOpened(m_projectPath); +} + +void ProjectManager::closeProject() +{ + if (m_projectPath.isEmpty()) + { + return; + } + + m_projectPath.clear(); + emit projectClosed(); +} diff --git a/src/barecode/src/core/ProjectManager.h b/src/barecode/src/core/ProjectManager.h new file mode 100644 index 0000000..9aedfcc --- /dev/null +++ b/src/barecode/src/core/ProjectManager.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +// --------------------------------------------------------------------------- +// ProjectManager – Tracks the currently open project directory and emits +// signals when the project changes so other components can react. +// --------------------------------------------------------------------------- +class ProjectManager : public QObject +{ + Q_OBJECT + +public: + explicit ProjectManager(QObject *parent = nullptr); + + QString currentProjectPath() const; + void openProject(const QString &path); + void closeProject(); + +signals: + void projectOpened(const QString &path); + void projectClosed(); + +private: + QString m_projectPath; +}; diff --git a/src/barecode/src/core/Settings.cpp b/src/barecode/src/core/Settings.cpp new file mode 100644 index 0000000..4ebc21f --- /dev/null +++ b/src/barecode/src/core/Settings.cpp @@ -0,0 +1,113 @@ +#include "Settings.h" + +Settings::Settings(QObject *parent) + : QObject(parent) + , m_settings(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode") +{ +} + +// --------------------------------------------------------------------------- +// Editor font +// --------------------------------------------------------------------------- +QFont Settings::editorFont() const +{ + QFont defaultFont("Monospace", 11); + defaultFont.setStyleHint(QFont::Monospace); + return m_settings.value("editor/font", defaultFont).value(); +} + +void Settings::setEditorFont(const QFont &font) +{ + m_settings.setValue("editor/font", font); + emit settingsChanged(); +} + +// --------------------------------------------------------------------------- +// Tab size +// --------------------------------------------------------------------------- +int Settings::tabSize() const +{ + return m_settings.value("editor/tabSize", 4).toInt(); +} + +void Settings::setTabSize(int size) +{ + m_settings.setValue("editor/tabSize", size); + emit settingsChanged(); +} + +// --------------------------------------------------------------------------- +// Spaces vs. tabs +// --------------------------------------------------------------------------- +bool Settings::useSpacesForTabs() const +{ + return m_settings.value("editor/useSpacesForTabs", true).toBool(); +} + +void Settings::setUseSpacesForTabs(bool use) +{ + m_settings.setValue("editor/useSpacesForTabs", use); + emit settingsChanged(); +} + +// --------------------------------------------------------------------------- +// File tree width +// --------------------------------------------------------------------------- +int Settings::fileTreeWidth() const +{ + return m_settings.value("layout/fileTreeWidth", 240).toInt(); +} + +void Settings::setFileTreeWidth(int width) +{ + m_settings.setValue("layout/fileTreeWidth", width); +} + +// --------------------------------------------------------------------------- +// Dark mode +// --------------------------------------------------------------------------- +bool Settings::darkMode() const +{ + return m_settings.value("appearance/darkMode", false).toBool(); +} + +void Settings::setDarkMode(bool dark) +{ + m_settings.setValue("appearance/darkMode", dark); +} + +// --------------------------------------------------------------------------- +// Last project path +// --------------------------------------------------------------------------- +QString Settings::lastProjectPath() const +{ + return m_settings.value("project/lastPath", QString()).toString(); +} + +void Settings::setLastProjectPath(const QString &path) +{ + m_settings.setValue("project/lastPath", path); +} + +// --------------------------------------------------------------------------- +// Session – geöffnete Dateien +// --------------------------------------------------------------------------- +QStringList Settings::lastOpenFiles() const +{ + return m_settings.value("session/openFiles", QStringList()).toStringList(); +} + +void Settings::setLastOpenFiles(const QStringList &files) +{ + m_settings.setValue("session/openFiles", files); +} + +QString Settings::lastActiveFile() const +{ + return m_settings.value("session/activeFile", QString()).toString(); +} + +void Settings::setLastActiveFile(const QString &file) +{ + m_settings.setValue("session/activeFile", file); +} diff --git a/src/barecode/src/core/Settings.h b/src/barecode/src/core/Settings.h new file mode 100644 index 0000000..1122864 --- /dev/null +++ b/src/barecode/src/core/Settings.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// Settings – Centralised persistent application settings. +// --------------------------------------------------------------------------- +class Settings : public QObject +{ + Q_OBJECT + +public: + explicit Settings(QObject *parent = nullptr); + + // Editor + QFont editorFont() const; + void setEditorFont(const QFont &font); + + int tabSize() const; + void setTabSize(int size); + + bool useSpacesForTabs() const; + void setUseSpacesForTabs(bool use); + + // Layout + int fileTreeWidth() const; + void setFileTreeWidth(int width); + + // Zuletzt geöffnete Dateien (Session-Wiederherstellung) + QStringList lastOpenFiles() const; + void setLastOpenFiles(const QStringList &files); + + QString lastActiveFile() const; + void setLastActiveFile(const QString &file); + + // Recent + QString lastProjectPath() const; + void setLastProjectPath(const QString &path); + + // Erscheinungsbild + bool darkMode() const; + void setDarkMode(bool dark); + +signals: + void settingsChanged(); + +private: + QSettings m_settings; +}; diff --git a/src/barecode/src/core/ThemeManager.cpp b/src/barecode/src/core/ThemeManager.cpp new file mode 100644 index 0000000..d9c9ba7 --- /dev/null +++ b/src/barecode/src/core/ThemeManager.cpp @@ -0,0 +1,115 @@ +#include "ThemeManager.h" + +#include +#include + +ThemeManager::ThemeManager(QObject *parent) + : QObject(parent) +{ +} + +void ThemeManager::applyTheme(Theme theme) +{ + m_currentTheme = theme; + QApplication::setStyle(QStyleFactory::create("Fusion")); + + if (theme == Theme::Dark) + { + QApplication::setPalette(buildDarkPalette()); + } + else + { + QApplication::setPalette(buildLightPalette()); + } + + emit themeChanged(theme); +} + +ThemeManager::Theme ThemeManager::currentTheme() const +{ + return m_currentTheme; +} + +QPalette ThemeManager::buildDarkPalette() +{ + QPalette p; + + const QColor bg = QColor("#1e1e1e"); + const QColor widget = QColor("#252526"); + const QColor alt = QColor("#2d2d30"); + const QColor hi = QColor("#264f78"); + const QColor hiText = QColor("#ffffff"); + const QColor text = QColor("#d4d4d4"); + const QColor disabled = QColor("#6d6d6d"); + const QColor btn = QColor("#3c3c3c"); + const QColor mid = QColor("#333333"); + const QColor dark = QColor("#1a1a1a"); + const QColor light = QColor("#454545"); + const QColor link = QColor("#569cd6"); + + p.setColor(QPalette::Window, bg); + p.setColor(QPalette::WindowText, text); + p.setColor(QPalette::Base, widget); + p.setColor(QPalette::AlternateBase, alt); + p.setColor(QPalette::Text, text); + p.setColor(QPalette::Button, btn); + p.setColor(QPalette::ButtonText, text); + p.setColor(QPalette::Highlight, hi); + p.setColor(QPalette::HighlightedText, hiText); + p.setColor(QPalette::Link, link); + p.setColor(QPalette::LinkVisited, link.darker(120)); + p.setColor(QPalette::Mid, mid); + p.setColor(QPalette::Dark, dark); + p.setColor(QPalette::Light, light); + p.setColor(QPalette::Shadow, QColor("#000000")); + p.setColor(QPalette::ToolTipBase, widget); + p.setColor(QPalette::ToolTipText, text); + p.setColor(QPalette::PlaceholderText, disabled); + + p.setColor(QPalette::Disabled, QPalette::WindowText, disabled); + p.setColor(QPalette::Disabled, QPalette::Text, disabled); + p.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); + + return p; +} + +QPalette ThemeManager::buildLightPalette() +{ + // Fusion-Standard-Palette + QPalette p; + + const QColor bg = QColor("#f3f3f3"); + const QColor widget = QColor("#ffffff"); + const QColor alt = QColor("#e8e8e8"); + const QColor hi = QColor("#0078d4"); + const QColor hiText = QColor("#ffffff"); + const QColor text = QColor("#1e1e1e"); + const QColor disabled = QColor("#a0a0a0"); + const QColor btn = QColor("#e1e1e1"); + const QColor mid = QColor("#c8c8c8"); + const QColor dark = QColor("#a0a0a0"); + const QColor light = QColor("#ffffff"); + const QColor link = QColor("#0078d4"); + + p.setColor(QPalette::Window, bg); + p.setColor(QPalette::WindowText, text); + p.setColor(QPalette::Base, widget); + p.setColor(QPalette::AlternateBase, alt); + p.setColor(QPalette::Text, text); + p.setColor(QPalette::Button, btn); + p.setColor(QPalette::ButtonText, text); + p.setColor(QPalette::Highlight, hi); + p.setColor(QPalette::HighlightedText, hiText); + p.setColor(QPalette::Link, link); + p.setColor(QPalette::LinkVisited, link.darker(130)); + p.setColor(QPalette::Mid, mid); + p.setColor(QPalette::Dark, dark); + p.setColor(QPalette::Light, light); + p.setColor(QPalette::PlaceholderText, disabled); + + p.setColor(QPalette::Disabled, QPalette::WindowText, disabled); + p.setColor(QPalette::Disabled, QPalette::Text, disabled); + p.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); + + return p; +} diff --git a/src/barecode/src/core/ThemeManager.h b/src/barecode/src/core/ThemeManager.h new file mode 100644 index 0000000..4096918 --- /dev/null +++ b/src/barecode/src/core/ThemeManager.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +// --------------------------------------------------------------------------- +// ThemeManager – Schaltet zwischen Hell- und Dunkelmodus um. +// --------------------------------------------------------------------------- +class ThemeManager : public QObject +{ + Q_OBJECT + +public: + enum class Theme { Light, Dark }; + + explicit ThemeManager(QObject *parent = nullptr); + + void applyTheme(Theme theme); + Theme currentTheme() const; + +signals: + void themeChanged(Theme theme); + +private: + static QPalette buildDarkPalette(); + static QPalette buildLightPalette(); + + Theme m_currentTheme = Theme::Light; +}; diff --git a/src/barecode/src/editor/CMakeLists.txt b/src/barecode/src/editor/CMakeLists.txt new file mode 100644 index 0000000..fe64f27 --- /dev/null +++ b/src/barecode/src/editor/CMakeLists.txt @@ -0,0 +1,35 @@ +set(EDITOR_SOURCES + EditorPanel.cpp + EditorPanel.h + CodeEditor.cpp + CodeEditor.h + LineNumberArea.cpp + LineNumberArea.h + EditorTab.cpp + EditorTab.h + SearchPanel.cpp + SearchPanel.h + FileSearchPanel.cpp + FileSearchPanel.h + ColorIndicator.cpp + ColorIndicator.h + SignatureHelper.cpp + SignatureHelper.h + SignatureTooltip.cpp + SignatureTooltip.h +) + +add_library(BareCode_Editor STATIC ${EDITOR_SOURCES}) + +target_link_libraries(BareCode_Editor PUBLIC + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Concurrent + BareCode_Highlighter +) + +target_include_directories(BareCode_Editor PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) diff --git a/src/barecode/src/editor/CodeEditor.cpp b/src/barecode/src/editor/CodeEditor.cpp new file mode 100644 index 0000000..f6aca9b --- /dev/null +++ b/src/barecode/src/editor/CodeEditor.cpp @@ -0,0 +1,556 @@ +#include "CodeEditor.h" +#include "LineNumberArea.h" +#include "ColorIndicator.h" +#include "SignatureHelper.h" + +#include "core/Settings.h" +#include "highlighter/HighlighterFactory.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CodeEditor::CodeEditor(Settings *settings, QWidget *parent) + : QPlainTextEdit(parent) + , m_settings(settings) +{ + m_lineNumberArea = new LineNumberArea(this); + m_colorIndicator = new ColorIndicator(this); + m_signatureHelper = new SignatureHelper(this); + setupEditor(); + + connect(this, &CodeEditor::blockCountChanged, + this, &CodeEditor::updateLineNumberAreaWidth); + + connect(this, &CodeEditor::updateRequest, + this, &CodeEditor::updateLineNumberArea); + + connect(this, &CodeEditor::cursorPositionChanged, + this, &CodeEditor::highlightCurrentLine); + + updateLineNumberAreaWidth(0); + highlightCurrentLine(); +} + +CodeEditor::~CodeEditor() = default; + +// --------------------------------------------------------------------------- +// Setup +// --------------------------------------------------------------------------- +void CodeEditor::setupEditor() +{ + applySettings(); + setLineWrapMode(QPlainTextEdit::NoWrap); +} + +void CodeEditor::applySettings() +{ + setFont(m_settings->editorFont()); + + const int tabStop = m_settings->tabSize(); + // Set tab stop width in pixels using font metrics + QFontMetrics fm(m_settings->editorFont()); + setTabStopDistance(static_cast(tabStop) * fm.horizontalAdvance(' ')); +} + +// --------------------------------------------------------------------------- +// File I/O +// --------------------------------------------------------------------------- +void CodeEditor::loadFile(const QString &filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QMessageBox::warning(this, tr("Open File"), + tr("Cannot open file:\n%1").arg(filePath)); + return; + } + + m_filePath = filePath; + + QTextStream in(&file); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + in.setEncoding(QStringConverter::Utf8); +#else + in.setCodec("UTF-8"); +#endif + + setPlainText(in.readAll()); + document()->setModified(false); + + installHighlighter(filePath); +} + +QString CodeEditor::filePath() const +{ + return m_filePath; +} + +bool CodeEditor::save() +{ + if (m_filePath.isEmpty()) + { + return saveAs(); + } + + return writeToFile(m_filePath); +} + +bool CodeEditor::saveAs() +{ + const QString path = QFileDialog::getSaveFileName( + this, + tr("Speichern unter"), + m_filePath + ); + + if (path.isEmpty()) + { + return false; + } + + m_filePath = path; + installHighlighter(m_filePath); + return writeToFile(m_filePath); +} + +bool CodeEditor::writeToFile(const QString &filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QMessageBox::warning(this, tr("Speichern"), + tr("Datei konnte nicht gespeichert werden:\n%1").arg(filePath)); + return false; + } + + QTextStream out(&file); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + out.setEncoding(QStringConverter::Utf8); +#else + out.setCodec("UTF-8"); +#endif + + out << toPlainText(); + document()->setModified(false); + emit fileSaved(filePath); + return true; +} + +void CodeEditor::installHighlighter(const QString &filePath) +{ + // Remove old highlighter first + delete m_highlighter; + m_highlighter = nullptr; + + m_highlighter = HighlighterFactory::createForFile(filePath, document()); +} + +bool CodeEditor::isModified() const +{ + return document()->isModified(); +} + +// --------------------------------------------------------------------------- +// Line number area +// --------------------------------------------------------------------------- +int CodeEditor::lineNumberAreaWidth() const +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) + { + max /= 10; + ++digits; + } + + const int padding = 8; + return fontMetrics().horizontalAdvance('9') * digits + padding * 2; +} + +void CodeEditor::updateLineNumberAreaWidth(int /*newBlockCount*/) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy != 0) + { + m_lineNumberArea->scroll(0, dy); + } + else + { + m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height()); + } + + if (rect.contains(viewport()->rect())) + { + updateLineNumberAreaWidth(0); + } +} + +void CodeEditor::paintEvent(QPaintEvent *event) +{ + // Zuerst den normalen Editor-Inhalt zeichnen + QPlainTextEdit::paintEvent(event); + + // Einrück-Führungslinien + const int tabSize = m_settings->tabSize(); + if (tabSize > 0) + { + QPainter painter(viewport()); + + QColor guideColor = palette().color(QPalette::Text); + guideColor.setAlpha(30); + painter.setPen(QPen(guideColor, 1, Qt::SolidLine)); + + const QFontMetrics fm(font()); + const int spaceWidth = fm.horizontalAdvance(' '); + const int tabPixels = tabSize * spaceWidth; + + if (tabPixels > 0) + { + int textOriginX = 0; + { + QTextBlock firstBlock = firstVisibleBlock(); + if (!firstBlock.isValid()) + { + firstBlock = document()->begin(); + } + if (firstBlock.isValid()) + { + const QRectF blockRect = blockBoundingGeometry(firstBlock) + .translated(contentOffset()); + const QTextLayout *layout = firstBlock.layout(); + if (layout && layout->lineCount() > 0) + { + textOriginX = static_cast(blockRect.left() + + layout->lineAt(0).position().x()); + } + else + { + textOriginX = static_cast(blockRect.left()); + } + } + } + + const int scrollX = horizontalScrollBar()->value(); + + QTextBlock block = firstVisibleBlock(); + const int bottom = event->rect().bottom(); + + while (block.isValid()) + { + const QRectF blockRect = blockBoundingGeometry(block) + .translated(contentOffset()); + if (blockRect.top() > bottom) { break; } + + if (block.isVisible()) + { + const QString text = block.text(); + int indentSpaces = 0; + for (const QChar &ch : text) + { + if (ch == ' ') { ++indentSpaces; } + else if (ch == '\t') { indentSpaces = ((indentSpaces / tabSize) + 1) * tabSize; } + else { break; } + } + + const int indentStops = indentSpaces / tabSize; + for (int stop = 1; stop <= indentStops; ++stop) + { + const int xPixel = textOriginX + stop * tabPixels - scrollX; + if (xPixel < lineNumberAreaWidth() || xPixel > viewport()->width()) + { + continue; + } + painter.drawLine(xPixel, + static_cast(blockRect.top()), + xPixel, + static_cast(blockRect.bottom())); + } + } + block = block.next(); + } + } + + // Farbvorschau-Quadrate zeichnen + m_colorIndicator->paint(painter, event); + } +} + +void CodeEditor::mousePressEvent(QMouseEvent *event) +{ + // Zuerst prüfen ob ein Farbquadrat geklickt wurde + if (m_colorIndicator->handleMousePress(event)) + { + return; + } + QPlainTextEdit::mousePressEvent(event); +} + +void CodeEditor::resizeEvent(QResizeEvent *event) +{ + QPlainTextEdit::resizeEvent(event); + + const QRect cr = contentsRect(); + m_lineNumberArea->setGeometry( + QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()) + ); +} + +void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(m_lineNumberArea); + + // Background + const QColor bgColor = palette().color(QPalette::Window).darker(110); + painter.fillRect(event->rect(), bgColor); + + const QColor lineNumColor = palette().color(QPalette::Mid); + const QColor activeColor = palette().color(QPalette::Text); + + const int currentLine = textCursor().blockNumber(); + + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = static_cast(blockBoundingGeometry(block).translated(contentOffset()).top()); + int bottom = top + static_cast(blockBoundingRect(block).height()); + + while (block.isValid() && top <= event->rect().bottom()) + { + if (block.isVisible() && bottom >= event->rect().top()) + { + const QString number = QString::number(blockNumber + 1); + painter.setPen(blockNumber == currentLine ? activeColor : lineNumColor); + painter.drawText( + 0, + top, + m_lineNumberArea->width() - 4, + fontMetrics().height(), + Qt::AlignRight, + number + ); + } + + block = block.next(); + top = bottom; + bottom = top + static_cast(blockBoundingRect(block).height()); + ++blockNumber; + } +} + +// --------------------------------------------------------------------------- +// Current line highlight +// --------------------------------------------------------------------------- +void CodeEditor::highlightCurrentLine() +{ + QList extraSelections; + + if (!isReadOnly()) + { + QTextEdit::ExtraSelection selection; + + const QColor lineColor = palette().color(QPalette::AlternateBase); + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +// --------------------------------------------------------------------------- +// Key handling – Tab/Shift+Tab, Smart-Backspace, Auto-Indent +// --------------------------------------------------------------------------- +void CodeEditor::keyPressEvent(QKeyEvent *event) +{ + const int tabSize = m_settings->tabSize(); + + // ----------------------------------------------------------------------- + // Shift+Tab: Einrückung zurückziehen + // ----------------------------------------------------------------------- + if (event->key() == Qt::Key_Backtab || + (event->key() == Qt::Key_Tab && event->modifiers() & Qt::ShiftModifier)) + { + QTextCursor cursor = textCursor(); + + QTextBlock startBlock = document()->findBlock(cursor.selectionStart()); + QTextBlock endBlock = document()->findBlock(cursor.selectionEnd()); + + cursor.beginEditBlock(); + for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next()) + { + const QString lineText = b.text(); + int toRemove = 0; + + if (m_settings->useSpacesForTabs()) + { + // Bis zu tabSize führende Leerzeichen entfernen + for (int i = 0; i < tabSize && i < lineText.length(); ++i) + { + if (lineText[i] == ' ') + { + ++toRemove; + } + else + { + break; + } + } + } + else + { + // Einen führenden Tab entfernen + if (!lineText.isEmpty() && lineText[0] == '\t') + { + toRemove = 1; + } + } + + if (toRemove > 0) + { + QTextCursor lineCursor(b); + lineCursor.movePosition(QTextCursor::StartOfBlock); + lineCursor.movePosition(QTextCursor::Right, + QTextCursor::KeepAnchor, + toRemove); + lineCursor.removeSelectedText(); + } + } + cursor.endEditBlock(); + return; + } + + // ----------------------------------------------------------------------- + // Tab: Einrücken (Leerzeichen oder echter Tab) + // ----------------------------------------------------------------------- + if (event->key() == Qt::Key_Tab) + { + QTextCursor cursor = textCursor(); + + if (cursor.hasSelection()) + { + // Mehrere Zeilen einrücken + QTextBlock startBlock = document()->findBlock(cursor.selectionStart()); + QTextBlock endBlock = document()->findBlock(cursor.selectionEnd()); + + cursor.beginEditBlock(); + for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next()) + { + QTextCursor lineCursor(b); + lineCursor.movePosition(QTextCursor::StartOfBlock); + if (m_settings->useSpacesForTabs()) + { + lineCursor.insertText(QString(tabSize, ' ')); + } + else + { + lineCursor.insertText("\t"); + } + } + cursor.endEditBlock(); + } + else + { + if (m_settings->useSpacesForTabs()) + { + // Zum nächsten Tab-Stop auffüllen + const int col = cursor.columnNumber(); + const int spacesNeeded = tabSize - (col % tabSize); + cursor.insertText(QString(spacesNeeded, ' ')); + } + else + { + cursor.insertText("\t"); + } + } + return; + } + + // ----------------------------------------------------------------------- + // Smart Backspace: springt zur vorherigen Einrückungsstufe + // ----------------------------------------------------------------------- + if (event->key() == Qt::Key_Backspace + && !textCursor().hasSelection() + && m_settings->useSpacesForTabs()) + { + QTextCursor cursor = textCursor(); + const int col = cursor.columnNumber(); + + if (col > 0) + { + // Prüfen ob links vom Cursor nur Leerzeichen bis Zeilenbeginn stehen + const QString lineText = cursor.block().text(); + const QString leftOfCursor = lineText.left(col); + const bool onlySpaces = leftOfCursor.trimmed().isEmpty(); + + if (onlySpaces && col > 0) + { + // Zur vorherigen Tab-Stop-Position springen + const int targetCol = ((col - 1) / tabSize) * tabSize; + const int toDelete = col - targetCol; + + cursor.movePosition(QTextCursor::Left, + QTextCursor::KeepAnchor, + toDelete); + cursor.removeSelectedText(); + return; + } + } + } + + // ----------------------------------------------------------------------- + // Enter / Return: Auto-Indent + // ----------------------------------------------------------------------- + if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) + { + QTextCursor cursor = textCursor(); + const QString currentLine = cursor.block().text(); + + // Führende Leerzeichen der aktuellen Zeile zählen + int leadingSpaces = 0; + for (const QChar &ch : currentLine) + { + if (ch == ' ') + { + ++leadingSpaces; + } + else if (ch == '\t') + { + leadingSpaces += tabSize; + } + else + { + break; + } + } + + QPlainTextEdit::keyPressEvent(event); + + if (leadingSpaces > 0) + { + const QString indent = m_settings->useSpacesForTabs() + ? QString(leadingSpaces, ' ') + : QString(leadingSpaces / tabSize, '\t'); + textCursor().insertText(indent); + } + return; + } + + QPlainTextEdit::keyPressEvent(event); +} + diff --git a/src/barecode/src/editor/CodeEditor.h b/src/barecode/src/editor/CodeEditor.h new file mode 100644 index 0000000..21581fe --- /dev/null +++ b/src/barecode/src/editor/CodeEditor.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include +#include + +class LineNumberArea; +class Settings; +class SyntaxHighlighter; +class ColorIndicator; +class SignatureHelper; + +// --------------------------------------------------------------------------- +// CodeEditor – Core editing widget. +// Features: +// • Line number gutter +// • Current-line highlight +// • Auto-indent on Enter +// • Tab → spaces (configurable) +// • Syntax highlighting (via pluggable SyntaxHighlighter) +// --------------------------------------------------------------------------- +class CodeEditor : public QPlainTextEdit +{ + Q_OBJECT + +public: + explicit CodeEditor(Settings *settings, QWidget *parent = nullptr); + ~CodeEditor() override; + + void loadFile(const QString &filePath); + void applySettings(); + + // Speichern + bool save(); + bool saveAs(); + + // Called by LineNumberArea + int lineNumberAreaWidth() const; + void lineNumberAreaPaintEvent(QPaintEvent *event); + + QString filePath() const; + bool isModified() const; + + // Öffentliche Hilfsmethoden für ColorIndicator + // (die Qt-Originale sind protected und von außen nicht erreichbar) + QTextBlock firstVisibleBlockPublic() const { return firstVisibleBlock(); } + QRectF blockBoundingGeometryPublic(const QTextBlock &b) const { return blockBoundingGeometry(b); } + QPointF contentOffsetPublic() const { return contentOffset(); } + +signals: + void fileSaved(const QString &filePath); + +protected: + void resizeEvent(QResizeEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + +private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect &rect, int dy); + +private: + void setupEditor(); + void installHighlighter(const QString &filePath); + bool writeToFile(const QString &filePath); + + Settings *m_settings = nullptr; + LineNumberArea *m_lineNumberArea = nullptr; + SyntaxHighlighter *m_highlighter = nullptr; + ColorIndicator *m_colorIndicator = nullptr; + SignatureHelper *m_signatureHelper = nullptr; + QString m_filePath; +}; diff --git a/src/barecode/src/editor/ColorIndicator.cpp b/src/barecode/src/editor/ColorIndicator.cpp new file mode 100644 index 0000000..60f4e04 --- /dev/null +++ b/src/barecode/src/editor/ColorIndicator.cpp @@ -0,0 +1,361 @@ +#include "ColorIndicator.h" +#include "CodeEditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// Kombinierter Regex — erfasst alle CSS-Farbformate in einer Runde +// --------------------------------------------------------------------------- +const QRegularExpression ColorIndicator::s_colorRegex( + // #rgb / #rrggbb / #rrggbbaa + R"(#(?:[0-9A-Fa-f]{8}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})(?=[^0-9A-Fa-f]|$))" + R"(|rgba?\s*\([^)]+\))" + R"(|hsla?\s*\([^)]+\))", + QRegularExpression::CaseInsensitiveOption +); + +// --------------------------------------------------------------------------- +// Konstruktor +// --------------------------------------------------------------------------- +ColorIndicator::ColorIndicator(CodeEditor *editor) + : QObject(editor) + , m_editor(editor) +{ + // Cache invalidieren und Viewport neu zeichnen wenn sich der Text ändert + connect(m_editor->document(), &QTextDocument::contentsChanged, + this, [this]() + { + m_cacheFirstBlock = -1; + m_cacheLastBlock = -1; + m_editor->viewport()->update(); + }); + + // Auch beim Scrollen neu zeichnen (Cache bleibt gültig, nur Position ändert sich) + connect(m_editor->verticalScrollBar(), &QScrollBar::valueChanged, + this, [this]() + { + m_cacheFirstBlock = -1; + m_cacheLastBlock = -1; + }); +} + +// --------------------------------------------------------------------------- +// Paint – wird aus CodeEditor::paintEvent aufgerufen +// --------------------------------------------------------------------------- +void ColorIndicator::paint(QPainter &painter, QPaintEvent *event) +{ + rebuildCache(); + + const int squareSize = m_editor->fontMetrics().height() - 4; + const int radius = 2; + + for (const ColorMatch &m : m_cache) + { + if (!event->rect().intersects(m.rect)) + { + continue; + } + + // Rahmen + painter.setPen(QColor(0, 0, 0, 80)); + painter.setBrush(m.color); + painter.drawRoundedRect(m.rect, radius, radius); + + // Schachbrettmuster als Hintergrund für transparente Farben + if (m.color.alpha() < 255) + { + const int half = squareSize / 2; + painter.setPen(Qt::NoPen); + painter.setBrush(QColor(180, 180, 180)); + painter.drawRect(m.rect.x(), m.rect.y(), half, half); + painter.drawRect(m.rect.x() + half, m.rect.y() + half, half, half); + painter.setBrush(m.color); + painter.drawRoundedRect(m.rect, radius, radius); + } + } +} + +// --------------------------------------------------------------------------- +// Mouse – wird aus CodeEditor::mousePressEvent aufgerufen +// --------------------------------------------------------------------------- +bool ColorIndicator::handleMousePress(QMouseEvent *event) +{ + for (const ColorMatch &m : m_cache) + { + if (!m.rect.contains(event->pos())) + { + continue; + } + + // Farb-Dialog öffnen + QColorDialog dlg(m.color, m_editor); + dlg.setOption(QColorDialog::ShowAlphaChannel, true); + dlg.setWindowTitle(QObject::tr("Farbe wählen")); + + if (dlg.exec() != QDialog::Accepted) + { + return true; + } + + const QColor newColor = dlg.selectedColor(); + + // Ursprünglichen Farbwert im Dokument ersetzen + QTextBlock block = m_editor->document()->findBlockByNumber(m.blockNumber); + if (!block.isValid()) + { + return true; + } + + // Neuen Farbwert als Hex-String formatieren + QString newValue; + if (newColor.alpha() < 255) + { + newValue = newColor.name(QColor::HexArgb); // #aarrggbb + // CSS erwartet #rrggbbaa — Bytes umstellen + // Qt liefert #aarrggbb, CSS will #rrggbbaa + newValue = QString("#%1%2%3%4") + .arg(newColor.red(), 2, 16, QChar('0')) + .arg(newColor.green(), 2, 16, QChar('0')) + .arg(newColor.blue(), 2, 16, QChar('0')) + .arg(newColor.alpha(), 2, 16, QChar('0')); + } + else + { + newValue = newColor.name(QColor::HexRgb); // #rrggbb + } + + QTextCursor cursor(block); + cursor.setPosition(block.position() + m.posInBlock); + cursor.setPosition(block.position() + m.posInBlock + m.length, + QTextCursor::KeepAnchor); + cursor.insertText(newValue); + + // Cache invalidieren + m_cache.clear(); + m_cacheFirstBlock = -1; + m_cacheLastBlock = -1; + + return true; + } + + return false; +} + +// --------------------------------------------------------------------------- +// Cache aufbauen – nur für sichtbare Blöcke +// --------------------------------------------------------------------------- +void ColorIndicator::rebuildCache() +{ + QTextBlock firstVisible = m_editor->firstVisibleBlockPublic(); + const int firstNum = firstVisible.blockNumber(); + + // Letzten sichtbaren Block bestimmen + int lastNum = firstNum; + { + QTextBlock b = firstVisible; + const int bot = m_editor->viewport()->height(); + while (b.isValid()) + { + const QRectF r = m_editor->blockBoundingGeometryPublic(b) + .translated(m_editor->contentOffsetPublic()); + if (r.top() > bot) + { + break; + } + lastNum = b.blockNumber(); + b = b.next(); + } + } + + // Cache noch aktuell? + if (firstNum == m_cacheFirstBlock && lastNum == m_cacheLastBlock) + { + return; + } + + m_cache.clear(); + m_cacheFirstBlock = firstNum; + m_cacheLastBlock = lastNum; + + const int squareSize = m_editor->fontMetrics().height() - 4; + const int scrollX = m_editor->horizontalScrollBar()->value(); + + QTextBlock block = firstVisible; + while (block.isValid() && block.blockNumber() <= lastNum) + { + const QRectF blockRect = m_editor->blockBoundingGeometryPublic(block) + .translated(m_editor->contentOffsetPublic()); + + const QList found = findColorsInBlock(block.text(), + block.blockNumber()); + for (ColorMatch m : found) + { + // X-Position des Farbwerts im Viewport berechnen + const QTextLayout *layout = block.layout(); + if (!layout || layout->lineCount() == 0) + { + continue; + } + + const QTextLine line = layout->lineAt(0); + // Position nach dem Ende des Farbwerts + const qreal endCharX = line.cursorToX(m.posInBlock + m.length); + const int x = static_cast(blockRect.left() + endCharX) + - scrollX + 3; + + if (x + squareSize > m_editor->viewport()->width()) + { + continue; + } + + const int y = static_cast(blockRect.top()) + + (static_cast(blockRect.height()) - squareSize) / 2; + + m.rect = QRect(x, y, squareSize, squareSize); + m_cache.append(m); + } + + block = block.next(); + } +} + +// --------------------------------------------------------------------------- +// Farbwerte in einer Zeile suchen +// --------------------------------------------------------------------------- +QList ColorIndicator::findColorsInBlock( + const QString &text, int blockNumber) const +{ + QList result; + + QRegularExpressionMatchIterator it = s_colorRegex.globalMatch(text); + while (it.hasNext()) + { + QRegularExpressionMatch match = it.next(); + const QString token = match.captured(0); + const QColor color = parseColor(token); + + if (!color.isValid()) + { + continue; + } + + ColorMatch m; + m.blockNumber = blockNumber; + m.posInBlock = static_cast(match.capturedStart()); + m.length = static_cast(match.capturedLength()); + m.color = color; + result.append(m); + } + + return result; +} + +// --------------------------------------------------------------------------- +// Farb-Parser +// --------------------------------------------------------------------------- +QColor ColorIndicator::parseColor(const QString &token) +{ + const QString t = token.trimmed(); + + if (t.startsWith('#')) { return parseHex(t); } + if (t.startsWith("rgba", Qt::CaseInsensitive)) { return parseRgba(t); } + if (t.startsWith("rgb", Qt::CaseInsensitive)) { return parseRgb(t); } + if (t.startsWith("hsla", Qt::CaseInsensitive)) { return parseHsla(t); } + if (t.startsWith("hsl", Qt::CaseInsensitive)) { return parseHsl(t); } + + return QColor(); +} + +QColor ColorIndicator::parseHex(const QString &s) +{ + // #rgb → #rrggbb + if (s.length() == 4) + { + return QColor(QString("#%1%1%2%2%3%3") + .arg(s[1]).arg(s[2]).arg(s[3])); + } + // #rrggbb + if (s.length() == 7) + { + return QColor(s); + } + // #rrggbbaa (CSS) → Qt braucht #aarrggbb + if (s.length() == 9) + { + const QString rr = s.mid(1, 2); + const QString gg = s.mid(3, 2); + const QString bb = s.mid(5, 2); + const QString aa = s.mid(7, 2); + return QColor(QString("#%1%2%3%4").arg(aa, rr, gg, bb)); + } + return QColor(); +} + +QColor ColorIndicator::parseRgb(const QString &s) +{ + // rgb(r, g, b) + static const QRegularExpression re( + R"(rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\))", + QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch m = re.match(s); + if (!m.hasMatch()) { return QColor(); } + return QColor(m.captured(1).toInt(), + m.captured(2).toInt(), + m.captured(3).toInt()); +} + +QColor ColorIndicator::parseRgba(const QString &s) +{ + // rgba(r, g, b, a) — a ist 0.0–1.0 + static const QRegularExpression re( + R"(rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([0-9.]+)\s*\))", + QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch m = re.match(s); + if (!m.hasMatch()) { return QColor(); } + return QColor(m.captured(1).toInt(), + m.captured(2).toInt(), + m.captured(3).toInt(), + qRound(m.captured(4).toDouble() * 255.0)); +} + +QColor ColorIndicator::parseHsl(const QString &s) +{ + // hsl(h, s%, l%) + static const QRegularExpression re( + R"(hsl\s*\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\))", + QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch m = re.match(s); + if (!m.hasMatch()) { return QColor(); } + QColor c; + c.setHsl(m.captured(1).toInt(), + qRound(m.captured(2).toInt() * 2.55), + qRound(m.captured(3).toInt() * 2.55)); + return c; +} + +QColor ColorIndicator::parseHsla(const QString &s) +{ + // hsla(h, s%, l%, a) + static const QRegularExpression re( + R"(hsla\s*\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([0-9.]+)\s*\))", + QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch m = re.match(s); + if (!m.hasMatch()) { return QColor(); } + QColor c; + c.setHsl(m.captured(1).toInt(), + qRound(m.captured(2).toInt() * 2.55), + qRound(m.captured(3).toInt() * 2.55), + qRound(m.captured(4).toDouble() * 255.0)); + return c; +} + + + diff --git a/src/barecode/src/editor/ColorIndicator.h b/src/barecode/src/editor/ColorIndicator.h new file mode 100644 index 0000000..2d19ede --- /dev/null +++ b/src/barecode/src/editor/ColorIndicator.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +class CodeEditor; +class QPainter; +class QPaintEvent; +class QMouseEvent; + +// --------------------------------------------------------------------------- +// ColorIndicator – Zeichnet kleine Farbquadrate neben CSS-Farbwerten und +// öffnet einen QColorDialog wenn der Nutzer darauf klickt. +// +// Unterstützte Formate: +// #rgb #rrggbb #rrggbbaa +// rgb(r, g, b) rgba(r, g, b, a) +// hsl(h, s%, l%) hsla(h, s%, l%, a) +// 140 benannte CSS-Farben (red, blue, cornflowerblue, ...) +// --------------------------------------------------------------------------- +class ColorIndicator : public QObject +{ + Q_OBJECT + +public: + explicit ColorIndicator(CodeEditor *editor); + + // Wird aus CodeEditor::paintEvent aufgerufen + void paint(QPainter &painter, QPaintEvent *event); + + // Wird aus CodeEditor::mousePressEvent aufgerufen + // Gibt true zurück wenn der Klick auf einem Farbquadrat war + bool handleMousePress(QMouseEvent *event); + +private: + struct ColorMatch + { + QRect rect; // Position des Quadrats im Viewport + QColor color; // Erkannte Farbe + int blockNumber; + int posInBlock; // Zeichenposition des Farbwerts im Block + int length; // Länge des Farbwerts im Text + }; + + void rebuildCache(); + QList findColorsInBlock(const QString &text, + int blockNumber) const; + + static QColor parseColor(const QString &token); + static QColor parseHex(const QString &s); + static QColor parseRgb(const QString &s); + static QColor parseRgba(const QString &s); + static QColor parseHsl(const QString &s); + static QColor parseHsla(const QString &s); + + CodeEditor *m_editor = nullptr; + QList m_cache; + int m_cacheFirstBlock = -1; + int m_cacheLastBlock = -1; + + // Kombinierter Regex für alle Farbformate + static const QRegularExpression s_colorRegex; +}; diff --git a/src/barecode/src/editor/EditorPanel.cpp b/src/barecode/src/editor/EditorPanel.cpp new file mode 100644 index 0000000..e2c424c --- /dev/null +++ b/src/barecode/src/editor/EditorPanel.cpp @@ -0,0 +1,258 @@ +#include "EditorPanel.h" +#include "EditorTab.h" +#include "CodeEditor.h" +#include "SearchPanel.h" +#include "FileSearchPanel.h" + +#include +#include +#include +#include + +EditorPanel::EditorPanel(Settings *settings, QWidget *parent) + : QWidget(parent) + , m_settings(settings) +{ + setupUi(); +} + +// --------------------------------------------------------------------------- +// Setup +// --------------------------------------------------------------------------- +void EditorPanel::setupUi() +{ + m_layout = new QVBoxLayout(this); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setSpacing(0); + + m_tabWidget = new QTabWidget(this); + m_tabWidget->setTabsClosable(true); + m_tabWidget->setMovable(true); + m_tabWidget->setDocumentMode(true); + + m_searchPanel = new SearchPanel(this); + m_fileSearch = new FileSearchPanel(this); + + m_layout->addWidget(m_tabWidget, 1); + m_layout->addWidget(m_searchPanel, 0); + m_layout->addWidget(m_fileSearch, 0); + + connect(m_tabWidget, &QTabWidget::tabCloseRequested, + this, &EditorPanel::onTabCloseRequested); + + connect(m_tabWidget, &QTabWidget::currentChanged, + this, &EditorPanel::onCurrentTabChanged); + + connect(m_fileSearch, &FileSearchPanel::fileLineRequested, + this, &EditorPanel::goToLine); +} + +// --------------------------------------------------------------------------- +// Hilfsmethoden +// --------------------------------------------------------------------------- +EditorTab *EditorPanel::currentTab() const +{ + return qobject_cast(m_tabWidget->currentWidget()); +} + +int EditorPanel::findTabForFile(const QString &filePath) const +{ + EditorTab *tab = m_openTabs.value(filePath, nullptr); + return tab ? m_tabWidget->indexOf(tab) : -1; +} + +// --------------------------------------------------------------------------- +// Öffentliche Slots +// --------------------------------------------------------------------------- +void EditorPanel::openFile(const QString &filePath) +{ + const int existing = findTabForFile(filePath); + if (existing != -1) + { + m_tabWidget->setCurrentIndex(existing); + return; + } + + EditorTab *tab = new EditorTab(filePath, m_settings, m_tabWidget); + const int index = m_tabWidget->addTab(tab, tab->fileName()); + m_tabWidget->setCurrentIndex(index); + m_tabWidget->setTabToolTip(index, filePath); + m_openTabs.insert(filePath, tab); + + // Änderungsindikator im Tab-Titel (● = ungespeichert) + connect(tab->editor()->document(), &QTextDocument::modificationChanged, + this, [this, tab](bool modified) + { + const int idx = m_tabWidget->indexOf(tab); + if (idx == -1) + { + return; + } + const QString name = QFileInfo(tab->filePath()).fileName(); + m_tabWidget->setTabText(idx, modified ? "● " + name : name); + }); + + // Tab-Titel nach "Speichern unter" aktualisieren (neuer Dateiname, kein Punkt) + connect(tab->editor(), &CodeEditor::fileSaved, this, [this, tab](const QString &savedPath) + { + const int idx = m_tabWidget->indexOf(tab); + if (idx != -1) + { + m_tabWidget->setTabText(idx, QFileInfo(savedPath).fileName()); + m_tabWidget->setTabToolTip(idx, savedPath); + } + emit currentFileSaved(savedPath); + }); +} + +void EditorPanel::saveCurrentFile() +{ + if (EditorTab *tab = currentTab()) + { + tab->save(); + } +} + +void EditorPanel::saveCurrentFileAs() +{ + if (EditorTab *tab = currentTab()) + { + tab->saveAs(); + } +} + +void EditorPanel::saveAllFiles() +{ + for (int i = 0; i < m_tabWidget->count(); ++i) + { + EditorTab *tab = qobject_cast(m_tabWidget->widget(i)); + if (tab && tab->isModified()) + { + tab->save(); + } + } +} + +void EditorPanel::showSearchPanel() +{ + m_fileSearch->hide(); + m_searchPanel->activate(); +} + +void EditorPanel::showFileSearchPanel() +{ + m_searchPanel->hide(); + m_fileSearch->activate(); +} + +void EditorPanel::setSearchRoot(const QString &path) +{ + m_fileSearch->setSearchRoot(path); +} + +void EditorPanel::goToLine(const QString &filePath, int line) +{ + // Datei öffnen falls noch nicht geöffnet + openFile(filePath); + + EditorTab *tab = m_openTabs.value(filePath, nullptr); + if (!tab) + { + return; + } + + m_tabWidget->setCurrentWidget(tab); + + // Zur gewünschten Zeile springen + CodeEditor *editor = tab->editor(); + QTextBlock block = editor->document()->findBlockByLineNumber(line - 1); + if (block.isValid()) + { + QTextCursor cursor(block); + cursor.movePosition(QTextCursor::StartOfBlock); + editor->setTextCursor(cursor); + editor->centerCursor(); + editor->setFocus(); + } +} + +QStringList EditorPanel::openFilePaths() const +{ + QStringList paths; + for (int i = 0; i < m_tabWidget->count(); ++i) + { + EditorTab *tab = qobject_cast(m_tabWidget->widget(i)); + if (tab) + { + paths.append(tab->filePath()); + } + } + return paths; +} + +QString EditorPanel::activeFilePath() const +{ + EditorTab *tab = currentTab(); + return tab ? tab->filePath() : QString(); +} + +void EditorPanel::restoreSession(const QStringList &files, const QString &activeFile) +{ + for (const QString &path : files) + { + if (QFile::exists(path)) + { + openFile(path); + } + } + + // Aktiven Tab wiederherstellen + if (!activeFile.isEmpty()) + { + const int idx = findTabForFile(activeFile); + if (idx != -1) + { + m_tabWidget->setCurrentIndex(idx); + } + } +} + +void EditorPanel::undo() +{ + if (EditorTab *tab = currentTab()) + { + tab->editor()->undo(); + } +} + +void EditorPanel::redo() +{ + if (EditorTab *tab = currentTab()) + { + tab->editor()->redo(); + } +} + +// --------------------------------------------------------------------------- +// Private Slots +// --------------------------------------------------------------------------- +void EditorPanel::onTabCloseRequested(int index) +{ + EditorTab *tab = qobject_cast(m_tabWidget->widget(index)); + if (!tab) + { + return; + } + + m_openTabs.remove(tab->filePath()); + m_tabWidget->removeTab(index); + tab->deleteLater(); + + m_searchPanel->setEditor(currentTab() ? currentTab()->editor() : nullptr); +} + +void EditorPanel::onCurrentTabChanged(int /*index*/) +{ + EditorTab *tab = currentTab(); + m_searchPanel->setEditor(tab ? tab->editor() : nullptr); +} diff --git a/src/barecode/src/editor/EditorPanel.h b/src/barecode/src/editor/EditorPanel.h new file mode 100644 index 0000000..5c789ac --- /dev/null +++ b/src/barecode/src/editor/EditorPanel.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include +#include +#include + +class EditorTab; +class Settings; +class SearchPanel; +class FileSearchPanel; + +// --------------------------------------------------------------------------- +// EditorPanel – Rechtes Panel: Tab-Leiste + Editoren + Such/Ersetzen-Panel. +// --------------------------------------------------------------------------- +class EditorPanel : public QWidget +{ + Q_OBJECT + +public: + explicit EditorPanel(Settings *settings, QWidget *parent = nullptr); + +public slots: + void openFile(const QString &filePath); + void saveCurrentFile(); + void saveCurrentFileAs(); + void saveAllFiles(); + void setSearchRoot(const QString &path); + void showSearchPanel(); + void showFileSearchPanel(); + void goToLine(const QString &filePath, int line); + + // Session + QStringList openFilePaths() const; + QString activeFilePath() const; + void restoreSession(const QStringList &files, const QString &activeFile); + void undo(); + void redo(); + +signals: + void currentFileSaved(const QString &filePath); + +private slots: + void onTabCloseRequested(int index); + void onCurrentTabChanged(int index); + +private: + void setupUi(); + int findTabForFile(const QString &filePath) const; + EditorTab *currentTab() const; + + Settings *m_settings = nullptr; + QVBoxLayout *m_layout = nullptr; + QTabWidget *m_tabWidget = nullptr; + SearchPanel *m_searchPanel = nullptr; + FileSearchPanel *m_fileSearch = nullptr; + + QHash m_openTabs; +}; diff --git a/src/barecode/src/editor/EditorTab.cpp b/src/barecode/src/editor/EditorTab.cpp new file mode 100644 index 0000000..0b0b8fa --- /dev/null +++ b/src/barecode/src/editor/EditorTab.cpp @@ -0,0 +1,53 @@ +#include "EditorTab.h" +#include "CodeEditor.h" + +#include + +EditorTab::EditorTab(const QString &filePath, Settings *settings, QWidget *parent) + : QWidget(parent) + , m_filePath(filePath) +{ + m_layout = new QVBoxLayout(this); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setSpacing(0); + + m_editor = new CodeEditor(settings, this); + m_editor->loadFile(filePath); + + m_layout->addWidget(m_editor); +} + +QString EditorTab::filePath() const +{ + return m_filePath; +} + +QString EditorTab::fileName() const +{ + return QFileInfo(m_filePath).fileName(); +} + +CodeEditor *EditorTab::editor() const +{ + return m_editor; +} + +bool EditorTab::isModified() const +{ + return m_editor->isModified(); +} + +bool EditorTab::save() +{ + const bool ok = m_editor->save(); + // Path may have changed if this was an untitled buffer saved for the first time + m_filePath = m_editor->filePath(); + return ok; +} + +bool EditorTab::saveAs() +{ + const bool ok = m_editor->saveAs(); + m_filePath = m_editor->filePath(); + return ok; +} diff --git a/src/barecode/src/editor/EditorTab.h b/src/barecode/src/editor/EditorTab.h new file mode 100644 index 0000000..3bf0d8f --- /dev/null +++ b/src/barecode/src/editor/EditorTab.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +class CodeEditor; +class Settings; + +// --------------------------------------------------------------------------- +// EditorTab – Widget placed inside each tab of the tab bar. +// Owns a CodeEditor for a single file. +// --------------------------------------------------------------------------- +class EditorTab : public QWidget +{ + Q_OBJECT + +public: + explicit EditorTab(const QString &filePath, Settings *settings, QWidget *parent = nullptr); + + QString filePath() const; + QString fileName() const; + CodeEditor *editor() const; + bool isModified() const; + + bool save(); + bool saveAs(); + +private: + QString m_filePath; + QVBoxLayout *m_layout = nullptr; + CodeEditor *m_editor = nullptr; +}; diff --git a/src/barecode/src/editor/FileSearchPanel.cpp b/src/barecode/src/editor/FileSearchPanel.cpp new file mode 100644 index 0000000..f7d0030 --- /dev/null +++ b/src/barecode/src/editor/FileSearchPanel.cpp @@ -0,0 +1,330 @@ +#include "FileSearchPanel.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// Konstruktor +// --------------------------------------------------------------------------- +FileSearchPanel::FileSearchPanel(QWidget *parent) + : QWidget(parent) +{ + setupUi(); + hide(); + + m_watcher = new QFutureWatcher>(this); + connect(m_watcher, &QFutureWatcher>::finished, + this, &FileSearchPanel::onSearchFinished); +} + +// --------------------------------------------------------------------------- +// UI +// --------------------------------------------------------------------------- +void FileSearchPanel::setupUi() +{ + QVBoxLayout *root = new QVBoxLayout(this); + root->setContentsMargins(6, 4, 6, 4); + root->setSpacing(4); + + // ---- Zeile 1: Suchbegriff ---- + QHBoxLayout *row1 = new QHBoxLayout(); + row1->addWidget(new QLabel(tr("Suchen in Dateien:"), this)); + + m_searchEdit = new QLineEdit(this); + m_searchEdit->setPlaceholderText(tr("Suchbegriff…")); + m_searchEdit->setClearButtonEnabled(true); + row1->addWidget(m_searchEdit, 1); + + m_btnSearch = new QPushButton(tr("Suchen"), this); + m_btnSearch->setDefault(true); + row1->addWidget(m_btnSearch); + + m_btnClose = new QPushButton(tr("✕"), this); + m_btnClose->setFixedWidth(24); + m_btnClose->setFlat(true); + m_btnClose->setToolTip(tr("Schließen")); + row1->addWidget(m_btnClose); + + root->addLayout(row1); + + // ---- Zeile 2: Optionen + Filter ---- + QHBoxLayout *row2 = new QHBoxLayout(); + m_chkCase = new QCheckBox(tr("Groß-/Kleinschreibung"), this); + m_chkWord = new QCheckBox(tr("Ganzes Wort"), this); + m_chkRegex = new QCheckBox(tr("Regex"), this); + + row2->addWidget(m_chkCase); + row2->addWidget(m_chkWord); + row2->addWidget(m_chkRegex); + row2->addSpacing(12); + + row2->addWidget(new QLabel(tr("Dateitypen:"), this)); + m_filterEdit = new QLineEdit(this); + m_filterEdit->setText("*.html *.php *.css *.js *.c *.cpp *.h"); + m_filterEdit->setFixedWidth(220); + m_filterEdit->setToolTip(tr("Leerzeichen-getrennte Muster, z.B.: *.php *.html")); + row2->addWidget(m_filterEdit); + row2->addStretch(); + + root->addLayout(row2); + + // ---- Fortschritt + Status ---- + m_progress = new QProgressBar(this); + m_progress->setRange(0, 0); // Unbestimmter Modus + m_progress->setFixedHeight(4); + m_progress->hide(); + root->addWidget(m_progress); + + m_statusLabel = new QLabel(this); + m_statusLabel->setStyleSheet("color: palette(mid);"); + root->addWidget(m_statusLabel); + + // ---- Ergebnisliste ---- + m_results = new QTreeWidget(this); + m_results->setHeaderHidden(true); + m_results->setRootIsDecorated(true); + m_results->setIndentation(16); + m_results->setUniformRowHeights(true); + m_results->setAlternatingRowColors(true); + root->addWidget(m_results, 1); + + // ---- Verbindungen ---- + connect(m_btnSearch, &QPushButton::clicked, this, &FileSearchPanel::onSearch); + connect(m_searchEdit, &QLineEdit::returnPressed, this, &FileSearchPanel::onSearch); + connect(m_btnClose, &QPushButton::clicked, this, [this]() + { + hide(); + }); + connect(m_results, &QTreeWidget::itemActivated, + this, &FileSearchPanel::onResultActivated); +} + +// --------------------------------------------------------------------------- +// Öffentliche Schnittstelle +// --------------------------------------------------------------------------- +void FileSearchPanel::setSearchRoot(const QString &path) +{ + m_searchRoot = path; +} + +void FileSearchPanel::activate() +{ + show(); + m_searchEdit->setFocus(); + m_searchEdit->selectAll(); +} + +// --------------------------------------------------------------------------- +// Suche starten +// --------------------------------------------------------------------------- +void FileSearchPanel::onSearch() +{ + const QString needle = m_searchEdit->text().trimmed(); + if (needle.isEmpty()) + { + return; + } + + if (m_searchRoot.isEmpty()) + { + m_statusLabel->setText(tr("Kein Projektverzeichnis geöffnet.")); + return; + } + + // Laufende Suche abbrechen + if (m_watcher->isRunning()) + { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + + m_results->clear(); + m_statusLabel->setText(tr("Suche läuft…")); + m_progress->show(); + m_btnSearch->setEnabled(false); + + const QString root = m_searchRoot; + const bool cs = m_chkCase->isChecked(); + const bool word = m_chkWord->isChecked(); + const bool regex = m_chkRegex->isChecked(); + const QStringList extensions = m_filterEdit->text().simplified().split(' ', + Qt::SkipEmptyParts); + + QFuture> future = QtConcurrent::run( + [this, root, needle, cs, word, regex, extensions]() + { + return searchInFiles(root, needle, cs, word, regex, extensions); + } + ); + + m_watcher->setFuture(future); +} + +// --------------------------------------------------------------------------- +// Suchergebnisse anzeigen +// --------------------------------------------------------------------------- +void FileSearchPanel::onSearchFinished() +{ + m_progress->hide(); + m_btnSearch->setEnabled(true); + + if (m_watcher->isCanceled()) + { + return; + } + + const QList matches = m_watcher->result(); + + // Ergebnisse gruppiert nach Datei aufbauen + QString currentFile; + QTreeWidgetItem *fileItem = nullptr; + int fileCount = 0; + int matchCount = 0; + + for (const Match &m : matches) + { + if (m.filePath != currentFile) + { + currentFile = m.filePath; + ++fileCount; + + fileItem = new QTreeWidgetItem(m_results); + fileItem->setText(0, QFileInfo(m.filePath).fileName()); + fileItem->setToolTip(0, m.filePath); + fileItem->setData(0, Qt::UserRole, m.filePath); + fileItem->setData(0, Qt::UserRole + 1, -1); + + QFont boldFont = fileItem->font(0); + boldFont.setBold(true); + fileItem->setFont(0, boldFont); + fileItem->setExpanded(true); + } + + QTreeWidgetItem *lineItem = new QTreeWidgetItem(fileItem); + lineItem->setText(0, QString(" Zeile %1: %2") + .arg(m.line) + .arg(m.content.trimmed().left(120))); + lineItem->setToolTip(0, m.content.trimmed()); + lineItem->setData(0, Qt::UserRole, m.filePath); + lineItem->setData(0, Qt::UserRole + 1, m.line); + + ++matchCount; + } + + // Datei-Titelzeilen um Trefferanzahl ergänzen + for (int i = 0; i < m_results->topLevelItemCount(); ++i) + { + QTreeWidgetItem *item = m_results->topLevelItem(i); + const int count = item->childCount(); + item->setText(0, QString("%1 (%2 Treffer)") + .arg(QFileInfo(item->data(0, Qt::UserRole).toString()).fileName()) + .arg(count)); + } + + if (matchCount == 0) + { + m_statusLabel->setText(tr("Keine Treffer gefunden.")); + } + else + { + m_statusLabel->setText(tr("%1 Treffer in %2 Datei(en).") + .arg(matchCount) + .arg(fileCount)); + } +} + +// --------------------------------------------------------------------------- +// Klick auf Treffer → Datei + Zeile öffnen +// --------------------------------------------------------------------------- +void FileSearchPanel::onResultActivated(QTreeWidgetItem *item, int /*column*/) +{ + const QString path = item->data(0, Qt::UserRole).toString(); + const int line = item->data(0, Qt::UserRole + 1).toInt(); + + if (path.isEmpty() || line < 0) + { + // Datei-Titelzeile: nur auf-/zuklappen + item->setExpanded(!item->isExpanded()); + return; + } + + emit fileLineRequested(path, line); +} + +// --------------------------------------------------------------------------- +// Eigentliche Suchroutine (läuft in Thread-Pool) +// --------------------------------------------------------------------------- +QList FileSearchPanel::searchInFiles( + const QString &root, + const QString &needle, + bool caseSensitive, + bool wholeWord, + bool useRegex, + const QStringList &extensions) const +{ + QList results; + + // Regulären Ausdruck vorbereiten + QString pattern = useRegex ? needle : QRegularExpression::escape(needle); + if (wholeWord) + { + pattern = "\\b" + pattern + "\\b"; + } + + QRegularExpression re(pattern, + caseSensitive + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); + + if (!re.isValid()) + { + return results; + } + + // Verzeichnis rekursiv durchsuchen + QDirIterator it(root, + extensions.isEmpty() + ? QStringList("*") + : extensions, + QDir::Files, + QDirIterator::Subdirectories); + + while (it.hasNext()) + { + if (m_watcher->isCanceled()) + { + break; + } + + const QString filePath = it.next(); + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + continue; + } + + QTextStream stream(&file); + stream.setEncoding(QStringConverter::Utf8); + + int lineNumber = 0; + while (!stream.atEnd()) + { + ++lineNumber; + const QString line = stream.readLine(); + + if (re.match(line).hasMatch()) + { + results.append({ filePath, lineNumber, line }); + } + } + } + + return results; +} diff --git a/src/barecode/src/editor/FileSearchPanel.h b/src/barecode/src/editor/FileSearchPanel.h new file mode 100644 index 0000000..97b9766 --- /dev/null +++ b/src/barecode/src/editor/FileSearchPanel.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// FileSearchPanel – Suche in allen Dateien eines Verzeichnisses. +// +// Ergebnisse werden als aufklappbare Liste angezeigt: +// Dateiname (N Treffer) +// └ Zeile 12: +// └ Zeile 34: +// +// Klick auf einen Treffer öffnet die Datei im Editor und springt zur Zeile. +// --------------------------------------------------------------------------- +class FileSearchPanel : public QWidget +{ + Q_OBJECT + +public: + explicit FileSearchPanel(QWidget *parent = nullptr); + + void setSearchRoot(const QString &path); + +public slots: + void activate(); + +signals: + void fileLineRequested(const QString &filePath, int line); + +private slots: + void onSearch(); + void onResultActivated(QTreeWidgetItem *item, int column); + void onSearchFinished(); + +private: + struct Match + { + QString filePath; + int line; + QString content; + }; + + void setupUi(); + QList searchInFiles(const QString &root, + const QString &needle, + bool caseSensitive, + bool wholeWord, + bool useRegex, + const QStringList &extensions) const; + + QString m_searchRoot; + + QLineEdit *m_searchEdit = nullptr; + QCheckBox *m_chkCase = nullptr; + QCheckBox *m_chkWord = nullptr; + QCheckBox *m_chkRegex = nullptr; + QLineEdit *m_filterEdit = nullptr; // Dateiendungen-Filter + QPushButton *m_btnSearch = nullptr; + QPushButton *m_btnClose = nullptr; + QLabel *m_statusLabel = nullptr; + QTreeWidget *m_results = nullptr; + QProgressBar *m_progress = nullptr; + + QFutureWatcher> *m_watcher = nullptr; +}; diff --git a/src/barecode/src/editor/LineNumberArea.cpp b/src/barecode/src/editor/LineNumberArea.cpp new file mode 100644 index 0000000..44ef836 --- /dev/null +++ b/src/barecode/src/editor/LineNumberArea.cpp @@ -0,0 +1,18 @@ +#include "LineNumberArea.h" +#include "CodeEditor.h" + +LineNumberArea::LineNumberArea(CodeEditor *editor) + : QWidget(editor) + , m_codeEditor(editor) +{ +} + +QSize LineNumberArea::sizeHint() const +{ + return QSize(m_codeEditor->lineNumberAreaWidth(), 0); +} + +void LineNumberArea::paintEvent(QPaintEvent *event) +{ + m_codeEditor->lineNumberAreaPaintEvent(event); +} diff --git a/src/barecode/src/editor/LineNumberArea.h b/src/barecode/src/editor/LineNumberArea.h new file mode 100644 index 0000000..1a6963a --- /dev/null +++ b/src/barecode/src/editor/LineNumberArea.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class CodeEditor; + +// --------------------------------------------------------------------------- +// LineNumberArea – Thin widget painted on the left side of the CodeEditor. +// Painted by CodeEditor::lineNumberAreaPaintEvent(). +// --------------------------------------------------------------------------- +class LineNumberArea : public QWidget +{ + Q_OBJECT + +public: + explicit LineNumberArea(CodeEditor *editor); + + QSize sizeHint() const override; + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + CodeEditor *m_codeEditor; +}; diff --git a/src/barecode/src/editor/SearchPanel.cpp b/src/barecode/src/editor/SearchPanel.cpp new file mode 100644 index 0000000..39704f6 --- /dev/null +++ b/src/barecode/src/editor/SearchPanel.cpp @@ -0,0 +1,492 @@ +#include "SearchPanel.h" +#include "CodeEditor.h" + +#include +#include +#include +#include +#include +#include + +SearchPanel::SearchPanel(QWidget *parent) + : QWidget(parent) +{ + setupUi(); + hide(); +} + +// --------------------------------------------------------------------------- +// UI +// --------------------------------------------------------------------------- +void SearchPanel::setupUi() +{ + m_grid = new QGridLayout(this); + m_grid->setContentsMargins(6, 4, 6, 4); + m_grid->setSpacing(4); + + // ---- Row 0: Suchen ---- + m_searchEdit = new QLineEdit(this); + m_searchEdit->setPlaceholderText(tr("Suchen…")); + m_searchEdit->setClearButtonEnabled(true); + + m_btnPrev = new QPushButton(tr("▲"), this); + m_btnNext = new QPushButton(tr("▼"), this); + m_btnPrev->setFixedWidth(28); + m_btnNext->setFixedWidth(28); + m_btnPrev->setToolTip(tr("Vorheriger Treffer (Shift+F3)")); + m_btnNext->setToolTip(tr("Nächster Treffer (F3)")); + + m_matchLabel = new QLabel(this); + m_matchLabel->setMinimumWidth(80); + + m_btnClose = new QPushButton(tr("✕"), this); + m_btnClose->setFixedWidth(24); + m_btnClose->setToolTip(tr("Schließen (Esc)")); + m_btnClose->setFlat(true); + + QHBoxLayout *searchRow = new QHBoxLayout(); + searchRow->addWidget(new QLabel(tr("Suchen:"), this)); + searchRow->addWidget(m_searchEdit, 1); + searchRow->addWidget(m_btnPrev); + searchRow->addWidget(m_btnNext); + searchRow->addWidget(m_matchLabel); + searchRow->addWidget(m_btnClose); + m_grid->addLayout(searchRow, 0, 0); + + // ---- Row 1: Ersetzen ---- + m_replaceEdit = new QLineEdit(this); + m_replaceEdit->setPlaceholderText(tr("Ersetzen durch…")); + m_replaceEdit->setClearButtonEnabled(true); + + m_btnReplace = new QPushButton(tr("Ersetzen"), this); + m_btnReplaceAll = new QPushButton(tr("Alle ersetzen"), this); + m_btnReplaceSelection = new QPushButton(tr("In Auswahl ersetzen"), this); + + QHBoxLayout *replaceRow = new QHBoxLayout(); + replaceRow->addWidget(new QLabel(tr("Ersetzen:"), this)); + replaceRow->addWidget(m_replaceEdit, 1); + replaceRow->addWidget(m_btnReplace); + replaceRow->addWidget(m_btnReplaceAll); + replaceRow->addWidget(m_btnReplaceSelection); + m_grid->addLayout(replaceRow, 1, 0); + + // ---- Row 2: Optionen ---- + m_chkCase = new QCheckBox(tr("Groß-/Kleinschreibung"), this); + m_chkWord = new QCheckBox(tr("Ganzes Wort"), this); + m_chkRegex = new QCheckBox(tr("Regulärer Ausdruck"), this); + + QHBoxLayout *optRow = new QHBoxLayout(); + optRow->addWidget(m_chkCase); + optRow->addWidget(m_chkWord); + optRow->addWidget(m_chkRegex); + optRow->addStretch(); + m_grid->addLayout(optRow, 2, 0); + + // ---- Connections ---- + connect(m_searchEdit, &QLineEdit::textChanged, + this, &SearchPanel::onSearchTextChanged); + + connect(m_searchEdit, &QLineEdit::returnPressed, + this, &SearchPanel::findNext); + + connect(m_btnNext, &QPushButton::clicked, this, &SearchPanel::findNext); + connect(m_btnPrev, &QPushButton::clicked, this, &SearchPanel::findPrevious); + + connect(m_btnReplace, &QPushButton::clicked, this, &SearchPanel::replaceCurrent); + connect(m_btnReplaceAll, &QPushButton::clicked, this, &SearchPanel::replaceAll); + connect(m_btnReplaceSelection, &QPushButton::clicked, this, &SearchPanel::replaceInSelection); + + connect(m_btnClose, &QPushButton::clicked, this, &SearchPanel::onCloseClicked); + + connect(m_chkCase, &QCheckBox::toggled, this, &SearchPanel::onOptionChanged); + connect(m_chkWord, &QCheckBox::toggled, this, &SearchPanel::onOptionChanged); + connect(m_chkRegex, &QCheckBox::toggled, this, &SearchPanel::onOptionChanged); +} + +// --------------------------------------------------------------------------- +// Public interface +// --------------------------------------------------------------------------- +void SearchPanel::setEditor(CodeEditor *editor) +{ + clearHighlights(); + m_editor = editor; +} + +void SearchPanel::activate() +{ + show(); + m_searchEdit->setFocus(); + m_searchEdit->selectAll(); + + // Pre-fill with selected text if short enough + if (m_editor) + { + const QString sel = m_editor->textCursor().selectedText(); + if (!sel.isEmpty() && !sel.contains('\n') && sel.length() < 200) + { + m_searchEdit->setText(sel); + } + } + + updateMatchLabel(); +} + +// --------------------------------------------------------------------------- +// Find helpers +// --------------------------------------------------------------------------- +QTextDocument::FindFlags SearchPanel::buildFindFlags(bool backwards) const +{ + QTextDocument::FindFlags flags; + if (backwards) { flags |= QTextDocument::FindBackward; } + if (m_chkCase->isChecked()) { flags |= QTextDocument::FindCaseSensitively; } + if (m_chkWord->isChecked()) { flags |= QTextDocument::FindWholeWords; } + return flags; +} + +bool SearchPanel::performFind(bool backwards) +{ + if (!m_editor || m_searchEdit->text().isEmpty()) + { + return false; + } + + const QTextDocument::FindFlags flags = buildFindFlags(backwards); + bool found = false; + + if (m_chkRegex->isChecked()) + { + QRegularExpression re(m_searchEdit->text()); + if (m_chkCase->isChecked()) + { + re.setPatternOptions(QRegularExpression::NoPatternOption); + } + else + { + re.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + } + found = m_editor->find(re, flags); + + // Wrap around + if (!found) + { + QTextCursor c = m_editor->textCursor(); + c.movePosition(backwards ? QTextCursor::End : QTextCursor::Start); + m_editor->setTextCursor(c); + found = m_editor->find(re, flags); + } + } + else + { + found = m_editor->find(m_searchEdit->text(), flags); + + // Wrap around + if (!found) + { + QTextCursor c = m_editor->textCursor(); + c.movePosition(backwards ? QTextCursor::End : QTextCursor::Start); + m_editor->setTextCursor(c); + found = m_editor->find(m_searchEdit->text(), flags); + } + } + + return found; +} + +void SearchPanel::highlightAllMatches() +{ + if (!m_editor) + { + return; + } + + QList extras; + + const QString needle = m_searchEdit->text(); + if (needle.isEmpty()) + { + m_editor->setExtraSelections(extras); + return; + } + + QTextCharFormat fmt; + fmt.setBackground(QColor("#3a3a00")); + fmt.setForeground(QColor("#ffff80")); + + QTextDocument *doc = m_editor->document(); + QTextCursor cursor(doc); + + const QTextDocument::FindFlags flags = buildFindFlags(false); + + while (true) + { + if (m_chkRegex->isChecked()) + { + QRegularExpression re(needle); + if (!m_chkCase->isChecked()) + { + re.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + } + cursor = doc->find(re, cursor, flags); + } + else + { + cursor = doc->find(needle, cursor, flags); + } + + if (cursor.isNull()) + { + break; + } + + QTextEdit::ExtraSelection sel; + sel.cursor = cursor; + sel.format = fmt; + extras.append(sel); + } + + m_editor->setExtraSelections(extras); +} + +void SearchPanel::clearHighlights() +{ + if (m_editor) + { + m_editor->setExtraSelections({}); + } +} + +void SearchPanel::updateMatchLabel() +{ + if (!m_editor || m_searchEdit->text().isEmpty()) + { + m_matchLabel->setText(QString()); + return; + } + + // Count total matches + int count = 0; + QTextDocument *doc = m_editor->document(); + QTextCursor cursor(doc); + const QTextDocument::FindFlags flags = buildFindFlags(false); + const QString needle = m_searchEdit->text(); + + while (true) + { + if (m_chkRegex->isChecked()) + { + QRegularExpression re(needle); + if (!m_chkCase->isChecked()) + { + re.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + } + cursor = doc->find(re, cursor, flags); + } + else + { + cursor = doc->find(needle, cursor, flags); + } + + if (cursor.isNull()) + { + break; + } + ++count; + } + + if (count == 0) + { + m_matchLabel->setText(tr("Kein Treffer")); + m_matchLabel->setStyleSheet("color: #cc4444;"); + } + else + { + m_matchLabel->setText(tr("%1 Treffer").arg(count)); + m_matchLabel->setStyleSheet(QString()); + } +} + +// --------------------------------------------------------------------------- +// Public slots +// --------------------------------------------------------------------------- +void SearchPanel::findNext() +{ + performFind(false); +} + +void SearchPanel::findPrevious() +{ + performFind(true); +} + +void SearchPanel::replaceCurrent() +{ + if (!m_editor) + { + return; + } + + QTextCursor cursor = m_editor->textCursor(); + + // If current selection matches the search term, replace it + // Otherwise just find the next occurrence first + const bool hasMatch = !cursor.selectedText().isEmpty(); + if (!hasMatch) + { + performFind(false); + return; + } + + cursor.insertText(m_replaceEdit->text()); + + // Move to next match + performFind(false); + updateMatchLabel(); + highlightAllMatches(); +} + +void SearchPanel::replaceAll() +{ + if (!m_editor || m_searchEdit->text().isEmpty()) + { + return; + } + + QTextDocument *doc = m_editor->document(); + QTextCursor cursor(doc); + cursor.beginEditBlock(); + + int count = 0; + const QTextDocument::FindFlags flags = buildFindFlags(false); + const QString needle = m_searchEdit->text(); + const QString replacement = m_replaceEdit->text(); + + while (true) + { + if (m_chkRegex->isChecked()) + { + QRegularExpression re(needle); + if (!m_chkCase->isChecked()) + { + re.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + } + cursor = doc->find(re, cursor, flags); + } + else + { + cursor = doc->find(needle, cursor, flags); + } + + if (cursor.isNull()) + { + break; + } + + cursor.insertText(replacement); + ++count; + } + + cursor.endEditBlock(); + + updateMatchLabel(); + clearHighlights(); + + QMessageBox::information(this, tr("Alle ersetzen"), + tr("%1 Ersetzung(en) durchgeführt.").arg(count)); +} + +void SearchPanel::replaceInSelection() +{ + if (!m_editor || m_searchEdit->text().isEmpty()) + { + return; + } + + QTextCursor selCursor = m_editor->textCursor(); + if (!selCursor.hasSelection()) + { + QMessageBox::information(this, tr("In Auswahl ersetzen"), + tr("Es ist kein Text ausgewählt.")); + return; + } + + // Work only within the selected region + const int selStart = selCursor.selectionStart(); + const int selEnd = selCursor.selectionEnd(); + + QTextDocument *doc = m_editor->document(); + QTextCursor cursor(doc); + cursor.setPosition(selStart); + cursor.beginEditBlock(); + + int count = 0; + int offset = 0; // Replacement may be longer/shorter than search term + const QTextDocument::FindFlags flags = buildFindFlags(false); + const QString needle = m_searchEdit->text(); + const QString replacement = m_replaceEdit->text(); + + while (true) + { + if (m_chkRegex->isChecked()) + { + QRegularExpression re(needle); + if (!m_chkCase->isChecked()) + { + re.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + } + cursor = doc->find(re, cursor, flags); + } + else + { + cursor = doc->find(needle, cursor, flags); + } + + if (cursor.isNull()) + { + break; + } + + // Stop if we've left the original selection + if (cursor.selectionEnd() > selEnd + offset) + { + break; + } + + offset += replacement.length() - cursor.selectedText().length(); + cursor.insertText(replacement); + ++count; + } + + cursor.endEditBlock(); + + updateMatchLabel(); + clearHighlights(); + + QMessageBox::information(this, tr("In Auswahl ersetzen"), + tr("%1 Ersetzung(en) in der Auswahl durchgeführt.").arg(count)); +} + +// --------------------------------------------------------------------------- +// Private slots +// --------------------------------------------------------------------------- +void SearchPanel::onSearchTextChanged(const QString &/*text*/) +{ + highlightAllMatches(); + updateMatchLabel(); +} + +void SearchPanel::onOptionChanged() +{ + highlightAllMatches(); + updateMatchLabel(); +} + +void SearchPanel::onCloseClicked() +{ + clearHighlights(); + m_matchLabel->setText(QString()); + hide(); + if (m_editor) + { + m_editor->setFocus(); + } +} diff --git a/src/barecode/src/editor/SearchPanel.h b/src/barecode/src/editor/SearchPanel.h new file mode 100644 index 0000000..b3e1158 --- /dev/null +++ b/src/barecode/src/editor/SearchPanel.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +class CodeEditor; + +// --------------------------------------------------------------------------- +// SearchPanel – Collapsible find/replace bar that operates on a CodeEditor. +// +// Capabilities: +// • Nächsten / Vorherigen Treffer suchen +// • Einzeln ersetzen +// • Alle ersetzen +// • Nur in Auswahl ersetzen +// • Optionen: Groß-/Kleinschreibung, Ganzes Wort, Reguläre Ausdrücke +// --------------------------------------------------------------------------- +class SearchPanel : public QWidget +{ + Q_OBJECT + +public: + explicit SearchPanel(QWidget *parent = nullptr); + + // Must be called whenever the active editor changes + void setEditor(CodeEditor *editor); + + // Toggle visibility and focus the search field + void activate(); + +public slots: + void findNext(); + void findPrevious(); + void replaceCurrent(); + void replaceAll(); + void replaceInSelection(); + +private slots: + void onSearchTextChanged(const QString &text); + void onOptionChanged(); // Für Checkbox-Signale (bool-Parameter wird ignoriert) + void onCloseClicked(); + +private: + void setupUi(); + + QTextDocument::FindFlags buildFindFlags(bool backwards = false) const; + bool performFind(bool backwards = false); + void highlightAllMatches(); + void clearHighlights(); + void updateMatchLabel(); + + CodeEditor *m_editor = nullptr; + + // Search row + QLineEdit *m_searchEdit = nullptr; + QPushButton *m_btnPrev = nullptr; + QPushButton *m_btnNext = nullptr; + QLabel *m_matchLabel = nullptr; + QPushButton *m_btnClose = nullptr; + + // Replace row + QLineEdit *m_replaceEdit = nullptr; + QPushButton *m_btnReplace = nullptr; + QPushButton *m_btnReplaceAll = nullptr; + QPushButton *m_btnReplaceSelection = nullptr; + + // Options row + QCheckBox *m_chkCase = nullptr; + QCheckBox *m_chkWord = nullptr; + QCheckBox *m_chkRegex = nullptr; + + QGridLayout *m_grid = nullptr; +}; diff --git a/src/barecode/src/editor/SignatureHelper.cpp b/src/barecode/src/editor/SignatureHelper.cpp new file mode 100644 index 0000000..c84f723 --- /dev/null +++ b/src/barecode/src/editor/SignatureHelper.cpp @@ -0,0 +1,222 @@ +#include "SignatureHelper.h" +#include "SignatureTooltip.h" +#include "CodeEditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +SignatureHelper::SignatureHelper(CodeEditor *editor) + : QObject(editor) + , m_editor(editor) +{ + // Tooltip als Kind des Viewports — bleibt im Fenster + m_tooltip = new SignatureTooltip(editor->window()); + + loadDatabase(); + + connect(m_editor, &CodeEditor::cursorPositionChanged, + this, &SignatureHelper::onCursorPositionChanged); +} + +// --------------------------------------------------------------------------- +// Datenbank laden +// --------------------------------------------------------------------------- +void SignatureHelper::loadDatabase() +{ + QFile f(":/php_functions.json"); + if (!f.open(QIODevice::ReadOnly)) + { + return; + } + + const QJsonDocument doc = QJsonDocument::fromJson(f.readAll()); + if (!doc.isArray()) + { + return; + } + + for (const QJsonValue &val : doc.array()) + { + const QJsonObject obj = val.toObject(); + const QString name = obj["name"].toString(); + if (name.isEmpty()) + { + continue; + } + + FunctionInfo info; + info.signature = obj["signature"].toString(); + info.description = obj["desc"].toString(); + m_functions.insert(name.toLower(), info); + } +} + +// --------------------------------------------------------------------------- +// Cursor-Bewegung auswerten +// --------------------------------------------------------------------------- +void SignatureHelper::onCursorPositionChanged() +{ + const QTextCursor cursor = m_editor->textCursor(); + const QString block = cursor.block().text(); + const int col = cursor.columnNumber(); + const QString leftText = block.left(col); + + const QString funcName = extractFunctionName(leftText); + + if (funcName.isEmpty()) + { + m_tooltip->hide(); + return; + } + + // Klammern zählen — wenn alle geschlossen, Tooltip ausblenden + if (countOpenParens(leftText) <= 0) + { + m_tooltip->hide(); + return; + } + + const QString key = funcName.toLower(); + if (!m_functions.contains(key)) + { + m_tooltip->hide(); + return; + } + + const FunctionInfo &info = m_functions[key]; + + // Position unter dem Cursor berechnen + const QRect cursorRect = m_editor->cursorRect(cursor); + const QPoint globalPos = m_editor->viewport()->mapToGlobal( + QPoint(cursorRect.left(), cursorRect.bottom() + 4) + ); + + m_tooltip->showSignature(info.signature, info.description, globalPos); +} + +// --------------------------------------------------------------------------- +// Funktionsnamen links vor der öffnenden Klammer extrahieren +// --------------------------------------------------------------------------- +QString SignatureHelper::extractFunctionName(const QString &text) const +{ + // Wir suchen das letzte '(' das zu einem Funktionsnamen gehört. + // Dabei müssen wir verschachtelte Klammern korrekt behandeln. + int depth = 0; + int openPos = -1; + + for (int i = text.length() - 1; i >= 0; --i) + { + const QChar ch = text[i]; + if (ch == ')') + { + ++depth; + } + else if (ch == '(') + { + if (depth == 0) + { + openPos = i; + break; + } + --depth; + } + } + + if (openPos <= 0) + { + return QString(); + } + + // Funktionsnamen direkt links von '(' lesen + int end = openPos - 1; + + // Leerzeichen überspringen + while (end >= 0 && text[end].isSpace()) + { + --end; + } + + if (end < 0) + { + return QString(); + } + + // Bezeichner-Zeichen sammeln (Buchstaben, Ziffern, _, :, \) + int start = end; + while (start > 0 && + (text[start - 1].isLetterOrNumber() || + text[start - 1] == '_' || + text[start - 1] == ':' || + text[start - 1] == '\\')) + { + --start; + } + + const QString name = text.mid(start, end - start + 1); + + // Schlüsselwörter und leere Namen ausschließen + static const QStringList keywords = { + "if", "else", "elseif", "while", "for", "foreach", + "switch", "match", "catch", "function", "fn" + }; + + if (name.isEmpty() || keywords.contains(name.toLower())) + { + return QString(); + } + + // Nur den letzten Teil nach :: oder -> nehmen + const int colonPos = name.lastIndexOf("::"); + const int arrowPos = name.lastIndexOf("->"); + const int backslashPos = name.lastIndexOf("\\"); + const int splitPos = qMax(backslashPos, qMax(colonPos, arrowPos)); + + if (splitPos >= 0) + { + return name.mid(splitPos + (name[splitPos] == ':' ? 2 : (name[splitPos] == '\\' ? 1 : 2))); + } + + return name; +} + +// --------------------------------------------------------------------------- +// Offene Klammern zählen +// --------------------------------------------------------------------------- +int SignatureHelper::countOpenParens(const QString &text) const +{ + int depth = 0; + bool inString = false; + QChar stringChar; + + for (int i = 0; i < text.length(); ++i) + { + const QChar ch = text[i]; + + // Einfache String-Erkennung (kein vollständiger PHP-Parser) + if (!inString && (ch == '\'' || ch == '"')) + { + inString = true; + stringChar = ch; + continue; + } + if (inString) + { + if (ch == stringChar && (i == 0 || text[i - 1] != '\\')) + { + inString = false; + } + continue; + } + + if (ch == '(') { ++depth; } + else if (ch == ')') { --depth; } + } + + return depth; +} diff --git a/src/barecode/src/editor/SignatureHelper.h b/src/barecode/src/editor/SignatureHelper.h new file mode 100644 index 0000000..9b1ec89 --- /dev/null +++ b/src/barecode/src/editor/SignatureHelper.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +class CodeEditor; +class SignatureTooltip; + +// --------------------------------------------------------------------------- +// SignatureHelper – Lädt die PHP-Funktionsdatenbank und zeigt beim Tippen +// automatisch die passende Funktionssignatur als Tooltip. +// +// Logik: +// • Bei jedem Tastendruck: Text links vom Cursor analysieren +// • Wenn "funktionsname(" erkannt wird → Tooltip anzeigen +// • Wenn ")" die öffnende Klammer schließt → Tooltip verstecken +// • Wenn Cursor sich weg bewegt → Tooltip verstecken +// --------------------------------------------------------------------------- +class SignatureHelper : public QObject +{ + Q_OBJECT + +public: + explicit SignatureHelper(CodeEditor *editor); + +private slots: + void onCursorPositionChanged(); + +private: + struct FunctionInfo + { + QString signature; + QString description; + }; + + void loadDatabase(); + void loadProjectFunctions(); + + // Extrahiert den Funktionsnamen direkt links vor dem letzten '(' + // Gibt leeren String zurück wenn kein Kontext gefunden + QString extractFunctionName(const QString &textUpToCursor) const; + + // Zählt offene Klammern — bei 0 ist der Aufruf abgeschlossen + int countOpenParens(const QString &textUpToCursor) const; + + CodeEditor *m_editor = nullptr; + SignatureTooltip *m_tooltip = nullptr; + + QHash m_functions; // name → info +}; diff --git a/src/barecode/src/editor/SignatureTooltip.cpp b/src/barecode/src/editor/SignatureTooltip.cpp new file mode 100644 index 0000000..3ac4099 --- /dev/null +++ b/src/barecode/src/editor/SignatureTooltip.cpp @@ -0,0 +1,91 @@ +#include "SignatureTooltip.h" + +#include +#include + +SignatureTooltip::SignatureTooltip(QWidget *parent) + : QFrame(parent, Qt::ToolTip | Qt::FramelessWindowHint) +{ + setFrameShape(QFrame::StyledPanel); + setFrameShadow(QFrame::Raised); + setAttribute(Qt::WA_ShowWithoutActivating); + + // Dezentes Styling passend zu Hell- und Dunkeltheme + setStyleSheet( + "SignatureTooltip {" + " background: palette(toolTipBase);" + " border: 1px solid palette(mid);" + " border-radius: 4px;" + " padding: 4px;" + "}" + ); + + m_layout = new QVBoxLayout(this); + m_layout->setContentsMargins(8, 6, 8, 6); + m_layout->setSpacing(3); + + // Signatur — Monospace, deutlich hervorgehoben + m_sigLabel = new QLabel(this); + m_sigLabel->setTextFormat(Qt::PlainText); + m_sigLabel->setWordWrap(false); + QFont sigFont = m_sigLabel->font(); + sigFont.setFamily("Monospace"); + sigFont.setStyleHint(QFont::Monospace); + sigFont.setPointSize(sigFont.pointSize()); + m_sigLabel->setFont(sigFont); + m_sigLabel->setStyleSheet("color: palette(toolTipText); font-weight: bold;"); + m_layout->addWidget(m_sigLabel); + + // Beschreibung — kleiner, gedimmt + m_descLabel = new QLabel(this); + m_descLabel->setTextFormat(Qt::PlainText); + m_descLabel->setWordWrap(false); + m_descLabel->setStyleSheet("color: palette(mid);"); + QFont descFont = m_descLabel->font(); + descFont.setPointSize(qMax(descFont.pointSize() - 1, 8)); + m_descLabel->setFont(descFont); + m_layout->addWidget(m_descLabel); + + hide(); +} + +void SignatureTooltip::showSignature(const QString &signature, + const QString &description, + const QPoint &globalPos) +{ + m_sigLabel->setText(signature); + + if (description.isEmpty()) + { + m_descLabel->hide(); + } + else + { + m_descLabel->setText(description); + m_descLabel->show(); + } + + adjustSize(); + + // Position so wählen dass das Popup nicht aus dem Bildschirm ragt + QPoint pos = globalPos; + const QRect screen = QApplication::primaryScreen()->availableGeometry(); + + if (pos.x() + width() > screen.right()) + { + pos.setX(screen.right() - width() - 4); + } + if (pos.y() + height() > screen.bottom()) + { + pos.setY(globalPos.y() - height() - 24); + } + + move(pos); + show(); + raise(); +} + +void SignatureTooltip::hide() +{ + QFrame::hide(); +} diff --git a/src/barecode/src/editor/SignatureTooltip.h b/src/barecode/src/editor/SignatureTooltip.h new file mode 100644 index 0000000..110062f --- /dev/null +++ b/src/barecode/src/editor/SignatureTooltip.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// SignatureTooltip – Schwebendes Popup das die Signatur einer Funktion zeigt. +// Erscheint unter dem Cursor, verschwindet automatisch wenn der Nutzer +// die Klammer schließt oder den Kontext verlässt. +// --------------------------------------------------------------------------- +class SignatureTooltip : public QFrame +{ + Q_OBJECT + +public: + explicit SignatureTooltip(QWidget *parent = nullptr); + + void showSignature(const QString &signature, + const QString &description, + const QPoint &globalPos); + void hide(); + +private: + QVBoxLayout *m_layout = nullptr; + QLabel *m_sigLabel = nullptr; + QLabel *m_descLabel = nullptr; +}; diff --git a/src/barecode/src/filetree/CMakeLists.txt b/src/barecode/src/filetree/CMakeLists.txt new file mode 100644 index 0000000..f269f5e --- /dev/null +++ b/src/barecode/src/filetree/CMakeLists.txt @@ -0,0 +1,17 @@ +set(FILETREE_SOURCES + FileTreePanel.cpp + FileTreePanel.h +) + +add_library(BareCode_FileTree STATIC ${FILETREE_SOURCES}) + +target_link_libraries(BareCode_FileTree PUBLIC + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +target_include_directories(BareCode_FileTree PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) diff --git a/src/barecode/src/filetree/FileTreePanel.cpp b/src/barecode/src/filetree/FileTreePanel.cpp new file mode 100644 index 0000000..1ed0221 --- /dev/null +++ b/src/barecode/src/filetree/FileTreePanel.cpp @@ -0,0 +1,259 @@ +#include "FileTreePanel.h" + +#include +#include +#include +#include +#include +#include + +FileTreePanel::FileTreePanel(QWidget *parent) + : QWidget(parent) +{ + setupUi(); +} + +// --------------------------------------------------------------------------- +// Setup +// --------------------------------------------------------------------------- +void FileTreePanel::setupUi() +{ + m_layout = new QVBoxLayout(this); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setSpacing(0); + + // Small header label showing the project name + m_label = new QLabel(tr("Kein Projekt geöffnet"), this); + m_label->setContentsMargins(6, 4, 6, 4); + m_label->setStyleSheet("font-weight: bold; background: palette(mid);"); + m_label->setWordWrap(true); + m_layout->addWidget(m_label); + + // File system model – show only the project subtree + m_model = new QFileSystemModel(this); + m_model->setReadOnly(false); + m_model->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); + + // Tree view + m_tree = new QTreeView(this); + m_tree->setModel(m_model); + m_tree->setAnimated(true); + m_tree->setIndentation(16); + m_tree->setSortingEnabled(true); + m_tree->sortByColumn(0, Qt::AscendingOrder); + m_tree->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tree->setHeaderHidden(true); + m_tree->setContextMenuPolicy(Qt::CustomContextMenu); + + // Hide all columns except the file name + for (int col = 1; col < m_model->columnCount(); ++col) + { + m_tree->hideColumn(col); + } + + m_layout->addWidget(m_tree); + + connect(m_tree, &QTreeView::activated, + this, &FileTreePanel::onItemActivated); + + connect(m_tree, &QTreeView::customContextMenuRequested, + this, &FileTreePanel::onContextMenuRequested); +} + +// --------------------------------------------------------------------------- +// Public interface +// --------------------------------------------------------------------------- +void FileTreePanel::setRootPath(const QString &path) +{ + const QModelIndex root = m_model->setRootPath(path); + m_tree->setRootIndex(root); + + const QString projectName = QDir(path).dirName(); + m_label->setText(projectName.isEmpty() ? path : projectName); +} + +void FileTreePanel::clearRoot() +{ + m_model->setRootPath(QString()); + m_tree->setRootIndex(QModelIndex()); + m_label->setText(tr("Kein Projekt geöffnet")); +} + +void FileTreePanel::triggerNewFile() +{ + onNewFile(); +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- +QString FileTreePanel::selectedDirectory() const +{ + const QModelIndex index = m_tree->currentIndex(); + if (!index.isValid()) + { + return m_model->rootPath(); + } + + const QString path = m_model->filePath(index); + const QFileInfo info(path); + return info.isDir() ? path : info.absolutePath(); +} + +// --------------------------------------------------------------------------- +// Slots +// --------------------------------------------------------------------------- +void FileTreePanel::onItemActivated(const QModelIndex &index) +{ + const QString path = m_model->filePath(index); + const QFileInfo info(path); + + if (info.isFile()) + { + emit fileActivated(path); + } +} + +void FileTreePanel::onContextMenuRequested(const QPoint &pos) +{ + QMenu menu(this); + + QAction *actNewFile = menu.addAction(tr("Neue Datei…")); + QAction *actNewFolder = menu.addAction(tr("Neuer Ordner…")); + menu.addSeparator(); + QAction *actDelete = menu.addAction(tr("Löschen")); + + // Disable delete if nothing is selected + const QModelIndex index = m_tree->indexAt(pos); + actDelete->setEnabled(index.isValid()); + + QAction *chosen = menu.exec(m_tree->viewport()->mapToGlobal(pos)); + + if (chosen == actNewFile) + { + onNewFile(); + } + else if (chosen == actNewFolder) + { + onNewFolder(); + } + else if (chosen == actDelete) + { + onDeleteEntry(); + } +} + +void FileTreePanel::onNewFile() +{ + const QString dir = selectedDirectory(); + if (dir.isEmpty()) + { + return; + } + + bool ok = false; + const QString name = QInputDialog::getText( + this, + tr("Neue Datei"), + tr("Dateiname:"), + QLineEdit::Normal, + QString(), + &ok + ); + + if (!ok || name.trimmed().isEmpty()) + { + return; + } + + const QString filePath = QDir(dir).filePath(name.trimmed()); + + if (QFile::exists(filePath)) + { + QMessageBox::warning(this, tr("Neue Datei"), + tr("Eine Datei mit diesem Namen existiert bereits:\n%1").arg(filePath)); + return; + } + + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly)) + { + QMessageBox::critical(this, tr("Neue Datei"), + tr("Datei konnte nicht angelegt werden:\n%1").arg(filePath)); + return; + } + file.close(); + + emit fileCreated(filePath); + + // Select the new file in the tree + const QModelIndex newIndex = m_model->index(filePath); + m_tree->setCurrentIndex(newIndex); + m_tree->scrollTo(newIndex); +} + +void FileTreePanel::onNewFolder() +{ + const QString dir = selectedDirectory(); + if (dir.isEmpty()) + { + return; + } + + bool ok = false; + const QString name = QInputDialog::getText( + this, + tr("Neuer Ordner"), + tr("Ordnername:"), + QLineEdit::Normal, + QString(), + &ok + ); + + if (!ok || name.trimmed().isEmpty()) + { + return; + } + + if (!QDir(dir).mkdir(name.trimmed())) + { + QMessageBox::critical(this, tr("Neuer Ordner"), + tr("Ordner konnte nicht angelegt werden:\n%1") + .arg(QDir(dir).filePath(name.trimmed()))); + } +} + +void FileTreePanel::onDeleteEntry() +{ + const QModelIndex index = m_tree->currentIndex(); + if (!index.isValid()) + { + return; + } + + const QString path = m_model->filePath(index); + const QFileInfo info(path); + const QString what = info.isDir() ? tr("Ordner") : tr("Datei"); + + const auto answer = QMessageBox::question( + this, + tr("%1 löschen").arg(what), + tr("%1 wirklich löschen?\n%2").arg(what, path), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No + ); + + if (answer != QMessageBox::Yes) + { + return; + } + + if (info.isDir()) + { + QDir(path).removeRecursively(); + } + else + { + QFile::remove(path); + } +} diff --git a/src/barecode/src/filetree/FileTreePanel.h b/src/barecode/src/filetree/FileTreePanel.h new file mode 100644 index 0000000..32c5c9e --- /dev/null +++ b/src/barecode/src/filetree/FileTreePanel.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// FileTreePanel – Left panel showing the project directory tree. +// Emits fileActivated(path) when the user double-clicks a file. +// Supports creating new files/folders via context menu. +// --------------------------------------------------------------------------- +class FileTreePanel : public QWidget +{ + Q_OBJECT + +public: + explicit FileTreePanel(QWidget *parent = nullptr); + + void setRootPath(const QString &path); + void clearRoot(); + void triggerNewFile(); // Called from MainWindow menu action + +signals: + void fileActivated(const QString &filePath); + void fileCreated(const QString &filePath); + +private slots: + void onItemActivated(const QModelIndex &index); + void onContextMenuRequested(const QPoint &pos); + void onNewFile(); + void onNewFolder(); + void onDeleteEntry(); + +private: + void setupUi(); + + // Returns the directory of the currently selected item + QString selectedDirectory() const; + + QVBoxLayout *m_layout = nullptr; + QLabel *m_label = nullptr; + QTreeView *m_tree = nullptr; + QFileSystemModel *m_model = nullptr; +}; diff --git a/src/barecode/src/highlighter/CMakeLists.txt b/src/barecode/src/highlighter/CMakeLists.txt new file mode 100644 index 0000000..3cbc2eb --- /dev/null +++ b/src/barecode/src/highlighter/CMakeLists.txt @@ -0,0 +1,19 @@ +set(HIGHLIGHTER_SOURCES + SyntaxHighlighter.cpp + SyntaxHighlighter.h + HighlighterFactory.cpp + HighlighterFactory.h +) + +add_library(BareCode_Highlighter STATIC ${HIGHLIGHTER_SOURCES}) + +target_link_libraries(BareCode_Highlighter PUBLIC + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +target_include_directories(BareCode_Highlighter PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) diff --git a/src/barecode/src/highlighter/HighlighterFactory.cpp b/src/barecode/src/highlighter/HighlighterFactory.cpp new file mode 100644 index 0000000..250e3a2 --- /dev/null +++ b/src/barecode/src/highlighter/HighlighterFactory.cpp @@ -0,0 +1,45 @@ +#include "HighlighterFactory.h" + +#include +#include +#include + +SyntaxHighlighter *HighlighterFactory::createForFile(const QString &filePath, + QTextDocument *document) +{ + // Erweiterung → Highlighter-Fabrik + // Neue Sprache hinzufügen: einfach einen Eintrag ergänzen. + static const QHash> registry = + { + // C / C++ + { "c", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "cc", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "cpp", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "cxx", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "h", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "hpp", [](QTextDocument *d) { return new CppHighlighter(d); } }, + { "hxx", [](QTextDocument *d) { return new CppHighlighter(d); } }, + + // CSS + { "css", [](QTextDocument *d) { return new CssHighlighter(d); } }, + + // HTML / Templates + { "html", [](QTextDocument *d) { return new HtmlHighlighter(d); } }, + { "htm", [](QTextDocument *d) { return new HtmlHighlighter(d); } }, + { "xhtml",[](QTextDocument *d) { return new HtmlHighlighter(d); } }, + + // PHP (HTML + eingebettetes PHP) + { "php", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "phtml",[](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "php3", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "php4", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "php5", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "php7", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + { "php8", [](QTextDocument *d) { return new PhpHighlighter(d); } }, + }; + + const QString ext = QFileInfo(filePath).suffix().toLower(); + const auto it = registry.find(ext); + + return (it != registry.end()) ? it.value()(document) : nullptr; +} diff --git a/src/barecode/src/highlighter/HighlighterFactory.h b/src/barecode/src/highlighter/HighlighterFactory.h new file mode 100644 index 0000000..8392758 --- /dev/null +++ b/src/barecode/src/highlighter/HighlighterFactory.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include "SyntaxHighlighter.h" + +// --------------------------------------------------------------------------- +// HighlighterFactory – Maps file extensions to the correct highlighter. +// To add a new language, register it in HighlighterFactory.cpp. +// --------------------------------------------------------------------------- +class HighlighterFactory +{ +public: + // Creates and returns a highlighter for the given file path. + // Returns nullptr if no highlighter is registered for this file type. + static SyntaxHighlighter *createForFile(const QString &filePath, + QTextDocument *document); +}; diff --git a/src/barecode/src/highlighter/SyntaxHighlighter.cpp b/src/barecode/src/highlighter/SyntaxHighlighter.cpp new file mode 100644 index 0000000..2a93936 --- /dev/null +++ b/src/barecode/src/highlighter/SyntaxHighlighter.cpp @@ -0,0 +1,514 @@ +#include "SyntaxHighlighter.h" +#include + +// =========================================================================== +// SyntaxHighlighter – Basis +// =========================================================================== +SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) + : QSyntaxHighlighter(parent) +{ +} + +void SyntaxHighlighter::highlightBlock(const QString &text) +{ + for (const HighlightRule &rule : m_rules) + { + QRegularExpressionMatchIterator it = rule.pattern.globalMatch(text); + while (it.hasNext()) + { + QRegularExpressionMatch match = it.next(); + setFormat( + static_cast(match.capturedStart()), + static_cast(match.capturedLength()), + rule.format + ); + } + } + + if (!m_hasMultiLineComment) + { + return; + } + + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + { + QRegularExpressionMatch m = m_commentStartExpression.match(text); + startIndex = m.hasMatch() ? static_cast(m.capturedStart()) : -1; + } + + while (startIndex >= 0) + { + QRegularExpressionMatch endMatch = m_commentEndExpression.match(text, startIndex); + int commentLength = 0; + + if (endMatch.hasMatch()) + { + commentLength = static_cast(endMatch.capturedStart()) + - startIndex + + static_cast(endMatch.capturedLength()); + } + else + { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + + setFormat(startIndex, commentLength, m_multiLineCommentFormat); + + if (!endMatch.hasMatch()) + { + break; + } + + QRegularExpressionMatch nextStart = + m_commentStartExpression.match(text, startIndex + commentLength); + startIndex = nextStart.hasMatch() + ? static_cast(nextStart.capturedStart()) + : -1; + } +} + +// =========================================================================== +// CppHighlighter +// =========================================================================== +CppHighlighter::CppHighlighter(QTextDocument *parent) + : SyntaxHighlighter(parent) +{ + m_hasMultiLineComment = true; + + QTextCharFormat keywordFormat; + keywordFormat.setForeground(QColor("#569CD6")); + keywordFormat.setFontWeight(QFont::Bold); + + const QStringList keywords = { + "alignas","alignof","and","and_eq","asm","auto","bitand","bitor", + "bool","break","case","catch","char","char8_t","char16_t","char32_t", + "class","compl","concept","const","consteval","constexpr","constinit", + "const_cast","continue","co_await","co_return","co_yield","decltype", + "default","delete","do","double","dynamic_cast","else","enum", + "explicit","export","extern","false","float","for","friend","goto", + "if","inline","int","long","mutable","namespace","new","noexcept", + "not","not_eq","nullptr","operator","or","or_eq","private","protected", + "public","register","reinterpret_cast","requires","return","short", + "signed","sizeof","static","static_assert","static_cast","struct", + "switch","template","this","thread_local","throw","true","try", + "typedef","typeid","typename","union","unsigned","using","virtual", + "void","volatile","wchar_t","while","xor","xor_eq","override","final" + }; + + for (const QString &kw : keywords) + { + HighlightRule rule; + rule.pattern = QRegularExpression(QString("\\b%1\\b").arg(kw)); + rule.format = keywordFormat; + m_rules.append(rule); + } + + QTextCharFormat preprocFormat; + preprocFormat.setForeground(QColor("#C586C0")); + { HighlightRule r; r.pattern = QRegularExpression("^\\s*#\\s*\\w+"); r.format = preprocFormat; m_rules.append(r); } + + QTextCharFormat stringFormat; + stringFormat.setForeground(QColor("#CE9178")); + { HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*")"); r.format = stringFormat; m_rules.append(r); } + { HighlightRule r; r.pattern = QRegularExpression(R"('(?:[^'\\]|\\.)*')"); r.format = stringFormat; m_rules.append(r); } + + QTextCharFormat numberFormat; + numberFormat.setForeground(QColor("#B5CEA8")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\b(0[xX][0-9A-Fa-f]+[uUlL]*|[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?[fFlLuU]*)\b)"); r.format = numberFormat; m_rules.append(r); } + + QTextCharFormat commentFormat; + commentFormat.setForeground(QColor("#6A9955")); + commentFormat.setFontItalic(true); + { HighlightRule r; r.pattern = QRegularExpression("//[^\n]*"); r.format = commentFormat; m_rules.append(r); } + + m_multiLineCommentFormat = commentFormat; + m_commentStartExpression = QRegularExpression(R"(/\*)"); + m_commentEndExpression = QRegularExpression(R"(\*/)"); +} + +void CppHighlighter::highlightBlock(const QString &text) +{ + SyntaxHighlighter::highlightBlock(text); +} + +// =========================================================================== +// CssHighlighter +// =========================================================================== +CssHighlighter::CssHighlighter(QTextDocument *parent) + : SyntaxHighlighter(parent) +{ + m_hasMultiLineComment = true; + + // Selektoren: .klasse #id element ::pseudo :pseudo + QTextCharFormat selectorFormat; + selectorFormat.setForeground(QColor("#D7BA7D")); + { HighlightRule r; r.pattern = QRegularExpression(R"([.#]?[\w-]+\s*(?=\s*[,{]))"); r.format = selectorFormat; m_rules.append(r); } + { HighlightRule r; r.pattern = QRegularExpression(R"(:{1,2}[\w-]+)"); r.format = selectorFormat; m_rules.append(r); } + + // Eigenschaften (property:) + QTextCharFormat propFormat; + propFormat.setForeground(QColor("#9CDCFE")); + { HighlightRule r; r.pattern = QRegularExpression(R"([\w-]+\s*(?=:))"); r.format = propFormat; m_rules.append(r); } + + // Werte – Farben #hex + QTextCharFormat colorFormat; + colorFormat.setForeground(QColor("#CE9178")); + { HighlightRule r; r.pattern = QRegularExpression(R"(#[0-9A-Fa-f]{3,8}\b)"); r.format = colorFormat; m_rules.append(r); } + + // Zahlen + Einheiten + QTextCharFormat numberFormat; + numberFormat.setForeground(QColor("#B5CEA8")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\b\d+\.?\d*(px|em|rem|%|vh|vw|pt|cm|mm|s|ms)?\b)"); r.format = numberFormat; m_rules.append(r); } + + // Strings + QTextCharFormat stringFormat; + stringFormat.setForeground(QColor("#CE9178")); + { HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = stringFormat; m_rules.append(r); } + + // !important + QTextCharFormat importantFormat; + importantFormat.setForeground(QColor("#F44747")); + importantFormat.setFontWeight(QFont::Bold); + { HighlightRule r; r.pattern = QRegularExpression(R"(!important)"); r.format = importantFormat; m_rules.append(r); } + + // @-Regeln + QTextCharFormat atFormat; + atFormat.setForeground(QColor("#C586C0")); + { HighlightRule r; r.pattern = QRegularExpression(R"(@[\w-]+)"); r.format = atFormat; m_rules.append(r); } + + QTextCharFormat commentFormat; + commentFormat.setForeground(QColor("#6A9955")); + commentFormat.setFontItalic(true); + m_multiLineCommentFormat = commentFormat; + m_commentStartExpression = QRegularExpression(R"(/\*)"); + m_commentEndExpression = QRegularExpression(R"(\*/)"); +} + +void CssHighlighter::highlightBlock(const QString &text) +{ + SyntaxHighlighter::highlightBlock(text); +} + +// =========================================================================== +// HtmlHighlighter +// =========================================================================== +HtmlHighlighter::HtmlHighlighter(QTextDocument *parent) + : SyntaxHighlighter(parent) +{ + // Tag-Namen
+ QTextCharFormat tagFormat; + tagFormat.setForeground(QColor("#569CD6")); + { HighlightRule r; r.pattern = QRegularExpression(R"()"); r.format = tagFormat; m_rules.append(r); } + + // Attribute name= + QTextCharFormat attrFormat; + attrFormat.setForeground(QColor("#9CDCFE")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\b[\w:-]+=)"); r.format = attrFormat; m_rules.append(r); } + + // Attributwerte "wert" 'wert' + QTextCharFormat valueFormat; + valueFormat.setForeground(QColor("#CE9178")); + { HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = valueFormat; m_rules.append(r); } + + // DOCTYPE + QTextCharFormat doctypeFormat; + doctypeFormat.setForeground(QColor("#808080")); + { HighlightRule r; r.pattern = QRegularExpression(R"(]*>)", QRegularExpression::CaseInsensitiveOption); r.format = doctypeFormat; m_rules.append(r); } + + // Entities & { + QTextCharFormat entityFormat; + entityFormat.setForeground(QColor("#D7BA7D")); + { HighlightRule r; r.pattern = QRegularExpression(R"(&(?:#\d+|#x[0-9A-Fa-f]+|[\w]+);)"); r.format = entityFormat; m_rules.append(r); } + + // Kommentare (mehrzeilig) + QTextCharFormat commentFormat; + commentFormat.setForeground(QColor("#6A9955")); + commentFormat.setFontItalic(true); + m_multiLineCommentFormat = commentFormat; + m_commentStartExpression = QRegularExpression(""); + m_hasMultiLineComment = true; +} + +void HtmlHighlighter::highlightBlock(const QString &text) +{ + SyntaxHighlighter::highlightBlock(text); +} + +// =========================================================================== +// PhpHighlighter +// =========================================================================== +PhpHighlighter::PhpHighlighter(QTextDocument *parent) + : SyntaxHighlighter(parent) +{ + // ---- HTML-Regeln (Basis, für den Teil außerhalb von ) ---- + + QTextCharFormat tagFormat; + tagFormat.setForeground(QColor("#569CD6")); + { HighlightRule r; r.pattern = QRegularExpression(R"()"); r.format = tagFormat; m_rules.append(r); } + + QTextCharFormat attrFormat; + attrFormat.setForeground(QColor("#9CDCFE")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\b[\w:-]+=)"); r.format = attrFormat; m_rules.append(r); } + + QTextCharFormat valueFormat; + valueFormat.setForeground(QColor("#CE9178")); + { HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = valueFormat; m_rules.append(r); } + + QTextCharFormat entityFormat; + entityFormat.setForeground(QColor("#D7BA7D")); + { HighlightRule r; r.pattern = QRegularExpression(R"(&(?:#\d+|#x[0-9A-Fa-f]+|[\w]+);)"); r.format = entityFormat; m_rules.append(r); } + + // HTML-Kommentare + QTextCharFormat htmlCommentFormat; + htmlCommentFormat.setForeground(QColor("#6A9955")); + htmlCommentFormat.setFontItalic(true); + m_multiLineCommentFormat = htmlCommentFormat; + m_commentStartExpression = QRegularExpression(""); + m_hasMultiLineComment = true; + + // ---- PHP-Tags hervorheben ---- + m_phpTagFormat.setForeground(QColor("#C586C0")); + m_phpTagFormat.setFontWeight(QFont::Bold); + + // ---- PHP-spezifische Regeln ---- + m_phpStringFormat.setForeground(QColor("#CE9178")); + m_phpCommentFormat.setForeground(QColor("#6A9955")); + m_phpCommentFormat.setFontItalic(true); + + // Keywords + QTextCharFormat kwFormat; + kwFormat.setForeground(QColor("#569CD6")); + kwFormat.setFontWeight(QFont::Bold); + + const QStringList phpKeywords = { + "abstract","and","array","as","break","callable","case","catch", + "class","clone","const","continue","declare","default","die","do", + "echo","else","elseif","empty","enddeclare","endfor","endforeach", + "endif","endswitch","endwhile","enum","extends","final","finally", + "fn","for","foreach","function","global","goto","if","implements", + "include","include_once","instanceof","insteadof","interface", + "isset","list","match","namespace","new","or","print","private", + "protected","public","readonly","require","require_once","return", + "static","switch","throw","trait","try","unset","use","var", + "while","xor","yield","null","true","false","NULL","TRUE","FALSE" + }; + + for (const QString &kw : phpKeywords) + { + HighlightRule r; + r.pattern = QRegularExpression(QString("\\b%1\\b").arg(kw)); + r.format = kwFormat; + m_phpRules.append(r); + } + + // Variablen $var + QTextCharFormat varFormat; + varFormat.setForeground(QColor("#9CDCFE")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\$[\w]+)"); r.format = varFormat; m_phpRules.append(r); } + + // Strings + { HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = m_phpStringFormat; m_phpRules.append(r); } + + // Zahlen + QTextCharFormat numFormat; + numFormat.setForeground(QColor("#B5CEA8")); + { HighlightRule r; r.pattern = QRegularExpression(R"(\b\d+\.?\d*\b)"); r.format = numFormat; m_phpRules.append(r); } + + // Einzeilige Kommentare + { HighlightRule r; r.pattern = QRegularExpression(R"((//|#)[^\n]*)"); r.format = m_phpCommentFormat; m_phpRules.append(r); } + + // Eingebaute Funktionen (Auswahl der häufigsten) + QTextCharFormat builtinFormat; + builtinFormat.setForeground(QColor("#DCDCAA")); + const QStringList builtins = { + "array_map","array_filter","array_keys","array_values","array_merge", + "array_push","array_pop","array_shift","array_slice","array_splice", + "count","strlen","substr","strpos","strtolower","strtoupper","trim", + "ltrim","rtrim","explode","implode","str_replace","preg_match", + "preg_replace","sprintf","printf","print_r","var_dump","isset", + "empty","unset","intval","floatval","strval","is_array","is_string", + "is_int","is_float","is_null","is_bool","is_numeric","date","time", + "mktime","json_encode","json_decode","header","session_start", + "htmlspecialchars","htmlentities","strip_tags","nl2br","round", + "floor","ceil","abs","min","max","rand","in_array","array_key_exists", + "sort","rsort","usort","ksort","krsort","ob_start","ob_get_clean" + }; + + for (const QString &fn : builtins) + { + HighlightRule r; + r.pattern = QRegularExpression(QString("\\b%1\\b").arg(fn)); + r.format = builtinFormat; + m_phpRules.append(r); + } +} + +void PhpHighlighter::highlightPhpRange(const QString &text, int start, int length) +{ + if (length <= 0) + { + return; + } + + const QString phpText = text.mid(start, length); + + for (const HighlightRule &rule : m_phpRules) + { + QRegularExpressionMatchIterator it = rule.pattern.globalMatch(phpText); + while (it.hasNext()) + { + QRegularExpressionMatch match = it.next(); + setFormat( + start + static_cast(match.capturedStart()), + static_cast(match.capturedLength()), + rule.format + ); + } + } + + // /* */ Block-Kommentare innerhalb des PHP-Bereichs mehrzeilig behandeln. + // Block-Zustand 3 = wir sind mitten in einem /* ... */ PHP-Kommentar. + static const QRegularExpression blockOpen(R"(/\*)"); + static const QRegularExpression blockClose(R"(\*/)"); + + int searchFrom = 0; + + // Waren wir bereits in einem Block-Kommentar? + if (previousBlockState() == 3) + { + QRegularExpressionMatch closeMatch = blockClose.match(phpText, 0); + if (closeMatch.hasMatch()) + { + const int end = static_cast(closeMatch.capturedStart()) + + static_cast(closeMatch.capturedLength()); + setFormat(start, end, m_phpCommentFormat); + searchFrom = end; + // Block-Kommentar geschlossen — Zustand wird weiter unten gesetzt + } + else + { + // Gesamter Bereich ist noch Kommentar + setFormat(start, length, m_phpCommentFormat); + setCurrentBlockState(3); + return; + } + } + + // Neue /* ... */ Kommentare innerhalb dieses PHP-Bereichs suchen + while (searchFrom < phpText.length()) + { + QRegularExpressionMatch openMatch = blockOpen.match(phpText, searchFrom); + if (!openMatch.hasMatch()) + { + break; + } + + const int openPos = static_cast(openMatch.capturedStart()); + QRegularExpressionMatch closeMatch = blockClose.match(phpText, openPos + 2); + + if (closeMatch.hasMatch()) + { + const int closeEnd = static_cast(closeMatch.capturedStart()) + + static_cast(closeMatch.capturedLength()); + setFormat(start + openPos, closeEnd - openPos, m_phpCommentFormat); + searchFrom = closeEnd; + } + else + { + // Kein schließendes */ gefunden — geht über Zeilenende + setFormat(start + openPos, length - openPos, m_phpCommentFormat); + setCurrentBlockState(3); + return; + } + } +} + +void PhpHighlighter::highlightBlock(const QString &text) +{ + // Zuerst HTML-Basis-Regeln auf den gesamten Text anwenden + SyntaxHighlighter::highlightBlock(text); + + // Block-Zustände: + // 0 = HTML-Modus + // 2 = innerhalb PHP-Block (kein /* */ Kommentar) + // 3 = innerhalb PHP /* */ Block-Kommentar + setCurrentBlockState(0); + + static const QRegularExpression phpOpen(R"(<\?(?:php|=)?\s?)", + QRegularExpression::CaseInsensitiveOption); + static const QRegularExpression phpClose(R"(\?>)"); + + int pos = 0; + + if (previousBlockState() == 2 || previousBlockState() == 3) + { + // Wir befinden uns bereits in einem PHP-Block (ggf. in einem Kommentar) + QRegularExpressionMatch closeMatch = phpClose.match(text, 0); + if (closeMatch.hasMatch()) + { + const int end = static_cast(closeMatch.capturedStart()) + + static_cast(closeMatch.capturedLength()); + highlightPhpRange(text, 0, end); + setFormat(static_cast(closeMatch.capturedStart()), + static_cast(closeMatch.capturedLength()), + m_phpTagFormat); + pos = end; + setCurrentBlockState(0); + } + else + { + highlightPhpRange(text, 0, text.length()); + // highlightPhpRange setzt den Zustand auf 3 falls nötig, + // sonst behalten wir 2 (offener PHP-Block ohne Kommentar) + if (currentBlockState() != 3) + { + setCurrentBlockState(2); + } + return; + } + } + + while (pos < text.length()) + { + QRegularExpressionMatch openMatch = phpOpen.match(text, pos); + if (!openMatch.hasMatch()) + { + break; + } + + const int openStart = static_cast(openMatch.capturedStart()); + const int openEnd = openStart + static_cast(openMatch.capturedLength()); + + setFormat(openStart, static_cast(openMatch.capturedLength()), m_phpTagFormat); + + QRegularExpressionMatch closeMatch = phpClose.match(text, openEnd); + if (closeMatch.hasMatch()) + { + const int closeStart = static_cast(closeMatch.capturedStart()); + const int closeEnd = closeStart + static_cast(closeMatch.capturedLength()); + + highlightPhpRange(text, openEnd, closeStart - openEnd); + setFormat(closeStart, static_cast(closeMatch.capturedLength()), m_phpTagFormat); + + pos = closeEnd; + setCurrentBlockState(0); + } + else + { + highlightPhpRange(text, openEnd, text.length() - openEnd); + if (currentBlockState() != 3) + { + setCurrentBlockState(2); + } + return; + } + } +} diff --git a/src/barecode/src/highlighter/SyntaxHighlighter.h b/src/barecode/src/highlighter/SyntaxHighlighter.h new file mode 100644 index 0000000..9c330ae --- /dev/null +++ b/src/barecode/src/highlighter/SyntaxHighlighter.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// SyntaxHighlighter – Regelbasierte Basis-Klasse. +// Unterklassen befüllen m_rules und können highlightBlock() überschreiben +// um mehrzeilige Konstrukte (Block-Kommentare, heredocs, …) zu behandeln. +// --------------------------------------------------------------------------- +class SyntaxHighlighter : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + explicit SyntaxHighlighter(QTextDocument *parent = nullptr); + +protected: + struct HighlightRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + + void highlightBlock(const QString &text) override; + + // Unterklassen befüllen dies im Konstruktor + QVector m_rules; + + // Mehrzeilige Block-Kommentare (/* ... */) + QRegularExpression m_commentStartExpression; + QRegularExpression m_commentEndExpression; + QTextCharFormat m_multiLineCommentFormat; + bool m_hasMultiLineComment = false; +}; + +// --------------------------------------------------------------------------- +// CppHighlighter – C und C++ +// --------------------------------------------------------------------------- +class CppHighlighter : public SyntaxHighlighter +{ + Q_OBJECT +public: + explicit CppHighlighter(QTextDocument *parent = nullptr); +protected: + void highlightBlock(const QString &text) override; +}; + +// --------------------------------------------------------------------------- +// CssHighlighter – CSS +// --------------------------------------------------------------------------- +class CssHighlighter : public SyntaxHighlighter +{ + Q_OBJECT +public: + explicit CssHighlighter(QTextDocument *parent = nullptr); +protected: + void highlightBlock(const QString &text) override; +}; + +// --------------------------------------------------------------------------- +// HtmlHighlighter – HTML (mit eingebettetem CSS in