diff --git a/CMakeLists.txt b/CMakeLists.txt
index 16e8f4b..eb10c64 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(BareCode
- VERSION 1.0.0
+ VERSION 1.1.0
DESCRIPTION "A modular code editor built with Qt6"
LANGUAGES CXX
)
diff --git a/README.md b/README.md
index 8b0ac51..f6e99d6 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# BareCode
-Ein modularer Code-Editor, entwickelt mit **C++17**, **Qt6** und **CMake**
-von **Dany Thinnes** | [Projekt Hirnfrei](https://www.projekt-hirnfrei.de)
+**BareCode – Schlanker Code-Editor für Web-Entwickler**
+Version 1.1.0
Kompiliert sauber auf **Linux**, **Windows** und **Haiku**.
diff --git a/main.cpp b/main.cpp
index c24c0bc..babe9b5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -7,7 +7,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
app.setApplicationName("BareCode");
- app.setApplicationVersion("1.0.0");
+ app.setApplicationVersion("1.1.0");
app.setOrganizationName("BareCode");
// Icon in allen verfügbaren Größen setzen
diff --git a/resources/php_functions.json b/resources/php_functions.json
new file mode 100644
index 0000000..1e81c97
--- /dev/null
+++ b/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/resources/resources.qrc b/resources/resources.qrc
index 38da93d..f3b588a 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -7,5 +7,6 @@
icon_48.png
icon_32.png
icon_16.png
+ php_functions.json
diff --git a/src/core/AboutDialog.cpp b/src/core/AboutDialog.cpp
index bc0ebd9..9feeca1 100644
--- a/src/core/AboutDialog.cpp
+++ b/src/core/AboutDialog.cpp
@@ -74,7 +74,7 @@ AboutDialog::AboutDialog(QWidget *parent)
info->addLayout(row);
};
- makeRow(tr("Version"), "1.0.0");
+ makeRow(tr("Version"), "1.1.0");
makeRow(tr("Entwickler"), "Dany Thinnes");
makeRow(tr("Projekt"), "Projekt Hirnfrei");
makeRow(tr("Framework"), QString("Qt %1").arg(qVersion()));
diff --git a/src/editor/CMakeLists.txt b/src/editor/CMakeLists.txt
index 63e8322..fe64f27 100644
--- a/src/editor/CMakeLists.txt
+++ b/src/editor/CMakeLists.txt
@@ -13,6 +13,10 @@ set(EDITOR_SOURCES
FileSearchPanel.h
ColorIndicator.cpp
ColorIndicator.h
+ SignatureHelper.cpp
+ SignatureHelper.h
+ SignatureTooltip.cpp
+ SignatureTooltip.h
)
add_library(BareCode_Editor STATIC ${EDITOR_SOURCES})
diff --git a/src/editor/CodeEditor.cpp b/src/editor/CodeEditor.cpp
index 0579409..f6aca9b 100644
--- a/src/editor/CodeEditor.cpp
+++ b/src/editor/CodeEditor.cpp
@@ -1,6 +1,7 @@
#include "CodeEditor.h"
#include "LineNumberArea.h"
#include "ColorIndicator.h"
+#include "SignatureHelper.h"
#include "core/Settings.h"
#include "highlighter/HighlighterFactory.h"
@@ -24,6 +25,7 @@ CodeEditor::CodeEditor(Settings *settings, QWidget *parent)
{
m_lineNumberArea = new LineNumberArea(this);
m_colorIndicator = new ColorIndicator(this);
+ m_signatureHelper = new SignatureHelper(this);
setupEditor();
connect(this, &CodeEditor::blockCountChanged,
diff --git a/src/editor/CodeEditor.h b/src/editor/CodeEditor.h
index 9ca7837..21581fe 100644
--- a/src/editor/CodeEditor.h
+++ b/src/editor/CodeEditor.h
@@ -9,6 +9,7 @@ class LineNumberArea;
class Settings;
class SyntaxHighlighter;
class ColorIndicator;
+class SignatureHelper;
// ---------------------------------------------------------------------------
// CodeEditor – Core editing widget.
@@ -70,5 +71,6 @@ private:
LineNumberArea *m_lineNumberArea = nullptr;
SyntaxHighlighter *m_highlighter = nullptr;
ColorIndicator *m_colorIndicator = nullptr;
+ SignatureHelper *m_signatureHelper = nullptr;
QString m_filePath;
};
diff --git a/src/editor/SignatureHelper.cpp b/src/editor/SignatureHelper.cpp
new file mode 100644
index 0000000..c84f723
--- /dev/null
+++ b/src/editor/SignatureHelper.cpp
@@ -0,0 +1,222 @@
+#include "SignatureHelper.h"
+#include "SignatureTooltip.h"
+#include "CodeEditor.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+SignatureHelper::SignatureHelper(CodeEditor *editor)
+ : QObject(editor)
+ , m_editor(editor)
+{
+ // Tooltip als Kind des Viewports — bleibt im Fenster
+ m_tooltip = new SignatureTooltip(editor->window());
+
+ loadDatabase();
+
+ connect(m_editor, &CodeEditor::cursorPositionChanged,
+ this, &SignatureHelper::onCursorPositionChanged);
+}
+
+// ---------------------------------------------------------------------------
+// Datenbank laden
+// ---------------------------------------------------------------------------
+void SignatureHelper::loadDatabase()
+{
+ QFile f(":/php_functions.json");
+ if (!f.open(QIODevice::ReadOnly))
+ {
+ return;
+ }
+
+ const QJsonDocument doc = QJsonDocument::fromJson(f.readAll());
+ if (!doc.isArray())
+ {
+ return;
+ }
+
+ for (const QJsonValue &val : doc.array())
+ {
+ const QJsonObject obj = val.toObject();
+ const QString name = obj["name"].toString();
+ if (name.isEmpty())
+ {
+ continue;
+ }
+
+ FunctionInfo info;
+ info.signature = obj["signature"].toString();
+ info.description = obj["desc"].toString();
+ m_functions.insert(name.toLower(), info);
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Cursor-Bewegung auswerten
+// ---------------------------------------------------------------------------
+void SignatureHelper::onCursorPositionChanged()
+{
+ const QTextCursor cursor = m_editor->textCursor();
+ const QString block = cursor.block().text();
+ const int col = cursor.columnNumber();
+ const QString leftText = block.left(col);
+
+ const QString funcName = extractFunctionName(leftText);
+
+ if (funcName.isEmpty())
+ {
+ m_tooltip->hide();
+ return;
+ }
+
+ // Klammern zählen — wenn alle geschlossen, Tooltip ausblenden
+ if (countOpenParens(leftText) <= 0)
+ {
+ m_tooltip->hide();
+ return;
+ }
+
+ const QString key = funcName.toLower();
+ if (!m_functions.contains(key))
+ {
+ m_tooltip->hide();
+ return;
+ }
+
+ const FunctionInfo &info = m_functions[key];
+
+ // Position unter dem Cursor berechnen
+ const QRect cursorRect = m_editor->cursorRect(cursor);
+ const QPoint globalPos = m_editor->viewport()->mapToGlobal(
+ QPoint(cursorRect.left(), cursorRect.bottom() + 4)
+ );
+
+ m_tooltip->showSignature(info.signature, info.description, globalPos);
+}
+
+// ---------------------------------------------------------------------------
+// Funktionsnamen links vor der öffnenden Klammer extrahieren
+// ---------------------------------------------------------------------------
+QString SignatureHelper::extractFunctionName(const QString &text) const
+{
+ // Wir suchen das letzte '(' das zu einem Funktionsnamen gehört.
+ // Dabei müssen wir verschachtelte Klammern korrekt behandeln.
+ int depth = 0;
+ int openPos = -1;
+
+ for (int i = text.length() - 1; i >= 0; --i)
+ {
+ const QChar ch = text[i];
+ if (ch == ')')
+ {
+ ++depth;
+ }
+ else if (ch == '(')
+ {
+ if (depth == 0)
+ {
+ openPos = i;
+ break;
+ }
+ --depth;
+ }
+ }
+
+ if (openPos <= 0)
+ {
+ return QString();
+ }
+
+ // Funktionsnamen direkt links von '(' lesen
+ int end = openPos - 1;
+
+ // Leerzeichen überspringen
+ while (end >= 0 && text[end].isSpace())
+ {
+ --end;
+ }
+
+ if (end < 0)
+ {
+ return QString();
+ }
+
+ // Bezeichner-Zeichen sammeln (Buchstaben, Ziffern, _, :, \)
+ int start = end;
+ while (start > 0 &&
+ (text[start - 1].isLetterOrNumber() ||
+ text[start - 1] == '_' ||
+ text[start - 1] == ':' ||
+ text[start - 1] == '\\'))
+ {
+ --start;
+ }
+
+ const QString name = text.mid(start, end - start + 1);
+
+ // Schlüsselwörter und leere Namen ausschließen
+ static const QStringList keywords = {
+ "if", "else", "elseif", "while", "for", "foreach",
+ "switch", "match", "catch", "function", "fn"
+ };
+
+ if (name.isEmpty() || keywords.contains(name.toLower()))
+ {
+ return QString();
+ }
+
+ // Nur den letzten Teil nach :: oder -> nehmen
+ const int colonPos = name.lastIndexOf("::");
+ const int arrowPos = name.lastIndexOf("->");
+ const int backslashPos = name.lastIndexOf("\\");
+ const int splitPos = qMax(backslashPos, qMax(colonPos, arrowPos));
+
+ if (splitPos >= 0)
+ {
+ return name.mid(splitPos + (name[splitPos] == ':' ? 2 : (name[splitPos] == '\\' ? 1 : 2)));
+ }
+
+ return name;
+}
+
+// ---------------------------------------------------------------------------
+// Offene Klammern zählen
+// ---------------------------------------------------------------------------
+int SignatureHelper::countOpenParens(const QString &text) const
+{
+ int depth = 0;
+ bool inString = false;
+ QChar stringChar;
+
+ for (int i = 0; i < text.length(); ++i)
+ {
+ const QChar ch = text[i];
+
+ // Einfache String-Erkennung (kein vollständiger PHP-Parser)
+ if (!inString && (ch == '\'' || ch == '"'))
+ {
+ inString = true;
+ stringChar = ch;
+ continue;
+ }
+ if (inString)
+ {
+ if (ch == stringChar && (i == 0 || text[i - 1] != '\\'))
+ {
+ inString = false;
+ }
+ continue;
+ }
+
+ if (ch == '(') { ++depth; }
+ else if (ch == ')') { --depth; }
+ }
+
+ return depth;
+}
diff --git a/src/editor/SignatureHelper.h b/src/editor/SignatureHelper.h
new file mode 100644
index 0000000..9b1ec89
--- /dev/null
+++ b/src/editor/SignatureHelper.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include
+#include
+#include
+
+class CodeEditor;
+class SignatureTooltip;
+
+// ---------------------------------------------------------------------------
+// SignatureHelper – Lädt die PHP-Funktionsdatenbank und zeigt beim Tippen
+// automatisch die passende Funktionssignatur als Tooltip.
+//
+// Logik:
+// • Bei jedem Tastendruck: Text links vom Cursor analysieren
+// • Wenn "funktionsname(" erkannt wird → Tooltip anzeigen
+// • Wenn ")" die öffnende Klammer schließt → Tooltip verstecken
+// • Wenn Cursor sich weg bewegt → Tooltip verstecken
+// ---------------------------------------------------------------------------
+class SignatureHelper : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit SignatureHelper(CodeEditor *editor);
+
+private slots:
+ void onCursorPositionChanged();
+
+private:
+ struct FunctionInfo
+ {
+ QString signature;
+ QString description;
+ };
+
+ void loadDatabase();
+ void loadProjectFunctions();
+
+ // Extrahiert den Funktionsnamen direkt links vor dem letzten '('
+ // Gibt leeren String zurück wenn kein Kontext gefunden
+ QString extractFunctionName(const QString &textUpToCursor) const;
+
+ // Zählt offene Klammern — bei 0 ist der Aufruf abgeschlossen
+ int countOpenParens(const QString &textUpToCursor) const;
+
+ CodeEditor *m_editor = nullptr;
+ SignatureTooltip *m_tooltip = nullptr;
+
+ QHash m_functions; // name → info
+};
diff --git a/src/editor/SignatureTooltip.cpp b/src/editor/SignatureTooltip.cpp
new file mode 100644
index 0000000..3ac4099
--- /dev/null
+++ b/src/editor/SignatureTooltip.cpp
@@ -0,0 +1,91 @@
+#include "SignatureTooltip.h"
+
+#include
+#include
+
+SignatureTooltip::SignatureTooltip(QWidget *parent)
+ : QFrame(parent, Qt::ToolTip | Qt::FramelessWindowHint)
+{
+ setFrameShape(QFrame::StyledPanel);
+ setFrameShadow(QFrame::Raised);
+ setAttribute(Qt::WA_ShowWithoutActivating);
+
+ // Dezentes Styling passend zu Hell- und Dunkeltheme
+ setStyleSheet(
+ "SignatureTooltip {"
+ " background: palette(toolTipBase);"
+ " border: 1px solid palette(mid);"
+ " border-radius: 4px;"
+ " padding: 4px;"
+ "}"
+ );
+
+ m_layout = new QVBoxLayout(this);
+ m_layout->setContentsMargins(8, 6, 8, 6);
+ m_layout->setSpacing(3);
+
+ // Signatur — Monospace, deutlich hervorgehoben
+ m_sigLabel = new QLabel(this);
+ m_sigLabel->setTextFormat(Qt::PlainText);
+ m_sigLabel->setWordWrap(false);
+ QFont sigFont = m_sigLabel->font();
+ sigFont.setFamily("Monospace");
+ sigFont.setStyleHint(QFont::Monospace);
+ sigFont.setPointSize(sigFont.pointSize());
+ m_sigLabel->setFont(sigFont);
+ m_sigLabel->setStyleSheet("color: palette(toolTipText); font-weight: bold;");
+ m_layout->addWidget(m_sigLabel);
+
+ // Beschreibung — kleiner, gedimmt
+ m_descLabel = new QLabel(this);
+ m_descLabel->setTextFormat(Qt::PlainText);
+ m_descLabel->setWordWrap(false);
+ m_descLabel->setStyleSheet("color: palette(mid);");
+ QFont descFont = m_descLabel->font();
+ descFont.setPointSize(qMax(descFont.pointSize() - 1, 8));
+ m_descLabel->setFont(descFont);
+ m_layout->addWidget(m_descLabel);
+
+ hide();
+}
+
+void SignatureTooltip::showSignature(const QString &signature,
+ const QString &description,
+ const QPoint &globalPos)
+{
+ m_sigLabel->setText(signature);
+
+ if (description.isEmpty())
+ {
+ m_descLabel->hide();
+ }
+ else
+ {
+ m_descLabel->setText(description);
+ m_descLabel->show();
+ }
+
+ adjustSize();
+
+ // Position so wählen dass das Popup nicht aus dem Bildschirm ragt
+ QPoint pos = globalPos;
+ const QRect screen = QApplication::primaryScreen()->availableGeometry();
+
+ if (pos.x() + width() > screen.right())
+ {
+ pos.setX(screen.right() - width() - 4);
+ }
+ if (pos.y() + height() > screen.bottom())
+ {
+ pos.setY(globalPos.y() - height() - 24);
+ }
+
+ move(pos);
+ show();
+ raise();
+}
+
+void SignatureTooltip::hide()
+{
+ QFrame::hide();
+}
diff --git a/src/editor/SignatureTooltip.h b/src/editor/SignatureTooltip.h
new file mode 100644
index 0000000..110062f
--- /dev/null
+++ b/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;
+};