BareCode V 1.1.0
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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**.
|
||||
|
||||
|
||||
2
main.cpp
2
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
|
||||
|
||||
1197
resources/php_functions.json
Normal file
1197
resources/php_functions.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,5 +7,6 @@
|
||||
<file>icon_48.png</file>
|
||||
<file>icon_32.png</file>
|
||||
<file>icon_16.png</file>
|
||||
<file>php_functions.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
222
src/editor/SignatureHelper.cpp
Normal file
222
src/editor/SignatureHelper.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "SignatureHelper.h"
|
||||
#include "SignatureTooltip.h"
|
||||
#include "CodeEditor.h"
|
||||
|
||||
#include <QTextCursor>
|
||||
#include <QTextBlock>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QRect>
|
||||
#include <QRegularExpression>
|
||||
|
||||
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;
|
||||
}
|
||||
51
src/editor/SignatureHelper.h
Normal file
51
src/editor/SignatureHelper.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
|
||||
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<QString, FunctionInfo> m_functions; // name → info
|
||||
};
|
||||
91
src/editor/SignatureTooltip.cpp
Normal file
91
src/editor/SignatureTooltip.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "SignatureTooltip.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
|
||||
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();
|
||||
}
|
||||
29
src/editor/SignatureTooltip.h
Normal file
29
src/editor/SignatureTooltip.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 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;
|
||||
};
|
||||
Reference in New Issue
Block a user