From 04c5212d54b5683cc5b8a5013066021d73ae5389 Mon Sep 17 00:00:00 2001 From: Dany Thinnes Date: Tue, 25 Aug 2026 14:56:27 +0200 Subject: [PATCH] =?UTF-8?q?Dateien,=20die=20als=20Parameter=20=C3=BCbergeb?= =?UTF-8?q?en=20werden,=20werden=20nach=20dem=20Start=20direkt=20geladen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- barecode/.gitignore | 3 + barecode/BareCode.desktop | 13 + barecode/BareCode.rc | 1 + barecode/CMakeLists.txt | 159 +++ barecode/LICENSE | 21 + barecode/PKGBUILD | 36 + barecode/PKGBUILD-git | 43 + barecode/README.md | 200 +++ barecode/barecode.desktop | 13 + barecode/bauen.sh | 133 ++ barecode/main.cpp | 106 ++ barecode/resources/BareCode.ico | Bin 0 -> 846 bytes barecode/resources/icon_128.png | Bin 0 -> 25174 bytes barecode/resources/icon_16.png | Bin 0 -> 824 bytes barecode/resources/icon_24.png | Bin 0 -> 1546 bytes barecode/resources/icon_256.png | Bin 0 -> 92012 bytes barecode/resources/icon_32.png | Bin 0 -> 2428 bytes barecode/resources/icon_48.png | Bin 0 -> 4824 bytes barecode/resources/icon_512.png | Bin 0 -> 310528 bytes barecode/resources/icon_64.png | Bin 0 -> 7750 bytes barecode/resources/php_functions.json | 1197 +++++++++++++++++ barecode/resources/resources.qrc | 12 + barecode/src/CMakeLists.txt | 4 + barecode/src/core/AboutDialog.cpp | 105 ++ barecode/src/core/AboutDialog.h | 14 + barecode/src/core/CMakeLists.txt | 28 + barecode/src/core/IPlugin.h | 26 + barecode/src/core/MainWindow.cpp | 412 ++++++ barecode/src/core/MainWindow.h | 99 ++ barecode/src/core/ProjectManager.cpp | 33 + barecode/src/core/ProjectManager.h | 27 + barecode/src/core/Settings.cpp | 113 ++ barecode/src/core/Settings.h | 52 + barecode/src/core/ThemeManager.cpp | 115 ++ barecode/src/core/ThemeManager.h | 29 + barecode/src/editor/CMakeLists.txt | 49 + barecode/src/editor/CodeEditor.cpp | 762 +++++++++++ barecode/src/editor/CodeEditor.h | 86 ++ barecode/src/editor/ColorIndicator.cpp | 361 +++++ barecode/src/editor/ColorIndicator.h | 67 + barecode/src/editor/DeadCodeAnalyzer.cpp | 181 +++ barecode/src/editor/DeadCodeAnalyzer.h | 39 + barecode/src/editor/DeadCodeDialog.cpp | 461 +++++++ barecode/src/editor/DeadCodeDialog.h | 62 + barecode/src/editor/EditorPanel.cpp | 301 +++++ barecode/src/editor/EditorPanel.h | 68 + barecode/src/editor/EditorTab.cpp | 53 + barecode/src/editor/EditorTab.h | 33 + barecode/src/editor/FileSearchPanel.cpp | 330 +++++ barecode/src/editor/FileSearchPanel.h | 77 ++ barecode/src/editor/FunctionIndex.cpp | 83 ++ barecode/src/editor/FunctionIndex.h | 47 + barecode/src/editor/FunctionListDialog.cpp | 52 + barecode/src/editor/FunctionListDialog.h | 30 + barecode/src/editor/FunctionListPanel.cpp | 332 +++++ barecode/src/editor/FunctionListPanel.h | 67 + barecode/src/editor/FunctionScanner.cpp | 158 +++ barecode/src/editor/FunctionScanner.h | 47 + barecode/src/editor/LineNumberArea.cpp | 18 + barecode/src/editor/LineNumberArea.h | 25 + barecode/src/editor/SearchPanel.cpp | 492 +++++++ barecode/src/editor/SearchPanel.h | 79 ++ barecode/src/editor/SignatureHelper.cpp | 222 +++ barecode/src/editor/SignatureHelper.h | 51 + barecode/src/editor/SignatureTooltip.cpp | 91 ++ barecode/src/editor/SignatureTooltip.h | 29 + barecode/src/editor/VariableCompleter.cpp | 256 ++++ barecode/src/editor/VariableCompleter.h | 43 + barecode/src/filetree/CMakeLists.txt | 17 + barecode/src/filetree/FileTreePanel.cpp | 259 ++++ barecode/src/filetree/FileTreePanel.h | 49 + barecode/src/highlighter/CMakeLists.txt | 19 + .../src/highlighter/HighlighterFactory.cpp | 45 + barecode/src/highlighter/HighlighterFactory.h | 18 + .../src/highlighter/SyntaxHighlighter.cpp | 589 ++++++++ barecode/src/highlighter/SyntaxHighlighter.h | 94 ++ barecode/translations/barecode_de.ts | 198 +++ barecode/translations/barecode_en.ts | 194 +++ 78 files changed, 9528 insertions(+) create mode 100644 barecode/.gitignore create mode 100644 barecode/BareCode.desktop create mode 100644 barecode/BareCode.rc create mode 100644 barecode/CMakeLists.txt create mode 100644 barecode/LICENSE create mode 100644 barecode/PKGBUILD create mode 100644 barecode/PKGBUILD-git create mode 100644 barecode/README.md create mode 100644 barecode/barecode.desktop create mode 100755 barecode/bauen.sh create mode 100644 barecode/main.cpp create mode 100644 barecode/resources/BareCode.ico create mode 100644 barecode/resources/icon_128.png create mode 100644 barecode/resources/icon_16.png create mode 100644 barecode/resources/icon_24.png create mode 100644 barecode/resources/icon_256.png create mode 100644 barecode/resources/icon_32.png create mode 100644 barecode/resources/icon_48.png create mode 100644 barecode/resources/icon_512.png create mode 100644 barecode/resources/icon_64.png create mode 100644 barecode/resources/php_functions.json create mode 100644 barecode/resources/resources.qrc create mode 100644 barecode/src/CMakeLists.txt create mode 100644 barecode/src/core/AboutDialog.cpp create mode 100644 barecode/src/core/AboutDialog.h create mode 100644 barecode/src/core/CMakeLists.txt create mode 100644 barecode/src/core/IPlugin.h create mode 100644 barecode/src/core/MainWindow.cpp create mode 100644 barecode/src/core/MainWindow.h create mode 100644 barecode/src/core/ProjectManager.cpp create mode 100644 barecode/src/core/ProjectManager.h create mode 100644 barecode/src/core/Settings.cpp create mode 100644 barecode/src/core/Settings.h create mode 100644 barecode/src/core/ThemeManager.cpp create mode 100644 barecode/src/core/ThemeManager.h create mode 100644 barecode/src/editor/CMakeLists.txt create mode 100644 barecode/src/editor/CodeEditor.cpp create mode 100644 barecode/src/editor/CodeEditor.h create mode 100644 barecode/src/editor/ColorIndicator.cpp create mode 100644 barecode/src/editor/ColorIndicator.h create mode 100644 barecode/src/editor/DeadCodeAnalyzer.cpp create mode 100644 barecode/src/editor/DeadCodeAnalyzer.h create mode 100644 barecode/src/editor/DeadCodeDialog.cpp create mode 100644 barecode/src/editor/DeadCodeDialog.h create mode 100644 barecode/src/editor/EditorPanel.cpp create mode 100644 barecode/src/editor/EditorPanel.h create mode 100644 barecode/src/editor/EditorTab.cpp create mode 100644 barecode/src/editor/EditorTab.h create mode 100644 barecode/src/editor/FileSearchPanel.cpp create mode 100644 barecode/src/editor/FileSearchPanel.h create mode 100644 barecode/src/editor/FunctionIndex.cpp create mode 100644 barecode/src/editor/FunctionIndex.h create mode 100644 barecode/src/editor/FunctionListDialog.cpp create mode 100644 barecode/src/editor/FunctionListDialog.h create mode 100644 barecode/src/editor/FunctionListPanel.cpp create mode 100644 barecode/src/editor/FunctionListPanel.h create mode 100644 barecode/src/editor/FunctionScanner.cpp create mode 100644 barecode/src/editor/FunctionScanner.h create mode 100644 barecode/src/editor/LineNumberArea.cpp create mode 100644 barecode/src/editor/LineNumberArea.h create mode 100644 barecode/src/editor/SearchPanel.cpp create mode 100644 barecode/src/editor/SearchPanel.h create mode 100644 barecode/src/editor/SignatureHelper.cpp create mode 100644 barecode/src/editor/SignatureHelper.h create mode 100644 barecode/src/editor/SignatureTooltip.cpp create mode 100644 barecode/src/editor/SignatureTooltip.h create mode 100644 barecode/src/editor/VariableCompleter.cpp create mode 100644 barecode/src/editor/VariableCompleter.h create mode 100644 barecode/src/filetree/CMakeLists.txt create mode 100644 barecode/src/filetree/FileTreePanel.cpp create mode 100644 barecode/src/filetree/FileTreePanel.h create mode 100644 barecode/src/highlighter/CMakeLists.txt create mode 100644 barecode/src/highlighter/HighlighterFactory.cpp create mode 100644 barecode/src/highlighter/HighlighterFactory.h create mode 100644 barecode/src/highlighter/SyntaxHighlighter.cpp create mode 100644 barecode/src/highlighter/SyntaxHighlighter.h create mode 100644 barecode/translations/barecode_de.ts create mode 100644 barecode/translations/barecode_en.ts diff --git a/barecode/.gitignore b/barecode/.gitignore new file mode 100644 index 0000000..7ab91cf --- /dev/null +++ b/barecode/.gitignore @@ -0,0 +1,3 @@ +{src/ +build/ +BareCodeAUR diff --git a/barecode/BareCode.desktop b/barecode/BareCode.desktop new file mode 100644 index 0000000..ade1b56 --- /dev/null +++ b/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/barecode/BareCode.rc b/barecode/BareCode.rc new file mode 100644 index 0000000..8650ce3 --- /dev/null +++ b/barecode/BareCode.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON "resources/BareCode.ico" diff --git a/barecode/CMakeLists.txt b/barecode/CMakeLists.txt new file mode 100644 index 0000000..a0ef7c2 --- /dev/null +++ b/barecode/CMakeLists.txt @@ -0,0 +1,159 @@ +cmake_minimum_required(VERSION 3.16) + +project(BareCode + VERSION 1.2.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 +# --------------------------------------------------------------------------- +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() + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +add_subdirectory(src) + +# --------------------------------------------------------------------------- +# Übersetzungen — lrelease → .qm → ins Build-Verzeichnis +# --------------------------------------------------------------------------- +find_program(LRELEASE_EXECUTABLE + NAMES lrelease lrelease-qt6 + HINTS "${Qt6_DIR}/../../../bin" + REQUIRED +) + +set(TS_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/translations/barecode_de.ts + ${CMAKE_CURRENT_SOURCE_DIR}/translations/barecode_en.ts +) + +set(QM_FILES) +foreach(TS_FILE ${TS_FILES}) + get_filename_component(TS_NAME ${TS_FILE} NAME_WE) + set(QM_FILE "${CMAKE_CURRENT_BINARY_DIR}/translations/${TS_NAME}.qm") + add_custom_command( + OUTPUT "${QM_FILE}" + COMMAND ${CMAKE_COMMAND} -E make_directory + "${CMAKE_CURRENT_BINARY_DIR}/translations" + COMMAND ${LRELEASE_EXECUTABLE} "${TS_FILE}" -qm "${QM_FILE}" + DEPENDS "${TS_FILE}" + COMMENT "lrelease: ${TS_NAME}.qm" + VERBATIM + ) + list(APPEND QM_FILES "${QM_FILE}") +endforeach() + +add_custom_target(BareCode_translations ALL DEPENDS ${QM_FILES}) + +# --------------------------------------------------------------------------- +# Resources +# --------------------------------------------------------------------------- +qt_add_resources(BARECODE_RESOURCES resources/resources.qrc) + +# --------------------------------------------------------------------------- +# Executable +# --------------------------------------------------------------------------- +if(PLATFORM_WINDOWS) + qt_add_executable(BareCode main.cpp BareCode.rc ${BARECODE_RESOURCES}) +else() + qt_add_executable(BareCode main.cpp ${BARECODE_RESOURCES}) +endif() + +add_dependencies(BareCode BareCode_translations) + +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} +) + +install(FILES LICENSE + DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/barecode +) + +# .qm-Dateien installieren +install(FILES ${QM_FILES} + DESTINATION ${CMAKE_INSTALL_DATADIR}/BareCode/translations +) + +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() + +if(PLATFORM_HAIKU) + install(FILES resources/icon_256.png + DESTINATION ${CMAKE_INSTALL_DATADIR}/BareCode + RENAME BareCode.png + ) + 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.\") + endif() + ") +endif() + +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/barecode/LICENSE b/barecode/LICENSE new file mode 100644 index 0000000..2fbdd76 --- /dev/null +++ b/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/barecode/PKGBUILD b/barecode/PKGBUILD new file mode 100644 index 0000000..bd36be7 --- /dev/null +++ b/barecode/PKGBUILD @@ -0,0 +1,36 @@ +# Maintainer: Dany Thinnes +# Projekt Hirnfrei - https://www.projekt-hirnfrei.de + +pkgname=barecode +pkgver=1.2.0 +pkgrel=1 +pkgdesc="Schlanker modularer Code-Editor für HTML, PHP, CSS und C++" +arch=('x86_64' 'aarch64') +url="https://www.projekt-hirnfrei.de" +license=('MIT') +depends=('qt6-base') +makedepends=('cmake' 'ninja') +provides=('barecode') +conflicts=('barecode-git') +source=("$pkgname-$pkgver.tar.gz::https://git.projekt-hirnfrei.de/diabolus/BareCode/archive/v$pkgver.tar.gz") +sha256sums=('SKIP') # Nach erstem Download ersetzen: sha256sum barecode-1.1.0.tar.gz + +build() { + cd "BareCode" + cmake -B build \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_SKIP_RPATH=ON + cmake --build build +} + +check() { + : +} + +package() { + cd "BareCode" + DESTDIR="$pkgdir" cmake --install build + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/barecode/PKGBUILD-git b/barecode/PKGBUILD-git new file mode 100644 index 0000000..566f386 --- /dev/null +++ b/barecode/PKGBUILD-git @@ -0,0 +1,43 @@ +# Maintainer: Dany Thinnes +# Projekt Hirnfrei - https://www.projekt-hirnfrei.de + +pkgname=barecode-git +pkgver=1.1.0.r0.g0000000 +pkgrel=1 +pkgdesc="Schlanker modularer Code-Editor für HTML, PHP, CSS und C++ (Git-Version)" +arch=('x86_64' 'aarch64') +url="https://www.projekt-hirnfrei.de" +license=('MIT') +depends=('qt6-base') +makedepends=('cmake' 'ninja' 'git') +provides=('barecode') +conflicts=('barecode') +source=("$pkgname::git+https://git.projekt-hirnfrei.de/diabolus/BareCode.git") +sha256sums=('SKIP') + +pkgver() { + cd "$pkgname" + git describe --long --tags 2>/dev/null \ + | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' \ + || printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" +} + +build() { + cd "$pkgname" + cmake -B build \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_SKIP_RPATH=ON + cmake --build build +} + +check() { + : +} + +package() { + cd "$pkgname" + DESTDIR="$pkgdir" cmake --install build + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/barecode/README.md b/barecode/README.md new file mode 100644 index 0000000..94dacb8 --- /dev/null +++ b/barecode/README.md @@ -0,0 +1,200 @@ +# BareCode + +**Schlanker, modularer Code-Editor für Web-Entwickler** +Version 1.2.0 — von **Dany Thinnes** | [Projekt Hirnfrei](https://www.projekt-hirnfrei.de) | [Discord](https://discord.projekt-hirnfrei.de) + +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 | +|---|---| +| Syntax-Highlighting | HTML, PHP, CSS, C/C++ — inkl. mehrzeiliger Kommentare über Leerzeilen | +| Tabs | Mehrere Dateien gleichzeitig, verschiebbar und schließbar | +| Änderungsindikator | ● im Tab-Titel bei ungespeicherten Änderungen | +| Zeilennummern | Eigener Gutter, aktuelle Zeile hervorgehoben | +| Einrück-Führungslinien | Vertikale Linien wie in VS Code | +| Klammerzugehörigkeit | Zusammengehörige Klammern werden grün hervorgehoben, fehlende rot | +| Auto-Indent | Einrückungstiefe wird bei Enter übernommen | +| Tab / Shift+Tab | Ein- und Ausrücken für einzelne Zeilen und Selektionen | +| 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 | +| Variablen-Popup | Vorschläge für $variablen beim Tippen (nur Anzeige, kein Autocomplete) | + +### 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 | +| Dark / Light Mode | Umschaltbar (Strg+Shift+D), wird gespeichert | +| Session | Geöffnete Dateien und aktiver Tab werden wiederhergestellt | + +--- + +## 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 | +| Projektfunktionen | Strg+Shift+P | +| Tote Funktionen | Strg+Shift+T | +| Dark Mode | Strg+Shift+D | + +--- + +## Projektstruktur + +``` +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, + │ # VariableCompleter, FunctionScanner, + │ # FunctionIndex, FunctionListPanel, + │ # FunctionListDialog, DeadCodeAnalyzer, + │ # DeadCodeDialog + ├── filetree/ # FileTreePanel + └── highlighter/ # SyntaxHighlighter, HighlighterFactory +``` + +Jedes Unterverzeichnis kompiliert als eigene statische Bibliothek. + +--- + +## 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 +``` + +--- + +### 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. + +--- + +## Neue Sprache 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 + +--- + +## Lizenz + +MIT License — Copyright (c) 2025 Dany Thinnes / Projekt Hirnfrei + +--- + +## Links + +- 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/barecode.desktop b/barecode/barecode.desktop new file mode 100644 index 0000000..e6b348c --- /dev/null +++ b/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/barecode/bauen.sh b/barecode/bauen.sh new file mode 100755 index 0000000..1eec33a --- /dev/null +++ b/barecode/bauen.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# --------------------------------------------------------------------------- +# BareCode – Build-Skript +# Verwendung: ./bauen.sh [release|debug|clean|install] +# --------------------------------------------------------------------------- + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +BUILD_TYPE="${1:-release}" +BUILD_DIR="build" + +# Farben +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +info() { echo -e "${BLUE}==>${NC} $1"; } +success() { echo -e "${GREEN}==>${NC} $1"; } +warn() { echo -e "${YELLOW}==>${NC} $1"; } +error() { echo -e "${RED}==>${NC} $1"; exit 1; } + +# --------------------------------------------------------------------------- +# clean +# --------------------------------------------------------------------------- +if [ "$BUILD_TYPE" = "clean" ]; then + info "Build-Verzeichnis wird gelöscht…" + rm -rf "$BUILD_DIR" + success "Fertig." + exit 0 +fi + +# --------------------------------------------------------------------------- +# Abhängigkeiten prüfen +# --------------------------------------------------------------------------- +info "Prüfe Abhängigkeiten…" + +command -v cmake &>/dev/null || error "cmake nicht gefunden. Installation: sudo pacman -S cmake" +command -v ninja &>/dev/null || error "ninja nicht gefunden. Installation: sudo pacman -S ninja" +command -v lrelease &>/dev/null || \ +command -v lrelease-qt6 &>/dev/null || \ + error "lrelease nicht gefunden. Installation: sudo pacman -S qt6-tools" + +# Qt6 prüfen +if ! pkg-config --exists Qt6Core 2>/dev/null; then + if ! cmake --find-package -DNAME=Qt6 -DCOMPILER_ID=GNU \ + -DLANGUAGE=CXX -DMODE=EXIST &>/dev/null 2>&1; then + warn "Qt6 konnte nicht automatisch geprüft werden — cmake wird es versuchen." + fi +fi + +success "Abhängigkeiten OK." + +# --------------------------------------------------------------------------- +# CMake-Build-Typ +# --------------------------------------------------------------------------- +case "$BUILD_TYPE" in + release|Release) + CMAKE_BUILD_TYPE="Release" + ;; + debug|Debug) + CMAKE_BUILD_TYPE="Debug" + ;; + install) + CMAKE_BUILD_TYPE="Release" + ;; + *) + error "Unbekannter Build-Typ: '$BUILD_TYPE'. Erlaubt: release, debug, clean, install" + ;; +esac + +# --------------------------------------------------------------------------- +# Konfigurieren +# --------------------------------------------------------------------------- +info "Konfiguriere mit CMake (${CMAKE_BUILD_TYPE})…" + +cmake -B "$BUILD_DIR" \ + -G Ninja \ + -DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + 2>&1 || error "CMake-Konfiguration fehlgeschlagen." + +success "Konfiguration OK." + +# --------------------------------------------------------------------------- +# Bauen +# --------------------------------------------------------------------------- +JOBS=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4) +info "Baue mit $JOBS parallelen Jobs…" + +cmake --build "$BUILD_DIR" -j"$JOBS" 2>&1 || error "Build fehlgeschlagen." + +success "Build erfolgreich!" + +# --------------------------------------------------------------------------- +# Installieren (optional) +# --------------------------------------------------------------------------- +if [ "$BUILD_TYPE" = "install" ]; then + info "Installiere nach /usr (sudo erforderlich)…" + sudo cmake --install "$BUILD_DIR" || error "Installation fehlgeschlagen." + success "BareCode wurde installiert." + echo "" + echo " Starten: BareCode" + exit 0 +fi + +# --------------------------------------------------------------------------- +# Fertig +# --------------------------------------------------------------------------- +BINARY="$BUILD_DIR/BareCode" +if [ -f "$BINARY" ]; then + # .qm-Dateien neben die Binary kopieren damit sie gefunden werden + mkdir -p "$BUILD_DIR/translations" + if compgen -G "$BUILD_DIR/translations/barecode_*.qm" > /dev/null 2>&1; then + success "Übersetzungen bereits vorhanden." + else + # Aus dem cmake-Zwischenverzeichnis holen + find "$BUILD_DIR" -name "barecode_*.qm" -not -path "$BUILD_DIR/translations/*" \ + -exec cp {} "$BUILD_DIR/translations/" \; 2>/dev/null || true + fi + + echo "" + success "BareCode ist bereit:" + echo " Starten: ./$BINARY" + echo " Installieren: ./bauen.sh install" + echo " Debug-Build: ./bauen.sh debug" + echo " Aufräumen: ./bauen.sh clean" +fi diff --git a/barecode/main.cpp b/barecode/main.cpp new file mode 100644 index 0000000..af1377f --- /dev/null +++ b/barecode/main.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "core/MainWindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + app.setApplicationName("BareCode"); + app.setApplicationVersion("1.2.0"); + app.setOrganizationName("BareCode"); + + // Icon + 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); + + // --------------------------------------------------------------------------- + // Übersetzung laden + // .qm-Dateien liegen im Unterverzeichnis "translations" neben der Binary + // oder unter /usr/share/BareCode/translations nach Installation + // --------------------------------------------------------------------------- + QSettings settings(QSettings::IniFormat, QSettings::UserScope, + "BareCode", "BareCode"); + QString locale = settings.value("language/locale", QString()).toString(); + + if (locale.isEmpty()) + { + locale = QLocale::system().name(); // z.B. "de_DE", "en_US" + } + + const QString shortLocale = locale.left(2); // "de", "en" + + // Suchpfade für .qm-Dateien + QStringList searchPaths; + searchPaths << QCoreApplication::applicationDirPath() + "/translations" + << QDir::homePath() + "/.local/share/BareCode/translations" + << "/usr/share/BareCode/translations" + << "/usr/local/share/BareCode/translations"; + + // Qt-eigene Übersetzungen (Dialoge, Standard-Buttons) + QTranslator qtTranslator; + if (qtTranslator.load("qt_" + locale, + QLibraryInfo::path(QLibraryInfo::TranslationsPath))) + { + app.installTranslator(&qtTranslator); + } + + // BareCode-Übersetzung — in allen Suchpfaden versuchen + QTranslator appTranslator; + bool loaded = false; + + for (const QString &path : searchPaths) + { + if (appTranslator.load(QString("barecode_%1").arg(locale), path) || + appTranslator.load(QString("barecode_%1").arg(shortLocale), path)) + { + app.installTranslator(&appTranslator); + loaded = true; + break; + } + } + + // Fallback: Englisch + if (!loaded && shortLocale != "de") + { + for (const QString &path : searchPaths) + { + if (appTranslator.load("barecode_en", path)) + { + app.installTranslator(&appTranslator); + break; + } + } + } + + MainWindow window; + window.show(); + + // Datei(en) öffnen, die beim Start per Kommandozeile übergeben wurden + // (z. B. Doppelklick auf eine Datei im Dateibrowser → "Öffnen mit BareCode"). + // Das erste Argument ist der Programmname selbst und wird übersprungen. + QStringList cliFiles = app.arguments(); + if (!cliFiles.isEmpty()) + { + cliFiles.removeFirst(); + } + if (!cliFiles.isEmpty()) + { + window.openFilesFromArguments(cliFiles); + } + + return app.exec(); +} diff --git a/barecode/resources/BareCode.ico b/barecode/resources/BareCode.ico new file mode 100644 index 0000000000000000000000000000000000000000..10ecf22bfb663edb716ab01df8db3a2fd38db6a7 GIT binary patch literal 846 zcmV-U1F`%70096201yxW0000W05}5x02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|5C8xG z5C{eU001BJ|6u?C0{=-wK~#90Et6en)^!}kKi}W~|7_3RdS-ibYi@2?s4OLuveaDQ zO?O_{3(-YaQIYMgfEdO9gh(UMhFQYJVu)D8luqEMVhvjSi5qLq_q_U4p<0CAVg?ur+r|E>cTwv z&3O`x&9DZ$rTg%Io%Vk0^VswIG)N3^c`+NB6*vA|_@&=!uI7Rut zRXVoqL@k|EE=+Rm&#S!o>I7#_e9GM$H;`2;BxX?B_oN0kKcI4@qQ7TnwdKKaamS$A zMz?F@ho^MU$-h+ExnFb)Xk_~%`u&fqs^__e#~xDW_!A1as8%Xmoc@J%ot^C4yPINb zk)&^sWMmuV=_#@sa}?UzcCzsT9@Q|!?P+xrcwIu1Sci&fW{U$Ya536hZDW!RIl3=9G&AjvW2Yi42N5;ms zl5XBj^`AM)zg?iEwMeDB#-7IyF!}9STKf7(5HUKbxg)P*3Umyt=ZEuCocni$(xI2A z{dyW-nkTWqGta*a814PN#F*nT!w@Mk$K0{#c+6;NE>Il07nZM6pZ*4`XOI?XYiS{b zK&)pNMj{7~q@EOz*KupYBuEQXFHd4urtoSNOH&N++gxy)FONBH3902(lD<*m^%)cb zV5n9B)Nq=SHxw>40z8s-58<^MR$SMkbki;@vBnfL6dg$oBF#XJ@8d!UOPi2K>N6Mk Y9|1UwoqZ$ZDF6Tf07*qoM6N<$g1^>?-2eap literal 0 HcmV?d00001 diff --git a/barecode/resources/icon_128.png b/barecode/resources/icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..bb49b56333d48bf08f7efe58efae840981130d85 GIT binary patch literal 25174 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 literal 0 HcmV?d00001 diff --git a/barecode/resources/icon_16.png b/barecode/resources/icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..7cba1e427a519cd56bc2e4a438e21b7f0c8e082a GIT binary patch literal 824 zcmV-81IPS{P)H`|_<|MUNSPZy7O=i+cU2hPVz14C-tv6nnFVeTj- zNDeMA0E1u<9S{0&n}H-jW&oHONXQ+J5er5L2_QU1n(rE- z(A7nnww74Ca*m|66$B1g2uL7AXlti^V2J9%Jo(Le5{%Fc+1xC}fei%mItmFc;d0Ut zh*=$ZPF}0gzGD}oM?a!{%Y7)TA{@Dc8Okz(3vegMFd2&ri*$6fk|rsHgwn&~tS+u_ z^U}|(t(F^JYczC0kP8b&rCMcWX@Q9sp5x5%Pl)x5LT^9Ct@m@|yVJb);aYvYHfbkE7ZRNA>;bPQ-@`y=}O zkE^QZxrWCcQs?*+3b?3NDqNiYg>{{s?AyDWVr!A4Z;)hU8|CRKvKw<0+S+*R(LMC` z_Aq_vGUe4(B;d~Rr`6Ous-$~FuOB`lN&4*AaWx-!MZ+hT)OGNXtaDIbeEGE`>8*F) zS8@F&HFXcGYy2std32Isq|ME|^Y#aPfBr|t#~vFLcrXlX7`9J&{luT!7?2CHX~7HDf}A%sAzXBb8z2alwl6p+_(Yr-T*3sf&p zVppc{Y86XU4Dj1raGNiWIc^E5+K#lL?LI_KnkVon>7x*6mIEdf&0FS zsR!q9`2ua1jv--=#);$f(&7UfM!4`!32}lrK~0lvfH?9vLqL-xGGR!qR%7-;g)iTE zJNx!L#T~caOtaZU5!wbzMraf4K3s&vD=PA0(Rzak&D8 z^_x)1(mZjDpfbb5+aBYZ8*bsq>&N);Raf%2XLs`LZ`_SYl0;yJGcy|X2CD}K`RPMH zU`a;@k8R(<`pwty%!_}eYgsR`8QB#BM9YVW=BvyeeTBGQWodUeFC9M0*oU_A$hKdQ z%Vv4-yWiyE;UQ|ZI!+ue=@^)so8|P>6aeoV8|B7Ni~}$?U&WlGIC43@&;{q-rh4+9 z1musG%*>wLxy#%YH`%J~CvC;kQ`YW{JQXHSyv=pbJx5POfM z(jJO|m?D~7c@sy+vRhZ4!=ee z8y(C0h~gN`BhDqNE0P?5#o)r!M3g9MlFMZv$Pf$+)5xvF<}0*Ly^1yJh{l+}zJq@! zUu+|jb3{=ym28DnA~D68j}T2V5U+?g0tLLHzD4$;QM6-_Ty=)#$-{_`aTrdO_F@62 z3O>eJGM9`-pdM5SmDE^lL5(cE=>~)}j~yVKev5d%jK5Gu%%_=xYT|TaNsI-FSP(sP z0in4J1mU7cEm$9bsM45x4V(N&>d7eusoSX~JSUKnpn@a?4jkSaPD^i+U9$ zpzR`vDNc+)AV_JERJs%IcPZf1yVKUu*%INv2yuBDDRg#QZp$tBxiZneUd5s&CbH;i zqyx72m`Ev2DY5i`^jUxl$gIAMOz#l2mvb%707*qoM6N<$g1I90ZU6uP literal 0 HcmV?d00001 diff --git a/barecode/resources/icon_256.png b/barecode/resources/icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..f18f69f0a0011543f0489f9dfedd64a805fb6592 GIT binary patch literal 92012 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 z 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⪚4Hb1%fj?SzACZ{*++ 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 Hu0mjfg;jcs literal 0 HcmV?d00001 diff --git a/barecode/resources/icon_32.png b/barecode/resources/icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..5982252aa8f1c93a44484e8e786274d7fa67d756 GIT binary patch literal 2428 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 literal 0 HcmV?d00001 diff --git a/barecode/resources/icon_64.png b/barecode/resources/icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..1025e8420d50f7873e234399ddaadc79c4613ebf GIT binary patch literal 7750 zcmV-M9=YL(P)pK9VkpK!nN%R6!~rK%T5yUniedz(ICPt+iDMFzCguYgZHG>) zE&5SGX_~qTD zaYP^nk7`5|M1&X>P!NNn2nJ&e5Fu(hCIYG;f*1?NASj{%RR|GcRIGq8={l-P3;__V z7!Zi{h`6%M;L#l{{q~pi@3;y4fNEw9AVB$H(%UurAFMM|Jz@+*RRm?Qv`p`i$Ftwd z&!T(u3Dm<8_52>f(gNPsSP>LZRa6ATV2lNgs0LI7jfxmS5H!ZLe-RXI*P!XW0*C=) z0L|wop%@~Hps}0>MnN^As)&F}5~yH6gzn5N-7Q;?*){axu~9^t&p=R3Lc}BiNIq3Gq8f=vb8gZXD3Nj%5y?W8ERYBq0dUiEOm91s z4NreA2R!pMmT$kAyFc?`!tPzz>6t9NEP$l@YOG}@{4ORp~hAf z))-Vk1q=dN^2u~1-B=XWWV(5GY44H+P|Qx0n5|J`YY}NpB?4FzTX-rY>i%pl%F49UDz5~#%_jIspDzDPD#kz%q2#DWvl2r3pa2C;$|gAvmh zxaKVxlRi@s)FjIh17ZYg3?j+LB@0(##HeD8;EYW`m~BZ5PQ{3un!)wD{NeK-C9W)T z_&Yz0A4iB_;$WHek2`^_uXrO5UGzD0*F(5oj~GJH0qvWtpX_Tw1WY#CfD%wiu8_=L zA)9yu(G!P_RBTk4+%sxnih`~w53vGoPL&Uf)Rj13{ zpZ^znk2{79CqD;2=wrtHRn|ZI#jMBA9c*w8(U0WOylCm%f ztTjYzRk8cJA2D^{A%hX7JLOom%q$3GmSZR+8Ujx5y+z zu+4GJ1V<&IgCu9k$esw4x(?#16wgf-Y>eq;ELx8twB{&c(siRYxTBiaD2isOCkxaD zxLv2m@R0}DyJr`(Pk1tJ=8z-s3wzMzy_in7wRtJhq!EIMHol8O%ospJh+6G~=IECM z6d|*|(41lnh^@eNpwlB5$2e+om*|lg(Yi)MpmHvOuMZ6gDlVy7qJU)bWiX=YrX`92 z7{OQvqapFJ9jra_7~It6gV5DJvG!=ElUP^-Fd3|}U$xtpCjP6Y&S)%t%j5ks^ zLRn{Fpd|{GV}(bikSs>1hXaBLF4SYJg4oQ`8pPh0o(LxU6%8O}fny4`N%~urSnLGV zyx|<=B%^oIjsaJpRgd1x8oI}xz>PassRw;5g8IOL&hfjS-;g*$va3X6vwF*hrO@%L zl;*1tGe~q>444F}F$7Ek7L&9T+lx>bUycARy5@z8%`QNW0x^*jNic^RB(`~iXpxv? zKr~_p2UNL zA(4niB}AncYkvRBf6rP$k8^#D4^R-QOAzKk5?05K)*v*^q<53E=>gjeW z^wC}Hz3)D(wM0KggNLkr3IokT(5Mh%6P03Sg+U>ZVp!5`j&35v7!w)^HZN2&)onR; zB7D-+DjqLS5s%$7l$NTNko`W?o(dT=;cK zMhZ)$1lb&t46f?1u(Zfvb%~Gu{onA8*S(U}`Q*Qe@ntgw)Yue;*3L0^#8J$zj6e-| zL84)X!0uab!G$r@BSwQ2mKT?(#A2lQQR7(?U)fD#TAyhkkQOr(LR3N^SyODJ)yB?f zNLng16KN8S@)Ah^>6{RvXYbyw1ukki=|hHR&c$FO1h zc38h3qwxqM34?mw4&z52X8xYLu%RX_@8#l8{3B<*;tUq&7Z`_tv59IMNeoqTGNO{e zIf|kt7io$mLkiJSD73*u5lYRHQg_pdP*TLE*|!rTXh=u5s#scCLH&qxKk!#v^Q}vG z<{v+m5MnM^7A%R$9gM{|hpikK%a-GgXCb7G$Ef(arrW7l`0cM4@7=?2JY@T!2lC3( zU&Mu9V-IOyyj*hStp_gL9J~G+rtVD3{zsG+RKs-G)GApv$P5rK7nt z6-iXq*JI`%d6;LMbRySXc`1MUuD4@E7!Jo+YtkljT#abT9mIfjMC<5n*vQQGqgdz< zlbmv4cGlO--+4Q()4>l1obr@ELRA?J$Gr9I*K))6F6U2P_&oORe3Vh}*p6$#pk$_v zn>PB(1S&a01nTH9Mocm%lcf~P*#%LP2n!iTQ?++-?>t(M_{R^uhaX?|6;6EOv3Tzh z5v(&L@W@V_D6B5>>?fZ9 zfOQt{J%=B1FqePjb9~`{evG-P9(y0#HMz@%6>3vAAY)vqWF-rTO&AP;$+R`wK(>S= z3^Y>N1Sd;-_VTooPUPCFF6Hmv_b!YTYVR@DCj5vIYYfx9sic7>gjlc!F)0t&bj%Z3 z9fOH^AtB-_#{)P0g7ITJ8TMD%e#8;H?6eo;`h#MvC4@i-fj9m6tGV&Jm-33!U&zw( z3O+=ts-pA^in%r=Jk`|4h!GnjRd)&#Yfq@_misiJEdiVo5hJ)x#lqquaWvo~AATR# zUUeBKop?eDC1P>b;C(=hq1)~7Z$G(?FJF8GQ*&zw!6)g9fJ>F0=`H&+_xNL2?)OoY z5R|BfSwCj!j@z-uVHB1Y7rEf8Ujx87hxemIYsDmMIQ%d!yYK?O{@G8kas3+R=jXB3 zVT^11zmT^`%;1zj`|c2tHt~ zO&yx3bSlTv;sSs9?)UNhmz~Kicif4!Bmo$k3LaIL5R{EaY{#$J$Y|t|Xwd-Ey)I_= zE*5s|z=&c-0~Q{8jJLh@oxI?*Gr0A(+o`G^Vv_kf>j)uGd(WA#cnLRr{|e4I>(5wR zTB1MbV=buqWZex8N(1Z~L#`i7CJrT>kdqrx7WdB6tsEae_e1>n@(cN+;I-VGso=AZ0c!c@Ki}GP@HA+aVM}m6imq*BCMI|vG>kf z7%l834p#`n6`TmO2W;a<*Wbj`Uifl8@tMyiJg}C!t`Q8*CTuux|1Es!ljm{C7e2{B z`)_9PvE6B%#-`F(Q`uI?cx6g$Hxa&4wH1tU)Po_QwC7wTn0Z*LQQqtIp=`KkQ)bL5E^YvJA=P?bHD>#HdVd+{E;uk7H?N6=PFuHdb)s z0Xu*7b8M_p?}1VbHLTmbl^S@@d;gA8PyZ8s{hM2;I#r4=A>y1R1dsQgSHARgZv5dl zc+(qRmuiy6He@Iza;aczjl&Q#w{m*&EsW0NZkADg!rb0=KSZi_CQP-Z$n>O-= zPoBpMpZ83b78VfG7Ew!S%o>M@AtcfwE$WLx2$89&E*c{t1S;3Tn8XI7D)-%gKj*yl zo&4$9Z{wkbRn~3YLR4j}6W7WaS~P}eE2OHB%CYw7C$caMXoTn?1ZAeOEZ%lA(T}rB z1T@r5C=)TMlpZ2;8#WSqb9~_3k8$dY|CAel{_n)7#E=p?=Mq517@4XP8%>#EKs6+n zcU3NksGvbps+mIs8gpl*REbQ^6cdsR27O+8_M7?g=Rd>jnl;Q$Pcx3m#FM`#I@*L) z;-Tvf4Y%Vw_m z-gkM~nXl)82Ony{5lvCT7(?*BB}t`V5F@@GyJH&GQebqAzjuk=xTA@?L@uRNd5LSYBR1Y{nv!T5T#2jm31jm{^JxnI0O_ z24;F)ZoT79p7Vm!x#?FoQ&ru>p`&6<0v+!?FMQ4^Tz}OSyz%vCva+WIw&jidwKC`&*6q2 zew#PF{;ZsI#Z;Zn^xIXAM|SMsHD|wt@BZ+|OwUXa>k%df42rQf5hXF05{FYJRZ2*T z4<6g;aLsi$^33PGh;z^T7%>K1=HmibvDCF^)25AF@ad27ov&ZO5eFZ{(vC+Gk#RO< zfYuQaHXLyjeLIEsK7s3K#8juE-t{1>^LsGXCD03zs3E1Sn!@wq&Yi5E?(wDn^$EUx z@s~N`@I$G`KBdD5p-!aCxr$3J`zB9)=BZqK@ugVjGSx4wvfR*9C5~%Spi)gUIC=A` zLKH*9FuQ3Bu{Xot|M!n^%4sj>y6bMhIhSr4Bb9U68Um-k;CcM)yO;78Z#a|w(q3xs zaZ^)BcN&?VW9o?Gcx-V<@G<#lfay+$g*$(ffUh1WbCe8XBGls{OS^XP@-t55hVNg_ zIcL6t5JQUnoyP_{*Dl?isJ(L;vtk^hX0+W%0p-kaK}C8#b)tbD#Mn-@Ei{9CpYy zf>fw;Ol{aiTz?QNOMSo+f&tsbj{EGr>o&xXiGvli9wX7Gc>wE}o15leKXo2gT>MoI zJM<9h+UM{}LUCiT&T{dkmvi!SPv^o5{|__k*3+AwNiZTd&mClxEB!_lz+w_%u}Kn5 zDNNgX0BJhQ`@qb)^|+Z?{`sHI=jqRSKG*&1#%v9Vs95Xrxt`NbeJ%%V-O6Y%M19TL zLk?$TXYy1T#5z!QDn|F+$za#R7!BF~>%`HGu(G_we|i3?y#38@r1qZR1I{KQrkZf! zfd?Mom9IXF*Sz)|cI=*KZtMQ3UR6qVB4AQTG^O4tiID~$F&Il3J4g_(O}Hz8p;T5v z2q=cx0}kZZcizi$PkRaP|KNuh4hFcYLkJ1|opb!+*SB!P&9^YSb{$O3vgYU$S?Z6l zF`#)fQ0fDl6RUuOw1Vx7ZU%LNyFk*7T4R4)6*RZQ=< zg{sq`_I1WF$q}U0e!HP$_Ax|E?E^mKQMA18hR8I|5u17;l9=1{nmNqW6z6~RQ#|7Z zFX5V>UXOE@=upR)K(r0G#=A7-dl`WH74Z%Kvg4cg&iUWab0E)+QzSLyMyPy=%u{>Z~uXy0b>l`{@(Wy2ji%0 ze8NeLsx`#1N3jGCo#`3I58Tao=N~Y>PBs5rjf(1XH1KFl#gA^UgL95AeDTYi{H*8m z&2N97nfLXFD3vB-UA) zbsdM@}nVXfufd++71Klow3`K>E)Yt}KdX;Y%PWxg<5XDQ(q!j@t{Y?n?M z!c2hZjMyd>PA%?G{Gi1FCdx$6|7@=^ZpEH zx3IEfKxHgZ1>5b?8!xl_4|ij%CH9l)x4j9PSs{(eMPI*|cfRX=>|I!9YQOye2tEyG zlmeFIT%oMDRah+YXxe5;hZeCFPIK{4ilpL%@2ByL^j2x2M7o7$xkw|MsD|lv8&Fqa zx?Q3%%pGZ(zDp z%$OajCmtv!DAk=BCZaL-L4x$)JH z5-80Hn+92Js{Na(9=&Zxvu9y|CFX7o%=8TX-`|p^Km3>&LNgI6IUFZ;YUtNBQ|s0t zA_R>&uaAu)vR%_oUQW6~X_DrHc^VBoBAUaZg4L8~Ym+isXl%kzrokp0f)X0j^k+6- zqiGPb(A1DPOK?gK~ywI zV-W@4QsNYG;EAE0*mOGzI{_s{98AuE7px2hzL=qgK}$-QgY<9=r#O62>Fc zdrW3}saKaww2b2ItA?}yEq%a!I>c=mF8x_-1~^)UW_XMdBdL<@h%t|>=Z0s41K9@i z-Bruyd62mQ#3JF4%2>fut8m1Lr=T0wGxYOxI*xG-8@6o1-F*w=#XWTV81gW7nd(Zb zh?oKc6!0y-mAYk7tu*>6!JwR0qWFKrN3z96z`6>jq@si|HV;Nje96QWCdiQFg|-8f zv;gXBY-QNhWOu1+AMfTxBjaNh^nuGY+p(0uV$&aw0n*EeCNusS@V(QJ=7bsMtCr7-nIr%tbzzARYoZTG42eZGnn?>S&-J9AWqL#NR5uOUYmR>= zuf7@IO6W(KTWoY(yhIyR;;YJVLg`iYhk7Rtu!`P`gg!JT> zXgeR2oiPbSlqT3{qD?UmN2$hk7?H^V+oGjHR3`m7FSd-Cgu$vFT%x$6n+p96*vHKX^el2rPIRnKuPjEEz0=Zq5=<_5}B-a?mE$z71LXhRqear+&{^zkob`PvK7;4!8% zg+6*O{hwaKx|jYXtUH)`xB|J>Clfan)xr=aq@VYfgKg1hQK)JmCh2%HGo0Je7hH5|%0o{rIW^KIDQ(Oy3u!a5)*mN>R2!!iX`W3q zr1JPazCQ839oN+f>(WLrB7#~=7!L_`VEwDk#Z9kc?-d_Gy1jIV?)nYtY=>BTJh1UK z=TaSX412!wKN#P2BSu3)O=FuI#5`gq`>bdpFl8WXjCP+euI<+U1Bgu+R9l;E_P^E#n}iMB2#)yi;h(%+-2am*5Z9>4h zRNg{Nv!N2#%M<3Q$M11Yuo+yNI7tp;6X2T?n_Ne%rH8z&q$kg$w| z3S&&_a1zBKVz798J;F!8Ck-2y8ZS|EmDVJ`HYRnRjVg66$cUzaYb$BcqKxQH zGCe)G9Z>_uTC7XM5aZP)>RtCUy!#i79=sFLfaJ&LQ(r_dlAb^Ke~(|9pv?nt;{X5v M07*qoM6N<$f(K&>VgLXD literal 0 HcmV?d00001 diff --git a/barecode/resources/php_functions.json b/barecode/resources/php_functions.json new file mode 100644 index 0000000..1e81c97 --- /dev/null +++ b/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/barecode/resources/resources.qrc b/barecode/resources/resources.qrc new file mode 100644 index 0000000..f3b588a --- /dev/null +++ b/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/barecode/src/CMakeLists.txt b/barecode/src/CMakeLists.txt new file mode 100644 index 0000000..bb9abf8 --- /dev/null +++ b/barecode/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(core) +add_subdirectory(editor) +add_subdirectory(filetree) +add_subdirectory(highlighter) diff --git a/barecode/src/core/AboutDialog.cpp b/barecode/src/core/AboutDialog.cpp new file mode 100644 index 0000000..d6621d7 --- /dev/null +++ b/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.2.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/barecode/src/core/AboutDialog.h b/barecode/src/core/AboutDialog.h new file mode 100644 index 0000000..d90939a --- /dev/null +++ b/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/barecode/src/core/CMakeLists.txt b/barecode/src/core/CMakeLists.txt new file mode 100644 index 0000000..e3b822e --- /dev/null +++ b/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/barecode/src/core/IPlugin.h b/barecode/src/core/IPlugin.h new file mode 100644 index 0000000..c7c3571 --- /dev/null +++ b/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/barecode/src/core/MainWindow.cpp b/barecode/src/core/MainWindow.cpp new file mode 100644 index 0000000..38776bd --- /dev/null +++ b/barecode/src/core/MainWindow.cpp @@ -0,0 +1,412 @@ +#include "MainWindow.h" + +#include +#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; + +// --------------------------------------------------------------------------- +// Datei(en) von der Kommandozeile öffnen +// --------------------------------------------------------------------------- +void MainWindow::openFilesFromArguments(const QStringList &filePaths) +{ + for (const QString &path : filePaths) + { + const QFileInfo info(path); + if (info.exists() && info.isFile()) + { + m_editor->openFile(info.absoluteFilePath()); + } + } +} + +// --------------------------------------------------------------------------- +// 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); + + mBearbeiten->addSeparator(); + + m_actFuncList = mBearbeiten->addAction(tr("&Projektfunktionen…"), this, &MainWindow::onShowFunctionList); + m_actFuncList->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_P); + + m_actDeadCode = mBearbeiten->addAction(tr("&Tote Funktionen suchen…"), this, &MainWindow::onShowDeadCode); + m_actDeadCode->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_T); + + // ---- 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); + + mAnsicht->addSeparator(); + + // Sprachauswahl + QMenu *mSprache = mAnsicht->addMenu(tr("Sprache")); + m_langGroup = new QActionGroup(this); + m_langGroup->setExclusive(true); + + const QSettings langSettings(QSettings::IniFormat, QSettings::UserScope, + "BareCode", "BareCode"); + const QString currentLocale = langSettings.value("language/locale", + QLocale::system().name()).toString(); + + struct LangEntry { QString locale; QString label; }; + const QList languages = { + { "de", "Deutsch" }, + { "en", "English" }, + }; + + for (const LangEntry &lang : languages) + { + QAction *act = mSprache->addAction(lang.label); + act->setCheckable(true); + act->setData(lang.locale); + act->setChecked(currentLocale.startsWith(lang.locale)); + m_langGroup->addAction(act); + connect(act, &QAction::triggered, this, [this, lang]() + { + onLanguageChanged(lang.locale); + }); + } + + // ---- 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); +} + +void MainWindow::onLanguageChanged(const QString &locale) +{ + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + s.setValue("language/locale", locale); + + QMessageBox::information(this, + tr("Sprache geändert"), + tr("Die Sprache wird beim nächsten Start von BareCode aktiv.") + ); +} + +// --------------------------------------------------------------------------- +// Slots – Hilfe +// --------------------------------------------------------------------------- +void MainWindow::onAbout() +{ + AboutDialog dlg(this); + dlg.exec(); +} + +// --------------------------------------------------------------------------- +// Slots – Projekt +// --------------------------------------------------------------------------- +void MainWindow::onShowDeadCode() +{ + m_editor->showDeadCode(); +} + +void MainWindow::onShowFunctionList() +{ + m_editor->showFunctionList(); +} + +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/barecode/src/core/MainWindow.h b/barecode/src/core/MainWindow.h new file mode 100644 index 0000000..beced93 --- /dev/null +++ b/barecode/src/core/MainWindow.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#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; + + // Datei(en) öffnen, die beim Programmstart per Kommandozeile übergeben + // wurden — z. B. durch Doppelklick auf eine Datei im Dateibrowser + // ("Öffnen mit BareCode"). + void openFilesFromArguments(const QStringList &filePaths); + +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(); + void onShowFunctionList(); + void onShowDeadCode(); + // Ansicht + void onToggleDarkMode(bool checked); + void onLanguageChanged(const QString &locale); + // 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_actFuncList = nullptr; + QAction *m_actDeadCode = nullptr; + QAction *m_actDarkMode = nullptr; + QActionGroup *m_langGroup = nullptr; + QAction *m_actAbout = nullptr; +}; diff --git a/barecode/src/core/ProjectManager.cpp b/barecode/src/core/ProjectManager.cpp new file mode 100644 index 0000000..c4ee879 --- /dev/null +++ b/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/barecode/src/core/ProjectManager.h b/barecode/src/core/ProjectManager.h new file mode 100644 index 0000000..9aedfcc --- /dev/null +++ b/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/barecode/src/core/Settings.cpp b/barecode/src/core/Settings.cpp new file mode 100644 index 0000000..4ebc21f --- /dev/null +++ b/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/barecode/src/core/Settings.h b/barecode/src/core/Settings.h new file mode 100644 index 0000000..1122864 --- /dev/null +++ b/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/barecode/src/core/ThemeManager.cpp b/barecode/src/core/ThemeManager.cpp new file mode 100644 index 0000000..d9c9ba7 --- /dev/null +++ b/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/barecode/src/core/ThemeManager.h b/barecode/src/core/ThemeManager.h new file mode 100644 index 0000000..4096918 --- /dev/null +++ b/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/barecode/src/editor/CMakeLists.txt b/barecode/src/editor/CMakeLists.txt new file mode 100644 index 0000000..c730a1f --- /dev/null +++ b/barecode/src/editor/CMakeLists.txt @@ -0,0 +1,49 @@ +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 + FunctionScanner.cpp + FunctionScanner.h + FunctionIndex.cpp + FunctionIndex.h + FunctionListPanel.cpp + FunctionListPanel.h + FunctionListDialog.cpp + FunctionListDialog.h + DeadCodeAnalyzer.cpp + DeadCodeAnalyzer.h + DeadCodeDialog.cpp + DeadCodeDialog.h + VariableCompleter.cpp + VariableCompleter.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/barecode/src/editor/CodeEditor.cpp b/barecode/src/editor/CodeEditor.cpp new file mode 100644 index 0000000..948faa8 --- /dev/null +++ b/barecode/src/editor/CodeEditor.cpp @@ -0,0 +1,762 @@ +#include "CodeEditor.h" +#include "LineNumberArea.h" +#include "ColorIndicator.h" +#include "SignatureHelper.h" +#include "FunctionIndex.h" +#include "VariableCompleter.h" + +#include "core/Settings.h" +#include "highlighter/HighlighterFactory.h" + +#include +#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); + m_varCompleter = new VariableCompleter(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::setFunctionIndex(FunctionIndex *index) +{ + m_functionIndex = index; +} + +void CodeEditor::mouseDoubleClickEvent(QMouseEvent *event) +{ + // Zuerst normales Verhalten — markiert das Wort unter dem Cursor + QPlainTextEdit::mouseDoubleClickEvent(event); + + if (!m_functionIndex || !m_functionIndex->isReady()) + { + return; + } + + // Markiertes Wort auslesen + const QString word = textCursor().selectedText().trimmed(); + if (word.isEmpty() || word.contains(' ')) + { + return; + } + + // Im Funktionsindex nachschlagen + const FunctionScanner::FunctionInfo info = m_functionIndex->lookup(word); + if (info.filePath.isEmpty()) + { + return; // Nicht gefunden — normales Verhalten bleibt + } + + // Nicht zur eigenen Definition springen wenn wir bereits dort sind + if (info.filePath == m_filePath && info.line == textCursor().blockNumber() + 1) + { + return; + } + + emit navigateToRequested(info.filePath, info.line); +} + +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 + Klammerzugehörigkeit +// --------------------------------------------------------------------------- +void CodeEditor::highlightCurrentLine() +{ + QList extraSelections; + + if (!isReadOnly()) + { + // Aktuelle Zeile hervorheben + QTextEdit::ExtraSelection lineSelection; + lineSelection.format.setBackground(palette().color(QPalette::AlternateBase)); + lineSelection.format.setProperty(QTextFormat::FullWidthSelection, true); + lineSelection.cursor = textCursor(); + lineSelection.cursor.clearSelection(); + extraSelections.append(lineSelection); + + // Klammerzugehörigkeit + matchBrackets(extraSelections); + } + + setExtraSelections(extraSelections); +} + +void CodeEditor::matchBrackets(QList &selections) +{ + static const QString openBrackets = "({["; + static const QString closeBrackets = ")}]"; + + QTextCursor cursor = textCursor(); + const QString blockText = cursor.block().text(); + const int col = cursor.columnNumber(); + + // Zeichen unter oder links vom Cursor prüfen + QChar ch; + int charPos = -1; + + // Zuerst Zeichen unter dem Cursor + if (col < blockText.length()) + { + ch = blockText[col]; + if (openBrackets.contains(ch) || closeBrackets.contains(ch)) + { + charPos = col; + } + } + + // Dann Zeichen links vom Cursor + if (charPos == -1 && col > 0) + { + ch = blockText[col - 1]; + if (openBrackets.contains(ch) || closeBrackets.contains(ch)) + { + charPos = col - 1; + } + } + + if (charPos == -1) + { + return; + } + + // Passende Klammer suchen + const bool isOpen = openBrackets.contains(ch); + const int bracketIndex = isOpen + ? openBrackets.indexOf(ch) + : closeBrackets.indexOf(ch); + const QChar matchChar = isOpen + ? closeBrackets[bracketIndex] + : openBrackets[bracketIndex]; + + // Dokumentposition der gefundenen Klammer + const int startPos = cursor.block().position() + charPos; + + // Passende Klammer suchen — vorwärts oder rückwärts + int depth = 0; + int matchPos = -1; + + if (isOpen) + { + // Vorwärts suchen + QTextCursor search(document()); + search.setPosition(startPos); + + while (!search.atEnd()) + { + search.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + const QChar c = search.selectedText()[0]; + search.clearSelection(); + + if (c == ch) { ++depth; } + else if (c == matchChar) + { + --depth; + if (depth == 0) + { + matchPos = search.position() - 1; + break; + } + } + } + } + else + { + // Rückwärts suchen + QTextCursor search(document()); + search.setPosition(startPos + 1); + + while (search.position() > 0) + { + search.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + const QChar c = search.selectedText()[0]; + search.clearSelection(); + + if (c == ch) { ++depth; } + else if (c == matchChar) + { + --depth; + if (depth == 0) + { + matchPos = search.position(); + break; + } + } + } + } + + // Formatierung + QTextCharFormat matchFormat; + if (matchPos >= 0) + { + // Gefunden — beide Klammern grün hervorheben + matchFormat.setBackground(QColor("#1a5a1a")); + matchFormat.setForeground(QColor("#88ff88")); + matchFormat.setFontWeight(QFont::Bold); + } + else + { + // Kein Match — rot markieren + matchFormat.setBackground(QColor("#5a1a1a")); + matchFormat.setForeground(QColor("#ff8888")); + matchFormat.setFontWeight(QFont::Bold); + } + + // Öffnende / schließende Klammer markieren + QTextEdit::ExtraSelection sel1; + sel1.cursor = QTextCursor(document()); + sel1.cursor.setPosition(startPos); + sel1.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + sel1.format = matchFormat; + selections.append(sel1); + + // Passende Klammer markieren (nur wenn gefunden) + if (matchPos >= 0) + { + QTextEdit::ExtraSelection sel2; + sel2.cursor = QTextCursor(document()); + sel2.cursor.setPosition(matchPos); + sel2.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + sel2.format = matchFormat; + selections.append(sel2); + } +} + +// --------------------------------------------------------------------------- +// 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()); + + // Wenn die Selektion genau am Anfang des letzten Blocks endet, + // diesen Block nicht mit einbeziehen — der Cursor steht dort nur + // mit Position 0, der Nutzer hat die Zeile nicht markiert + if (cursor.hasSelection() && + cursor.selectionEnd() == endBlock.position() && + endBlock != startBlock) + { + endBlock = endBlock.previous(); + } + + cursor.beginEditBlock(); + for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next()) + { + const QString lineText = b.text(); + int toRemove = 0; + + if (m_settings->useSpacesForTabs()) + { + for (int i = 0; i < tabSize && i < lineText.length(); ++i) + { + if (lineText[i] == ' ') { ++toRemove; } + else { break; } + } + } + else + { + 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()) + { + QTextBlock startBlock = document()->findBlock(cursor.selectionStart()); + QTextBlock endBlock = document()->findBlock(cursor.selectionEnd()); + + // Gleiche Korrektur: Cursor am Zeilenanfang → Zeile nicht einrücken + if (cursor.selectionEnd() == endBlock.position() && + endBlock != startBlock) + { + endBlock = endBlock.previous(); + } + + 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); + + // Variablen-Popup nach jedem Tastendruck aktualisieren + m_varCompleter->handleKeyPress(event); +} + +// --------------------------------------------------------------------------- +// Fokus verloren — z. B. beim Wechsel zu einem anderen Tab. +// Ein noch offenes Variablen-Popup muss hier geschlossen werden, sonst +// bleibt es als verwaistes Fenster stehen und kann bei mehreren offenen +// Dateien den Fokus blockieren. +// --------------------------------------------------------------------------- +void CodeEditor::focusOutEvent(QFocusEvent *event) +{ + QPlainTextEdit::focusOutEvent(event); + m_varCompleter->notifyFocusLost(); +} + diff --git a/barecode/src/editor/CodeEditor.h b/barecode/src/editor/CodeEditor.h new file mode 100644 index 0000000..af87818 --- /dev/null +++ b/barecode/src/editor/CodeEditor.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include +#include +#include + +class LineNumberArea; +class Settings; +class SyntaxHighlighter; +class ColorIndicator; +class SignatureHelper; +class FunctionIndex; +class VariableCompleter; + +// --------------------------------------------------------------------------- +// 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(); } + + void setFunctionIndex(FunctionIndex *index); + +signals: + void fileSaved(const QString &filePath); + void navigateToRequested(const QString &filePath, int line); + +protected: + void resizeEvent(QResizeEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseDoubleClickEvent(QMouseEvent *event) override; + void focusOutEvent(QFocusEvent *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); + void matchBrackets(QList &selections); + + Settings *m_settings = nullptr; + LineNumberArea *m_lineNumberArea = nullptr; + SyntaxHighlighter *m_highlighter = nullptr; + ColorIndicator *m_colorIndicator = nullptr; + SignatureHelper *m_signatureHelper = nullptr; + FunctionIndex *m_functionIndex = nullptr; + VariableCompleter *m_varCompleter = nullptr; + QString m_filePath; +}; diff --git a/barecode/src/editor/ColorIndicator.cpp b/barecode/src/editor/ColorIndicator.cpp new file mode 100644 index 0000000..60f4e04 --- /dev/null +++ b/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/barecode/src/editor/ColorIndicator.h b/barecode/src/editor/ColorIndicator.h new file mode 100644 index 0000000..2d19ede --- /dev/null +++ b/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/barecode/src/editor/DeadCodeAnalyzer.cpp b/barecode/src/editor/DeadCodeAnalyzer.cpp new file mode 100644 index 0000000..3a930d6 --- /dev/null +++ b/barecode/src/editor/DeadCodeAnalyzer.cpp @@ -0,0 +1,181 @@ +#include "DeadCodeAnalyzer.h" + +#include +#include +#include +#include +#include +#include +#include + +DeadCodeAnalyzer::DeadCodeAnalyzer(QObject *parent) + : QObject(parent) +{ + m_scanner = new FunctionScanner(this); +} + +QList DeadCodeAnalyzer::analyze( + const QString &projectRoot, + const QStringList &extensions, + const QStringList &excludeDirs) const +{ + // ----------------------------------------------------------------------- + // Schritt 1: Alle Dateien sammeln (mit Exclude-Filter) + // ----------------------------------------------------------------------- + QStringList allFiles; + QDirIterator it(projectRoot, extensions, QDir::Files, + QDirIterator::Subdirectories); + + while (it.hasNext()) + { + const QString path = it.next(); + + // Exclude-Verzeichnisse prüfen + bool excluded = false; + if (!excludeDirs.isEmpty()) + { + const QStringList parts = path.split('/'); + for (const QString &excl : excludeDirs) + { + if (parts.contains(excl.trimmed(), Qt::CaseInsensitive)) + { + excluded = true; + break; + } + } + } + + if (!excluded) + { + allFiles.append(path); + } + } + + const int totalFiles = allFiles.size(); + + // ----------------------------------------------------------------------- + // Schritt 2: Alle Funktionsdefinitionen aus nicht-excluded Dateien + // ----------------------------------------------------------------------- + QHash definitions; + + for (const QString &path : allFiles) + { + const QList funcs = m_scanner->scanFile(path); + for (const FunctionScanner::FunctionInfo &func : funcs) + { + if (func.name.startsWith("__")) + { + continue; + } + const QString key = func.name.toLower(); + if (!definitions.contains(key)) + { + definitions.insert(key, func); + } + } + } + + if (definitions.isEmpty()) + { + return {}; + } + + // ----------------------------------------------------------------------- + // Schritt 3: Alle Dateien EINMAL lesen, alle Aufrufe sammeln + // ----------------------------------------------------------------------- + QSet calledFunctions; + + static const QRegularExpression identifierRegex( + R"((?:->|::|\b)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\s*\()" + R"(|['"]([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)['"])" + ); + + static const QRegularExpression defLineRegex( + R"(\bfunction\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*))" + ); + + int filesScanned = 0; + + for (const QString &filePath : allFiles) + { + ++filesScanned; + + // Fortschritt signalisieren + emit progressUpdate(filesScanned, totalFiles, + QFileInfo(filePath).fileName()); + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + continue; + } + + QTextStream stream(&file); + stream.setEncoding(QStringConverter::Utf8); + + while (!stream.atEnd()) + { + const QString line = stream.readLine(); + const QString trimmed = line.trimmed(); + + if (trimmed.startsWith("//") || + trimmed.startsWith("*") || + trimmed.startsWith("#") || + trimmed.startsWith("/*")) + { + continue; + } + + // Definitionen auf dieser Zeile nicht als Aufruf werten + QSet definedOnThisLine; + { + QRegularExpressionMatchIterator dit = defLineRegex.globalMatch(line); + while (dit.hasNext()) + { + definedOnThisLine.insert(dit.next().captured(1).toLower()); + } + } + + QRegularExpressionMatchIterator mit = identifierRegex.globalMatch(line); + while (mit.hasNext()) + { + const QRegularExpressionMatch match = mit.next(); + const QString name = match.captured(1).isEmpty() + ? match.captured(2).toLower() + : match.captured(1).toLower(); + + if (name.isEmpty() || definedOnThisLine.contains(name)) + { + continue; + } + + if (definitions.contains(name)) + { + calledFunctions.insert(name); + } + } + } + } + + // ----------------------------------------------------------------------- + // Schritt 4: Nicht aufgerufene Funktionen zurückgeben + // ----------------------------------------------------------------------- + QList dead; + + for (auto it2 = definitions.begin(); it2 != definitions.end(); ++it2) + { + if (!calledFunctions.contains(it2.key())) + { + const FunctionScanner::FunctionInfo &func = it2.value(); + DeadFunction d; + d.info = func; + d.reason = func.className.isEmpty() + ? QObject::tr("Globale Funktion — kein Aufruf gefunden") + : QObject::tr("Methode von %1 — kein Aufruf gefunden") + .arg(func.className); + dead.append(d); + } + } + + return dead; +} diff --git a/barecode/src/editor/DeadCodeAnalyzer.h b/barecode/src/editor/DeadCodeAnalyzer.h new file mode 100644 index 0000000..0431fde --- /dev/null +++ b/barecode/src/editor/DeadCodeAnalyzer.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +#include "FunctionScanner.h" + +// --------------------------------------------------------------------------- +// DeadCodeAnalyzer – Findet Funktionen die definiert aber nie aufgerufen werden. +// --------------------------------------------------------------------------- +class DeadCodeAnalyzer : public QObject +{ + Q_OBJECT + +public: + struct DeadFunction + { + FunctionScanner::FunctionInfo info; + QString reason; + }; + + explicit DeadCodeAnalyzer(QObject *parent = nullptr); + + // excludeDirs: Verzeichnisnamen die komplett übersprungen werden + // z.B. {"vendor", "lib", "node_modules"} + QList analyze(const QString &projectRoot, + const QStringList &extensions = {"*.php"}, + const QStringList &excludeDirs = {}) const; + +signals: + // Fortschritt während der Analyse (läuft im Thread) + void progressUpdate(int filesScanned, int filesTotal, + const QString ¤tFile) const; + +private: + FunctionScanner *m_scanner = nullptr; +}; diff --git a/barecode/src/editor/DeadCodeDialog.cpp b/barecode/src/editor/DeadCodeDialog.cpp new file mode 100644 index 0000000..9669c85 --- /dev/null +++ b/barecode/src/editor/DeadCodeDialog.cpp @@ -0,0 +1,461 @@ +#include "DeadCodeDialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DeadCodeDialog::DeadCodeDialog(QWidget *parent) + : QDialog(parent, Qt::Window) +{ + setWindowTitle(tr("Tote Funktionen – BareCode")); + setMinimumSize(650, 500); + + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + if (s.contains("deadcode/geometry")) + { + restoreGeometry(s.value("deadcode/geometry").toByteArray()); + } + else + { + resize(780, 620); + } + + m_analyzer = new DeadCodeAnalyzer(this); + m_watcher = new QFutureWatcher>(this); + + connect(m_watcher, &QFutureWatcher>::finished, + this, &DeadCodeDialog::onAnalysisFinished); + + // Fortschritts-Signal aus dem Analyzer-Thread sicher in den UI-Thread leiten + connect(m_analyzer, &DeadCodeAnalyzer::progressUpdate, + this, &DeadCodeDialog::onProgressUpdate, + Qt::QueuedConnection); + + setupUi(); +} + +// --------------------------------------------------------------------------- +// UI +// --------------------------------------------------------------------------- +void DeadCodeDialog::setupUi() +{ + QVBoxLayout *root = new QVBoxLayout(this); + root->setSpacing(8); + root->setContentsMargins(12, 12, 12, 12); + + // ---- Warnbox ---- + QFrame *warningBox = new QFrame(this); + warningBox->setStyleSheet( + "QFrame {" + " background: #3a2a00;" + " border: 1px solid #7a5a00;" + " border-radius: 4px;" + "}" + ); + QHBoxLayout *warnLayout = new QHBoxLayout(warningBox); + warnLayout->setContentsMargins(8, 6, 8, 6); + + QLabel *warnIcon = new QLabel(warningBox); + warnIcon->setFixedSize(20, 20); + warnIcon->setStyleSheet( + "background: #ffcc00;" + "color: #1a1a00;" + "font-weight: bold;" + "font-size: 13px;" + "border-radius: 10px;" + ); + warnIcon->setText("!"); + warnIcon->setAlignment(Qt::AlignCenter); + warnLayout->addWidget(warnIcon); + + QLabel *warnText = new QLabel( + tr("Kandidatenliste — kein Aufruf per Regex gefunden. " + "Dynamische Aufrufe (call_user_func, Strings, Hooks) werden nicht erkannt. " + "Bitte vor dem Löschen manuell prüfen."), + warningBox + ); + warnText->setWordWrap(true); + warnText->setStyleSheet("color: #ffcc88;"); + warnLayout->addWidget(warnText, 1); + root->addWidget(warningBox); + + // ---- Exclude-Verzeichnisse ---- + QHBoxLayout *excludeRow = new QHBoxLayout(); + excludeRow->addWidget(new QLabel(tr("Ausschließen:"), this)); + + m_excludeEdit = new QLineEdit(this); + m_excludeEdit->setPlaceholderText(tr("vendor lib node_modules (leerzeichen-getrennt)")); + m_excludeEdit->setToolTip(tr( + "Verzeichnisnamen die bei der Analyse übersprungen werden.\n" + "Leerzeichen-getrennt, z.B.: vendor lib node_modules cache" + )); + + // Letzte Einstellung wiederherstellen + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + m_excludeEdit->setText(s.value("deadcode/excludeDirs", "vendor lib node_modules").toString()); + + excludeRow->addWidget(m_excludeEdit, 1); + + // Verzeichnis-Auswahl Button + QPushButton *btnBrowse = new QPushButton(tr("+ Verzeichnis"), this); + btnBrowse->setToolTip(tr("Verzeichnis aus dem Projekt auswählen und zur Ausschlussliste hinzufügen")); + connect(btnBrowse, &QPushButton::clicked, this, [this]() + { + const QString startPath = m_projectRoot.isEmpty() + ? QDir::homePath() + : m_projectRoot; + + const QString dir = QFileDialog::getExistingDirectory( + this, + tr("Verzeichnis ausschließen"), + startPath, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks + ); + + if (dir.isEmpty()) + { + return; + } + + // Nur den letzten Verzeichnisnamen verwenden, nicht den vollen Pfad + // So funktioniert der Exclude auch für gleichnamige Unterverzeichnisse + const QString dirName = QFileInfo(dir).fileName(); + + // Prüfen ob bereits in der Liste + const QStringList current = m_excludeEdit->text() + .simplified() + .split(' ', Qt::SkipEmptyParts); + if (current.contains(dirName, Qt::CaseInsensitive)) + { + return; + } + + // Anhängen + QString newText = m_excludeEdit->text().trimmed(); + if (!newText.isEmpty()) + { + newText += ' '; + } + newText += dirName; + m_excludeEdit->setText(newText); + }); + excludeRow->addWidget(btnBrowse); + + // Löschen-Button — ganzes Feld leeren + QPushButton *btnClear = new QPushButton(tr("✕"), this); + btnClear->setFixedWidth(28); + btnClear->setFlat(true); + btnClear->setToolTip(tr("Ausschlussliste leeren")); + connect(btnClear, &QPushButton::clicked, this, [this]() + { + m_excludeEdit->clear(); + }); + excludeRow->addWidget(btnClear); + + root->addLayout(excludeRow); + + // ---- Steuerleiste ---- + QHBoxLayout *ctrlRow = new QHBoxLayout(); + + m_btnAnalyze = new QPushButton(tr("Analyse starten"), this); + ctrlRow->addWidget(m_btnAnalyze); + + m_btnExport = new QPushButton(tr("Als TXT exportieren"), this); + m_btnExport->setEnabled(false); + ctrlRow->addWidget(m_btnExport); + + ctrlRow->addStretch(); + + m_statusLabel = new QLabel(this); + m_statusLabel->setStyleSheet("color: palette(mid);"); + ctrlRow->addWidget(m_statusLabel); + + root->addLayout(ctrlRow); + + // ---- Fortschrittsbereich ---- + m_progress = new QProgressBar(this); + m_progress->setRange(0, 100); + m_progress->setTextVisible(true); + m_progress->setFormat("%v / %m Dateien"); + m_progress->hide(); + root->addWidget(m_progress); + + m_progressLabel = new QLabel(this); + m_progressLabel->setStyleSheet("color: palette(mid); font-size: 11px;"); + m_progressLabel->hide(); + root->addWidget(m_progressLabel); + + // ---- Ergebnistabelle ---- + m_results = new QTreeWidget(this); + m_results->setColumnCount(4); + m_results->setHeaderLabels({ + tr("Funktion"), + tr("Klasse"), + tr("Datei"), + tr("Zeile") + }); + m_results->setRootIsDecorated(false); + m_results->setAlternatingRowColors(true); + m_results->setSortingEnabled(true); + m_results->sortByColumn(0, Qt::AscendingOrder); + m_results->setSelectionMode(QAbstractItemView::SingleSelection); + + m_results->header()->setSectionResizeMode(0, QHeaderView::Interactive); + m_results->header()->setSectionResizeMode(1, QHeaderView::Interactive); + m_results->header()->setSectionResizeMode(2, QHeaderView::Stretch); + m_results->header()->setSectionResizeMode(3, QHeaderView::Fixed); + m_results->header()->resizeSection(0, 200); + m_results->header()->resizeSection(1, 120); + m_results->header()->resizeSection(3, 60); + + QFont mono("Monospace"); + mono.setStyleHint(QFont::Monospace); + m_results->setFont(mono); + + root->addWidget(m_results, 1); + + // ---- Verbindungen ---- + connect(m_btnAnalyze, &QPushButton::clicked, this, &DeadCodeDialog::onAnalyze); + connect(m_btnExport, &QPushButton::clicked, this, &DeadCodeDialog::onExportClicked); + connect(m_results, &QTreeWidget::itemActivated, + this, &DeadCodeDialog::onItemActivated); +} + +// --------------------------------------------------------------------------- +// Öffentliche Schnittstelle +// --------------------------------------------------------------------------- +void DeadCodeDialog::setProjectRoot(const QString &path) +{ + // Alte Exclude-Liste für das vorherige Projekt speichern + if (!m_projectRoot.isEmpty()) + { + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + const QString oldKey = "deadcode/exclude/" + + QString(m_projectRoot).replace('/', '_').replace('\\', '_'); + s.setValue(oldKey, m_excludeEdit->text()); + } + + m_projectRoot = path; + m_results->clear(); + m_statusLabel->setText(QString()); + m_btnExport->setEnabled(false); + + // Exclude-Liste für das neue Projekt laden + if (!path.isEmpty()) + { + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + const QString key = "deadcode/exclude/" + + QString(path).replace('/', '_').replace('\\', '_'); + + // Projektspezifisch vorhanden? Sonst globalen Fallback nehmen + const QString saved = s.value(key, + s.value("deadcode/excludeDirs", "vendor lib node_modules").toString() + ).toString(); + + m_excludeEdit->setText(saved); + } +} + +// --------------------------------------------------------------------------- +// Analyse starten +// --------------------------------------------------------------------------- +void DeadCodeDialog::onAnalyze() +{ + if (m_projectRoot.isEmpty()) + { + QMessageBox::information(this, tr("Analyse"), + tr("Bitte zuerst ein Projekt öffnen.")); + return; + } + + if (m_watcher->isRunning()) + { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + + // Exclude-Liste projektspezifisch speichern + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + const QString key = "deadcode/exclude/" + + QString(m_projectRoot).replace('/', '_').replace('\\', '_'); + s.setValue(key, m_excludeEdit->text()); + s.setValue("deadcode/excludeDirs", m_excludeEdit->text()); // globaler Fallback + + const QStringList excludeDirs = m_excludeEdit->text() + .simplified() + .split(' ', Qt::SkipEmptyParts); + + m_results->clear(); + m_btnAnalyze->setEnabled(false); + m_btnExport->setEnabled(false); + m_progress->setValue(0); + m_progress->setMaximum(0); // Unbestimmter Modus bis wir die Dateizahl kennen + m_progress->show(); + m_progressLabel->setText(tr("Dateien werden gezählt…")); + m_progressLabel->show(); + m_statusLabel->setText(tr("Analysiere…")); + + const QString root = m_projectRoot; + DeadCodeAnalyzer *analyzer = m_analyzer; + + QFuture> future = + QtConcurrent::run([analyzer, root, excludeDirs]() + { + return analyzer->analyze(root, {"*.php"}, excludeDirs); + }); + + m_watcher->setFuture(future); +} + +// --------------------------------------------------------------------------- +// Fortschritt aktualisieren (QueuedConnection — Thread-sicher) +// --------------------------------------------------------------------------- +void DeadCodeDialog::onProgressUpdate(int filesScanned, int filesTotal, + const QString ¤tFile) +{ + if (m_progress->maximum() != filesTotal) + { + m_progress->setMaximum(filesTotal); + } + m_progress->setValue(filesScanned); + m_progressLabel->setText(tr("(%1 / %2) %3") + .arg(filesScanned) + .arg(filesTotal) + .arg(currentFile)); +} + +// --------------------------------------------------------------------------- +// Analyse abgeschlossen +// --------------------------------------------------------------------------- +void DeadCodeDialog::onAnalysisFinished() +{ + m_progress->hide(); + m_progressLabel->hide(); + m_btnAnalyze->setEnabled(true); + + if (m_watcher->isCanceled()) + { + return; + } + + const QList dead = m_watcher->result(); + + m_results->setSortingEnabled(false); + + for (const DeadCodeAnalyzer::DeadFunction &d : dead) + { + QTreeWidgetItem *item = new QTreeWidgetItem(m_results); + item->setText(0, d.info.signature); + item->setText(1, d.info.className.isEmpty() ? tr("(global)") : d.info.className); + item->setText(2, QFileInfo(d.info.filePath).fileName()); + item->setText(3, QString::number(d.info.line)); + item->setToolTip(0, d.reason); + item->setToolTip(2, d.info.filePath); + item->setData(0, Qt::UserRole, d.info.filePath); + item->setData(0, Qt::UserRole + 1, d.info.line); + + if (d.info.className.isEmpty()) + { + item->setForeground(1, QColor("#888888")); + } + } + + m_results->setSortingEnabled(true); + m_results->sortByColumn(0, Qt::AscendingOrder); + + if (dead.isEmpty()) + { + m_statusLabel->setText(tr("✓ Keine ungenutzten Funktionen gefunden.")); + m_statusLabel->setStyleSheet("color: #44bb44;"); + } + else + { + m_statusLabel->setText(tr("%1 Kandidaten gefunden").arg(dead.size())); + m_statusLabel->setStyleSheet("color: palette(mid);"); + m_btnExport->setEnabled(true); + } +} + +// --------------------------------------------------------------------------- +// Klick auf Treffer +// --------------------------------------------------------------------------- +void DeadCodeDialog::onItemActivated(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) + { + emit fileLineRequested(path, line); + } +} + +// --------------------------------------------------------------------------- +// Export +// --------------------------------------------------------------------------- +void DeadCodeDialog::onExportClicked() +{ + const QString path = QFileDialog::getSaveFileName( + this, + tr("Ergebnis exportieren"), + QString("barecode_deadcode_%1.txt") + .arg(QDateTime::currentDateTime().toString("yyyyMMdd_HHmm")), + tr("Textdateien (*.txt)") + ); + if (path.isEmpty()) { return; } + + QFile file(path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QMessageBox::warning(this, tr("Export"), + tr("Datei konnte nicht geschrieben werden:\n%1").arg(path)); + return; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + + out << "BareCode – Analyse ungenutzter Funktionen\n"; + out << "Projekt: " << m_projectRoot << "\n"; + out << "Ausgeschlossen: " << m_excludeEdit->text() << "\n"; + out << "Datum: " << QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm") << "\n"; + out << QString("─").repeated(70) << "\n\n"; + + for (int i = 0; i < m_results->topLevelItemCount(); ++i) + { + QTreeWidgetItem *item = m_results->topLevelItem(i); + out << item->text(0) << "\n"; + out << " Klasse: " << item->text(1) << "\n"; + out << " Datei: " << item->toolTip(2) << "\n"; + out << " Zeile: " << item->text(3) << "\n\n"; + } + + out << QString("─").repeated(70) << "\n"; + out << m_results->topLevelItemCount() << " Kandidaten\n"; + out << "Hinweis: Dynamische Aufrufe werden nicht erkannt.\n"; + + QMessageBox::information(this, tr("Export"), + tr("Exportiert nach:\n%1").arg(path)); +} + +// --------------------------------------------------------------------------- +// Fenstergeometrie speichern +// --------------------------------------------------------------------------- +void DeadCodeDialog::closeEvent(QCloseEvent *event) +{ + if (m_watcher->isRunning()) + { + m_watcher->cancel(); + } + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + s.setValue("deadcode/geometry", saveGeometry()); + event->accept(); +} diff --git a/barecode/src/editor/DeadCodeDialog.h b/barecode/src/editor/DeadCodeDialog.h new file mode 100644 index 0000000..f7a4028 --- /dev/null +++ b/barecode/src/editor/DeadCodeDialog.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DeadCodeAnalyzer.h" + +class DeadCodeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DeadCodeDialog(QWidget *parent = nullptr); + + void setProjectRoot(const QString &path); + +signals: + void fileLineRequested(const QString &filePath, int line); + +private slots: + void onAnalyze(); + void onAnalysisFinished(); + void onProgressUpdate(int filesScanned, int filesTotal, + const QString ¤tFile); + void onItemActivated(QTreeWidgetItem *item, int column); + void onExportClicked(); + +protected: + void closeEvent(QCloseEvent *event) override; + +private: + void setupUi(); + + QString m_projectRoot; + + // Einstellungen + QLineEdit *m_excludeEdit = nullptr; + + // Steuerung + QPushButton *m_btnAnalyze = nullptr; + QPushButton *m_btnExport = nullptr; + + // Fortschritt + QProgressBar *m_progress = nullptr; + QLabel *m_progressLabel = nullptr; + + // Status + Ergebnisse + QLabel *m_statusLabel = nullptr; + QTreeWidget *m_results = nullptr; + + DeadCodeAnalyzer *m_analyzer = nullptr; + QFutureWatcher> *m_watcher = nullptr; +}; diff --git a/barecode/src/editor/EditorPanel.cpp b/barecode/src/editor/EditorPanel.cpp new file mode 100644 index 0000000..92766b3 --- /dev/null +++ b/barecode/src/editor/EditorPanel.cpp @@ -0,0 +1,301 @@ +#include "EditorPanel.h" +#include "EditorTab.h" +#include "CodeEditor.h" +#include "SearchPanel.h" +#include "FileSearchPanel.h" +#include "FunctionListDialog.h" +#include "DeadCodeDialog.h" +#include "FunctionIndex.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_funcDialog = new FunctionListDialog(window()); + m_deadCode = new DeadCodeDialog(window()); + m_funcIndex = new FunctionIndex(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); + + connect(m_funcDialog, &FunctionListDialog::fileLineRequested, + this, &EditorPanel::goToLine); + + connect(m_deadCode, &DeadCodeDialog::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); + + // FunctionIndex dem Editor mitgeben für Doppelklick-Navigation + tab->editor()->setFunctionIndex(m_funcIndex); + + // Doppelklick auf Funktion → zur Definition springen + connect(tab->editor(), &CodeEditor::navigateToRequested, + this, &EditorPanel::goToLine); + + // Ä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); + + // Index und Funktionsliste aktualisieren + m_funcIndex->refresh(); + if (m_funcDialog->isVisible()) + { + m_funcDialog->refresh(); + } + }); +} + +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::showFunctionList() +{ + m_funcDialog->show(); + m_funcDialog->raise(); + m_funcDialog->activateWindow(); +} + +void EditorPanel::showDeadCode() +{ + m_deadCode->show(); + m_deadCode->raise(); + m_deadCode->activateWindow(); +} + +void EditorPanel::setSearchRoot(const QString &path) +{ + m_fileSearch->setSearchRoot(path); + m_funcDialog->setProjectRoot(path); + m_deadCode->setProjectRoot(path); + m_funcIndex->setProjectRoot(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/barecode/src/editor/EditorPanel.h b/barecode/src/editor/EditorPanel.h new file mode 100644 index 0000000..e90c518 --- /dev/null +++ b/barecode/src/editor/EditorPanel.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include +#include + +class EditorTab; +class Settings; +class SearchPanel; +class FileSearchPanel; +class FunctionListDialog; +class DeadCodeDialog; +class FunctionIndex; + +// --------------------------------------------------------------------------- +// 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 showFunctionList(); + void showDeadCode(); + 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; + FunctionListDialog *m_funcDialog = nullptr; + DeadCodeDialog *m_deadCode = nullptr; + FunctionIndex *m_funcIndex = nullptr; + + QHash m_openTabs; +}; diff --git a/barecode/src/editor/EditorTab.cpp b/barecode/src/editor/EditorTab.cpp new file mode 100644 index 0000000..0b0b8fa --- /dev/null +++ b/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/barecode/src/editor/EditorTab.h b/barecode/src/editor/EditorTab.h new file mode 100644 index 0000000..3bf0d8f --- /dev/null +++ b/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/barecode/src/editor/FileSearchPanel.cpp b/barecode/src/editor/FileSearchPanel.cpp new file mode 100644 index 0000000..f7d0030 --- /dev/null +++ b/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/barecode/src/editor/FileSearchPanel.h b/barecode/src/editor/FileSearchPanel.h new file mode 100644 index 0000000..97b9766 --- /dev/null +++ b/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/barecode/src/editor/FunctionIndex.cpp b/barecode/src/editor/FunctionIndex.cpp new file mode 100644 index 0000000..a2ec7ce --- /dev/null +++ b/barecode/src/editor/FunctionIndex.cpp @@ -0,0 +1,83 @@ +#include "FunctionIndex.h" + +#include + +FunctionIndex::FunctionIndex(QObject *parent) + : QObject(parent) +{ + m_scanner = new FunctionScanner(this); + m_watcher = new QFutureWatcher>(this); + + connect(m_watcher, &QFutureWatcher>::finished, + this, &FunctionIndex::onScanFinished); +} + +void FunctionIndex::setProjectRoot(const QString &path) +{ + m_projectRoot = path; + m_ready = false; + m_index.clear(); + + if (!path.isEmpty()) + { + refresh(); + } +} + +void FunctionIndex::refresh() +{ + if (m_projectRoot.isEmpty()) + { + return; + } + + if (m_watcher->isRunning()) + { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + + FunctionScanner *scanner = m_scanner; + const QString root = m_projectRoot; + + m_watcher->setFuture( + QtConcurrent::run([scanner, root]() + { + return scanner->scanDirectory(root); + }) + ); +} + +void FunctionIndex::onScanFinished() +{ + if (m_watcher->isCanceled()) + { + return; + } + + m_index.clear(); + const QList all = m_watcher->result(); + + for (const FunctionScanner::FunctionInfo &func : all) + { + const QString key = func.name.toLower(); + // Ersten Eintrag bevorzugen (globale Funktionen vor Methoden) + if (!m_index.contains(key) || func.className.isEmpty()) + { + m_index.insert(key, func); + } + } + + m_ready = true; + emit indexReady(); +} + +FunctionScanner::FunctionInfo FunctionIndex::lookup(const QString &name) const +{ + return m_index.value(name.toLower(), FunctionScanner::FunctionInfo{}); +} + +bool FunctionIndex::isReady() const +{ + return m_ready; +} diff --git a/barecode/src/editor/FunctionIndex.h b/barecode/src/editor/FunctionIndex.h new file mode 100644 index 0000000..2446d14 --- /dev/null +++ b/barecode/src/editor/FunctionIndex.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "FunctionScanner.h" + +// --------------------------------------------------------------------------- +// FunctionIndex – Singleton-artiger Index aller Projektfunktionen. +// Wird von CodeEditor (Doppelklick-Navigation) und SignatureHelper genutzt. +// Aktualisiert sich asynchron wenn setProjectRoot() aufgerufen wird. +// --------------------------------------------------------------------------- +class FunctionIndex : public QObject +{ + Q_OBJECT + +public: + explicit FunctionIndex(QObject *parent = nullptr); + + void setProjectRoot(const QString &path); + void refresh(); + + // Sucht eine Funktion nach Name (Groß-/Kleinschreibung ignoriert) + // Gibt ungültige FunctionInfo zurück wenn nicht gefunden (filePath ist leer) + FunctionScanner::FunctionInfo lookup(const QString &name) const; + + bool isReady() const; + +signals: + void indexReady(); + +private slots: + void onScanFinished(); + +private: + QString m_projectRoot; + FunctionScanner *m_scanner = nullptr; + + QFutureWatcher> *m_watcher = nullptr; + + // name.toLower() → FunctionInfo + QHash m_index; + bool m_ready = false; +}; diff --git a/barecode/src/editor/FunctionListDialog.cpp b/barecode/src/editor/FunctionListDialog.cpp new file mode 100644 index 0000000..ab7c56b --- /dev/null +++ b/barecode/src/editor/FunctionListDialog.cpp @@ -0,0 +1,52 @@ +#include "FunctionListDialog.h" +#include "FunctionListPanel.h" + +#include +#include +#include + +FunctionListDialog::FunctionListDialog(QWidget *parent) + : QDialog(parent, Qt::Window) +{ + setWindowTitle(tr("Projektfunktionen – BareCode")); + setMinimumSize(500, 400); + + // Fenstergröße und -position wiederherstellen + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + if (s.contains("funclist/geometry")) + { + restoreGeometry(s.value("funclist/geometry").toByteArray()); + } + else + { + resize(600, 700); + } + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + m_panel = new FunctionListPanel(this); + m_panel->show(); // Immer sichtbar — Panel ist jetzt der gesamte Dialog-Inhalt + layout->addWidget(m_panel); + + connect(m_panel, &FunctionListPanel::fileLineRequested, + this, &FunctionListDialog::fileLineRequested); +} + +void FunctionListDialog::setProjectRoot(const QString &path) +{ + m_panel->setProjectRoot(path); +} + +void FunctionListDialog::refresh() +{ + m_panel->refresh(); +} + +void FunctionListDialog::closeEvent(QCloseEvent *event) +{ + QSettings s(QSettings::IniFormat, QSettings::UserScope, "BareCode", "BareCode"); + s.setValue("funclist/geometry", saveGeometry()); + event->accept(); +} diff --git a/barecode/src/editor/FunctionListDialog.h b/barecode/src/editor/FunctionListDialog.h new file mode 100644 index 0000000..9310f60 --- /dev/null +++ b/barecode/src/editor/FunctionListDialog.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +class FunctionListPanel; + +// --------------------------------------------------------------------------- +// FunctionListDialog – Eigenständiges Fenster für die Projektfunktionen. +// Bleibt offen während man im Editor arbeitet (non-modal). +// --------------------------------------------------------------------------- +class FunctionListDialog : public QDialog +{ + Q_OBJECT + +public: + explicit FunctionListDialog(QWidget *parent = nullptr); + + void setProjectRoot(const QString &path); + void refresh(); + +protected: + void closeEvent(QCloseEvent *event) override; + +signals: + void fileLineRequested(const QString &filePath, int line); + +private: + FunctionListPanel *m_panel = nullptr; +}; diff --git a/barecode/src/editor/FunctionListPanel.cpp b/barecode/src/editor/FunctionListPanel.cpp new file mode 100644 index 0000000..c6441b3 --- /dev/null +++ b/barecode/src/editor/FunctionListPanel.cpp @@ -0,0 +1,332 @@ +#include "FunctionListPanel.h" + +#include +#include +#include +#include + +FunctionListPanel::FunctionListPanel(QWidget *parent) + : QWidget(parent) +{ + m_scanner = new FunctionScanner(this); + m_watcher = new QFutureWatcher>(this); + + connect(m_watcher, &QFutureWatcher>::finished, + this, &FunctionListPanel::onScanFinished); + + setupUi(); +} + +// --------------------------------------------------------------------------- +// UI +// --------------------------------------------------------------------------- +void FunctionListPanel::setupUi() +{ + QVBoxLayout *root = new QVBoxLayout(this); + root->setContentsMargins(0, 0, 0, 0); + root->setSpacing(0); + + // ---- Kopfzeile ---- + QWidget *header = new QWidget(this); + header->setStyleSheet("background: palette(mid);"); + QHBoxLayout *headerLayout = new QHBoxLayout(header); + headerLayout->setContentsMargins(6, 4, 6, 4); + headerLayout->setSpacing(4); + + QLabel *title = new QLabel(tr("Projektfunktionen"), header); + QFont boldFont = title->font(); + boldFont.setBold(true); + title->setFont(boldFont); + headerLayout->addWidget(title); + headerLayout->addStretch(); + + m_btnRefresh = new QPushButton(tr("↻"), header); + m_btnRefresh->setFixedSize(24, 24); + m_btnRefresh->setFlat(true); + m_btnRefresh->setToolTip(tr("Neu scannen")); + headerLayout->addWidget(m_btnRefresh); + + root->addWidget(header); + + // ---- Filter + Gruppierung ---- + QHBoxLayout *toolRow = new QHBoxLayout(); + toolRow->setContentsMargins(6, 4, 6, 4); + toolRow->setSpacing(4); + + m_filterEdit = new QLineEdit(this); + m_filterEdit->setPlaceholderText(tr("Funktion suchen…")); + m_filterEdit->setClearButtonEnabled(true); + toolRow->addWidget(m_filterEdit, 1); + + m_groupCombo = new QComboBox(this); + m_groupCombo->addItem(tr("Nach Datei"), "file"); + m_groupCombo->addItem(tr("Nach Klasse"), "class"); + m_groupCombo->addItem(tr("Alphabetisch"), "alpha"); + m_groupCombo->setFixedWidth(120); + toolRow->addWidget(m_groupCombo); + + root->addLayout(toolRow); + + // ---- Status ---- + m_statusLabel = new QLabel(this); + m_statusLabel->setContentsMargins(6, 0, 6, 2); + m_statusLabel->setStyleSheet("color: palette(mid); font-size: 11px;"); + root->addWidget(m_statusLabel); + + // ---- Ergebnisbaum ---- + m_tree = new QTreeWidget(this); + m_tree->setHeaderHidden(true); + m_tree->setRootIsDecorated(true); + m_tree->setIndentation(14); + m_tree->setAlternatingRowColors(false); + m_tree->setAnimated(true); + + // Monospace-Font für Parameter + QFont monoFont("Monospace", m_tree->font().pointSize()); + monoFont.setStyleHint(QFont::Monospace); + m_tree->setFont(monoFont); + + root->addWidget(m_tree, 1); + + // ---- Verbindungen ---- + connect(m_btnRefresh, &QPushButton::clicked, + this, &FunctionListPanel::refresh); + + connect(m_filterEdit, &QLineEdit::textChanged, + this, &FunctionListPanel::onFilterChanged); + + connect(m_groupCombo, QOverload::of(&QComboBox::currentIndexChanged), + this, &FunctionListPanel::onGroupingChanged); + + connect(m_tree, &QTreeWidget::itemActivated, + this, &FunctionListPanel::onItemActivated); +} + +// --------------------------------------------------------------------------- +// Öffentliche Schnittstelle +// --------------------------------------------------------------------------- +void FunctionListPanel::setProjectRoot(const QString &path) +{ + m_projectRoot = path; + if (!path.isEmpty()) + { + refresh(); + } + else + { + m_tree->clear(); + m_statusLabel->setText(QString()); + m_lastResult.clear(); + } +} + +void FunctionListPanel::activate() +{ + m_filterEdit->setFocus(); + m_filterEdit->selectAll(); + if (m_lastResult.isEmpty() && !m_projectRoot.isEmpty()) + { + refresh(); + } +} + +// --------------------------------------------------------------------------- +// Scan starten +// --------------------------------------------------------------------------- +void FunctionListPanel::refresh() +{ + if (m_projectRoot.isEmpty()) + { + m_statusLabel->setText(tr("Kein Projekt geöffnet.")); + return; + } + + if (m_watcher->isRunning()) + { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + + m_statusLabel->setText(tr("Scanne…")); + m_btnRefresh->setEnabled(false); + + const QString root = m_projectRoot; + FunctionScanner *scanner = m_scanner; + + QFuture> future = + QtConcurrent::run([scanner, root]() + { + return scanner->scanDirectory(root); + }); + + m_watcher->setFuture(future); +} + +// --------------------------------------------------------------------------- +// Scan abgeschlossen +// --------------------------------------------------------------------------- +void FunctionListPanel::onScanFinished() +{ + m_btnRefresh->setEnabled(true); + + if (m_watcher->isCanceled()) + { + return; + } + + m_lastResult = m_watcher->result(); + populateTree(m_lastResult); +} + +// --------------------------------------------------------------------------- +// Baum befüllen +// --------------------------------------------------------------------------- +void FunctionListPanel::populateTree(const QList &functions) +{ + m_tree->clear(); + + const QString groupBy = m_groupCombo->currentData().toString(); + const QString filter = m_filterEdit->text().trimmed().toLower(); + + // Funktionen filtern + QList filtered; + for (const auto &f : functions) + { + if (filter.isEmpty() || + f.name.toLower().contains(filter) || + f.parameters.toLower().contains(filter) || + f.className.toLower().contains(filter)) + { + filtered.append(f); + } + } + + if (groupBy == "alpha") + { + // Alphabetisch — keine Gruppen + std::sort(filtered.begin(), filtered.end(), + [](const FunctionScanner::FunctionInfo &a, + const FunctionScanner::FunctionInfo &b) + { + return a.name.toLower() < b.name.toLower(); + }); + + for (const auto &f : filtered) + { + QTreeWidgetItem *item = new QTreeWidgetItem(m_tree); + formatFunctionItem(item, f); + } + } + else + { + // Gruppiert nach Datei oder Klasse + QMap> groups; + + for (const auto &f : filtered) + { + QString key; + if (groupBy == "class") + { + key = f.className.isEmpty() ? tr("(global)") : f.className; + } + else + { + key = QFileInfo(f.filePath).fileName(); + } + groups[key].append(f); + } + + for (auto it = groups.begin(); it != groups.end(); ++it) + { + QTreeWidgetItem *groupItem = new QTreeWidgetItem(m_tree); + groupItem->setText(0, QString("%1 (%2)") + .arg(it.key()) + .arg(it.value().size())); + groupItem->setData(0, Qt::UserRole, QString()); + groupItem->setData(0, Qt::UserRole + 1, -1); + + QFont boldFont = groupItem->font(0); + boldFont.setBold(true); + groupItem->setFont(0, boldFont); + groupItem->setExpanded(true); + + // Funktionen innerhalb der Gruppe alphabetisch + auto &list = it.value(); + std::sort(list.begin(), list.end(), + [](const FunctionScanner::FunctionInfo &a, + const FunctionScanner::FunctionInfo &b) + { + return a.name.toLower() < b.name.toLower(); + }); + + for (const auto &f : list) + { + QTreeWidgetItem *item = new QTreeWidgetItem(groupItem); + formatFunctionItem(item, f); + } + } + } + + // Statuszeile + const int total = functions.size(); + const int shown = filtered.size(); + if (filter.isEmpty()) + { + m_statusLabel->setText(tr("%1 Funktionen gefunden").arg(total)); + } + else + { + m_statusLabel->setText(tr("%1 von %2 Funktionen").arg(shown).arg(total)); + } +} + +void FunctionListPanel::formatFunctionItem(QTreeWidgetItem *item, + const FunctionScanner::FunctionInfo &f) +{ + // Anzeige: name(parameter) — Zeilennummer klein dahinter + const QString display = QString("%1(%2)") + .arg(f.name) + .arg(f.parameters); + + item->setText(0, display); + item->setToolTip(0, QString("%1\nZeile %2").arg(f.filePath).arg(f.line)); + item->setData(0, Qt::UserRole, f.filePath); + item->setData(0, Qt::UserRole + 1, f.line); + + // Zeilennummer in gedimmter Farbe als zweite Spalte simulieren + // (über ToolTip gelöst da wir nur eine Spalte haben) +} + +// --------------------------------------------------------------------------- +// Slots +// --------------------------------------------------------------------------- +void FunctionListPanel::onItemActivated(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) + { + item->setExpanded(!item->isExpanded()); + return; + } + + emit fileLineRequested(path, line); +} + +void FunctionListPanel::onFilterChanged(const QString &text) +{ + Q_UNUSED(text) + if (!m_lastResult.isEmpty()) + { + populateTree(m_lastResult); + } +} + +void FunctionListPanel::onGroupingChanged(int /*index*/) +{ + if (!m_lastResult.isEmpty()) + { + populateTree(m_lastResult); + } +} diff --git a/barecode/src/editor/FunctionListPanel.h b/barecode/src/editor/FunctionListPanel.h new file mode 100644 index 0000000..fd283be --- /dev/null +++ b/barecode/src/editor/FunctionListPanel.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FunctionScanner.h" + +// --------------------------------------------------------------------------- +// FunctionListPanel – Zeigt alle im Projekt definierten Funktionen +// als durchsuchbare, sortierbare Liste. +// +// Gruppierung: nach Datei oder nach Klasse +// Klick: öffnet Datei und springt zur Definition +// Aktualisierung: automatisch nach jedem Speichern +// --------------------------------------------------------------------------- +class FunctionListPanel : public QWidget +{ + Q_OBJECT + +public: + explicit FunctionListPanel(QWidget *parent = nullptr); + + void setProjectRoot(const QString &path); + +public slots: + void refresh(); + void activate(); + +signals: + void fileLineRequested(const QString &filePath, int line); + +private slots: + void onScanFinished(); + void onItemActivated(QTreeWidgetItem *item, int column); + void onFilterChanged(const QString &text); + void onGroupingChanged(int index); + +private: + void setupUi(); + void populateTree(const QList &functions); + void applyFilter(const QString &text); + static void formatFunctionItem(QTreeWidgetItem *item, + const FunctionScanner::FunctionInfo &f); + + QString m_projectRoot; + + QLineEdit *m_filterEdit = nullptr; + QComboBox *m_groupCombo = nullptr; + QPushButton *m_btnRefresh = nullptr; + QLabel *m_statusLabel = nullptr; + QTreeWidget *m_tree = nullptr; + + FunctionScanner *m_scanner = nullptr; + QFutureWatcher> *m_watcher = nullptr; + + // Letztes Scan-Ergebnis für Filter ohne Neuscan + QList m_lastResult; +}; diff --git a/barecode/src/editor/FunctionScanner.cpp b/barecode/src/editor/FunctionScanner.cpp new file mode 100644 index 0000000..10a8a02 --- /dev/null +++ b/barecode/src/editor/FunctionScanner.cpp @@ -0,0 +1,158 @@ +#include "FunctionScanner.h" + +#include +#include +#include +#include +#include + +FunctionScanner::FunctionScanner(QObject *parent) + : QObject(parent) +{ +} + +// --------------------------------------------------------------------------- +// Verzeichnis rekursiv scannen +// --------------------------------------------------------------------------- +QList FunctionScanner::scanDirectory( + const QString &rootPath, + const QStringList &extensions) const +{ + QList results; + + QDirIterator it(rootPath, + extensions, + QDir::Files, + QDirIterator::Subdirectories); + + while (it.hasNext()) + { + const QString path = it.next(); + results.append(scanFile(path)); + } + + return results; +} + +// --------------------------------------------------------------------------- +// Einzelne Datei scannen +// --------------------------------------------------------------------------- +QList FunctionScanner::scanFile(const QString &filePath) const +{ + QList results; + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + return results; + } + + QTextStream stream(&file); + stream.setEncoding(QStringConverter::Utf8); + + QStringList lines; + while (!stream.atEnd()) + { + lines.append(stream.readLine()); + } + + // Regex für Funktionsdefinitionen: + // optional: public/protected/private/static/abstract/final + // gefolgt von: function name( + static const QRegularExpression funcRegex( + R"((?:(?:public|protected|private|static|abstract|final)\s+)*)" + R"(function\s+(&?\s*[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\s*\()", + QRegularExpression::CaseInsensitiveOption + ); + + for (int i = 0; i < lines.size(); ++i) + { + const QString &line = lines[i]; + + // Zeilen in Kommentaren überspringen + const QString trimmed = line.trimmed(); + if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("#")) + { + continue; + } + + QRegularExpressionMatch match = funcRegex.match(line); + if (!match.hasMatch()) + { + continue; + } + + FunctionInfo info; + info.name = match.captured(1).trimmed(); + info.filePath = filePath; + info.line = i + 1; + info.className = detectClassContext(lines, i); + info.parameters = extractParameters(line, static_cast(match.capturedEnd()) - 1); + info.signature = info.name + "(" + info.parameters + ")"; + + // Konstruktoren und magische Methoden kennzeichnen + // aber trotzdem aufnehmen — sie sind nützlich in der Liste + + results.append(info); + } + + return results; +} + +// --------------------------------------------------------------------------- +// Parameter aus der Funktionssignatur extrahieren +// Behandelt auch mehrzeilige Signaturen mit öffnender Klammer am Ende +// --------------------------------------------------------------------------- +QString FunctionScanner::extractParameters(const QString &line, int parenPos) +{ + // Inhalt zwischen ( und ) extrahieren + // Einfache Version: nur die erste Zeile — reicht für 99% aller Fälle + const int openParen = parenPos; + int depth = 0; + int closePos = -1; + + for (int i = openParen; i < line.length(); ++i) + { + if (line[i] == '(') { ++depth; } + else if (line[i] == ')') + { + --depth; + if (depth == 0) + { + closePos = i; + break; + } + } + } + + if (closePos == -1) + { + // Klammer geht über Zeilenende — gekürzt anzeigen + return line.mid(openParen + 1).trimmed() + "…"; + } + + return line.mid(openParen + 1, closePos - openParen - 1).trimmed(); +} + +// --------------------------------------------------------------------------- +// Klassenkontext erkennen — rückwärts durch den Code suchen +// --------------------------------------------------------------------------- +QString FunctionScanner::detectClassContext(const QStringList &lines, int functionLineIndex) +{ + static const QRegularExpression classRegex( + R"((?:class|interface|trait|enum)\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*))", + QRegularExpression::CaseInsensitiveOption + ); + + // Rückwärts suchen — letztes class/interface/trait vor dieser Zeile + for (int i = functionLineIndex - 1; i >= 0; --i) + { + QRegularExpressionMatch match = classRegex.match(lines[i]); + if (match.hasMatch()) + { + return match.captured(1); + } + } + + return QString(); // Globale Funktion +} diff --git a/barecode/src/editor/FunctionScanner.h b/barecode/src/editor/FunctionScanner.h new file mode 100644 index 0000000..cd08243 --- /dev/null +++ b/barecode/src/editor/FunctionScanner.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// FunctionScanner – Scannt PHP-Dateien nach Funktionsdefinitionen. +// +// Liefert für jede gefundene Funktion: +// - Name +// - Parameter (vollständige Signatur) +// - Dateipfad +// - Zeilennummer +// +// Wird von FunctionListPanel (Anzeige) und DeadCodeAnalyzer (Stufe 1) +// gemeinsam genutzt. +// --------------------------------------------------------------------------- +class FunctionScanner : public QObject +{ + Q_OBJECT + +public: + struct FunctionInfo + { + QString name; // Funktionsname + QString parameters; // Parameter wie definiert, z.B. "$id, $name = null" + QString signature; // name(parameters) — fertig formatiert + QString filePath; // Absoluter Pfad zur Datei + int line = 0; // Zeilennummer der Definition + QString className; // Klassen- oder Namespace-Kontext, leer = global + }; + + explicit FunctionScanner(QObject *parent = nullptr); + + // Synchroner Scan — für direkten Aufruf aus Threads + QList scanDirectory(const QString &rootPath, + const QStringList &extensions = {"*.php"}) const; + + // Scannt eine einzelne Datei + QList scanFile(const QString &filePath) const; + +private: + static QString extractParameters(const QString &line, int parenPos); + static QString detectClassContext(const QStringList &lines, int functionLineIndex); +}; diff --git a/barecode/src/editor/LineNumberArea.cpp b/barecode/src/editor/LineNumberArea.cpp new file mode 100644 index 0000000..44ef836 --- /dev/null +++ b/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/barecode/src/editor/LineNumberArea.h b/barecode/src/editor/LineNumberArea.h new file mode 100644 index 0000000..1a6963a --- /dev/null +++ b/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/barecode/src/editor/SearchPanel.cpp b/barecode/src/editor/SearchPanel.cpp new file mode 100644 index 0000000..39704f6 --- /dev/null +++ b/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/barecode/src/editor/SearchPanel.h b/barecode/src/editor/SearchPanel.h new file mode 100644 index 0000000..b3e1158 --- /dev/null +++ b/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/barecode/src/editor/SignatureHelper.cpp b/barecode/src/editor/SignatureHelper.cpp new file mode 100644 index 0000000..c84f723 --- /dev/null +++ b/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/barecode/src/editor/SignatureHelper.h b/barecode/src/editor/SignatureHelper.h new file mode 100644 index 0000000..9b1ec89 --- /dev/null +++ b/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/barecode/src/editor/SignatureTooltip.cpp b/barecode/src/editor/SignatureTooltip.cpp new file mode 100644 index 0000000..3ac4099 --- /dev/null +++ b/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/barecode/src/editor/SignatureTooltip.h b/barecode/src/editor/SignatureTooltip.h new file mode 100644 index 0000000..110062f --- /dev/null +++ b/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/barecode/src/editor/VariableCompleter.cpp b/barecode/src/editor/VariableCompleter.cpp new file mode 100644 index 0000000..64d57af --- /dev/null +++ b/barecode/src/editor/VariableCompleter.cpp @@ -0,0 +1,256 @@ +#include "VariableCompleter.h" +#include "CodeEditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +VariableCompleter::VariableCompleter(CodeEditor *editor) + : QObject(editor) + , m_editor(editor) +{ + // Popup als reines Anzeige-Fenster — dieselbe Fensterart wie + // SignatureTooltip, die nachweislich nie den Fokus an sich reißt. + // Wichtig: Ein echtes Elternfenster (editor->window()) angeben, sonst + // behandelt der Fenstermanager das Popup als eigenständiges Fenster. + // Das führte dazu, dass bei mehreren offenen Dateien/Tabs verwaiste + // Popups entstehen konnten, die den Fokus übernehmen und die + // Texteingabe blockieren. + m_popup = new QListWidget(editor->window()); + m_popup->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint); + m_popup->setAttribute(Qt::WA_ShowWithoutActivating); + m_popup->setFocusPolicy(Qt::NoFocus); + m_popup->setMaximumHeight(200); + m_popup->setMinimumWidth(180); + m_popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_popup->setStyleSheet( + "QListWidget {" + " border: 1px solid palette(mid);" + " background: palette(toolTipBase);" + " color: palette(toolTipText);" + " font-family: Monospace;" + "}" + "QListWidget::item:selected {" + " background: palette(highlight);" + " color: palette(highlightedText);" + "}" + ); + + connect(m_popup, &QListWidget::itemActivated, + this, &VariableCompleter::onItemActivated); +} + +// --------------------------------------------------------------------------- +// Nach jedem Tastendruck aufrufen +// --------------------------------------------------------------------------- +void VariableCompleter::handleKeyPress(QKeyEvent *event) +{ + // Popup-Navigation + if (m_popup->isVisible()) + { + if (event->key() == Qt::Key_Escape) + { + hidePopup(); + return; + } + if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) + { + if (m_popup->currentItem()) + { + onItemActivated(m_popup->currentItem()); + } + hidePopup(); + return; + } + if (event->key() == Qt::Key_Down) + { + const int next = qMin(m_popup->currentRow() + 1, + m_popup->count() - 1); + m_popup->setCurrentRow(next); + return; + } + if (event->key() == Qt::Key_Up) + { + const int prev = qMax(m_popup->currentRow() - 1, 0); + m_popup->setCurrentRow(prev); + return; + } + } + + // Nach dem normalen Tastendruck Popup aktualisieren + // (der Event wurde bereits an QPlainTextEdit weitergegeben) + updatePopup(); +} + +// --------------------------------------------------------------------------- +// Popup aktualisieren +// --------------------------------------------------------------------------- +void VariableCompleter::updatePopup() +{ + const QString prefix = currentPrefix(); + + // Nur bei $ und mindestens einem weiteren Zeichen anzeigen + if (prefix.length() < 2 || !prefix.startsWith('$')) + { + hidePopup(); + return; + } + + const QStringList allVars = collectVariables(); + const QString filter = prefix.toLower(); + + QStringList matches; + for (const QString &var : allVars) + { + if (var.toLower().startsWith(filter) && var != prefix) + { + matches.append(var); + } + } + + if (matches.isEmpty()) + { + hidePopup(); + return; + } + + // Popup befüllen + m_popup->clear(); + for (const QString &var : matches) + { + m_popup->addItem(var); + } + m_popup->setCurrentRow(0); + + // Größe anpassen + const int itemHeight = m_popup->sizeHintForRow(0) + 2; + const int height = qMin(matches.size() * itemHeight + 4, 200); + m_popup->setFixedHeight(height); + + // Position unter dem Cursor + const QRect cursorRect = m_editor->cursorRect(); + QPoint pos = m_editor->viewport()->mapToGlobal( + QPoint(cursorRect.left(), cursorRect.bottom() + 2) + ); + + // Nicht aus dem Bildschirm herausragen + const QRect screen = QApplication::primaryScreen()->availableGeometry(); + if (pos.x() + m_popup->width() > screen.right()) + { + pos.setX(screen.right() - m_popup->width()); + } + if (pos.y() + height > screen.bottom()) + { + pos.setY(cursorRect.top() - height - 2); + } + + m_popup->move(pos); + m_popup->show(); + m_popup->raise(); +} + +void VariableCompleter::hidePopup() +{ + m_popup->hide(); + m_popup->clear(); +} + +// --------------------------------------------------------------------------- +// Editor hat den Fokus verloren (z. B. Tab-Wechsel) — Popup schließen +// --------------------------------------------------------------------------- +void VariableCompleter::notifyFocusLost() +{ + hidePopup(); +} + +// --------------------------------------------------------------------------- +// Variablen im aktuellen Dokument sammeln +// --------------------------------------------------------------------------- +QStringList VariableCompleter::collectVariables() const +{ + static const QRegularExpression varRegex(R"(\$[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)"); + + QSet seen; + QStringList result; + + const QString text = m_editor->toPlainText(); + QRegularExpressionMatchIterator it = varRegex.globalMatch(text); + + while (it.hasNext()) + { + const QString var = it.next().captured(0); + if (!seen.contains(var)) + { + seen.insert(var); + result.append(var); + } + } + + result.sort(Qt::CaseInsensitive); + return result; +} + +// --------------------------------------------------------------------------- +// Text links vom Cursor — das angefangene $variable +// --------------------------------------------------------------------------- +QString VariableCompleter::currentPrefix() const +{ + const QTextCursor cursor = m_editor->textCursor(); + const QString line = cursor.block().text(); + const int col = cursor.columnNumber(); + + if (col == 0) + { + return QString(); + } + + // Rückwärts gehen bis zum $ oder einem Nicht-Bezeichner-Zeichen + int start = col - 1; + while (start > 0) + { + const QChar c = line[start - 1]; + if (!c.isLetterOrNumber() && c != '_' && c != '$') + { + break; + } + --start; + } + + const QString token = line.mid(start, col - start); + return token.startsWith('$') ? token : QString(); +} + +// --------------------------------------------------------------------------- +// Klick oder Enter — Variable einfügen +// --------------------------------------------------------------------------- +void VariableCompleter::onItemActivated(QListWidgetItem *item) +{ + if (!item) + { + return; + } + + const QString selected = item->text(); + const QString prefix = currentPrefix(); + + if (prefix.isEmpty()) + { + hidePopup(); + return; + } + + // Prefix durch den vollständigen Variablennamen ersetzen + QTextCursor cursor = m_editor->textCursor(); + cursor.movePosition(QTextCursor::Left, + QTextCursor::KeepAnchor, + prefix.length()); + cursor.insertText(selected); + + m_editor->setTextCursor(cursor); + hidePopup(); +} diff --git a/barecode/src/editor/VariableCompleter.h b/barecode/src/editor/VariableCompleter.h new file mode 100644 index 0000000..08743e9 --- /dev/null +++ b/barecode/src/editor/VariableCompleter.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include + +class CodeEditor; + +// --------------------------------------------------------------------------- +// VariableCompleter – Zeigt ein Popup mit passenden Variablennamen +// wenn der Nutzer $ tippt und weiter eingibt. +// +// Kein Autocomplete — nur Anzeige. Klick oder Enter übernimmt. +// Escape oder Weiterschreiben ohne Treffer schließt das Popup. +// --------------------------------------------------------------------------- +class VariableCompleter : public QObject +{ + Q_OBJECT + +public: + explicit VariableCompleter(CodeEditor *editor); + + // Muss nach jedem Tastendruck aufgerufen werden + void handleKeyPress(QKeyEvent *event); + + // Muss aufgerufen werden, wenn der Editor den Fokus verliert + // (z. B. beim Wechsel des Tabs) — schließt ein evtl. offenes Popup, + // damit es nicht als "Geisterfenster" stehen bleibt. + void notifyFocusLost(); + +private slots: + void onItemActivated(QListWidgetItem *item); + +private: + void updatePopup(); + void hidePopup(); + QStringList collectVariables() const; + QString currentPrefix() const; // "$me" etc. links vom Cursor + + CodeEditor *m_editor = nullptr; + QListWidget *m_popup = nullptr; +}; diff --git a/barecode/src/filetree/CMakeLists.txt b/barecode/src/filetree/CMakeLists.txt new file mode 100644 index 0000000..f269f5e --- /dev/null +++ b/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/barecode/src/filetree/FileTreePanel.cpp b/barecode/src/filetree/FileTreePanel.cpp new file mode 100644 index 0000000..1ed0221 --- /dev/null +++ b/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/barecode/src/filetree/FileTreePanel.h b/barecode/src/filetree/FileTreePanel.h new file mode 100644 index 0000000..32c5c9e --- /dev/null +++ b/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/barecode/src/highlighter/CMakeLists.txt b/barecode/src/highlighter/CMakeLists.txt new file mode 100644 index 0000000..3cbc2eb --- /dev/null +++ b/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/barecode/src/highlighter/HighlighterFactory.cpp b/barecode/src/highlighter/HighlighterFactory.cpp new file mode 100644 index 0000000..250e3a2 --- /dev/null +++ b/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/barecode/src/highlighter/HighlighterFactory.h b/barecode/src/highlighter/HighlighterFactory.h new file mode 100644 index 0000000..8392758 --- /dev/null +++ b/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/barecode/src/highlighter/SyntaxHighlighter.cpp b/barecode/src/highlighter/SyntaxHighlighter.cpp new file mode 100644 index 0000000..4658293 --- /dev/null +++ b/barecode/src/highlighter/SyntaxHighlighter.cpp @@ -0,0 +1,589 @@ +#include "SyntaxHighlighter.h" +#include + +// =========================================================================== +// SyntaxHighlighter – Basis +// =========================================================================== +SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) + : QSyntaxHighlighter(parent) +{ +} + +void SyntaxHighlighter::highlightBlock(const QString &text) +{ + // Einzel-Zeilen-Regeln anwenden + 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) + { + setCurrentBlockState(0); + return; + } + + // Mehrzeilige Kommentare + // Zustand 0 = normal, 1 = mitten in /* ... */ + setCurrentBlockState(0); + + // Leere Zeile mitten im Kommentar — Zustand weitertragen + if (text.isEmpty()) + { + if (previousBlockState() == 1) + { + setCurrentBlockState(1); + } + return; + } + + int startIndex = 0; + + if (previousBlockState() == 1) + { + // Vorherige Zeile war mitten im Kommentar — ab Zeilenanfang nach Ende suchen + QRegularExpressionMatch endMatch = m_commentEndExpression.match(text, 0); + + if (endMatch.hasMatch()) + { + // Ende des Kommentars gefunden + const int commentLength = static_cast(endMatch.capturedStart()) + + static_cast(endMatch.capturedLength()); + setFormat(0, commentLength, m_multiLineCommentFormat); + + // Nach weiteren Kommentaren in der gleichen Zeile suchen + QRegularExpressionMatch nextStart = + m_commentStartExpression.match(text, commentLength); + startIndex = nextStart.hasMatch() + ? static_cast(nextStart.capturedStart()) + : -1; + } + else + { + // Noch kein Ende — gesamte Zeile ist Kommentar + setFormat(0, text.length(), m_multiLineCommentFormat); + setCurrentBlockState(1); + return; + } + } + else + { + // Neuen Kommentaranfang suchen + 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 + { + // Kommentar geht über Zeilenende + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + + setFormat(startIndex, commentLength, m_multiLineCommentFormat); + + if (!endMatch.hasMatch()) + { + break; + } + + // Nach weiteren Kommentaren in dieser Zeile suchen + 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 + ); + } + } + + static const QRegularExpression blockOpen(R"(/\*)"); + static const QRegularExpression blockClose(R"(\*/)"); + + int searchFrom = 0; + + // Leere Zeile mitten im PHP-Blockkommentar — Zustand weitertragen + if (phpText.trimmed().isEmpty()) + { + if (previousBlockState() == 3) + { + setFormat(start, length, m_phpCommentFormat); + setCurrentBlockState(3); + } + return; + } + + 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; + } + else + { + setFormat(start, length, m_phpCommentFormat); + setCurrentBlockState(3); + return; + } + } + + 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 + { + 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 + // (setzt auch den State für HTML Kommentare) + SyntaxHighlighter::highlightBlock(text); + + // Block-Zustände: + // 0 = HTML-Modus + // 1 = HTML Kommentar (von Basisklasse verwaltet) + // 2 = innerhalb PHP-Block (kein /* */ Kommentar) + // 3 = innerhalb PHP /* */ Block-Kommentar + + // State 1 (HTML-Kommentar) wurde von der Basisklasse gesetzt — nicht überschreiben + if (currentBlockState() == 1) + { + return; + } + + // Wenn der vorherige Block ein HTML-Kommentar war und dieser noch nicht + // abgeschlossen wurde, hat die Basisklasse das bereits korrekt behandelt. + // Wir setzen nur dann auf 0 zurück wenn wir sicher nicht in HTML-Kommentar sind. + if (previousBlockState() != 1) + { + setCurrentBlockState(0); + } + + // Leere Zeile — Zustand weitertragen + if (text.isEmpty()) + { + const int prev = previousBlockState(); + if (prev == 2 || prev == 3) + { + setCurrentBlockState(prev); + } + return; + } + + 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()); + 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/barecode/src/highlighter/SyntaxHighlighter.h b/barecode/src/highlighter/SyntaxHighlighter.h new file mode 100644 index 0000000..9c330ae --- /dev/null +++ b/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