From d151fe4f0e1d0ddb5d264d4e59b11160e1115add Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 15:13:18 -0700
Subject: [PATCH 001/160] [Refactor] Update include file path to fix testing
errors
---
src/CodeEditor.cpp | 6 +++---
src/MainWindow.cpp | 2 +-
src/main.cpp | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 4259f81..947dc59 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -1,6 +1,6 @@
-#include "CodeEditor.h"
-#include "MainWindow.h"
-#include "LineNumberArea.h"
+#include "../include/CodeEditor.h"
+#include "../include/MainWindow.h"
+#include "../include/LineNumberArea.h"
#include
#include
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index ae44543..a687ac3 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,4 +1,4 @@
-#include "MainWindow.h"
+#include "../include/MainWindow.h"
#include
#include
diff --git a/src/main.cpp b/src/main.cpp
index b7aa619..313b85a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,4 @@
-#include "MainWindow.h"
+#include "../include/MainWindow.h"
#include
#include
From bcca0dbaec35a51f4ada195d2de8d06d9f83298e Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 15:13:46 -0700
Subject: [PATCH 002/160] Added testing to the build
---
CMakeLists.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 49c46d0..aa40a27 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,7 +47,7 @@ endif()
set(CMAKE_PREFIX_PATH ${Qt_DIR})
# Find Qt Widgets
-find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Widgets REQUIRED)
+find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Widgets Test REQUIRED)
# Add executable and source files
add_executable(${TARGET_NAME}
@@ -58,6 +58,8 @@ add_executable(${TARGET_NAME}
include/CodeEditor.h
)
+add_subdirectory(tests)
+
qt_add_resources(APP_RESOURCES resources.qrc)
target_sources(${TARGET_NAME} PRIVATE ${APP_RESOURCES})
From e068893f2c23b0f1250a6f3c70f715dc7c48acfa Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 15:14:05 -0700
Subject: [PATCH 003/160] [Make] Added automating testing from Make file
---
Makefile | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Makefile b/Makefile
index f990940..b0973ed 100644
--- a/Makefile
+++ b/Makefile
@@ -75,3 +75,11 @@ install:
fi \
fi
@echo "$(PROJECT) installed."
+
+test:
+ @for test in ./build/tests/test_*; do \
+ if [ -f $$test ]; then \
+ echo "Running $$test..."; \
+ $$test; \
+ fi; \
+ done
From f165366cea8efb64ed703f5d3f853be95f72eb47 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 15:14:26 -0700
Subject: [PATCH 004/160] [Test] CMakeLists file for testing directory
---
tests/CMakeLists.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 tests/CMakeLists.txt
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..7bf9e34
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Enable testing
+enable_testing()
+
+# Add individual test executables
+add_executable(test_mainwindow
+ test_mainwindow.cpp
+ ../src/MainWindow.cpp
+ ../src/CodeEditor.cpp
+ ../include/MainWindow.h
+ ../include/CodeEditor.h
+)
+
+# Link each test with necessary libraries
+target_link_libraries(test_mainwindow PRIVATE Qt6::Widgets Qt6::Test)
+
+# Register each test with CTest
+add_test(NAME test_mainwindow COMMAND test_mainwindow)
+
+# Set the runtime output directory for the test executables
+set_target_properties(test_mainwindow PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
+)
\ No newline at end of file
From d07ddc3db7cb876e9837c6121cf5a521fc285962 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 15:14:51 -0700
Subject: [PATCH 005/160] [Test] Added init :test: mainwindow
---
tests/test_mainwindow.cpp | 51 +++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 tests/test_mainwindow.cpp
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
new file mode 100644
index 0000000..67797be
--- /dev/null
+++ b/tests/test_mainwindow.cpp
@@ -0,0 +1,51 @@
+#include "../include/MainWindow.h"
+
+#include
+#include
+#include
+
+class TestMainWindow : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase(); // Runs before all tests
+ void cleanupTestCase(); // Runs after all tests
+ void testWindowTitle();
+ void testMenuBar();
+ void testNewFileAction();
+};
+
+void TestMainWindow::initTestCase()
+{
+ qDebug() << "Initializing MainWindow tests...";
+}
+
+void TestMainWindow::cleanupTestCase()
+{
+ qDebug() << "Cleaning up MainWindow tests...";
+}
+
+void TestMainWindow::testWindowTitle()
+{
+ MainWindow window;
+ QCOMPARE(window.windowTitle(), QString("CodeAstra ~ Code Editor"));
+}
+
+void TestMainWindow::testMenuBar()
+{
+ MainWindow window;
+ QMenuBar *menuBar = window.menuBar();
+ QVERIFY(menuBar != nullptr);
+ QCOMPARE(menuBar->actions().size(), 3); // File, Help, CodeAstra
+}
+
+void TestMainWindow::testNewFileAction()
+{
+ MainWindow window;
+ QAction *newAction = window.findChild("New File");
+ QVERIFY(newAction != nullptr);
+}
+
+QTEST_MAIN(TestMainWindow)
+#include "test_mainwindow.moc"
From ef882ff4834adcf2a1171cc7ca08c8a90eb5f9cf Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 9 Mar 2025 18:13:36 -0700
Subject: [PATCH 006/160] [Update] Added Syntax to the test build
---
src/Syntax.cpp | 2 +-
tests/CMakeLists.txt | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index 553c927..80d1043 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -1,4 +1,4 @@
-#include "Syntax.h"
+#include "../include/Syntax.h"
Syntax::Syntax(QTextDocument *parent) : QSyntaxHighlighter(parent)
{
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7bf9e34..a291c85 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,8 +6,10 @@ add_executable(test_mainwindow
test_mainwindow.cpp
../src/MainWindow.cpp
../src/CodeEditor.cpp
+ ../src/Syntax.cpp
../include/MainWindow.h
../include/CodeEditor.h
+ ../include/Syntax.h
)
# Link each test with necessary libraries
From 0ba2f8335ccc0f63f9525e61dc1c27f7d9093226 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:38:29 -0700
Subject: [PATCH 007/160] [Update] Refactor MainWindow initialization and
enhance file dialog filters
---
src/MainWindow.cpp | 59 ++++++++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 25 deletions(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 23e3a83..1333f98 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -12,33 +12,45 @@
#include
#include
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ editor(new CodeEditor(this)),
+ syntax(new Syntax(editor->document())),
+ tree(nullptr)
{
setWindowTitle("CodeAstra ~ Code Editor");
- editor = new CodeEditor(this);
- syntax = new Syntax(editor->document());
-
+ // Set tab width to 4 spaces
QFontMetrics metrics(editor->font());
int spaceWidth = metrics.horizontalAdvance(" ");
editor->setTabStopDistance(spaceWidth * 4);
+ editor->setLineWrapMode(QPlainTextEdit::NoWrap);
+
+ initTree();
+ createMenuBar();
+ showMaximized();
+}
+MainWindow::~MainWindow() {}
+
+void MainWindow::initTree()
+{
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(splitter);
tree = new Tree(splitter, this);
- splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- splitter->setHandleWidth(5);
- splitter->setSizes(QList() << 20 << 950);
splitter->addWidget(editor);
- createMenuBar();
- showMaximized();
+ splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ splitter->setHandleWidth(5);
+ splitter->setSizes(QList() << 150 << 800);
+ splitter->setStretchFactor(0, 1);
+ splitter->setStretchFactor(1, 3);
+ splitter->setChildrenCollapsible(false);
+ splitter->setOpaqueResize(true);
}
-MainWindow::~MainWindow() {}
-
void MainWindow::createMenuBar()
{
QMenuBar *menuBar = new QMenuBar(this);
@@ -56,17 +68,11 @@ void MainWindow::createMenuBar()
void MainWindow::createFileActions(QMenu *fileMenu)
{
- QAction *newAction = createAction(QIcon::fromTheme("document-new"), tr("&New File..."), QKeySequence::New, tr("Create a new file"), &MainWindow::newFile);
- fileMenu->addAction(newAction);
-
- QAction *openAction = createAction(QIcon::fromTheme("document-open"), tr("&Open..."), QKeySequence::Open, tr("Open an existing file"), &MainWindow::openFile);
- fileMenu->addAction(openAction);
-
- QAction *saveAction = createAction(QIcon::fromTheme("document-save"), tr("&Save"), QKeySequence::Save, tr("Save your file"), &MainWindow::saveFile);
- fileMenu->addAction(saveAction);
-
- QAction *saveAsAction = createAction(QIcon::fromTheme("document-saveAs"), tr("&Save As"), QKeySequence::SaveAs, tr("Save current file as..."), &MainWindow::saveFileAs);
- fileMenu->addAction(saveAsAction);
+ fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), &MainWindow::newFile));
+ fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), &MainWindow::openFile));
+ fileMenu->addSeparator();
+ fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), &MainWindow::saveFile));
+ fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), &MainWindow::saveFileAs));
}
void MainWindow::createHelpActions(QMenu *helpMenu)
@@ -143,12 +149,13 @@ void MainWindow::showAbout()
QString::number((QT_VERSION >> 8) & 0xFF) + "." + // Minor version
QString::number(QT_VERSION & 0xFF)); // Patch version
- QMessageBox::about(this, "About Code Astra", aboutText);
+ QMessageBox::about(this, tr("About"), aboutText);
}
void MainWindow::openFile()
{
- QString fileName = QFileDialog::getOpenFileName(this, "Open File");
+ QString fileName = QFileDialog::getOpenFileName(this, "Open File", QString(),
+ "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
if (!fileName.isEmpty())
{
QFile file(fileName);
@@ -202,7 +209,9 @@ void MainWindow::saveFile()
void MainWindow::saveFileAs()
{
- QString fileName = QFileDialog::getSaveFileName(this, "Save File As");
+ QString fileName = QFileDialog::getSaveFileName(this, "Save File As", QString(),
+ "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
+
if (!fileName.isEmpty())
{
currentFileName = fileName;
From a12b36d0dfe18d230b5d61cc6e51c50035c69c09 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:38:39 -0700
Subject: [PATCH 008/160] [Update] Simplify CodeEditor constructor by
initializing lineNumberArea in the member initializer list
---
src/CodeEditor.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 4259f81..3ccb5be 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -5,10 +5,10 @@
#include
#include
-CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
+CodeEditor::CodeEditor(QWidget *parent)
+ : QPlainTextEdit(parent),
+ lineNumberArea(new LineNumberArea(this))
{
- lineNumberArea = new LineNumberArea(this);
-
connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
From e352206ba1468ffeb70f9a9021870e51eedd1f74 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:38:47 -0700
Subject: [PATCH 009/160] [Update] Improve icon creation by adding error
handling and using antialiasing for round icons
---
src/main.cpp | 46 +++++++++++++++++++++++++++++-----------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/src/main.cpp b/src/main.cpp
index b7aa619..aadd252 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,19 +13,22 @@
QIcon createRoundIcon(const QString &iconPath)
{
QPixmap pixmap(iconPath);
-
- // Create a round mask
- QBitmap mask(pixmap.size());
- mask.fill(Qt::white);
-
- QPainter painter(&mask);
- painter.setBrush(Qt::black);
+ if (pixmap.isNull())
+ {
+ qWarning() << "Failed to load icon:" << iconPath;
+ return QIcon();
+ }
+
+ QPixmap roundPixmap(pixmap.size());
+ roundPixmap.fill(Qt::transparent);
+
+ QPainter painter(&roundPixmap);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setBrush(QBrush(pixmap));
painter.setPen(Qt::NoPen);
painter.drawEllipse(0, 0, pixmap.width(), pixmap.height());
- pixmap.setMask(mask);
-
- return QIcon(pixmap);
+ return QIcon(roundPixmap);
}
int main(int argc, char *argv[])
@@ -33,17 +36,26 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
QIcon roundIcon = createRoundIcon(":/resources/app_icon.png");
- QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ if (roundIcon.isNull())
+ {
+ qWarning() << "Failed to load round icon!";
+ }
+
+ QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
font.setPointSize(12);
-
+
app.setFont(font);
app.setWindowIcon(roundIcon);
- app.setApplicationVersion("0.0.1");
- app.setOrganizationName("Chris Dedman");
- app.setApplicationName("CodeAstra");
- MainWindow window;
- window.show();
+ app.setApplicationVersion(QStringLiteral("0.0.1"));
+ app.setOrganizationName(QStringLiteral("Chris Dedman"));
+ app.setApplicationName(QStringLiteral("CodeAstra"));
+ app.setApplicationDisplayName(QStringLiteral("CodeAstra"));
+
+ app.setStyle("Fusion");
+
+ QScopedPointer window(new MainWindow);
+ window->show();
return app.exec();
}
\ No newline at end of file
From fecca4b965949797d0ba2e5a340004a6c50dafa4 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:38:52 -0700
Subject: [PATCH 010/160] [Add] Declare initTree method in MainWindow class for
tree initialization
---
include/MainWindow.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 81bcf80..e48cb8b 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -10,7 +10,6 @@
#include
#include
#include
-#include
class MainWindow : public QMainWindow
{
@@ -20,6 +19,7 @@ class MainWindow : public QMainWindow
explicit MainWindow(QWidget *parent = nullptr);
virtual ~MainWindow();
void loadFileInEditor(const QString &filePath);
+ void initTree();
private slots:
void newFile();
From 8286019e43e2a84ddd37fa9625b1b651d8022228 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:39:09 -0700
Subject: [PATCH 011/160] [Refactor] Refactor Tree constructor to initialize
members in the initializer list and enhance setupTree method
---
src/Tree.cpp | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/Tree.cpp b/src/Tree.cpp
index c5405a0..01adf03 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -7,11 +7,12 @@
#include
#include
-Tree::Tree(QSplitter *splitter, MainWindow *mainWindow) : QObject(splitter), mainWindow(mainWindow)
+Tree::Tree(QSplitter *splitter, MainWindow *mainWindow)
+ : QObject(splitter),
+ model(new QFileSystemModel()),
+ tree(new QTreeView(splitter)),
+ mainWindow(mainWindow)
{
- model = new QFileSystemModel();
- tree = new QTreeView(splitter);
-
setupModel();
setupTree();
@@ -25,7 +26,6 @@ void Tree::setupModel()
model->setRootPath(getDirectoryPath());
model->setIconProvider(new QFileIconProvider);
model->setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
-
}
void Tree::setupTree()
@@ -37,14 +37,15 @@ void Tree::setupTree()
tree->setIndentation(20);
tree->setSortingEnabled(false);
tree->sortByColumn(1, Qt::AscendingOrder);
+ tree->setHeaderHidden(true);
- tree->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(tree, &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);
-
- for (int i = 1; i <= 3; ++i)
+ for (int i = 1; i <= model->columnCount(); ++i)
{
tree->setColumnHidden(i, true);
}
+
+ tree->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(tree, &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);
}
QString Tree::getDirectoryPath()
From bb89ad41e1bedd123cd78766b76b9c2ed979f85c Mon Sep 17 00:00:00 2001
From: Chris
Date: Sun, 16 Mar 2025 12:39:16 -0700
Subject: [PATCH 012/160] Update README to reflect progress on file creation
and syntax highlighting features
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 8f868f0..03be487 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,9 @@ Please, check the [wiki](https://github.com/sandbox-science/CodeAstra/wiki) for
- [x] Basic text editing
- [x] Open a file
- [x] Save file
- - [ ] Create a new file
-- [ ] File tree navigation
-- [ ] Syntax highlighting
+ - [ ] Create a new file ~ in progress
+- [x] File tree navigation
+- [ ] Syntax highlighting ~ in progress
- [ ] Plugin system
## To-Do
From f564991c1ff70f4da3073140ef3d2e6bac61712d Mon Sep 17 00:00:00 2001
From: Chris
Date: Tue, 18 Mar 2025 19:18:07 -0700
Subject: [PATCH 013/160] [Update] Bump application version to 0.1.0 in
main.cpp
---
src/main.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main.cpp b/src/main.cpp
index aadd252..93247d6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -47,7 +47,7 @@ int main(int argc, char *argv[])
app.setFont(font);
app.setWindowIcon(roundIcon);
- app.setApplicationVersion(QStringLiteral("0.0.1"));
+ app.setApplicationVersion(QStringLiteral("0.1.0"));
app.setOrganizationName(QStringLiteral("Chris Dedman"));
app.setApplicationName(QStringLiteral("CodeAstra"));
app.setApplicationDisplayName(QStringLiteral("CodeAstra"));
From a984cf44d0ba272632cb15bd1861650bdd7ecbf7 Mon Sep 17 00:00:00 2001
From: Chris
Date: Tue, 18 Mar 2025 20:46:01 -0700
Subject: [PATCH 014/160] [Add] Implement comment functionality in CodeEditor
with language-specific symbols
---
src/CodeEditor.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 4259f81..8ebbd13 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -26,6 +26,11 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
moveCursor(QTextCursor::WordLeft, QTextCursor::KeepAnchor);
return;
}
+ if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Slash)
+ {
+ addComment();
+ return;
+ }
if (mode == NORMAL)
{
@@ -57,6 +62,99 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
}
}
+QString CodeEditor::getFileExtension()
+{
+ QString filePath = getCurrentFileName();
+ if (!QFile::exists(filePath))
+ {
+ return QString();
+ }
+
+ // Extract the file extension from the file path
+ return QFileInfo(filePath).suffix().toLower();
+}
+
+void CodeEditor::addLanguageSymbol(QTextCursor &cursor, const QString commentSymbol)
+{
+ // If text is selected, comment/uncomment selected text
+ if (cursor.hasSelection())
+ {
+ int start = cursor.selectionStart();
+ int end = cursor.selectionEnd();
+
+ cursor.setPosition(start);
+ int startBlockNumber = cursor.blockNumber();
+ cursor.setPosition(end);
+ int endBlockNumber = cursor.blockNumber();
+
+ cursor.setPosition(start);
+ for (int i = startBlockNumber; i <= endBlockNumber; ++i)
+ {
+ cursor.movePosition(QTextCursor::StartOfLine);
+ QString lineText = cursor.block().text();
+
+ if (lineText.startsWith(commentSymbol))
+ {
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 3);
+ cursor.removeSelectedText();
+ }
+ else
+ {
+ cursor.insertText(commentSymbol + " ");
+ }
+
+ cursor.movePosition(QTextCursor::NextBlock);
+ }
+ }
+ else
+ {
+ // If no text is selected, comment/uncomment the current line
+ cursor.select(QTextCursor::LineUnderCursor);
+ QString lineText = cursor.selectedText();
+
+ if (lineText.startsWith(commentSymbol))
+ {
+ lineText.remove(0, 3);
+ }
+ else
+ {
+ lineText.prepend(commentSymbol + " ");
+ }
+
+ cursor.insertText(lineText);
+ }
+}
+
+void CodeEditor::addComment()
+{
+ QTextCursor cursor = textCursor();
+ QString fileExtension = getFileExtension();
+ qDebug() << "File Extension:" << fileExtension;
+
+ if (fileExtension == "cpp" || fileExtension == "h" ||
+ fileExtension == "hpp" || fileExtension == "c" ||
+ fileExtension == "java" || fileExtension == "go" ||
+ fileExtension == "json")
+ {
+ addLanguageSymbol(cursor, "//");
+ }
+ else if (fileExtension == "py" || fileExtension == "yaml" ||
+ fileExtension == "yml" || fileExtension == "sh" ||
+ fileExtension == "bash")
+ {
+ addLanguageSymbol(cursor, "#");
+ }
+ else if (fileExtension == "sql")
+ {
+ addLanguageSymbol(cursor, "--");
+ }
+ else
+ {
+ qDebug() << "Unsupported file extension for commenting.";
+ return;
+ }
+}
+
int CodeEditor::lineNumberAreaWidth()
{
int digits = 1;
From 09370ce340a5a9d0599aee8370ff49df13443c18 Mon Sep 17 00:00:00 2001
From: Chris
Date: Tue, 18 Mar 2025 20:46:15 -0700
Subject: [PATCH 015/160] [Add] Implement functionality to set current file
name in CodeEditor upon loading a file
---
include/CodeEditor.h | 6 ++++++
src/MainWindow.cpp | 1 +
2 files changed, 7 insertions(+)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index e1f4d59..ae8c6b2 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -19,6 +19,8 @@ class CodeEditor : public QPlainTextEdit
Mode mode = NORMAL;
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
+ QString getCurrentFileName() const { return currentFileName; }
+ void setCurrentFileName(const QString &fileName) { currentFileName = fileName; }
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -31,6 +33,10 @@ private slots:
private:
QWidget *lineNumberArea;
+ QString currentFileName;
+ QString getFileExtension();
+ void addLanguageSymbol(QTextCursor &cursor, const QString commentSymbol);
+ void addComment();
};
#endif // CODEEDITOR_H
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 23e3a83..cb7cd3b 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -223,6 +223,7 @@ void MainWindow::loadFileInEditor(const QString &filePath)
editor->setPlainText(in.readAll());
file.close();
+ editor->setCurrentFileName(filePath);
currentFileName = filePath;
setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
}
From e683a52cf19d8940a2faac2610e72453574d1c42 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 16:27:57 -0700
Subject: [PATCH 016/160] [Updated] Refactor CodeEditor.h to correct parameter
type in addLanguageSymbol and add comment-related methods
---
include/CodeEditor.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index ae8c6b2..0446920 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -35,7 +35,9 @@ private slots:
QWidget *lineNumberArea;
QString currentFileName;
QString getFileExtension();
- void addLanguageSymbol(QTextCursor &cursor, const QString commentSymbol);
+ void addLanguageSymbol(QTextCursor &cursor, const QString &commentSymbol);
+ void commentSelection(QTextCursor &cursor, const QString &commentSymbol);
+ void commentLine(QTextCursor &cursor, const QString &commentSymbol);
void addComment();
};
From 4e8137b317b46fb3d451f2e40b6dd27a83c746d3 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 16:29:06 -0700
Subject: [PATCH 017/160] Refactor MainWindow to remove currentFileName and
delegate file name management to CodeEditor
---
include/MainWindow.h | 1 -
src/MainWindow.cpp | 9 ++++-----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 81bcf80..c2f8451 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -37,7 +37,6 @@ private slots:
const QKeySequence &shortcut, const QString &statusTip,
void (MainWindow::*slot)());
CodeEditor *editor;
- QString currentFileName;
Syntax *syntax;
Tree *tree;
};
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index cb7cd3b..14f159b 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -169,7 +169,7 @@ void MainWindow::openFile()
}
file.close();
- currentFileName = fileName;
+ editor->setCurrentFileName(fileName);
setWindowTitle("CodeAstra ~ " + QFileInfo(fileName).fileName());
}
@@ -177,13 +177,13 @@ void MainWindow::openFile()
void MainWindow::saveFile()
{
- if (currentFileName.isEmpty())
+ if (editor->getCurrentFileName().isEmpty())
{
saveFileAs();
return;
}
- QFile file(currentFileName);
+ QFile file(editor->getCurrentFileName());
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, "Error", "Cannot save file: " + file.errorString());
@@ -205,7 +205,7 @@ void MainWindow::saveFileAs()
QString fileName = QFileDialog::getSaveFileName(this, "Save File As");
if (!fileName.isEmpty())
{
- currentFileName = fileName;
+ editor->setCurrentFileName(fileName);
saveFile();
}
}
@@ -224,6 +224,5 @@ void MainWindow::loadFileInEditor(const QString &filePath)
file.close();
editor->setCurrentFileName(filePath);
- currentFileName = filePath;
setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
}
From 6c5371472a8f99697ee00283e94b2390946c4d5f Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 16:29:24 -0700
Subject: [PATCH 018/160] Refactor comment functionality in CodeEditor to
streamline selection and line commenting
---
src/CodeEditor.cpp | 78 ++++++++++++++++++++++++++--------------------
1 file changed, 44 insertions(+), 34 deletions(-)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 8ebbd13..0bd81af 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -74,57 +74,67 @@ QString CodeEditor::getFileExtension()
return QFileInfo(filePath).suffix().toLower();
}
-void CodeEditor::addLanguageSymbol(QTextCursor &cursor, const QString commentSymbol)
+void CodeEditor::addLanguageSymbol(QTextCursor &cursor, const QString &commentSymbol)
{
- // If text is selected, comment/uncomment selected text
if (cursor.hasSelection())
{
- int start = cursor.selectionStart();
- int end = cursor.selectionEnd();
-
- cursor.setPosition(start);
- int startBlockNumber = cursor.blockNumber();
- cursor.setPosition(end);
- int endBlockNumber = cursor.blockNumber();
-
- cursor.setPosition(start);
- for (int i = startBlockNumber; i <= endBlockNumber; ++i)
- {
- cursor.movePosition(QTextCursor::StartOfLine);
- QString lineText = cursor.block().text();
-
- if (lineText.startsWith(commentSymbol))
- {
- cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 3);
- cursor.removeSelectedText();
- }
- else
- {
- cursor.insertText(commentSymbol + " ");
- }
-
- cursor.movePosition(QTextCursor::NextBlock);
- }
+ commentSelection(cursor, commentSymbol);
}
else
{
- // If no text is selected, comment/uncomment the current line
- cursor.select(QTextCursor::LineUnderCursor);
- QString lineText = cursor.selectedText();
+ commentLine(cursor, commentSymbol);
+ }
+}
+
+// Comment/uncomment the selected text or the current line
+void CodeEditor::commentSelection(QTextCursor &cursor, const QString &commentSymbol)
+{
+ int start = cursor.selectionStart();
+ int end = cursor.selectionEnd();
+
+ cursor.setPosition(start);
+ int startBlockNumber = cursor.blockNumber();
+ cursor.setPosition(end);
+ int endBlockNumber = cursor.blockNumber();
+
+ cursor.setPosition(start);
+ for (int i = startBlockNumber; i <= endBlockNumber; ++i)
+ {
+ cursor.movePosition(QTextCursor::StartOfLine);
+ QString lineText = cursor.block().text();
if (lineText.startsWith(commentSymbol))
{
- lineText.remove(0, 3);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 3);
+ cursor.removeSelectedText();
}
else
{
- lineText.prepend(commentSymbol + " ");
+ cursor.insertText(commentSymbol + " ");
}
- cursor.insertText(lineText);
+ cursor.movePosition(QTextCursor::NextBlock);
}
}
+// Comment/uncomment the single current line
+void CodeEditor::commentLine(QTextCursor &cursor, const QString &commentSymbol)
+{
+ cursor.select(QTextCursor::LineUnderCursor);
+ QString lineText = cursor.selectedText();
+
+ if (lineText.startsWith(commentSymbol))
+ {
+ lineText.remove(0, 3);
+ }
+ else
+ {
+ lineText.prepend(commentSymbol + " ");
+ }
+
+ cursor.insertText(lineText);
+}
+
void CodeEditor::addComment()
{
QTextCursor cursor = textCursor();
From 98c430777ac1a164279e23984e3245290da9a534 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:19:55 -0700
Subject: [PATCH 019/160] [Add] Include LineNumberArea.h in the executable
target
---
CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bc4f222..75eb2f2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,7 @@ add_executable(${TARGET_NAME}
include/CodeEditor.h
include/Syntax.h
include/Tree.h
+ include/LineNumberArea.h
)
qt_add_resources(APP_RESOURCES resources.qrc)
From c5ece45e574667aec6c753cc1e65a2121b9f7041 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:20:33 -0700
Subject: [PATCH 020/160] [Refactor] Replace include guards with #pragma once
in CodeEditor and LineNumberArea headers
---
include/CodeEditor.h | 7 ++-----
include/LineNumberArea.h | 27 ++++++++++++---------------
2 files changed, 14 insertions(+), 20 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index e1f4d59..4054768 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -1,5 +1,4 @@
-#ifndef CODEEDITOR_H
-#define CODEEDITOR_H
+#pragma once
#include
#include
@@ -31,6 +30,4 @@ private slots:
private:
QWidget *lineNumberArea;
-};
-
-#endif // CODEEDITOR_H
+};
\ No newline at end of file
diff --git a/include/LineNumberArea.h b/include/LineNumberArea.h
index ac052ef..dd5980c 100644
--- a/include/LineNumberArea.h
+++ b/include/LineNumberArea.h
@@ -1,5 +1,4 @@
-#ifndef LINENUMBER_H
-#define LINENUMBER_H
+#pragma once
#include "CodeEditor.h"
@@ -10,21 +9,19 @@
class LineNumberArea : public QWidget
{
public:
- LineNumberArea(CodeEditor *editor) : QWidget(editor), codeEditor(editor) {}
+ LineNumberArea(CodeEditor *editor) : QWidget(editor), m_codeEditor(editor) {}
- QSize sizeHint() const override
- {
- return QSize(codeEditor->lineNumberAreaWidth(), 0);
- }
+ QSize sizeHint() const override
+ {
+ return QSize(m_codeEditor->lineNumberAreaWidth(), 0);
+ }
protected:
- void paintEvent(QPaintEvent *event) override
- {
- codeEditor->lineNumberAreaPaintEvent(event);
- }
+ void paintEvent(QPaintEvent *event) override
+ {
+ m_codeEditor->lineNumberAreaPaintEvent(event);
+ }
private:
- CodeEditor *codeEditor;
-};
-
-#endif // LINENUMBER_H
\ No newline at end of file
+ CodeEditor *m_codeEditor;
+};
\ No newline at end of file
From b4980287f2290f5e75ee0809a57e791e782105a5 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:21:12 -0700
Subject: [PATCH 021/160] [Refactor] Replace include guards with #pragma once
in MainWindow and Tree headers + change row pointer to smart pointer
---
include/MainWindow.h | 91 ++++++++++++++++++++++----------------------
include/Tree.h | 26 +++++++------
2 files changed, 60 insertions(+), 57 deletions(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index e48cb8b..402bc18 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -1,45 +1,46 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include "CodeEditor.h"
-#include "Syntax.h"
-#include "Tree.h"
-
-#include
-#include
-#include
-#include
-#include
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- explicit MainWindow(QWidget *parent = nullptr);
- virtual ~MainWindow();
- void loadFileInEditor(const QString &filePath);
- void initTree();
-
-private slots:
- void newFile();
- void openFile();
- void saveFile();
- void saveFileAs();
- void showAbout();
-
-private:
- void createMenuBar();
- void createFileActions(QMenu *fileMenu);
- void createHelpActions(QMenu *helpMenu);
- void createAppActions(QMenu *appMenu);
- QAction *createAction(const QIcon &icon, const QString &text,
- const QKeySequence &shortcut, const QString &statusTip,
- void (MainWindow::*slot)());
- CodeEditor *editor;
- QString currentFileName;
- Syntax *syntax;
- Tree *tree;
-};
-
-#endif // MAINWINDOW_H
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class CodeEditor;
+class Syntax;
+class Tree;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ virtual ~MainWindow();
+ void loadFileInEditor(const QString &filePath);
+ // Initialize the file tree view and set it as the central widget
+ // of the main window, alongside the code editor
+ void initTree();
+
+private slots:
+ void newFile();
+ void openFile();
+ void saveFile();
+ void saveFileAs();
+ void showAbout();
+
+private:
+ void createMenuBar();
+ void createFileActions(QMenu *fileMenu);
+ void createHelpActions(QMenu *helpMenu);
+ void createAppActions(QMenu *appMenu);
+ QAction *createAction(const QIcon &icon, const QString &text,
+ const QKeySequence &shortcut, const QString &statusTip,
+ void (MainWindow::*slot)());
+ std::unique_ptr editor;
+ QString currentFileName;
+ std::unique_ptr syntax;
+ std::unique_ptr tree;
+};
\ No newline at end of file
diff --git a/include/Tree.h b/include/Tree.h
index 9584606..4a54eb9 100644
--- a/include/Tree.h
+++ b/include/Tree.h
@@ -1,19 +1,21 @@
-#ifndef TREE_H
-#define TREE_H
+#pragma once
#include
-#include
-#include
#include
+#include
-class MainWindow; // Forward declaration
+// Forward declarations
+class MainWindow;
+class QTreeView;
+class QFileSystemModel;
+class QFileIconProvider;
class Tree : public QObject
{
Q_OBJECT
public:
- Tree(QSplitter *splitter, MainWindow *mainWindow);
+ explicit Tree(QSplitter *splitter, MainWindow *mainWindow);
~Tree();
private:
@@ -21,11 +23,11 @@ class Tree : public QObject
void setupModel();
void setupTree();
void openFile(const QModelIndex &index);
- QString getDirectoryPath();
+ QString getDirectoryPath() const;
- QFileSystemModel *model;
- QTreeView *tree;
- MainWindow *mainWindow;
-};
+ std::unique_ptr m_iconProvider;
+ std::unique_ptr m_model;
+ std::unique_ptr m_tree;
-#endif // TREE_H
+ MainWindow *m_mainWindow;
+};
\ No newline at end of file
From 113d20646634da16e2f8d757d64c05fb6c66bd4f Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:21:22 -0700
Subject: [PATCH 022/160] [Refactor] Replace include guards with #pragma once
and change QList to QVector for syntax rules in Syntax.h
---
include/Syntax.h | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/include/Syntax.h b/include/Syntax.h
index 4b40f5a..9adfed0 100644
--- a/include/Syntax.h
+++ b/include/Syntax.h
@@ -1,5 +1,4 @@
-#ifndef SYNTAX_H
-#define SYNTAX_H
+#pragma once
#include
#include
@@ -22,7 +21,7 @@ class Syntax : public QSyntaxHighlighter
QRegularExpression pattern;
QTextCharFormat format;
};
- QList syntaxRules;
+ QVector syntaxRules;
QTextCharFormat keywordFormat;
QTextCharFormat singleLineCommentFormat;
@@ -30,8 +29,15 @@ class Syntax : public QSyntaxHighlighter
QTextCharFormat functionFormat;
QTextCharFormat parenthesisFormat;
QTextCharFormat charFormat;
+ QTextCharFormat iterationFormat;
void addPattern(const QString &pattern, const QTextCharFormat &format);
-};
-#endif // SYNTAX_H
\ No newline at end of file
+ // Initialization functions for different syntax highlighting rules
+ void initKeywordRules();
+ void initCommentRules();
+ void initFunctionRules();
+ void initParenthesisRules();
+ void initCharRules();
+ void initQuotationRules();
+};
From b12e995453d8043bf5e5ff1f5cce2a9e7e710df6 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:21:37 -0700
Subject: [PATCH 023/160] [Refactor] Improve memory management by using smart
pointers for editor and tree in MainWindow
---
src/MainWindow.cpp | 47 ++++++++++++++++++++--------------------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 1333f98..c0b5b94 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,6 +1,7 @@
#include "MainWindow.h"
#include "Syntax.h"
#include "Tree.h"
+#include "CodeEditor.h"
#include
#include
@@ -14,8 +15,8 @@
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
- editor(new CodeEditor(this)),
- syntax(new Syntax(editor->document())),
+ editor(std::make_unique(this)),
+ syntax(std::make_unique(editor->document())),
tree(nullptr)
{
setWindowTitle("CodeAstra ~ Code Editor");
@@ -38,10 +39,9 @@ void MainWindow::initTree()
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(splitter);
- tree = new Tree(splitter, this);
-
- splitter->addWidget(editor);
+ tree = std::make_unique(splitter, this);
+ splitter->addWidget(editor.get());
splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
splitter->setHandleWidth(5);
splitter->setSizes(QList() << 150 << 800);
@@ -158,27 +158,7 @@ void MainWindow::openFile()
"C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
if (!fileName.isEmpty())
{
- QFile file(fileName);
- if (!file.open(QFile::ReadOnly | QFile::Text))
- {
- QMessageBox::warning(this, "Error", "Cannot open file: " + file.errorString());
- return;
- }
-
- QTextStream in(&file);
- if (editor)
- {
- editor->setPlainText(in.readAll());
- }
- else
- {
- QMessageBox::critical(this, "Error", "Editor is not initialized.");
- }
- file.close();
-
- currentFileName = fileName;
-
- setWindowTitle("CodeAstra ~ " + QFileInfo(fileName).fileName());
+ loadFileInEditor(fileName);
}
}
@@ -202,6 +182,11 @@ void MainWindow::saveFile()
{
out << editor->toPlainText();
}
+ else
+ {
+ QMessageBox::critical(this, "Error", "Editor is not initialized.");
+ return;
+ }
file.close();
statusBar()->showMessage("File saved successfully.", 2000);
@@ -229,7 +214,15 @@ void MainWindow::loadFileInEditor(const QString &filePath)
}
QTextStream in(&file);
- editor->setPlainText(in.readAll());
+ if (editor)
+ {
+ editor->setPlainText(in.readAll());
+ }
+ else
+ {
+ QMessageBox::critical(this, "Error", "Editor is not initialized.");
+ return;
+ }
file.close();
currentFileName = filePath;
From 53aafe5b64a042ece41077a70388b10021ffebaa Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:22:21 -0700
Subject: [PATCH 024/160] [Refactor] Organize syntax highlighting rules into
separate initialization functions for better readability and maintainability
---
src/Syntax.cpp | 132 +++++++++++++++++++++++++++++++++----------------
1 file changed, 89 insertions(+), 43 deletions(-)
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index 553c927..3b35f4a 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -1,49 +1,95 @@
#include "Syntax.h"
+#include
+#include
-Syntax::Syntax(QTextDocument *parent) : QSyntaxHighlighter(parent)
+Syntax::Syntax(QTextDocument *parent)
+ : QSyntaxHighlighter(parent)
{
- keywordFormat.setForeground(Qt::blue);
- keywordFormat.setFontWeight(QFont::Bold);
- QStringList keywordPatterns;
- keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b"
- << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b"
- << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b"
- << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b"
- << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b"
- << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b"
- << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b"
- << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b"
- << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b"
- << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bforeach\\b";
- foreach (const QString &pattern, keywordPatterns)
- {
- addPattern(pattern, keywordFormat);
- }
+ initKeywordRules();
+ initFunctionRules();
+ initParenthesisRules();
+ initCharRules();
- // Single line comment format expression
- singleLineCommentFormat.setForeground(Qt::darkGray);
- addPattern("//[^\n]*", singleLineCommentFormat);
+ // Keep these two calls are at the end
+ // to correctly apply the rules for strings and comments
+ initCommentRules();
+ initQuotationRules();
+}
+
+void Syntax::initKeywordRules()
+{
+ // Keyword format
+ keywordFormat.setForeground(Qt::blue);
+ keywordFormat.setFontWeight(QFont::Bold);
+
+ QStringList keywordPatterns = {
+ "\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
+ "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b",
+ "\\bfriend\\b", "\\binline\\b", "\\bint\\b",
+ "\\blong\\b", "\\bnamespace\\b", "\\boperator\\b",
+ "\\bprivate\\b", "\\bprotected\\b", "\\bpublic\\b",
+ "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
+ "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
+ "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
+ "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b",
+ "\\bvoid\\b", "\\bvolatile\\b", "\\bforeach\\b"};
+
+ for (const QString &pattern : keywordPatterns)
+ {
+ addPattern(pattern, keywordFormat);
+ }
- // Double quotation mark for string
- quotationMark.setForeground(Qt::darkGreen);
- addPattern("\".*\"", quotationMark);
+ iterationFormat.setForeground(Qt::darkMagenta);
+ iterationFormat.setFontWeight(QFont::Bold);
+ QStringList iterationPatterns = {
+ "\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
+ for (const QString &pattern : iterationPatterns)
+ {
+ addPattern(pattern, iterationFormat);
+ }
+}
- // Function format expression
- functionFormat.setFontItalic(true);
- functionFormat.setForeground(Qt::darkYellow);
- addPattern("\\b[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", functionFormat);
+void Syntax::initCommentRules()
+{
+ // Single line comment format expression
+ singleLineCommentFormat.setForeground(Qt::darkGray);
+ addPattern("//[^\n]*", singleLineCommentFormat);
- // Color pattern for parenthesis
- QColor parenthesisColor("#6495ED");
- parenthesisFormat.setForeground(parenthesisColor);
- addPattern("[()]", parenthesisFormat);
+ // TO-DO: Add multi-line comment support
+}
- // Regex for single character format 'a', '\n', etc
- charFormat.setForeground(Qt::darkCyan);
- addPattern("'(\\\\.|[^'])'", charFormat);
+void Syntax::initQuotationRules()
+{
+ // Double quotation mark for string
+ quotationMark.setForeground(Qt::darkGreen);
+ addPattern("\"(\\\\.|[^\"\\\\])*\"", quotationMark);
+
+ // TO-DO: Add single quotation mark for character
+}
+
+void Syntax::initFunctionRules()
+{
+ // Function format expression
+ functionFormat.setFontItalic(true);
+ functionFormat.setForeground(Qt::darkYellow);
+ addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", functionFormat);
+}
+
+void Syntax::initParenthesisRules()
+{
+ // Color pattern for parenthesis
+ QColor parenthesisColor("#6495ED");
+ parenthesisFormat.setForeground(parenthesisColor);
+ addPattern("[()]", parenthesisFormat);
+}
+
+// Regex for single character format 'a', '\n', etc.
+void Syntax::initCharRules()
+{
+ charFormat.setForeground(Qt::darkCyan);
+ addPattern("'(\\\\.|[^'])'", charFormat);
}
-// Add syntax highlighting patterns
void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
{
SyntaxRule rule;
@@ -54,13 +100,13 @@ void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
void Syntax::highlightBlock(const QString &text)
{
- foreach (const SyntaxRule &rule, syntaxRules)
- {
- QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
- while (matchIterator.hasNext())
+ for (const SyntaxRule &rule : syntaxRules)
{
- QRegularExpressionMatch match = matchIterator.next();
- setFormat(match.capturedStart(), match.capturedLength(), rule.format);
+ QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
+ while (matchIterator.hasNext())
+ {
+ QRegularExpressionMatch match = matchIterator.next();
+ setFormat(match.capturedStart(), match.capturedLength(), rule.format);
+ }
}
- }
}
From ed48a0c7ee721a592265f5557ebe8ff442f5dd2d Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:22:38 -0700
Subject: [PATCH 025/160] [Refactor] Replace raw pointers with smart pointers
for improved memory management in Tree class
---
src/Tree.cpp | 112 +++++++++++++++++++++++++++++++--------------------
1 file changed, 69 insertions(+), 43 deletions(-)
diff --git a/src/Tree.cpp b/src/Tree.cpp
index 01adf03..acaabde 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -4,76 +4,102 @@
#include
#include
+#include
#include
#include
Tree::Tree(QSplitter *splitter, MainWindow *mainWindow)
: QObject(splitter),
- model(new QFileSystemModel()),
- tree(new QTreeView(splitter)),
- mainWindow(mainWindow)
+ m_iconProvider(std::make_unique()),
+ m_model(std::make_unique()),
+ m_tree(std::make_unique(splitter)),
+ m_mainWindow(mainWindow)
{
- setupModel();
- setupTree();
+ setupModel();
+ setupTree();
- connect(tree, &QTreeView::doubleClicked, this, &Tree::openFile);
+ connect(m_tree.get(), &QTreeView::doubleClicked, this, &Tree::openFile);
}
Tree::~Tree() {}
void Tree::setupModel()
{
- model->setRootPath(getDirectoryPath());
- model->setIconProvider(new QFileIconProvider);
- model->setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
+ m_model->setRootPath(getDirectoryPath());
+ m_model->setIconProvider(m_iconProvider.get());
+ m_model->setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
}
void Tree::setupTree()
{
- tree->setModel(model);
- tree->setRootIndex(model->index(model->rootPath()));
- tree->setRootIsDecorated(true);
- tree->setAnimated(true);
- tree->setIndentation(20);
- tree->setSortingEnabled(false);
- tree->sortByColumn(1, Qt::AscendingOrder);
- tree->setHeaderHidden(true);
-
- for (int i = 1; i <= model->columnCount(); ++i)
- {
- tree->setColumnHidden(i, true);
- }
-
- tree->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(tree, &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);
+ m_tree->setModel(m_model.get());
+ m_tree->setRootIndex(m_model->index(m_model->rootPath()));
+ m_tree->setRootIsDecorated(true);
+ m_tree->setAnimated(true);
+ m_tree->setIndentation(20);
+ m_tree->setSortingEnabled(false);
+ m_tree->sortByColumn(1, Qt::AscendingOrder);
+ m_tree->setHeaderHidden(true);
+
+ for (int i = 1; i <= m_model->columnCount(); ++i)
+ {
+ m_tree->setColumnHidden(i, true);
+ }
+
+ m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_tree.get(), &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);
}
-QString Tree::getDirectoryPath()
+QString Tree::getDirectoryPath() const
{
- return QFileDialog::getExistingDirectory(
- nullptr, QObject::tr("Open Directory"), QDir::homePath(),
- QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ return QFileDialog::getExistingDirectory(
+ nullptr, QObject::tr("Open Directory"), QDir::homePath(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
}
void Tree::openFile(const QModelIndex &index)
{
- QString filePath = model->filePath(index);
- QFileInfo fileInfo(filePath);
-
- // Ensure it's a file, not a folder before loading
- if (fileInfo.isFile())
- {
- mainWindow->loadFileInEditor(filePath);
- }
+ QString filePath = m_model->filePath(index);
+ QFileInfo fileInfo(filePath);
+
+ // Ensure it's a file, not a folder before loading
+ if (!fileInfo.exists() || !fileInfo.isFile())
+ {
+ qWarning() << "Selected index is not a valid file:" << filePath;
+ return;
+ }
+
+ m_mainWindow->loadFileInEditor(filePath);
}
+// Context menu for file operations
+// such as creating new files, folders, renaming, and deleting
+// This function is called when the user right-clicks on the tree view
void Tree::showContextMenu(const QPoint &pos)
{
- // TO_DO: Implement delete a file
- // TO_DO: Implement rename a file
- // TO_DO: Implement create a new file
- // TO_DO: Implement create a new folder
+ QMenu contextMenu;
+
+ QAction *newFileAction = contextMenu.addAction("New File");
+ QAction *newFolderAction = contextMenu.addAction("New Folder");
+ QAction *renameAction = contextMenu.addAction("Rename");
+ QAction *deleteAction = contextMenu.addAction("Delete");
+
+ QAction *selectedAction = contextMenu.exec(m_tree->viewport()->mapToGlobal(pos));
- // use pos param for testing purpose for now
- tree->indexAt(pos);
+ if (selectedAction == newFileAction)
+ {
+ // TO-DO: implement file creation
+ }
+ else if (selectedAction == newFolderAction)
+ {
+ // TO-DO: implement folder creation
+ }
+ else if (selectedAction == renameAction)
+ {
+ // TO-DO: implement rename file/folder
+ }
+ else if (selectedAction == deleteAction)
+ {
+ // TO-DO: implement file deletion
+ }
}
From a6657d0295cc656d4b4c95dfb5ea2eecfcd14e57 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 19:40:13 -0700
Subject: [PATCH 026/160] [Refactor] Consistently prefix member variables with
'm_' in CodeEditor, LineNumberArea, MainWindow, and Syntax classes for
improved readability
---
include/CodeEditor.h | 2 +-
include/LineNumberArea.h | 8 +++----
include/MainWindow.h | 8 +++----
include/Syntax.h | 22 +++++++++---------
src/CodeEditor.cpp | 14 ++++++------
src/MainWindow.cpp | 32 +++++++++++++-------------
src/Syntax.cpp | 49 ++++++++++++++++++++--------------------
7 files changed, 67 insertions(+), 68 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index 4054768..b3d1ed5 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -29,5 +29,5 @@ private slots:
void updateLineNumberArea(const QRect &rect, int dy);
private:
- QWidget *lineNumberArea;
+ QWidget *m_lineNumberArea;
};
\ No newline at end of file
diff --git a/include/LineNumberArea.h b/include/LineNumberArea.h
index dd5980c..64f923d 100644
--- a/include/LineNumberArea.h
+++ b/include/LineNumberArea.h
@@ -9,19 +9,19 @@
class LineNumberArea : public QWidget
{
public:
- LineNumberArea(CodeEditor *editor) : QWidget(editor), m_codeEditor(editor) {}
+ LineNumberArea(CodeEditor *editor) : QWidget(editor), codeEditor(editor) {}
QSize sizeHint() const override
{
- return QSize(m_codeEditor->lineNumberAreaWidth(), 0);
+ return QSize(codeEditor->lineNumberAreaWidth(), 0);
}
protected:
void paintEvent(QPaintEvent *event) override
{
- m_codeEditor->lineNumberAreaPaintEvent(event);
+ codeEditor->lineNumberAreaPaintEvent(event);
}
private:
- CodeEditor *m_codeEditor;
+ CodeEditor *codeEditor;
};
\ No newline at end of file
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 402bc18..9487c91 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -39,8 +39,8 @@ private slots:
QAction *createAction(const QIcon &icon, const QString &text,
const QKeySequence &shortcut, const QString &statusTip,
void (MainWindow::*slot)());
- std::unique_ptr editor;
- QString currentFileName;
- std::unique_ptr syntax;
- std::unique_ptr tree;
+ std::unique_ptr m_editor;
+ std::unique_ptr m_syntax;
+ std::unique_ptr m_tree;
+ QString m_currentFileName;
};
\ No newline at end of file
diff --git a/include/Syntax.h b/include/Syntax.h
index 9adfed0..35f0ea0 100644
--- a/include/Syntax.h
+++ b/include/Syntax.h
@@ -18,18 +18,18 @@ class Syntax : public QSyntaxHighlighter
private:
struct SyntaxRule
{
- QRegularExpression pattern;
- QTextCharFormat format;
+ QRegularExpression m_pattern;
+ QTextCharFormat m_format;
};
- QVector syntaxRules;
-
- QTextCharFormat keywordFormat;
- QTextCharFormat singleLineCommentFormat;
- QTextCharFormat quotationMark;
- QTextCharFormat functionFormat;
- QTextCharFormat parenthesisFormat;
- QTextCharFormat charFormat;
- QTextCharFormat iterationFormat;
+ QVector m_syntaxRules;
+
+ QTextCharFormat m_keywordFormat;
+ QTextCharFormat m_singleLineCommentFormat;
+ QTextCharFormat m_quotationMark;
+ QTextCharFormat m_functionFormat;
+ QTextCharFormat m_parenthesisFormat;
+ QTextCharFormat m_charFormat;
+ QTextCharFormat m_iterationFormat;
void addPattern(const QString &pattern, const QTextCharFormat &format);
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 3ccb5be..47c88ab 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -7,7 +7,7 @@
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent),
- lineNumberArea(new LineNumberArea(this))
+ m_lineNumberArea(new LineNumberArea(this))
{
connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
@@ -82,11 +82,11 @@ void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
if (dy)
{
- lineNumberArea->scroll(0, dy);
+ m_lineNumberArea->scroll(0, dy);
}
else
{
- lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
+ m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
}
if (rect.contains(viewport()->rect()))
@@ -100,7 +100,7 @@ void CodeEditor::resizeEvent(QResizeEvent *e)
QPlainTextEdit::resizeEvent(e);
QRect cr = contentsRect();
- lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
+ m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}
void CodeEditor::highlightCurrentLine()
@@ -128,13 +128,13 @@ void CodeEditor::highlightCurrentLine()
void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
- QPainter painter(lineNumberArea);
+ QPainter painter(m_lineNumberArea);
// Match the background color of the editor
painter.fillRect(event->rect(), palette().color(QPalette::Base));
// Draw a separating line between the number area and the text editor
- int separatorX = lineNumberArea->width() - 4;
+ int separatorX = m_lineNumberArea->width() - 4;
painter.drawLine(separatorX, event->rect().top(), separatorX, event->rect().bottom());
QTextBlock block = firstVisibleBlock();
@@ -152,7 +152,7 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
QString number = QString::number(blockNumber + 1);
painter.setPen(Qt::darkGray);
- painter.drawText(0, top + padding, lineNumberArea->width(), lineHeight,
+ painter.drawText(0, top + padding, m_lineNumberArea->width(), lineHeight,
Qt::AlignCenter, number);
}
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index c0b5b94..5f29718 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -15,17 +15,17 @@
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
- editor(std::make_unique(this)),
- syntax(std::make_unique(editor->document())),
- tree(nullptr)
+ m_editor(std::make_unique(this)),
+ m_syntax(std::make_unique(m_editor->document())),
+ m_tree(nullptr)
{
setWindowTitle("CodeAstra ~ Code Editor");
// Set tab width to 4 spaces
- QFontMetrics metrics(editor->font());
+ QFontMetrics metrics(m_editor->font());
int spaceWidth = metrics.horizontalAdvance(" ");
- editor->setTabStopDistance(spaceWidth * 4);
- editor->setLineWrapMode(QPlainTextEdit::NoWrap);
+ m_editor->setTabStopDistance(spaceWidth * 4);
+ m_editor->setLineWrapMode(QPlainTextEdit::NoWrap);
initTree();
createMenuBar();
@@ -39,9 +39,9 @@ void MainWindow::initTree()
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(splitter);
- tree = std::make_unique(splitter, this);
+ m_tree = std::make_unique(splitter, this);
- splitter->addWidget(editor.get());
+ splitter->addWidget(m_editor.get());
splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
splitter->setHandleWidth(5);
splitter->setSizes(QList() << 150 << 800);
@@ -164,13 +164,13 @@ void MainWindow::openFile()
void MainWindow::saveFile()
{
- if (currentFileName.isEmpty())
+ if (m_currentFileName.isEmpty())
{
saveFileAs();
return;
}
- QFile file(currentFileName);
+ QFile file(m_currentFileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, "Error", "Cannot save file: " + file.errorString());
@@ -178,9 +178,9 @@ void MainWindow::saveFile()
}
QTextStream out(&file);
- if (editor)
+ if (m_editor)
{
- out << editor->toPlainText();
+ out << m_editor->toPlainText();
}
else
{
@@ -199,7 +199,7 @@ void MainWindow::saveFileAs()
if (!fileName.isEmpty())
{
- currentFileName = fileName;
+ m_currentFileName = fileName;
saveFile();
}
}
@@ -214,9 +214,9 @@ void MainWindow::loadFileInEditor(const QString &filePath)
}
QTextStream in(&file);
- if (editor)
+ if (m_editor)
{
- editor->setPlainText(in.readAll());
+ m_editor->setPlainText(in.readAll());
}
else
{
@@ -225,6 +225,6 @@ void MainWindow::loadFileInEditor(const QString &filePath)
}
file.close();
- currentFileName = filePath;
+ m_currentFileName = filePath;
setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
}
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index 3b35f4a..9f841c2 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -19,8 +19,8 @@ Syntax::Syntax(QTextDocument *parent)
void Syntax::initKeywordRules()
{
// Keyword format
- keywordFormat.setForeground(Qt::blue);
- keywordFormat.setFontWeight(QFont::Bold);
+ m_keywordFormat.setForeground(Qt::blue);
+ m_keywordFormat.setFontWeight(QFont::Bold);
QStringList keywordPatterns = {
"\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
@@ -36,24 +36,23 @@ void Syntax::initKeywordRules()
for (const QString &pattern : keywordPatterns)
{
- addPattern(pattern, keywordFormat);
+ addPattern(pattern, m_keywordFormat);
}
- iterationFormat.setForeground(Qt::darkMagenta);
- iterationFormat.setFontWeight(QFont::Bold);
- QStringList iterationPatterns = {
- "\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
+ m_iterationFormat.setForeground(Qt::darkMagenta);
+ m_iterationFormat.setFontWeight(QFont::Bold);
+ QStringList iterationPatterns = {"\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
for (const QString &pattern : iterationPatterns)
{
- addPattern(pattern, iterationFormat);
+ addPattern(pattern, m_iterationFormat);
}
}
void Syntax::initCommentRules()
{
// Single line comment format expression
- singleLineCommentFormat.setForeground(Qt::darkGray);
- addPattern("//[^\n]*", singleLineCommentFormat);
+ m_singleLineCommentFormat.setForeground(Qt::darkGray);
+ addPattern("//[^\n]*", m_singleLineCommentFormat);
// TO-DO: Add multi-line comment support
}
@@ -61,8 +60,8 @@ void Syntax::initCommentRules()
void Syntax::initQuotationRules()
{
// Double quotation mark for string
- quotationMark.setForeground(Qt::darkGreen);
- addPattern("\"(\\\\.|[^\"\\\\])*\"", quotationMark);
+ m_quotationMark.setForeground(Qt::darkGreen);
+ addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
// TO-DO: Add single quotation mark for character
}
@@ -70,43 +69,43 @@ void Syntax::initQuotationRules()
void Syntax::initFunctionRules()
{
// Function format expression
- functionFormat.setFontItalic(true);
- functionFormat.setForeground(Qt::darkYellow);
- addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", functionFormat);
+ m_functionFormat.setFontItalic(true);
+ m_functionFormat.setForeground(Qt::darkYellow);
+ addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", m_functionFormat);
}
void Syntax::initParenthesisRules()
{
// Color pattern for parenthesis
QColor parenthesisColor("#6495ED");
- parenthesisFormat.setForeground(parenthesisColor);
- addPattern("[()]", parenthesisFormat);
+ m_parenthesisFormat.setForeground(parenthesisColor);
+ addPattern("[()]", m_parenthesisFormat);
}
// Regex for single character format 'a', '\n', etc.
void Syntax::initCharRules()
{
- charFormat.setForeground(Qt::darkCyan);
- addPattern("'(\\\\.|[^'])'", charFormat);
+ m_charFormat.setForeground(Qt::darkCyan);
+ addPattern("'(\\\\.|[^'])'", m_charFormat);
}
void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
{
SyntaxRule rule;
- rule.pattern = QRegularExpression(pattern);
- rule.format = format;
- syntaxRules.append(rule);
+ rule.m_pattern = QRegularExpression(pattern);
+ rule.m_format = format;
+ m_syntaxRules.append(rule);
}
void Syntax::highlightBlock(const QString &text)
{
- for (const SyntaxRule &rule : syntaxRules)
+ for (const SyntaxRule &rule : m_syntaxRules)
{
- QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
+ QRegularExpressionMatchIterator matchIterator = rule.m_pattern.globalMatch(text);
while (matchIterator.hasNext())
{
QRegularExpressionMatch match = matchIterator.next();
- setFormat(match.capturedStart(), match.capturedLength(), rule.format);
+ setFormat(match.capturedStart(), match.capturedLength(), rule.m_format);
}
}
}
From a714767c1632335d5d9dba986bea869b52719f10 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 20:13:05 -0700
Subject: [PATCH 027/160] [Refactor] Emit status messages on mode changes in
CodeEditor for improved user feedback
---
include/CodeEditor.h | 3 +++
src/CodeEditor.cpp | 18 ++++++++++++++----
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index b3d1ed5..2ab350e 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -19,6 +19,9 @@ class CodeEditor : public QPlainTextEdit
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
+signals:
+ void statusMessageChanged(const QString &message);
+
protected:
void keyPressEvent(QKeyEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 47c88ab..217e0c4 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -4,6 +4,7 @@
#include
#include
+#include
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent),
@@ -33,6 +34,7 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
{
case Qt::Key_I:
mode = INSERT;
+ emit statusMessageChanged("Insert mode activated");
break;
case Qt::Key_A:
moveCursor(QTextCursor::Left);
@@ -46,14 +48,22 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
case Qt::Key_W:
moveCursor(QTextCursor::Up);
break;
- case Qt::Key_Escape:
- mode = NORMAL;
+ default:
+ emit statusMessageChanged("Insert mode is not active. Press 'i' to enter insert mode.");
break;
}
}
- else
+ else if (mode == INSERT)
{
- QPlainTextEdit::keyPressEvent(event);
+ if (event->key() == Qt::Key_Escape)
+ {
+ mode = NORMAL;
+ emit statusMessageChanged("Normal mode activated. Press 'escape' to return to normal mode.");
+ }
+ else
+ {
+ QPlainTextEdit::keyPressEvent(event);
+ }
}
}
From 1be84619c743202f9cff2176ac122a2d17ad5e14 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 20:13:13 -0700
Subject: [PATCH 028/160] [Refactor] Enhance status message display in
MainWindow with timestamps for better user feedback
---
src/MainWindow.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 5f29718..fa5cf71 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -21,6 +21,12 @@ MainWindow::MainWindow(QWidget *parent)
{
setWindowTitle("CodeAstra ~ Code Editor");
+ connect(m_editor.get(), &CodeEditor::statusMessageChanged, this, [this](const QString &message)
+ {
+ QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss");
+ statusBar()->showMessage("[" + timestamp + "] " + message, 4000);
+ });
+
// Set tab width to 4 spaces
QFontMetrics metrics(m_editor->font());
int spaceWidth = metrics.horizontalAdvance(" ");
From 8fbb4f4f123b318756b9fd4246af6b494168816c Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 20:19:29 -0700
Subject: [PATCH 029/160] [Refactor] Emit status message on file save in
MainWindow for improved user feedback
---
src/MainWindow.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index fa5cf71..4078c85 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -195,7 +195,7 @@ void MainWindow::saveFile()
}
file.close();
- statusBar()->showMessage("File saved successfully.", 2000);
+ emit m_editor->statusMessageChanged("File saved successfully.");
}
void MainWindow::saveFileAs()
From 2533fed09c9140f8277f0dce2e025b09105b5c07 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:43:20 -0700
Subject: [PATCH 030/160] [Refactor] Remove unused file handling methods and
reorganize member variables in MainWindow for improved clarity
---
include/MainWindow.h | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 9487c91..bd786f3 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -11,6 +11,7 @@
class CodeEditor;
class Syntax;
class Tree;
+class FileManager;
class MainWindow : public QMainWindow
{
@@ -19,16 +20,12 @@ class MainWindow : public QMainWindow
public:
explicit MainWindow(QWidget *parent = nullptr);
virtual ~MainWindow();
- void loadFileInEditor(const QString &filePath);
+
// Initialize the file tree view and set it as the central widget
// of the main window, alongside the code editor
void initTree();
private slots:
- void newFile();
- void openFile();
- void saveFile();
- void saveFileAs();
void showAbout();
private:
@@ -38,9 +35,11 @@ private slots:
void createAppActions(QMenu *appMenu);
QAction *createAction(const QIcon &icon, const QString &text,
const QKeySequence &shortcut, const QString &statusTip,
- void (MainWindow::*slot)());
+ const std::function &slot);
+
std::unique_ptr m_editor;
std::unique_ptr m_syntax;
std::unique_ptr m_tree;
- QString m_currentFileName;
+
+ FileManager * m_FileManager;
};
\ No newline at end of file
From 38b19c84720ae68392cb70742589d9abf00b6bd9 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:43:33 -0700
Subject: [PATCH 031/160] [Refactor] Update Tree class constructor to use
FileManager instead of MainWindow for improved modularity
---
include/Tree.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/Tree.h b/include/Tree.h
index 4a54eb9..039d9a1 100644
--- a/include/Tree.h
+++ b/include/Tree.h
@@ -5,17 +5,17 @@
#include
// Forward declarations
-class MainWindow;
class QTreeView;
class QFileSystemModel;
class QFileIconProvider;
+class FileManager;
class Tree : public QObject
{
Q_OBJECT
public:
- explicit Tree(QSplitter *splitter, MainWindow *mainWindow);
+ explicit Tree(QSplitter *splitter, FileManager *FileManager);
~Tree();
private:
@@ -29,5 +29,5 @@ class Tree : public QObject
std::unique_ptr m_model;
std::unique_ptr m_tree;
- MainWindow *m_mainWindow;
+ FileManager * m_FileManager;
};
\ No newline at end of file
From ddc3af4ba757e35b590bf9c2b3715bf8f392ede0 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:43:46 -0700
Subject: [PATCH 032/160] [Refactor] Update Tree class constructor to use
FileManager instead of MainWindow for improved modularity
---
src/Tree.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/Tree.cpp b/src/Tree.cpp
index acaabde..cd02124 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -1,19 +1,20 @@
#include "Tree.h"
-#include "MainWindow.h"
#include "CodeEditor.h"
+#include "FileManager.h"
#include
#include
#include
#include
#include
+#include
-Tree::Tree(QSplitter *splitter, MainWindow *mainWindow)
+Tree::Tree(QSplitter *splitter, FileManager *FileManager)
: QObject(splitter),
m_iconProvider(std::make_unique()),
m_model(std::make_unique()),
m_tree(std::make_unique(splitter)),
- m_mainWindow(mainWindow)
+ m_FileManager(FileManager)
{
setupModel();
setupTree();
@@ -69,7 +70,7 @@ void Tree::openFile(const QModelIndex &index)
return;
}
- m_mainWindow->loadFileInEditor(filePath);
+ m_FileManager->loadFileInEditor(filePath);
}
// Context menu for file operations
From 6b06bae7ba6166e2221cf19f1fdbaf05bf816dc9 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:43:55 -0700
Subject: [PATCH 033/160] [Refactor] Integrate FileManager into MainWindow for
improved file handling and modularity
---
src/MainWindow.cpp | 98 +++++-----------------------------------------
1 file changed, 9 insertions(+), 89 deletions(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 4078c85..0365279 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -2,6 +2,7 @@
#include "Syntax.h"
#include "Tree.h"
#include "CodeEditor.h"
+#include "FileManager.h"
#include
#include
@@ -17,7 +18,8 @@ MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
m_editor(std::make_unique(this)),
m_syntax(std::make_unique(m_editor->document())),
- m_tree(nullptr)
+ m_tree(nullptr),
+ m_FileManager(new FileManager(m_editor.get(), this))
{
setWindowTitle("CodeAstra ~ Code Editor");
@@ -45,7 +47,7 @@ void MainWindow::initTree()
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(splitter);
- m_tree = std::make_unique(splitter, this);
+ m_tree = std::make_unique(splitter, m_FileManager);
splitter->addWidget(m_editor.get());
splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -74,11 +76,11 @@ void MainWindow::createMenuBar()
void MainWindow::createFileActions(QMenu *fileMenu)
{
- fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), &MainWindow::newFile));
- fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), &MainWindow::openFile));
+ fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), [this]() { m_FileManager->newFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), [this]() { m_FileManager->openFile(); }));
fileMenu->addSeparator();
- fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), &MainWindow::saveFile));
- fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), &MainWindow::saveFileAs));
+ fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), [this]() { m_FileManager->saveFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), [this]() { m_FileManager->saveFileAs(); }));
}
void MainWindow::createHelpActions(QMenu *helpMenu)
@@ -97,7 +99,7 @@ void MainWindow::createAppActions(QMenu *appMenu)
appMenu->addAction(aboutAction);
}
-QAction *MainWindow::createAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QString &statusTip, void (MainWindow::*slot)())
+QAction *MainWindow::createAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QString &statusTip, const std::function &slot)
{
QAction *action = new QAction(icon, text, this);
@@ -108,11 +110,6 @@ QAction *MainWindow::createAction(const QIcon &icon, const QString &text, const
return action;
}
-void MainWindow::newFile()
-{
- // TO-DO: Implement new file function
-}
-
void MainWindow::showAbout()
{
// Extract the C++ version from the __cplusplus macro
@@ -157,80 +154,3 @@ void MainWindow::showAbout()
QMessageBox::about(this, tr("About"), aboutText);
}
-
-void MainWindow::openFile()
-{
- QString fileName = QFileDialog::getOpenFileName(this, "Open File", QString(),
- "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
- if (!fileName.isEmpty())
- {
- loadFileInEditor(fileName);
- }
-}
-
-void MainWindow::saveFile()
-{
- if (m_currentFileName.isEmpty())
- {
- saveFileAs();
- return;
- }
-
- QFile file(m_currentFileName);
- if (!file.open(QFile::WriteOnly | QFile::Text))
- {
- QMessageBox::warning(this, "Error", "Cannot save file: " + file.errorString());
- return;
- }
-
- QTextStream out(&file);
- if (m_editor)
- {
- out << m_editor->toPlainText();
- }
- else
- {
- QMessageBox::critical(this, "Error", "Editor is not initialized.");
- return;
- }
- file.close();
-
- emit m_editor->statusMessageChanged("File saved successfully.");
-}
-
-void MainWindow::saveFileAs()
-{
- QString fileName = QFileDialog::getSaveFileName(this, "Save File As", QString(),
- "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
-
- if (!fileName.isEmpty())
- {
- m_currentFileName = fileName;
- saveFile();
- }
-}
-
-void MainWindow::loadFileInEditor(const QString &filePath)
-{
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
- {
- QMessageBox::warning(this, "Error", "Cannot open file: " + file.errorString());
- return;
- }
-
- QTextStream in(&file);
- if (m_editor)
- {
- m_editor->setPlainText(in.readAll());
- }
- else
- {
- QMessageBox::critical(this, "Error", "Editor is not initialized.");
- return;
- }
- file.close();
-
- m_currentFileName = filePath;
- setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
-}
From 1497e7fa316ce2665dba80a0722ed543d3880da8 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:44:19 -0700
Subject: [PATCH 034/160] [Feature] Implement FileManager class for handling
file operations including new, save, and open functionalities
---
include/FileManager.h | 31 ++++++++++++
src/FileManager.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
create mode 100644 include/FileManager.h
create mode 100644 src/FileManager.cpp
diff --git a/include/FileManager.h b/include/FileManager.h
new file mode 100644
index 0000000..e311f33
--- /dev/null
+++ b/include/FileManager.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+
+class CodeEditor;
+class MainWindow;
+
+/**
+ * @class FileManager
+ * @brief Manages file operations such as creating, saving, and opening files.
+ */
+class FileManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ FileManager(CodeEditor *editor, MainWindow *mainWindow);
+ ~FileManager();
+
+public slots:
+ void newFile();
+ void saveFile();
+ void saveFileAs();
+ void openFile();
+ void loadFileInEditor(const QString &filePath);
+
+private:
+ std::unique_ptr m_editor;
+ QString m_currentFileName;
+ MainWindow *m_mainWindow;
+};
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
new file mode 100644
index 0000000..858ca2a
--- /dev/null
+++ b/src/FileManager.cpp
@@ -0,0 +1,109 @@
+#include "FileManager.h"
+
+#include
+#include
+#include
+#include
+#include "CodeEditor.h"
+#include "MainWindow.h"
+
+FileManager::FileManager(CodeEditor *editor, MainWindow *mainWindow)
+ : m_editor(editor),
+ m_currentFileName(""),
+ m_mainWindow(mainWindow)
+{
+ if (!m_editor)
+ {
+ qWarning() << "Editor is NOT initialized in FileManager!";
+ }
+ else
+ {
+ qDebug() << "Editor is properly initialized in FileManager.";
+ }
+}
+
+FileManager::~FileManager() {}
+
+void FileManager::newFile()
+{
+ // Logic to create a new file
+}
+
+void FileManager::saveFile()
+{
+ qDebug() << "Saving file:" << m_currentFileName;
+ if (m_currentFileName.isEmpty())
+ {
+ saveFileAs();
+ return;
+ }
+
+ QFile file(m_currentFileName);
+ if (!file.open(QFile::WriteOnly | QFile::Text))
+ {
+ QMessageBox::warning(nullptr, "Error", "Cannot save file: " + file.errorString());
+ return;
+ }
+
+ QTextStream out(&file);
+ if (m_editor)
+ {
+ out << m_editor->toPlainText();
+ }
+ else
+ {
+ QMessageBox::critical(nullptr, "Error", "Editor is not initialized.");
+ return;
+ }
+ file.close();
+
+ emit m_editor->statusMessageChanged("File saved successfully.");
+}
+
+void FileManager::saveFileAs()
+{
+ QString fileName = QFileDialog::getSaveFileName(nullptr, "Save File As", QString(),
+ "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
+
+ if (!fileName.isEmpty())
+ {
+ m_currentFileName = fileName;
+ saveFile();
+ }
+}
+
+void FileManager::openFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(nullptr, "Open File", QString(),
+ "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
+ if (!fileName.isEmpty())
+ {
+ loadFileInEditor(fileName);
+ }
+}
+
+void FileManager::loadFileInEditor(const QString &filePath)
+{
+ qDebug() << "Loading file:" << filePath;
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ QMessageBox::warning(nullptr, "Error", "Cannot open file: " + file.errorString());
+ return;
+ }
+
+ QTextStream in(&file);
+ if (m_editor)
+ {
+ m_editor->setPlainText(in.readAll());
+ }
+ else
+ {
+ QMessageBox::critical(nullptr, "Error", "Editor is not initialized.");
+ return;
+ }
+ file.close();
+
+ m_currentFileName = filePath;
+ m_mainWindow->setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
+}
\ No newline at end of file
From 2c18d5a93c9eb6d3624d8f48c44ee0d4aad75c72 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 22:44:26 -0700
Subject: [PATCH 035/160] [Refactor] Add FileManager source and header files to
CMakeLists for proper inclusion
---
CMakeLists.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75eb2f2..b1599e1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,11 +56,13 @@ add_executable(${TARGET_NAME}
src/CodeEditor.cpp
src/Syntax.cpp
src/Tree.cpp
+ src/FileManager.cpp
include/MainWindow.h
include/CodeEditor.h
include/Syntax.h
include/Tree.h
include/LineNumberArea.h
+ include/FileManager.h
)
qt_add_resources(APP_RESOURCES resources.qrc)
From d4fbf88412f51bb7e98e0b481939a66feb2f535d Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 23:14:12 -0700
Subject: [PATCH 036/160] [Fix] Fix merge conflict
---
include/CodeEditor.h | 3 ---
src/CodeEditor.cpp | 1 +
src/MainWindow.cpp | 8 ++++----
3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index 8106ba9..740f180 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -24,9 +24,6 @@ class CodeEditor : public QPlainTextEdit
signals:
void statusMessageChanged(const QString &message);
-signals:
- void statusMessageChanged(const QString &message);
-
protected:
void keyPressEvent(QKeyEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index a6d70f9..9070140 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent),
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 6e92fac..6d0e950 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -170,13 +170,13 @@ void MainWindow::openFile()
void MainWindow::saveFile()
{
- if (editor->getCurrentFileName().isEmpty())
+ if (m_editor->getCurrentFileName().isEmpty())
{
saveFileAs();
return;
}
- QFile file(editor->getCurrentFileName());
+ QFile file(m_editor->getCurrentFileName());
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, "Error", "Cannot save file: " + file.errorString());
@@ -205,7 +205,7 @@ void MainWindow::saveFileAs()
if (!fileName.isEmpty())
{
- editor->setCurrentFileName(fileName);
+ m_editor->setCurrentFileName(fileName);
saveFile();
}
}
@@ -231,6 +231,6 @@ void MainWindow::loadFileInEditor(const QString &filePath)
}
file.close();
- editor->setCurrentFileName(filePath);
+ m_editor->setCurrentFileName(filePath);
setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
}
From c84a1aafcfe98cfaff958def1b8b7872b8d807cd Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 23:17:32 -0700
Subject: [PATCH 037/160] [Refactor] Correct variable name for current file in
CodeEditor class
---
include/CodeEditor.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index 740f180..a0e04f2 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -18,8 +18,8 @@ class CodeEditor : public QPlainTextEdit
Mode mode = NORMAL;
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
- QString getCurrentFileName() const { return currentFileName; }
- void setCurrentFileName(const QString &fileName) { currentFileName = fileName; }
+ QString getCurrentFileName() const { return m_currentFileName; }
+ void setCurrentFileName(const QString &fileName) { m_currentFileName = fileName; }
signals:
void statusMessageChanged(const QString &message);
@@ -35,10 +35,11 @@ private slots:
private:
QWidget *m_lineNumberArea;
- QString currentFileName;
+ QString m_currentFileName;
+
QString getFileExtension();
void addLanguageSymbol(QTextCursor &cursor, const QString &commentSymbol);
void commentSelection(QTextCursor &cursor, const QString &commentSymbol);
void commentLine(QTextCursor &cursor, const QString &commentSymbol);
- void addComment();
+ void addComment();
};
\ No newline at end of file
From 35016a46cda2b97b3efe45dc02ec87f437d0269e Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 20 Mar 2025 23:26:14 -0700
Subject: [PATCH 038/160] [Add] Emit status message on file load in MainWindow
for improved user feedback
---
src/MainWindow.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 6d0e950..366b94d 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -233,4 +233,5 @@ void MainWindow::loadFileInEditor(const QString &filePath)
m_editor->setCurrentFileName(filePath);
setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
+ emit m_editor->statusMessageChanged("File loaded successfully: " + QFileInfo(filePath).fileName());
}
From 1c4683da8eab162d64619283d2011ea165f26923 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 19:43:52 -0700
Subject: [PATCH 039/160] [CI] Inital CI implementation
Implement first version of GitHub Action CI for cross-platform testing
---
.github/workflows/cpp.yml | 72 +++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
create mode 100644 .github/workflows/cpp.yml
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
new file mode 100644
index 0000000..2356b05
--- /dev/null
+++ b/.github/workflows/cpp.yml
@@ -0,0 +1,72 @@
+name: C++ CI
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ # Install C++ Compiler & Build Tools
+ - name: Set up C++ environment (Ubuntu)
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y g++ make cmake
+ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100
+ g++ --version
+ cmake --version
+ make --version
+
+ - name: Set up C++ environment (macOS)
+ if: matrix.os == 'macos-latest'
+ run: |
+ brew install gcc make cmake
+ echo 'export PATH="/usr/local/opt/gcc/bin:$PATH"' >> ~/.bash_profile
+ source ~/.bash_profile
+ g++ --version
+ cmake --version
+ make --version
+
+ - name: Set up C++ environment (Windows)
+ if: matrix.os == 'windows-latest'
+ run: |
+ choco install mingw --version=8.1.0-1
+ choco install make cmake
+ echo C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ echo C:\ProgramData\chocolatey\lib\cmake\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ g++ --version
+ cmake --version
+ make --version
+
+ # Install Qt6
+ - name: Install Qt6 (Ubuntu)
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get install -y qt6-base-dev
+
+ - name: Install Qt6 (macOS)
+ if: matrix.os == 'macos-latest'
+ run: |
+ brew install qt6
+ echo 'export PATH="/opt/homebrew/opt/qt6/bin:$PATH"' >> ~/.bash_profile
+ source ~/.bash_profile
+
+ - name: Install Qt6 (Windows)
+ if: matrix.os == 'windows-latest'
+ run: |
+ choco install qt6 --version=6.2.4
+ echo C:\Qt\6.2.4\msvc2019_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+
+ # Build the Project
+ - name: Build project
+ run: make
From 20cdcdedc1817f6579db673e34b5b98803165d8e Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 19:50:05 -0700
Subject: [PATCH 040/160] [CI] Fix bug on Ubuntu
---
.github/workflows/cpp.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index 2356b05..de91346 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -22,7 +22,6 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y g++ make cmake
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100
g++ --version
cmake --version
make --version
@@ -30,7 +29,7 @@ jobs:
- name: Set up C++ environment (macOS)
if: matrix.os == 'macos-latest'
run: |
- brew install gcc make cmake
+ brew install make cmake
echo 'export PATH="/usr/local/opt/gcc/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
g++ --version
From 64ce837162af1d219b9a70c4ea14a7b9766202fa Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 19:53:01 -0700
Subject: [PATCH 041/160] [CI] Bug Fix second attempt
---
.github/workflows/cpp.yml | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index de91346..fc1e907 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -52,6 +52,8 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install -y qt6-base-dev
+ echo 'export PATH="/usr/lib/qt6/bin:$PATH"' >> ~/.bashrc
+ source ~/.bashrc
- name: Install Qt6 (macOS)
if: matrix.os == 'macos-latest'
@@ -59,13 +61,16 @@ jobs:
brew install qt6
echo 'export PATH="/opt/homebrew/opt/qt6/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
+ qmake --version
- name: Install Qt6 (Windows)
if: matrix.os == 'windows-latest'
run: |
- choco install qt6 --version=6.2.4
- echo C:\Qt\6.2.4\msvc2019_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ Invoke-WebRequest -Uri "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" -OutFile "qt-installer.exe"
+ Start-Process -FilePath ".\qt-installer.exe" -ArgumentList "--silent", "--platform minimal", "--accept-licenses", "--default-answer" -NoNewWindow -Wait
+ echo C:\Qt\6.6.0\msvc2019_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ qmake --version
# Build the Project
- name: Build project
- run: make
+ run: make build
From 9650369be5b7e8c8c3c8516920b32dce1da4f370 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 19:59:01 -0700
Subject: [PATCH 042/160] [CI] Added installation and try fix window error
---
.github/workflows/cpp.yml | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index fc1e907..68d16b8 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -66,11 +66,15 @@ jobs:
- name: Install Qt6 (Windows)
if: matrix.os == 'windows-latest'
run: |
- Invoke-WebRequest -Uri "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" -OutFile "qt-installer.exe"
- Start-Process -FilePath ".\qt-installer.exe" -ArgumentList "--silent", "--platform minimal", "--accept-licenses", "--default-answer" -NoNewWindow -Wait
- echo C:\Qt\6.6.0\msvc2019_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ python -m pip install aqtinstall
+ python -m aqt install-qt windows desktop 6.6.0 win64_mingw --outputdir C:\Qt
+ echo C:\Qt\6.6.0\mingw_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
qmake --version
# Build the Project
- name: Build project
run: make build
+
+ # Install the Project with desktop shortcut
+ - name: Install project
+ run: echo "y" | make install
From 38c9317adcd0b6ad1f4251717d538382bd1546ed Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 20:11:42 -0700
Subject: [PATCH 043/160] [CI] fix bug on errors
---
.github/workflows/cpp.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index 68d16b8..3cbd8e1 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -12,6 +12,9 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
+ fail-fast: false
+
+ continue-on-error: true
steps:
- uses: actions/checkout@v4
@@ -61,7 +64,6 @@ jobs:
brew install qt6
echo 'export PATH="/opt/homebrew/opt/qt6/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
- qmake --version
- name: Install Qt6 (Windows)
if: matrix.os == 'windows-latest'
@@ -69,7 +71,6 @@ jobs:
python -m pip install aqtinstall
python -m aqt install-qt windows desktop 6.6.0 win64_mingw --outputdir C:\Qt
echo C:\Qt\6.6.0\mingw_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- qmake --version
# Build the Project
- name: Build project
From 923f2ea06ee518cb0c8ff6892db77be9a34e64ae Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 20:16:45 -0700
Subject: [PATCH 044/160] [CI Bug] Fix bug on windows python version + linux
install work around
---
.github/workflows/cpp.yml | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index 3cbd8e1..33e294a 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -19,6 +19,13 @@ jobs:
steps:
- uses: actions/checkout@v4
+ # Set up Python 3.10 or later
+ - name: Set up Python 3.10 (Windows)
+ if: matrix.os == 'windows-latest'
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.10'
+
# Install C++ Compiler & Build Tools
- name: Set up C++ environment (Ubuntu)
if: matrix.os == 'ubuntu-latest'
@@ -77,5 +84,12 @@ jobs:
run: make build
# Install the Project with desktop shortcut
- - name: Install project
+ - name: Install project (Mac/Windows)
+ if: matrix.os != 'ubuntu-latest'
run: echo "y" | make install
+
+ # Install the Project without desktop shortcut (Linux)
+ # This is a work around for Linux shortcut bug
+ - name: Install project (Linux)
+ if: matrix.os == 'ubuntu-latest'
+ run: echo "n" | make install
From 880d4632dcb719fd90b08695f4d35108dd8e9674 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 20:22:21 -0700
Subject: [PATCH 045/160] [Bug] Fixing Windows CI bug
---
.github/workflows/cpp.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index 33e294a..cc6a5e6 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -86,7 +86,9 @@ jobs:
# Install the Project with desktop shortcut
- name: Install project (Mac/Windows)
if: matrix.os != 'ubuntu-latest'
- run: echo "y" | make install
+ run: |
+ cd ${{ github.workspace }}
+ echo "y" | make install
# Install the Project without desktop shortcut (Linux)
# This is a work around for Linux shortcut bug
From e66e8a795e59a75f6c5c77b0e7506ce9170dc5fa Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 20:31:07 -0700
Subject: [PATCH 046/160] [CI] Removed windows CI test
---
.github/workflows/cpp.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index cc6a5e6..677e800 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
+ os: [ubuntu-latest, macos-latest] # TO-DO: Add back windows-latest when the project is tested on a Windows machine.
fail-fast: false
continue-on-error: true
From 41d2f70a067184ff1f45e981d5d96be1bdd02b08 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Fri, 21 Mar 2025 21:19:16 -0700
Subject: [PATCH 047/160] [Doc] Added development badges
---
README.md | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/README.md b/README.md
index 03be487..67753b0 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,27 @@
+
+
+
+ [](https://github.com/sandbox-science/CodeAstra/actions/workflows/cpp.yml)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
CodeAstra ~ Modern Code Editor
CodeAstra is a modern, extensible, and lightweight code editor built using C++ and Qt6, designed to offer a fast, customizable, and feature-rich development experience. Inspired by NeoVim and VSCode, it **will** provide efficient file navigation, syntax highlighting, and a powerful plugin system, making it an ideal choice for developers who need speed, flexibility, and control. With a focus on performance and usability, the editor **will** support split views, an integrated terminal, customizable key bindings, and seamless Git integration, catering to both beginners and power users.
From cc1c56fd99a00366e41c4e075f76339a6c0c5631 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:09:17 -0700
Subject: [PATCH 048/160] [Refactor] Adjust formatting and organization in
FileManager class for improved readability + conged FileManager to instance
---
include/FileManager.h | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/include/FileManager.h b/include/FileManager.h
index e311f33..4209eae 100644
--- a/include/FileManager.h
+++ b/include/FileManager.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
class CodeEditor;
class MainWindow;
@@ -11,21 +12,36 @@ class MainWindow;
*/
class FileManager : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- FileManager(CodeEditor *editor, MainWindow *mainWindow);
- ~FileManager();
+ static FileManager &getInstance(CodeEditor *editor = nullptr, MainWindow *mainWindow = nullptr)
+ {
+ static FileManager instance(editor, mainWindow);
+ return instance;
+ }
+
+ FileManager(const FileManager &) = delete;
+ FileManager &operator=(const FileManager &) = delete;
+
+ QString getFileExtension() const;
+ QString getCurrentFileName() const;
+
+ void setCurrentFileName(const QString fileName);
+ void initialize(CodeEditor *editor, MainWindow *mainWindow);
public slots:
- void newFile();
- void saveFile();
- void saveFileAs();
- void openFile();
- void loadFileInEditor(const QString &filePath);
+ void newFile();
+ void saveFile();
+ void saveFileAs();
+ void openFile();
+ void loadFileInEditor(const QString &filePath);
private:
- std::unique_ptr m_editor;
- QString m_currentFileName;
- MainWindow *m_mainWindow;
+ FileManager(CodeEditor *editor, MainWindow *mainWindow);
+ ~FileManager();
+
+ CodeEditor *m_editor;
+ MainWindow *m_mainWindow;
+ QString m_currentFileName;
};
From a61e4ddfa1698c006eb8a4ce311bef69379cea6f Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:10:50 -0700
Subject: [PATCH 049/160] [Refactor] Improve FileManager class initialization
and file handling logic
---
src/FileManager.cpp | 74 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 56 insertions(+), 18 deletions(-)
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index 858ca2a..7ce460c 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -8,22 +8,29 @@
#include "MainWindow.h"
FileManager::FileManager(CodeEditor *editor, MainWindow *mainWindow)
- : m_editor(editor),
- m_currentFileName(""),
- m_mainWindow(mainWindow)
+ : m_editor(editor), m_mainWindow(mainWindow)
{
- if (!m_editor)
- {
- qWarning() << "Editor is NOT initialized in FileManager!";
- }
- else
- {
- qDebug() << "Editor is properly initialized in FileManager.";
- }
+ qDebug() << "FileManager initialized.";
}
FileManager::~FileManager() {}
+void FileManager::initialize(CodeEditor *editor, MainWindow *mainWindow)
+{
+ m_editor = editor;
+ m_mainWindow = mainWindow;
+}
+
+QString FileManager::getCurrentFileName() const
+{
+ return m_currentFileName;
+}
+
+void FileManager::setCurrentFileName(const QString fileName)
+{
+ m_currentFileName = fileName;
+}
+
void FileManager::newFile()
{
// Logic to create a new file
@@ -31,13 +38,14 @@ void FileManager::newFile()
void FileManager::saveFile()
{
- qDebug() << "Saving file:" << m_currentFileName;
if (m_currentFileName.isEmpty())
{
saveFileAs();
return;
}
+ qDebug() << "Saving file:" << m_currentFileName;
+
QFile file(m_currentFileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
@@ -62,8 +70,14 @@ void FileManager::saveFile()
void FileManager::saveFileAs()
{
- QString fileName = QFileDialog::getSaveFileName(nullptr, "Save File As", QString(),
- "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
+ QString fileExtension = getFileExtension();
+ QString filter = "All Files (*);;C++ Files (*.cpp *.h);;Text Files (*.txt)";
+ if (!fileExtension.isEmpty())
+ {
+ filter = QString("%1 Files (*.%2);;%3").arg(fileExtension.toUpper(), fileExtension, filter);
+ }
+
+ QString fileName = QFileDialog::getSaveFileName(nullptr, "Save File As", QString(), filter);
if (!fileName.isEmpty())
{
@@ -75,13 +89,20 @@ void FileManager::saveFileAs()
void FileManager::openFile()
{
QString fileName = QFileDialog::getOpenFileName(nullptr, "Open File", QString(),
- "C++ Files (*.cpp *.h);;Text Files (*.txt);;All Files (*)");
+ "All Files (*);;C++ Files (*.cpp *.h);;Text Files (*.txt)");
if (!fileName.isEmpty())
{
+ qDebug() << "Opening file: " << fileName;
+ m_currentFileName = fileName;
loadFileInEditor(fileName);
}
+ else
+ {
+ qDebug() << "No file selected.";
+ }
}
+
void FileManager::loadFileInEditor(const QString &filePath)
{
qDebug() << "Loading file:" << filePath;
@@ -104,6 +125,23 @@ void FileManager::loadFileInEditor(const QString &filePath)
}
file.close();
- m_currentFileName = filePath;
- m_mainWindow->setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
-}
\ No newline at end of file
+ if (m_mainWindow)
+ {
+ m_mainWindow->setWindowTitle("CodeAstra ~ " + QFileInfo(filePath).fileName());
+ }
+ else
+ {
+ qWarning() << "MainWindow is initialized in FileManager.";
+ }
+}
+
+QString FileManager::getFileExtension() const
+{
+ if (m_currentFileName.isEmpty())
+ {
+ qDebug() << "Error: No File name set!";
+ return QString();
+ }
+
+ return QFileInfo(m_currentFileName).suffix().toLower();
+}
From 7894c2d32e64a32098e8f4b6ed1ead16b5d6a594 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:11:04 -0700
Subject: [PATCH 050/160] [Refactor] Remove unused current file name methods
and update FileManager declaration in CodeEditor
---
include/CodeEditor.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index a0e04f2..1b67b00 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -3,6 +3,8 @@
#include
#include
+class FileManager; // Forward declaration
+
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
@@ -18,8 +20,6 @@ class CodeEditor : public QPlainTextEdit
Mode mode = NORMAL;
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
- QString getCurrentFileName() const { return m_currentFileName; }
- void setCurrentFileName(const QString &fileName) { m_currentFileName = fileName; }
signals:
void statusMessageChanged(const QString &message);
@@ -35,9 +35,8 @@ private slots:
private:
QWidget *m_lineNumberArea;
- QString m_currentFileName;
+ FileManager *m_fileManager;
- QString getFileExtension();
void addLanguageSymbol(QTextCursor &cursor, const QString &commentSymbol);
void commentSelection(QTextCursor &cursor, const QString &commentSymbol);
void commentLine(QTextCursor &cursor, const QString &commentSymbol);
From 741250b99141ac0ea368776a89c5e3aeef1e8eb6 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:11:22 -0700
Subject: [PATCH 051/160] [Refactor] Integrate FileManager instance into
CodeEditor and remove unused getFileExtension method
---
src/CodeEditor.cpp | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 9070140..0d23421 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -1,6 +1,7 @@
#include "CodeEditor.h"
#include "MainWindow.h"
#include "LineNumberArea.h"
+#include "FileManager.h"
#include
#include
@@ -9,7 +10,8 @@
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent),
- m_lineNumberArea(new LineNumberArea(this))
+ m_lineNumberArea(new LineNumberArea(this)),
+ m_fileManager(&FileManager::getInstance())
{
connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
@@ -73,18 +75,6 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
}
}
-QString CodeEditor::getFileExtension()
-{
- QString filePath = getCurrentFileName();
- if (!QFile::exists(filePath))
- {
- return QString();
- }
-
- // Extract the file extension from the file path
- return QFileInfo(filePath).suffix().toLower();
-}
-
void CodeEditor::addLanguageSymbol(QTextCursor &cursor, const QString &commentSymbol)
{
if (cursor.hasSelection())
@@ -116,7 +106,7 @@ void CodeEditor::commentSelection(QTextCursor &cursor, const QString &commentSym
if (lineText.startsWith(commentSymbol))
{
- cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 3);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, commentSymbol.length() + 1);
cursor.removeSelectedText();
}
else
@@ -136,7 +126,7 @@ void CodeEditor::commentLine(QTextCursor &cursor, const QString &commentSymbol)
if (lineText.startsWith(commentSymbol))
{
- lineText.remove(0, 3);
+ lineText.remove(0, commentSymbol.length() + 1);
}
else
{
@@ -149,7 +139,7 @@ void CodeEditor::commentLine(QTextCursor &cursor, const QString &commentSymbol)
void CodeEditor::addComment()
{
QTextCursor cursor = textCursor();
- QString fileExtension = getFileExtension();
+ QString fileExtension = m_fileManager->getFileExtension();
qDebug() << "File Extension:" << fileExtension;
if (fileExtension == "cpp" || fileExtension == "h" ||
@@ -172,7 +162,6 @@ void CodeEditor::addComment()
else
{
qDebug() << "Unsupported file extension for commenting.";
- return;
}
}
From 7de8ed4551808c0c75098a445c9a2493d50688cd Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:11:40 -0700
Subject: [PATCH 052/160] [Refactor] Remove unused QFile include and adjust
FileManager pointer formatting in MainWindow
---
include/MainWindow.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index bd786f3..acf4366 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -6,7 +6,6 @@
#include
#include
#include
-#include
class CodeEditor;
class Syntax;
@@ -41,5 +40,5 @@ private slots:
std::unique_ptr m_syntax;
std::unique_ptr m_tree;
- FileManager * m_FileManager;
+ FileManager *m_fileManager;
};
\ No newline at end of file
From 999cc444b9d3a03dfc7718418dfdeb2bb257bd47 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:12:11 -0700
Subject: [PATCH 053/160] [Refactor] Replace FileManager instance creation with
singleton access and update related usages in MainWindow
---
src/MainWindow.cpp | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 0365279..b3c78a2 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -6,21 +6,19 @@
#include
#include
-#include
-#include
#include
#include
#include
#include
-#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
m_editor(std::make_unique(this)),
m_syntax(std::make_unique(m_editor->document())),
m_tree(nullptr),
- m_FileManager(new FileManager(m_editor.get(), this))
+ m_fileManager(&FileManager::getInstance())
{
+ m_fileManager->initialize(m_editor.get(), this);
setWindowTitle("CodeAstra ~ Code Editor");
connect(m_editor.get(), &CodeEditor::statusMessageChanged, this, [this](const QString &message)
@@ -47,7 +45,7 @@ void MainWindow::initTree()
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(splitter);
- m_tree = std::make_unique(splitter, m_FileManager);
+ m_tree = std::make_unique(splitter, m_fileManager);
splitter->addWidget(m_editor.get());
splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -76,18 +74,21 @@ void MainWindow::createMenuBar()
void MainWindow::createFileActions(QMenu *fileMenu)
{
- fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), [this]() { m_FileManager->newFile(); }));
- fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), [this]() { m_FileManager->openFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), [this]() { m_fileManager->newFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), [this]() { m_fileManager->openFile(); }));
fileMenu->addSeparator();
- fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), [this]() { m_FileManager->saveFile(); }));
- fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), [this]() { m_FileManager->saveFileAs(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), [this]() { m_fileManager->saveFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), [this]() { m_fileManager->saveFileAs(); }));
}
void MainWindow::createHelpActions(QMenu *helpMenu)
{
QAction *helpDoc = new QAction(tr("Documentation"), this);
connect(helpDoc, &QAction::triggered, this, []()
- { QDesktopServices::openUrl(QUrl("https://github.com/sandbox-science/CodeAstra/wiki")); });
+ {
+ QDesktopServices::openUrl(QUrl("https://github.com/sandbox-science/CodeAstra/wiki"));
+ });
+
helpDoc->setStatusTip(tr("Open Wiki"));
helpMenu->addAction(helpDoc);
}
From c198be04a1b6a9b40252903119a1aba21ae6b1fc Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:12:23 -0700
Subject: [PATCH 054/160] [Refactor] Update openFile method to use FileManager
singleton for file operations
---
src/Tree.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Tree.cpp b/src/Tree.cpp
index cd02124..f8fab29 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -70,7 +70,8 @@ void Tree::openFile(const QModelIndex &index)
return;
}
- m_FileManager->loadFileInEditor(filePath);
+ FileManager::getInstance().setCurrentFileName(filePath);
+ FileManager::getInstance().loadFileInEditor(filePath);
}
// Context menu for file operations
From bbae1349308fd3fdeb1f4f4f05364b80c0210c59 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:51:04 -0700
Subject: [PATCH 055/160] [Refactor] Add class documentation for classes header
file
---
include/CodeEditor.h | 8 ++++++++
include/FileManager.h | 6 ++++++
include/LineNumberArea.h | 9 +++++++++
include/MainWindow.h | 8 ++++++++
include/Syntax.h | 11 +++++++++++
include/Tree.h | 8 ++++++++
6 files changed, 50 insertions(+)
diff --git a/include/CodeEditor.h b/include/CodeEditor.h
index 1b67b00..dd8afa8 100644
--- a/include/CodeEditor.h
+++ b/include/CodeEditor.h
@@ -5,6 +5,14 @@
class FileManager; // Forward declaration
+/**
+ * @class CodeEditor
+ * @brief A custom code editor widget that extends QPlainTextEdit.
+ *
+ * The CodeEditor class provides a code editor with line number area, syntax highlighting,
+ * and basic editing modes (NORMAL and INSERT). It emits signals for status messages and
+ * handles key press and resize events.
+ */
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
diff --git a/include/FileManager.h b/include/FileManager.h
index 4209eae..160026f 100644
--- a/include/FileManager.h
+++ b/include/FileManager.h
@@ -9,6 +9,12 @@ class MainWindow;
/**
* @class FileManager
* @brief Manages file operations such as creating, saving, and opening files.
+ *
+ * The FileManager class is a singleton that handles multiple file-related operations
+ * within the application. It interacts with the CodeEditor and MainWindow classes
+ * to perform tasks such as creating new files, saving existing files, and opening
+ * files from the filesystem. The class ensures that only one instance of FileManager
+ * exists and provides a global point of access to it.
*/
class FileManager : public QObject
{
diff --git a/include/LineNumberArea.h b/include/LineNumberArea.h
index 64f923d..1f2a85e 100644
--- a/include/LineNumberArea.h
+++ b/include/LineNumberArea.h
@@ -6,6 +6,15 @@
#include
#include
+/**
+ * @class LineNumberArea
+ * @brief A widget that displays line numbers for the CodeEditor.
+ *
+ * The LineNumberArea class is a QWidget that is used to display line numbers
+ * alongside the CodeEditor widget.
+ *
+ * @note This class is intended to be used as a part of the CodeEditor widget.
+ */
class LineNumberArea : public QWidget
{
public:
diff --git a/include/MainWindow.h b/include/MainWindow.h
index acf4366..7cd1ce8 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -12,6 +12,13 @@ class Syntax;
class Tree;
class FileManager;
+/**
+ * @class MainWindow
+ * @brief The MainWindow class represents the main UI window of the application.
+ *
+ * This class is responsible for initializing and managing the main components
+ * of the application, including the file tree view, code editor, and menu bar.
+ */
class MainWindow : public QMainWindow
{
Q_OBJECT
@@ -32,6 +39,7 @@ private slots:
void createFileActions(QMenu *fileMenu);
void createHelpActions(QMenu *helpMenu);
void createAppActions(QMenu *appMenu);
+
QAction *createAction(const QIcon &icon, const QString &text,
const QKeySequence &shortcut, const QString &statusTip,
const std::function &slot);
diff --git a/include/Syntax.h b/include/Syntax.h
index 35f0ea0..dcfc5c7 100644
--- a/include/Syntax.h
+++ b/include/Syntax.h
@@ -5,6 +5,17 @@
#include
#include
+/**
+ * @class Syntax
+ * @brief A class for syntax highlighting in a QTextDocument.
+ *
+ * This class inherits from QSyntaxHighlighter and provides functionality
+ * to highlight different syntax elements such as keywords, comments,
+ * functions, parentheses, characters, and quotations in a QTextDocument.
+ *
+ * The Syntax class uses regular expressions to define patterns for different
+ * syntax elements and applies corresponding text formats to them.
+ */
class Syntax : public QSyntaxHighlighter
{
Q_OBJECT
diff --git a/include/Tree.h b/include/Tree.h
index 039d9a1..2fc65a1 100644
--- a/include/Tree.h
+++ b/include/Tree.h
@@ -10,6 +10,13 @@ class QFileSystemModel;
class QFileIconProvider;
class FileManager;
+/**
+ * @class Tree
+ * @brief A class that represents a tree view for displaying the file system.
+ *
+ * The Tree class is responsible for creating and managing a tree view that displays
+ * the file system.
+ */
class Tree : public QObject
{
Q_OBJECT
@@ -23,6 +30,7 @@ class Tree : public QObject
void setupModel();
void setupTree();
void openFile(const QModelIndex &index);
+
QString getDirectoryPath() const;
std::unique_ptr m_iconProvider;
From f1eef649c765ef0b8c4f345cd5dddbc5bc87996a Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 18:51:11 -0700
Subject: [PATCH 056/160] [Refactor] Remove unnecessary newline in Syntax
constructor for improved readability
---
src/FileManager.cpp | 1 -
src/Syntax.cpp | 3 +--
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index 7ce460c..ab3c6a3 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -102,7 +102,6 @@ void FileManager::openFile()
}
}
-
void FileManager::loadFileInEditor(const QString &filePath)
{
qDebug() << "Loading file:" << filePath;
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index 9f841c2..4f71a6e 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -2,8 +2,7 @@
#include
#include
-Syntax::Syntax(QTextDocument *parent)
- : QSyntaxHighlighter(parent)
+Syntax::Syntax(QTextDocument *parent) : QSyntaxHighlighter(parent)
{
initKeywordRules();
initFunctionRules();
From 036bfe3b30e518ad74551555332c9d451d8435d9 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 20:59:16 -0700
Subject: [PATCH 057/160] [Refactor] Update include directives to use relative
paths for unit test
---
src/FileManager.cpp | 6 +++---
src/Syntax.cpp | 3 ++-
src/Tree.cpp | 6 +++---
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index ab3c6a3..a9728db 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -1,11 +1,11 @@
-#include "FileManager.h"
+#include "../include/FileManager.h"
+#include "../include/CodeEditor.h"
+#include "../include/MainWindow.h"
#include
#include
#include
#include
-#include "CodeEditor.h"
-#include "MainWindow.h"
FileManager::FileManager(CodeEditor *editor, MainWindow *mainWindow)
: m_editor(editor), m_mainWindow(mainWindow)
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index e516db1..18f2266 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -1,6 +1,7 @@
+#include "../include/Syntax.h"
+
#include
#include
-#include "../include/Syntax.h"
Syntax::Syntax(QTextDocument *parent) : QSyntaxHighlighter(parent)
{
diff --git a/src/Tree.cpp b/src/Tree.cpp
index f8fab29..d60076e 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -1,6 +1,6 @@
-#include "Tree.h"
-#include "CodeEditor.h"
-#include "FileManager.h"
+#include "../include/Tree.h"
+#include "../include/CodeEditor.h"
+#include "../include/FileManager.h"
#include
#include
From 04ed7f4318cf2944624dc3838b59da0b7b449a61 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 20:59:31 -0700
Subject: [PATCH 058/160] [Refactor] Add object names to menu items in
createMenuBar for improved accessibility (required for UnitTests)
---
src/MainWindow.cpp | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index de4b2c2..8203ee8 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -62,8 +62,13 @@ void MainWindow::createMenuBar()
QMenuBar *menuBar = new QMenuBar(this);
QMenu *fileMenu = menuBar->addMenu("File");
+ fileMenu->setObjectName("File");
+
QMenu *helpMenu = menuBar->addMenu("Help");
- QMenu *appMenu = menuBar->addMenu("CodeAstra");
+ helpMenu->setObjectName("Help");
+
+ QMenu *appMenu = menuBar->addMenu("CodeAstra");
+ appMenu->setObjectName("CodeAstra");
createFileActions(fileMenu);
createHelpActions(helpMenu);
From c44394a5fb92475a179e01ed2493048e7e76a14e Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 21:33:32 -0700
Subject: [PATCH 059/160] [Refactor] Rename target variables and restructure
CMakeLists.txt for clarity and organization (to work with Unit Tests)
---
CMakeLists.txt | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2c293c7..06a1427 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.16)
# Project name
-set(TARGET_NAME CodeAstra)
+set(TARGET_NAME CodeAstraApp)
+set(EXECUTABLE_NAME CodeAstra)
set(QT_MAJOR_VERSION 6)
@@ -49,9 +50,8 @@ set(CMAKE_PREFIX_PATH ${Qt_DIR})
# Find Qt Widgets
find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Widgets Test REQUIRED)
-# Add executable and source files
-add_executable(${TARGET_NAME}
- src/main.cpp
+# Create the CodeAstra library
+add_library(${TARGET_NAME}
src/MainWindow.cpp
src/CodeEditor.cpp
src/Syntax.cpp
@@ -65,31 +65,42 @@ add_executable(${TARGET_NAME}
include/FileManager.h
)
+# Create the executable for the application
+add_executable(${EXECUTABLE_NAME}
+ src/main.cpp
+)
+
+# Link the main executable with the CodeAstra library and Qt libraries
+target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${TARGET_NAME} Qt${QT_MAJOR_VERSION}::Widgets)
+
+# Add the tests subdirectory
add_subdirectory(tests)
+# Qt resource files (if any)
qt_add_resources(APP_RESOURCES resources.qrc)
-target_sources(${TARGET_NAME} PRIVATE ${APP_RESOURCES})
+target_sources(${EXECUTABLE_NAME} PRIVATE ${APP_RESOURCES})
# Compiler flags per OS
if(MSVC)
- target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
+ target_compile_options(${EXECUTABLE_NAME} PRIVATE /W4 /WX)
elseif(APPLE)
- target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
- set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
+ target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
+ set_target_properties(${EXECUTABLE_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
else()
- target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
+ target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()
# Include directories
-target_include_directories(${TARGET_NAME} PRIVATE ${Qt${QT_MAJOR_VERSION}_INCLUDE_DIRS})
+target_include_directories(${EXECUTABLE_NAME} PRIVATE ${Qt${QT_MAJOR_VERSION}_INCLUDE_DIRS})
+target_include_directories(${EXECUTABLE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
# Set output names properly for Debug and Release
-set_target_properties(${TARGET_NAME} PROPERTIES
+set_target_properties(${EXECUTABLE_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
- DEBUG_OUTPUT_NAME "${TARGET_NAME}d"
- RELEASE_OUTPUT_NAME ${TARGET_NAME}
+ DEBUG_OUTPUT_NAME "${EXECUTABLE_NAME}d"
+ RELEASE_OUTPUT_NAME ${EXECUTABLE_NAME}
)
-# Link necessary Qt libraries
+# Link necessary Qt libraries to CodeAstra library
target_link_libraries(${TARGET_NAME} PRIVATE Qt${QT_MAJOR_VERSION}::Widgets)
\ No newline at end of file
From 14c2589dea064515f29c573a10e1a52d3d5d435c Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 21:33:56 -0700
Subject: [PATCH 060/160] [Refactor] Update test_mainwindow CMake configuration
to link with CodeAstra library and improve organization
---
tests/CMakeLists.txt | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a291c85..7023a6e 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -4,16 +4,10 @@ enable_testing()
# Add individual test executables
add_executable(test_mainwindow
test_mainwindow.cpp
- ../src/MainWindow.cpp
- ../src/CodeEditor.cpp
- ../src/Syntax.cpp
- ../include/MainWindow.h
- ../include/CodeEditor.h
- ../include/Syntax.h
)
-# Link each test with necessary libraries
-target_link_libraries(test_mainwindow PRIVATE Qt6::Widgets Qt6::Test)
+# Link the test with the CodeAstra library and necessary Qt libraries
+target_link_libraries(test_mainwindow PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test)
# Register each test with CTest
add_test(NAME test_mainwindow COMMAND test_mainwindow)
@@ -21,4 +15,8 @@ add_test(NAME test_mainwindow COMMAND test_mainwindow)
# Set the runtime output directory for the test executables
set_target_properties(test_mainwindow PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
-)
\ No newline at end of file
+)
+
+set_property(SOURCE test_mainwindow.cpp PROPERTY SKIP_AUTOMOC OFF)
+
+target_include_directories(test_mainwindow PRIVATE ${CMAKE_SOURCE_DIR}/include)
\ No newline at end of file
From c0b69c62682f16d26716da2170236b024ee96fe2 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 21:34:53 -0700
Subject: [PATCH 061/160] [Refactor] Update include directives to use local
paths instead of relative path
---
src/CodeEditor.cpp | 8 ++++----
src/FileManager.cpp | 6 +++---
src/MainWindow.cpp | 10 +++++-----
src/Syntax.cpp | 2 +-
src/Tree.cpp | 6 +++---
src/main.cpp | 2 +-
6 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/CodeEditor.cpp b/src/CodeEditor.cpp
index 4dec245..0d23421 100644
--- a/src/CodeEditor.cpp
+++ b/src/CodeEditor.cpp
@@ -1,7 +1,7 @@
-#include "../include/CodeEditor.h"
-#include "../include/MainWindow.h"
-#include "../include/LineNumberArea.h"
-#include "../include/FileManager.h"
+#include "CodeEditor.h"
+#include "MainWindow.h"
+#include "LineNumberArea.h"
+#include "FileManager.h"
#include
#include
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index a9728db..454321c 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -1,6 +1,6 @@
-#include "../include/FileManager.h"
-#include "../include/CodeEditor.h"
-#include "../include/MainWindow.h"
+#include "FileManager.h"
+#include "CodeEditor.h"
+#include "MainWindow.h"
#include
#include
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 8203ee8..68ce95b 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,8 +1,8 @@
-#include "../include/MainWindow.h"
-#include "../include/Syntax.h"
-#include "../include/Tree.h"
-#include "../include/CodeEditor.h"
-#include "../include/FileManager.h"
+#include "MainWindow.h"
+#include "Syntax.h"
+#include "Tree.h"
+#include "CodeEditor.h"
+#include "FileManager.h"
#include
#include
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
index 18f2266..5896a88 100644
--- a/src/Syntax.cpp
+++ b/src/Syntax.cpp
@@ -1,4 +1,4 @@
-#include "../include/Syntax.h"
+#include "Syntax.h"
#include
#include
diff --git a/src/Tree.cpp b/src/Tree.cpp
index d60076e..f8fab29 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -1,6 +1,6 @@
-#include "../include/Tree.h"
-#include "../include/CodeEditor.h"
-#include "../include/FileManager.h"
+#include "Tree.h"
+#include "CodeEditor.h"
+#include "FileManager.h"
#include
#include
diff --git a/src/main.cpp b/src/main.cpp
index cfe70f2..93247d6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,4 @@
-#include "../include/MainWindow.h"
+#include "MainWindow.h"
#include
#include
From fa6e3425130d68c79c717f936655a4573d82555c Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 21:36:19 -0700
Subject: [PATCH 062/160] [Refactor] Improve test structure and initialization
in TestMainWindow
---
tests/test_mainwindow.cpp | 52 +++++++++++++++++++++++++--------------
1 file changed, 34 insertions(+), 18 deletions(-)
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index 67797be..b25a1cb 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -1,51 +1,67 @@
-#include "../include/MainWindow.h"
-
#include
#include
-#include
+
+#include "MainWindow.h"
+#include "CodeEditor.h"
+#include "FileManager.h"
class TestMainWindow : public QObject
{
Q_OBJECT
private slots:
- void initTestCase(); // Runs before all tests
- void cleanupTestCase(); // Runs after all tests
+ void initTestCase();
+ void cleanupTestCase();
void testWindowTitle();
+ void testEditorInitialization();
void testMenuBar();
- void testNewFileAction();
+
+private:
+ std::unique_ptr mainWindow;
};
void TestMainWindow::initTestCase()
{
qDebug() << "Initializing MainWindow tests...";
+ mainWindow = std::make_unique();
+ mainWindow->show();
}
void TestMainWindow::cleanupTestCase()
{
qDebug() << "Cleaning up MainWindow tests...";
+ mainWindow.reset();
}
void TestMainWindow::testWindowTitle()
{
- MainWindow window;
- QCOMPARE(window.windowTitle(), QString("CodeAstra ~ Code Editor"));
+ QCOMPARE(mainWindow->windowTitle(), "CodeAstra ~ Code Editor");
}
-void TestMainWindow::testMenuBar()
+void TestMainWindow::testEditorInitialization()
{
- MainWindow window;
- QMenuBar *menuBar = window.menuBar();
- QVERIFY(menuBar != nullptr);
- QCOMPARE(menuBar->actions().size(), 3); // File, Help, CodeAstra
+ QVERIFY2(mainWindow->findChild() != nullptr,
+ "MainWindow must contain a CodeEditor.");
}
-void TestMainWindow::testNewFileAction()
+void TestMainWindow::testMenuBar()
{
- MainWindow window;
- QAction *newAction = window.findChild("New File");
- QVERIFY(newAction != nullptr);
+ QMenuBar *menuBar = mainWindow->menuBar();
+ QVERIFY2(menuBar != nullptr, "MainWindow must have a QMenuBar.");
+ QCOMPARE(menuBar->actions().size(), 3); // File, Help, CodeAstra
+
+ QMenu *fileMenu = menuBar->findChild("File");
+ QVERIFY2(fileMenu != nullptr, "QMenuBar must contain a 'File' menu.");
+ QCOMPARE(fileMenu->title(), "File");
+
+ QMenu *helpMenu = menuBar->findChild("Help");
+ QVERIFY2(helpMenu != nullptr, "QMenuBar must contain a 'Help' menu.");
+ QCOMPARE(helpMenu->title(), "Help");
+
+ QMenu *appMenu = menuBar->findChild("CodeAstra");
+ QVERIFY2(appMenu != nullptr, "QMenuBar must contain a 'CodeAstra' menu.");
+ QCOMPARE(appMenu->title(), "CodeAstra");
}
QTEST_MAIN(TestMainWindow)
-#include "test_mainwindow.moc"
+#include "test_mainwindow.moc"
\ No newline at end of file
From 3d54fb9d69ab9d851f0efd263feba7bfd79ce342 Mon Sep 17 00:00:00 2001
From: Chris
Date: Sat, 22 Mar 2025 21:54:34 -0700
Subject: [PATCH 063/160] [Refactor] Update comment
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 06a1427..e7d76fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,7 +76,7 @@ target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${TARGET_NAME} Qt${QT_MAJOR_VER
# Add the tests subdirectory
add_subdirectory(tests)
-# Qt resource files (if any)
+# Qt resource files
qt_add_resources(APP_RESOURCES resources.qrc)
target_sources(${EXECUTABLE_NAME} PRIVATE ${APP_RESOURCES})
From 4f48a2ea1add87bc280d109fb1a851cd5e747279 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Sun, 23 Mar 2025 14:32:02 -0700
Subject: [PATCH 064/160] [Doc] updated C++ version
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 67753b0..3a0d99e 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
-
+
From 6f1c6490cdf8005459bf38176d577c8261fbddf5 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:21:24 -0700
Subject: [PATCH 065/160] [added] Add test_tree executable and update CMake
configuration
---
tests/CMakeLists.txt | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7023a6e..48b3ff8 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,17 +6,30 @@ add_executable(test_mainwindow
test_mainwindow.cpp
)
+# Add test_tree executable
+add_executable(test_tree
+ test_tree.cpp
+)
+
# Link the test with the CodeAstra library and necessary Qt libraries
target_link_libraries(test_mainwindow PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test)
+target_link_libraries(test_tree PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test)
# Register each test with CTest
add_test(NAME test_mainwindow COMMAND test_mainwindow)
+add_test(NAME test_tree COMMAND test_tree)
# Set the runtime output directory for the test executables
set_target_properties(test_mainwindow PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
)
+set_target_properties(test_tree PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
+)
set_property(SOURCE test_mainwindow.cpp PROPERTY SKIP_AUTOMOC OFF)
+set_property(SOURCE test_tree.cpp PROPERTY SKIP_AUTOMOC OFF)
-target_include_directories(test_mainwindow PRIVATE ${CMAKE_SOURCE_DIR}/include)
\ No newline at end of file
+# Include directories for tests
+target_include_directories(test_mainwindow PRIVATE ${CMAKE_SOURCE_DIR}/include)
+target_include_directories(test_tree PRIVATE ${CMAKE_SOURCE_DIR}/include)
From 4aeafd55a0d9505df55aebb8550068c46356fde0 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:22:25 -0700
Subject: [PATCH 066/160] [Refactor] Moved getDirectoryPath method from
FileManager and createAction method from MainWindow from private to public
---
include/FileManager.h | 2 ++
include/MainWindow.h | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/FileManager.h b/include/FileManager.h
index 160026f..bccf188 100644
--- a/include/FileManager.h
+++ b/include/FileManager.h
@@ -43,6 +43,8 @@ public slots:
void openFile();
void loadFileInEditor(const QString &filePath);
+ QString getDirectoryPath() const;
+
private:
FileManager(CodeEditor *editor, MainWindow *mainWindow);
~FileManager();
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 7cd1ce8..591a273 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -31,6 +31,10 @@ class MainWindow : public QMainWindow
// of the main window, alongside the code editor
void initTree();
+ QAction *createAction(const QIcon &icon, const QString &text,
+ const QKeySequence &shortcut, const QString &statusTip,
+ const std::function &slot);
+
private slots:
void showAbout();
@@ -40,10 +44,6 @@ private slots:
void createHelpActions(QMenu *helpMenu);
void createAppActions(QMenu *appMenu);
- QAction *createAction(const QIcon &icon, const QString &text,
- const QKeySequence &shortcut, const QString &statusTip,
- const std::function &slot);
-
std::unique_ptr m_editor;
std::unique_ptr m_syntax;
std::unique_ptr m_tree;
From 45fc75395acaa128aa438f6db0f0fb734f9d3324 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:22:34 -0700
Subject: [PATCH 067/160] [Refactor] Simplify Tree constructor by removing
FileManager dependency and reorganizing method visibility
---
include/Tree.h | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/include/Tree.h b/include/Tree.h
index 2fc65a1..210c733 100644
--- a/include/Tree.h
+++ b/include/Tree.h
@@ -22,20 +22,18 @@ class Tree : public QObject
Q_OBJECT
public:
- explicit Tree(QSplitter *splitter, FileManager *FileManager);
+ explicit Tree(QSplitter *splitter);
~Tree();
-private:
- void showContextMenu(const QPoint &pos);
- void setupModel();
+ void initialize(const QString &directory);
+ void setupModel(const QString &directory);
void setupTree();
void openFile(const QModelIndex &index);
- QString getDirectoryPath() const;
+private:
+ void showContextMenu(const QPoint &pos);
std::unique_ptr m_iconProvider;
std::unique_ptr m_model;
std::unique_ptr m_tree;
-
- FileManager * m_FileManager;
};
\ No newline at end of file
From 0f41a6b92bbbe9794757c10352421060182d80c2 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:22:49 -0700
Subject: [PATCH 068/160] [added] Implement getDirectoryPath method to allow
directory selection
---
src/FileManager.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index 454321c..6f6c89e 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -144,3 +144,10 @@ QString FileManager::getFileExtension() const
return QFileInfo(m_currentFileName).suffix().toLower();
}
+
+QString FileManager::getDirectoryPath() const
+{
+ return QFileDialog::getExistingDirectory(
+ nullptr, QObject::tr("Open Directory"), QDir::homePath(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+}
From a10d9244b841b65094bd129aaf3e08866832072f Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:23:00 -0700
Subject: [PATCH 069/160] [added] Implement Open Project action in file menu to
initialize tree with selected directory
---
src/MainWindow.cpp | 333 +++++++++++++++++++++++----------------------
1 file changed, 171 insertions(+), 162 deletions(-)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 68ce95b..1e1b2a6 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,162 +1,171 @@
-#include "MainWindow.h"
-#include "Syntax.h"
-#include "Tree.h"
-#include "CodeEditor.h"
-#include "FileManager.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent),
- m_editor(std::make_unique(this)),
- m_syntax(std::make_unique(m_editor->document())),
- m_tree(nullptr),
- m_fileManager(&FileManager::getInstance())
-{
- m_fileManager->initialize(m_editor.get(), this);
- setWindowTitle("CodeAstra ~ Code Editor");
-
- connect(m_editor.get(), &CodeEditor::statusMessageChanged, this, [this](const QString &message)
- {
- QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss");
- statusBar()->showMessage("[" + timestamp + "] " + message, 4000);
- });
-
- // Set tab width to 4 spaces
- QFontMetrics metrics(m_editor->font());
- int spaceWidth = metrics.horizontalAdvance(" ");
- m_editor->setTabStopDistance(spaceWidth * 4);
- m_editor->setLineWrapMode(QPlainTextEdit::NoWrap);
-
- initTree();
- createMenuBar();
- showMaximized();
-}
-
-MainWindow::~MainWindow() {}
-
-void MainWindow::initTree()
-{
- QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
- setCentralWidget(splitter);
-
- m_tree = std::make_unique(splitter, m_fileManager);
-
- splitter->addWidget(m_editor.get());
- splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- splitter->setHandleWidth(5);
- splitter->setSizes(QList() << 150 << 800);
- splitter->setStretchFactor(0, 1);
- splitter->setStretchFactor(1, 3);
- splitter->setChildrenCollapsible(false);
- splitter->setOpaqueResize(true);
-}
-
-void MainWindow::createMenuBar()
-{
- QMenuBar *menuBar = new QMenuBar(this);
-
- QMenu *fileMenu = menuBar->addMenu("File");
- fileMenu->setObjectName("File");
-
- QMenu *helpMenu = menuBar->addMenu("Help");
- helpMenu->setObjectName("Help");
-
- QMenu *appMenu = menuBar->addMenu("CodeAstra");
- appMenu->setObjectName("CodeAstra");
-
- createFileActions(fileMenu);
- createHelpActions(helpMenu);
- createAppActions(appMenu);
-
- setMenuBar(menuBar);
-}
-
-void MainWindow::createFileActions(QMenu *fileMenu)
-{
- fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), [this]() { m_fileManager->newFile(); }));
- fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), [this]() { m_fileManager->openFile(); }));
- fileMenu->addSeparator();
- fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), [this]() { m_fileManager->saveFile(); }));
- fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), [this]() { m_fileManager->saveFileAs(); }));
-}
-
-void MainWindow::createHelpActions(QMenu *helpMenu)
-{
- QAction *helpDoc = new QAction(tr("Documentation"), this);
- connect(helpDoc, &QAction::triggered, this, []()
- {
- QDesktopServices::openUrl(QUrl("https://github.com/sandbox-science/CodeAstra/wiki"));
- });
-
- helpDoc->setStatusTip(tr("Open Wiki"));
- helpMenu->addAction(helpDoc);
-}
-
-void MainWindow::createAppActions(QMenu *appMenu)
-{
- QAction *aboutAction = new QAction("About CodeAstra", this);
- connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout);
- appMenu->addAction(aboutAction);
-}
-
-QAction *MainWindow::createAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QString &statusTip, const std::function &slot)
-{
- QAction *action = new QAction(icon, text, this);
-
- action->setShortcuts(QList{shortcut});
- action->setStatusTip(statusTip);
- connect(action, &QAction::triggered, this, slot);
-
- return action;
-}
-
-void MainWindow::showAbout()
-{
- // Extract the C++ version from the __cplusplus macro
- QString cppVersion;
- if (__cplusplus == 201103L)
- {
- cppVersion = "C++11";
- }
- else if (__cplusplus == 201402L)
- {
- cppVersion = "C++14";
- }
- else if (__cplusplus == 201703L)
- {
- cppVersion = "C++17";
- }
- else if (__cplusplus == 202002L)
- {
- cppVersion = "C++20";
- }
- else
- {
- cppVersion = "C++";
- }
-
- // Construct the about text
- QString aboutText = QString(
- ""
- "%1
"
- "Version: %2
"
- "Developed by %3.
"
- "Built with %4 and Qt %5.
"
- "© 2025 %3. All rights reserved."
- "
")
- .arg(QApplication::applicationName().toHtmlEscaped(),
- QApplication::applicationVersion().toHtmlEscaped(),
- QApplication::organizationName().toHtmlEscaped(),
- cppVersion,
- QString::number(QT_VERSION >> 16) + "." + // Major version
- QString::number((QT_VERSION >> 8) & 0xFF) + "." + // Minor version
- QString::number(QT_VERSION & 0xFF)); // Patch version
-
- QMessageBox::about(this, tr("About"), aboutText);
-}
+#include "MainWindow.h"
+#include "Syntax.h"
+#include "Tree.h"
+#include "CodeEditor.h"
+#include "FileManager.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ m_editor(std::make_unique(this)),
+ m_syntax(std::make_unique(m_editor->document())),
+ m_tree(nullptr),
+ m_fileManager(&FileManager::getInstance())
+{
+ m_fileManager->initialize(m_editor.get(), this);
+ setWindowTitle("CodeAstra ~ Code Editor");
+
+ connect(m_editor.get(), &CodeEditor::statusMessageChanged, this, [this](const QString &message)
+ {
+ QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss");
+ statusBar()->showMessage("[" + timestamp + "] " + message, 4000);
+ });
+
+ // Set tab width to 4 spaces
+ QFontMetrics metrics(m_editor->font());
+ int spaceWidth = metrics.horizontalAdvance(" ");
+ m_editor->setTabStopDistance(spaceWidth * 4);
+ m_editor->setLineWrapMode(QPlainTextEdit::NoWrap);
+
+ initTree();
+ createMenuBar();
+ showMaximized();
+}
+
+MainWindow::~MainWindow() {}
+
+void MainWindow::initTree()
+{
+ QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
+ setCentralWidget(splitter);
+
+ m_tree = std::make_unique(splitter);
+
+ splitter->addWidget(m_editor.get());
+ splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ splitter->setHandleWidth(5);
+ splitter->setSizes(QList() << 150 << 800);
+ splitter->setStretchFactor(0, 1);
+ splitter->setStretchFactor(1, 3);
+ splitter->setChildrenCollapsible(false);
+ splitter->setOpaqueResize(true);
+}
+
+void MainWindow::createMenuBar()
+{
+ QMenuBar *menuBar = new QMenuBar(this);
+
+ QMenu *fileMenu = menuBar->addMenu("File");
+ fileMenu->setObjectName("File");
+
+ QMenu *helpMenu = menuBar->addMenu("Help");
+ helpMenu->setObjectName("Help");
+
+ QMenu *appMenu = menuBar->addMenu("CodeAstra");
+ appMenu->setObjectName("CodeAstra");
+
+ createFileActions(fileMenu);
+ createHelpActions(helpMenu);
+ createAppActions(appMenu);
+
+ setMenuBar(menuBar);
+}
+
+void MainWindow::createFileActions(QMenu *fileMenu)
+{
+ fileMenu->addAction(createAction(QIcon(), tr("&New"), QKeySequence::New, tr("Create a new file"), [this]() { m_fileManager->newFile(); }));
+ fileMenu->addSeparator();
+ fileMenu->addAction(createAction(QIcon(), tr("&Open &Project"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_O), tr("Open a project"), [this]()
+ {
+ QString projectPath = m_fileManager->getDirectoryPath();
+ if (!projectPath.isEmpty())
+ {
+ m_tree->initialize(projectPath);
+ }
+ }));
+ fileMenu->addAction(createAction(QIcon(), tr("&Open"), QKeySequence::Open, tr("Open an existing file"), [this]() { m_fileManager->openFile(); }));
+ fileMenu->addSeparator();
+ fileMenu->addAction(createAction(QIcon(), tr("&Save"), QKeySequence::Save, tr("Save the current file"), [this]() { m_fileManager->saveFile(); }));
+ fileMenu->addAction(createAction(QIcon(), tr("Save &As"), QKeySequence::SaveAs, tr("Save the file with a new name"), [this]() { m_fileManager->saveFileAs(); }));
+}
+
+void MainWindow::createHelpActions(QMenu *helpMenu)
+{
+ QAction *helpDoc = new QAction(tr("Documentation"), this);
+ connect(helpDoc, &QAction::triggered, this, []()
+ {
+ QDesktopServices::openUrl(QUrl("https://github.com/sandbox-science/CodeAstra/wiki"));
+ });
+
+ helpDoc->setStatusTip(tr("Open Wiki"));
+ helpMenu->addAction(helpDoc);
+}
+
+void MainWindow::createAppActions(QMenu *appMenu)
+{
+ QAction *aboutAction = new QAction("About CodeAstra", this);
+ connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout);
+ appMenu->addAction(aboutAction);
+}
+
+QAction *MainWindow::createAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QString &statusTip, const std::function &slot)
+{
+ QAction *action = new QAction(icon, text, this);
+
+ action->setShortcuts(QList{shortcut});
+ action->setStatusTip(statusTip);
+ connect(action, &QAction::triggered, this, slot);
+
+ return action;
+}
+
+void MainWindow::showAbout()
+{
+ // Extract the C++ version from the __cplusplus macro
+ QString cppVersion;
+ if (__cplusplus == 201103L)
+ {
+ cppVersion = "C++11";
+ }
+ else if (__cplusplus == 201402L)
+ {
+ cppVersion = "C++14";
+ }
+ else if (__cplusplus == 201703L)
+ {
+ cppVersion = "C++17";
+ }
+ else if (__cplusplus == 202002L)
+ {
+ cppVersion = "C++20";
+ }
+ else
+ {
+ cppVersion = "C++";
+ }
+
+ // Construct the about text
+ QString aboutText = QString(
+ ""
+ "%1
"
+ "Version: %2
"
+ "Developed by %3.
"
+ "Built with %4 and Qt %5.
"
+ "© 2025 %3. All rights reserved."
+ "
")
+ .arg(QApplication::applicationName().toHtmlEscaped(),
+ QApplication::applicationVersion().toHtmlEscaped(),
+ QApplication::organizationName().toHtmlEscaped(),
+ cppVersion,
+ QString::number(QT_VERSION >> 16) + "." + // Major version
+ QString::number((QT_VERSION >> 8) & 0xFF) + "." + // Minor version
+ QString::number(QT_VERSION & 0xFF)); // Patch version
+
+ QMessageBox::about(this, tr("About"), aboutText);
+}
From ef2f1dd2cbbc48d0cf07b784cc60139e52922322 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:23:11 -0700
Subject: [PATCH 070/160] Refactor Tree class to remove FileManager dependency
and streamline initialization process
---
src/Tree.cpp | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/src/Tree.cpp b/src/Tree.cpp
index f8fab29..185d0ab 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -9,24 +9,26 @@
#include
#include
-Tree::Tree(QSplitter *splitter, FileManager *FileManager)
+Tree::Tree(QSplitter *splitter)
: QObject(splitter),
m_iconProvider(std::make_unique()),
m_model(std::make_unique()),
- m_tree(std::make_unique(splitter)),
- m_FileManager(FileManager)
+ m_tree(std::make_unique(splitter))
{
- setupModel();
- setupTree();
-
connect(m_tree.get(), &QTreeView::doubleClicked, this, &Tree::openFile);
}
Tree::~Tree() {}
-void Tree::setupModel()
+void Tree::initialize(const QString &directory)
{
- m_model->setRootPath(getDirectoryPath());
+ setupModel(directory);
+ setupTree();
+}
+
+void Tree::setupModel(const QString &directory)
+{
+ m_model->setRootPath(directory);
m_model->setIconProvider(m_iconProvider.get());
m_model->setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
}
@@ -51,13 +53,6 @@ void Tree::setupTree()
connect(m_tree.get(), &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);
}
-QString Tree::getDirectoryPath() const
-{
- return QFileDialog::getExistingDirectory(
- nullptr, QObject::tr("Open Directory"), QDir::homePath(),
- QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
-}
-
void Tree::openFile(const QModelIndex &index)
{
QString filePath = m_model->filePath(index);
From d463bdd7bb1d97071bd500368bad8e023af384b4 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:23:24 -0700
Subject: [PATCH 071/160] [added] Implement tests for QSplitter initialization
and action creation in TestMainWindow
---
tests/test_mainwindow.cpp | 47 +++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index b25a1cb..14567c0 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include
#include "MainWindow.h"
#include "CodeEditor.h"
@@ -15,6 +16,8 @@ private slots:
void testWindowTitle();
void testEditorInitialization();
void testMenuBar();
+ void testInitTree();
+ void testCreateAction();
private:
std::unique_ptr mainWindow;
@@ -48,19 +51,55 @@ void TestMainWindow::testMenuBar()
{
QMenuBar *menuBar = mainWindow->menuBar();
QVERIFY2(menuBar != nullptr, "MainWindow must have a QMenuBar.");
- QCOMPARE(menuBar->actions().size(), 3); // File, Help, CodeAstra
+ QCOMPARE_EQ(menuBar->actions().size(), 3); // File, Help, CodeAstra
QMenu *fileMenu = menuBar->findChild("File");
QVERIFY2(fileMenu != nullptr, "QMenuBar must contain a 'File' menu.");
- QCOMPARE(fileMenu->title(), "File");
+ QCOMPARE_EQ(fileMenu->title(), "File");
QMenu *helpMenu = menuBar->findChild("Help");
QVERIFY2(helpMenu != nullptr, "QMenuBar must contain a 'Help' menu.");
- QCOMPARE(helpMenu->title(), "Help");
+ QCOMPARE_EQ(helpMenu->title(), "Help");
QMenu *appMenu = menuBar->findChild("CodeAstra");
QVERIFY2(appMenu != nullptr, "QMenuBar must contain a 'CodeAstra' menu.");
- QCOMPARE(appMenu->title(), "CodeAstra");
+ QCOMPARE_EQ(appMenu->title(), "CodeAstra");
+}
+
+void TestMainWindow::testInitTree()
+{
+ QSplitter *splitter = dynamic_cast(mainWindow->centralWidget());
+ QVERIFY2(splitter != nullptr, "Central widget should be a QSplitter.");
+
+ QCOMPARE_EQ(splitter->handleWidth(), 5);
+ QCOMPARE_EQ(splitter->childrenCollapsible(), false);
+ QCOMPARE_EQ(splitter->opaqueResize(), true);
+
+ QList sizes = splitter->sizes();
+ QCOMPARE_EQ(sizes.size(), 2);
+}
+
+void TestMainWindow::testCreateAction()
+{
+ // Mock parameters for createAction
+ QIcon icon;
+ QString text = "Test Action";
+ QKeySequence shortcut = QKeySequence(Qt::CTRL | Qt::Key_T);
+ QString statusTip = "This is a test action";
+ bool slotCalled = false;
+
+ auto slot = [&slotCalled]() { slotCalled = true; };
+
+ QAction *action = mainWindow->createAction(icon, text, shortcut, statusTip, slot);
+
+ QVERIFY2(action != nullptr, "Action should be successfully created.");
+ QCOMPARE_EQ(action->text(), text);
+ QCOMPARE_EQ(action->shortcuts().first(), shortcut);
+ QCOMPARE_EQ(action->statusTip(), statusTip);
+
+ // Simulate triggering the action
+ action->trigger();
+ QCOMPARE_EQ(slotCalled, true);
}
QTEST_MAIN(TestMainWindow)
From 03ff07606c8167cea2bf7fe382139bf4470ccdb8 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 00:23:34 -0700
Subject: [PATCH 072/160] [added] Implement unit tests for Tree class to
validate openFile method with invalid input
---
tests/test_tree.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 tests/test_tree.cpp
diff --git a/tests/test_tree.cpp b/tests/test_tree.cpp
new file mode 100644
index 0000000..f00465c
--- /dev/null
+++ b/tests/test_tree.cpp
@@ -0,0 +1,44 @@
+#include
+#include
+#include "Tree.h"
+#include "FileManager.h"
+#include "CodeEditor.h"
+
+#include
+#include
+#include
+
+class TestTree : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void testOpenFile_invalid();
+};
+
+void TestTree::initTestCase()
+{
+ qDebug() << "Initializing TestTree tests...";
+}
+
+void TestTree::cleanupTestCase()
+{
+ qDebug() << "Cleaning up TestTree tests...";
+}
+
+void TestTree::testOpenFile_invalid()
+{
+ QSplitter *splitter = new QSplitter;
+ Tree tree(splitter);
+
+ QModelIndex index;
+
+ tree.openFile(index);
+
+ QVERIFY2(FileManager::getInstance().getCurrentFileName().isEmpty(), "FileManager should not process an invalid file.");
+}
+
+QTEST_MAIN(TestTree)
+#include "test_tree.moc"
From 3a1ac20faa6d01dba103bddb597df02f5cb276d6 Mon Sep 17 00:00:00 2001
From: Giovanni Rivera
Date: Wed, 26 Mar 2025 20:22:13 -0700
Subject: [PATCH 073/160] =?UTF-8?q?=E2=99=BB=20Refactor:=20Add=20Makefile?=
=?UTF-8?q?=20deps=20for=20testing?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Makefile | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index b0973ed..92474bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
PROJECT = CodeAstra
-BUILD_DIR = build
+BUILD_DIR = $(PWD)/build
EXECUTABLE = $(PROJECT)
# Set CMake options
@@ -45,7 +45,7 @@ uninstall: clean
fi
# Install the project
-install:
+install: build
@echo "Installing $(PROJECT)..."
@cd $(BUILD_DIR) && make
@echo "Do you want to create a shortcut on the desktop? (Y/n)"
@@ -76,7 +76,10 @@ install:
fi
@echo "$(PROJECT) installed."
-test:
+build_tests: build
+ @cd $(BUILD_DIR)/tests/ && make
+
+test: build_tests
@for test in ./build/tests/test_*; do \
if [ -f $$test ]; then \
echo "Running $$test..."; \
From 223ad42c63772656ed6301de2dfb31077384c6d0 Mon Sep 17 00:00:00 2001
From: Giovanni Rivera
Date: Wed, 26 Mar 2025 20:24:38 -0700
Subject: [PATCH 074/160] =?UTF-8?q?=F0=9F=94=A5=20Feature:=20Add=20dockeri?=
=?UTF-8?q?zed=20tests?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Dockerfile | 26 ++++++++++++++++++++++++++
run_dockerized_tests.sh | 8 ++++++++
2 files changed, 34 insertions(+)
create mode 100644 Dockerfile
create mode 100644 run_dockerized_tests.sh
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..9a550a3
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,26 @@
+FROM ubuntu:22.04 AS builder
+WORKDIR /
+
+# Add dependencies
+RUN apt-get update
+RUN apt-get install -y --no-install-recommends \
+ git \
+ ca-certificates \
+ g++ \
+ cmake \
+ make \
+ mesa-common-dev \
+ qt6-base-dev \
+ x11-utils \
+ x11-xserver-utils \
+ xvfb
+RUN rm -rf /var/lib/apt/lists/*
+
+# Copy CodeAstra into the container
+COPY . /CodeAstra
+WORKDIR /CodeAstra
+
+# Run dockerized tests script
+RUN chmod +x ./run_dockerized_tests.sh
+
+CMD ["./run_dockerized_tests.sh"]
diff --git a/run_dockerized_tests.sh b/run_dockerized_tests.sh
new file mode 100644
index 0000000..c0b8574
--- /dev/null
+++ b/run_dockerized_tests.sh
@@ -0,0 +1,8 @@
+#!/bin/bash -e
+
+# Start Xvfb server
+Xvfb :99 -screen 0 1024x768x24 &
+export DISPLAY=:99
+
+# Run tests
+make test
From e81e2c8d1d2cf9998eae50637049e457d7b84db9 Mon Sep 17 00:00:00 2001
From: Giovanni Rivera
Date: Thu, 27 Mar 2025 00:46:01 -0700
Subject: [PATCH 075/160] =?UTF-8?q?=E2=99=BB=20Refactor:=20Fix=20docker=20?=
=?UTF-8?q?command=20errors=20and=20add=20run=5Fdocker.sh?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Dockerfile | 6 +++---
run_docker.sh | 5 +++++
run_dockerized_tests.sh => test_with_xvbf.sh | 0
3 files changed, 8 insertions(+), 3 deletions(-)
create mode 100755 run_docker.sh
rename run_dockerized_tests.sh => test_with_xvbf.sh (100%)
diff --git a/Dockerfile b/Dockerfile
index 9a550a3..7c3b361 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:22.04 AS builder
+FROM ubuntu:24.04 AS builder
WORKDIR /
# Add dependencies
@@ -21,6 +21,6 @@ COPY . /CodeAstra
WORKDIR /CodeAstra
# Run dockerized tests script
-RUN chmod +x ./run_dockerized_tests.sh
+RUN chmod +x ./test_with_xvbf.sh
-CMD ["./run_dockerized_tests.sh"]
+CMD ["./test_with_xvbf.sh"]
diff --git a/run_docker.sh b/run_docker.sh
new file mode 100755
index 0000000..2aa18f5
--- /dev/null
+++ b/run_docker.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+docker build -t "code-astra:tester" .
+docker run --name "code-astra-tester" "code-astra:tester"
+docker rm "code-astra-tester"
diff --git a/run_dockerized_tests.sh b/test_with_xvbf.sh
similarity index 100%
rename from run_dockerized_tests.sh
rename to test_with_xvbf.sh
From dba4f8701f0113f084ef49da1a0b34245b4dcc7a Mon Sep 17 00:00:00 2001
From: Giovanni Rivera
Date: Thu, 27 Mar 2025 01:03:10 -0700
Subject: [PATCH 076/160] =?UTF-8?q?=F0=9F=9A=A8=20Test:=20Add=20test=20wor?=
=?UTF-8?q?kflow?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/test.yml | 94 ++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
create mode 100644 .github/workflows/test.yml
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..331582d
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,94 @@
+name: Tests
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+jobs:
+ native:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest] # TODO: Add windows-latest when officially supported
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v4
+
+ # Set up Python 3.10 or later
+ - name: Set up Python 3.10 (Windows)
+ if: matrix.os == 'windows-latest'
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.10'
+
+ # Install C++ Compiler & Build Tools
+ - name: Set up C++ environment (Ubuntu)
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y g++ make cmake
+ g++ --version
+ cmake --version
+ make --version
+
+ - name: Set up C++ environment (macOS)
+ if: matrix.os == 'macos-latest'
+ run: |
+ brew install make cmake
+ echo 'export PATH="/usr/local/opt/gcc/bin:$PATH"' >> ~/.bash_profile
+ source ~/.bash_profile
+ g++ --version
+ cmake --version
+ make --version
+
+ - name: Set up C++ environment (Windows)
+ if: matrix.os == 'windows-latest'
+ run: |
+ choco install mingw --version=8.1.0-1
+ choco install make cmake
+ echo C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ echo C:\ProgramData\chocolatey\lib\cmake\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+ g++ --version
+ cmake --version
+ make --version
+
+ # Install Qt6
+ - name: Install Qt6 (Ubuntu)
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get install -y qt6-base-dev
+ echo 'export PATH="/usr/lib/qt6/bin:$PATH"' >> ~/.bashrc
+ source ~/.bashrc
+
+ - name: Install Qt6 (macOS)
+ if: matrix.os == 'macos-latest'
+ run: |
+ brew install qt6
+ echo 'export PATH="/opt/homebrew/opt/qt6/bin:$PATH"' >> ~/.bash_profile
+ source ~/.bash_profile
+
+ - name: Install Qt6 (Windows)
+ if: matrix.os == 'windows-latest'
+ run: |
+ python -m pip install aqtinstall
+ python -m aqt install-qt windows desktop 6.6.0 win64_mingw --outputdir C:\Qt
+ echo C:\Qt\6.6.0\mingw_64\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+
+ # Build the Project
+ - name: Build project
+ run: make build
+
+ - name: Run Unit Tests
+ run: make test
+
+ docker:
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v4
+
+ - name: Run Docker Test
+ run: |
+ chmod +x ./run_docker.sh
+ ./run_docker.sh
From 712f5c073c5f51908265c483a044225223b22818 Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Thu, 27 Mar 2025 01:25:14 -0700
Subject: [PATCH 077/160] fix: Fix CI stratgey for runs-on
---
.github/workflows/test.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 331582d..3e92e19 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -84,6 +84,10 @@ jobs:
run: make test
docker:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
From ca15903a23a5ba2dd8190bd3afe1647cf848391b Mon Sep 17 00:00:00 2001
From: Chris Dedman Rollet <61106361+chrisdedman@users.noreply.github.com>
Date: Thu, 27 Mar 2025 01:28:46 -0700
Subject: [PATCH 078/160] Fix: Fix tentative for docker test
---
.github/workflows/test.yml | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3e92e19..a42cd6f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -84,10 +84,7 @@ jobs:
run: make test
docker:
- strategy:
- matrix:
- os: [ubuntu-latest, macos-latest]
- runs-on: ${{ matrix.os }}
+ runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
From a6af4f2bc967646bb8dc2132473ffa733ad95aee Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:22:16 -0700
Subject: [PATCH 079/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Reintroduce=20Sy?=
=?UTF-8?q?ntax=20class=20for=20custom=20syntax=20highlighting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/Syntax.h | 54 ------------------------------------
include/Syntax/Syntax.h | 61 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 54 deletions(-)
delete mode 100644 include/Syntax.h
create mode 100644 include/Syntax/Syntax.h
diff --git a/include/Syntax.h b/include/Syntax.h
deleted file mode 100644
index dcfc5c7..0000000
--- a/include/Syntax.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-/**
- * @class Syntax
- * @brief A class for syntax highlighting in a QTextDocument.
- *
- * This class inherits from QSyntaxHighlighter and provides functionality
- * to highlight different syntax elements such as keywords, comments,
- * functions, parentheses, characters, and quotations in a QTextDocument.
- *
- * The Syntax class uses regular expressions to define patterns for different
- * syntax elements and applies corresponding text formats to them.
- */
-class Syntax : public QSyntaxHighlighter
-{
- Q_OBJECT
-
-public:
- Syntax(QTextDocument *parent = nullptr);
-
-protected:
- void highlightBlock(const QString &text) override;
-
-private:
- struct SyntaxRule
- {
- QRegularExpression m_pattern;
- QTextCharFormat m_format;
- };
- QVector m_syntaxRules;
-
- QTextCharFormat m_keywordFormat;
- QTextCharFormat m_singleLineCommentFormat;
- QTextCharFormat m_quotationMark;
- QTextCharFormat m_functionFormat;
- QTextCharFormat m_parenthesisFormat;
- QTextCharFormat m_charFormat;
- QTextCharFormat m_iterationFormat;
-
- void addPattern(const QString &pattern, const QTextCharFormat &format);
-
- // Initialization functions for different syntax highlighting rules
- void initKeywordRules();
- void initCommentRules();
- void initFunctionRules();
- void initParenthesisRules();
- void initCharRules();
- void initQuotationRules();
-};
diff --git a/include/Syntax/Syntax.h b/include/Syntax/Syntax.h
new file mode 100644
index 0000000..c3efe17
--- /dev/null
+++ b/include/Syntax/Syntax.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include
+#include
+#include
+
+/**
+ * @class Syntax
+ * @brief A custom syntax highlighter class that extends QSyntaxHighlighter to provide
+ * syntax highlighting functionality based on user-defined rules.
+ *
+ * This class allows you to define syntax highlighting rules using regular expressions
+ * and associated text formats. It applies these rules to text blocks to highlight
+ * specific patterns.
+ *
+ * @note This class inherits the constructor from QSyntaxHighlighter.
+ */
+class Syntax : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ using QSyntaxHighlighter::QSyntaxHighlighter;
+
+ virtual ~Syntax() = default;
+
+protected:
+ /**
+ * @brief Highlights the given text block based on the defined syntax rules.
+ *
+ * @param text The text block to be highlighted.
+ */
+ void highlightBlock(const QString &text) override;
+
+public:
+ /**
+ * @struct SyntaxRule
+ * @brief Represents a single syntax highlighting rule.
+ *
+ * A syntax rule consists of a regular expression pattern and a text format
+ * to apply to matching text.
+ */
+ struct SyntaxRule
+ {
+ QRegularExpression m_pattern;
+ QTextCharFormat m_format;
+ };
+
+ QVector m_syntaxRules;
+
+ /**
+ * @brief Adds a new syntax highlighting rule.
+ *
+ * This method allows you to define a new rule by specifying a regular expression
+ * pattern and the corresponding text format.
+ *
+ * @param pattern The regular expression pattern for the rule.
+ * @param format The text format to apply to matches of the pattern.
+ */
+ void addPattern(const QString &pattern, const QTextCharFormat &format);
+};
\ No newline at end of file
From e65b1a331fe36501ed45664109186556e60b4e42 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:22:27 -0700
Subject: [PATCH 080/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Add=20SyntaxCpp?=
=?UTF-8?q?=20class=20for=20C/C++=20syntax=20highlighting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/Syntax/SyntaxCpp.h | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 include/Syntax/SyntaxCpp.h
diff --git a/include/Syntax/SyntaxCpp.h b/include/Syntax/SyntaxCpp.h
new file mode 100644
index 0000000..d67a23b
--- /dev/null
+++ b/include/Syntax/SyntaxCpp.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/**
+ * @class SyntaxCpp
+ * @brief A syntax highlighter class for C/C++ code, inheriting from the Syntax base class.
+ *
+ * This class provides syntax highlighting for C and C++ code by defining various
+ * QTextCharFormat rules for different C++ language elements.
+ */
+class SyntaxCpp : public Syntax
+{
+public:
+ SyntaxCpp(QTextDocument *parent = nullptr);
+
+private:
+ QTextCharFormat m_keywordFormat;
+ QTextCharFormat m_singleLineCommentFormat;
+ QTextCharFormat m_quotationMark;
+ QTextCharFormat m_functionFormat;
+ QTextCharFormat m_parenthesisFormat;
+ QTextCharFormat m_charFormat;
+ QTextCharFormat m_iterationFormat;
+
+ // Initialization functions for different syntax highlighting rules
+ void initKeywordRules();
+ void initCommentRules();
+ void initFunctionRules();
+ void initParenthesisRules();
+ void initCharRules();
+ void initQuotationRules();
+};
From 51cbcf9a1d63f07f65340b91ef77980598a0e7c5 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:22:51 -0700
Subject: [PATCH 081/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Add=20SyntaxGo?=
=?UTF-8?q?=20foundation=20class=20for=20Go=20syntax=20highlighting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/Syntax/SyntaxGo.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 include/Syntax/SyntaxGo.h
diff --git a/include/Syntax/SyntaxGo.h b/include/Syntax/SyntaxGo.h
new file mode 100644
index 0000000..5dc9644
--- /dev/null
+++ b/include/Syntax/SyntaxGo.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/**
+ * @class SyntaxGo
+ * @brief A syntax highlighter class for Go code, inheriting from the Syntax base class.
+ *
+ * This class provides syntax highlighting for Golang code by defining
+ * various QTextCharFormat rules for different Go language elements.
+ */
+class SyntaxGo : public Syntax
+{
+public:
+ SyntaxGo(QTextDocument *parent = nullptr);
+
+private:
+ QTextCharFormat m_quotationMark;
+
+ // Initialization functions for different syntax highlighting rules
+ void initQuotationRules();
+};
From 2038876e46db94fd39f57a08b37a895155ab8a52 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:23:00 -0700
Subject: [PATCH 082/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Reintroduce=20Sy?=
=?UTF-8?q?ntax=20class=20with=20highlightBlock=20and=20addPattern=20metho?=
=?UTF-8?q?ds?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Syntax.cpp | 111 ------------------------------------------
src/Syntax/Syntax.cpp | 22 +++++++++
2 files changed, 22 insertions(+), 111 deletions(-)
delete mode 100644 src/Syntax.cpp
create mode 100644 src/Syntax/Syntax.cpp
diff --git a/src/Syntax.cpp b/src/Syntax.cpp
deleted file mode 100644
index 5896a88..0000000
--- a/src/Syntax.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "Syntax.h"
-
-#include
-#include
-
-Syntax::Syntax(QTextDocument *parent) : QSyntaxHighlighter(parent)
-{
- initKeywordRules();
- initFunctionRules();
- initParenthesisRules();
- initCharRules();
-
- // Keep these two calls are at the end
- // to correctly apply the rules for strings and comments
- initCommentRules();
- initQuotationRules();
-}
-
-void Syntax::initKeywordRules()
-{
- // Keyword format
- m_keywordFormat.setForeground(Qt::blue);
- m_keywordFormat.setFontWeight(QFont::Bold);
-
- QStringList keywordPatterns = {
- "\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
- "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b",
- "\\bfriend\\b", "\\binline\\b", "\\bint\\b",
- "\\blong\\b", "\\bnamespace\\b", "\\boperator\\b",
- "\\bprivate\\b", "\\bprotected\\b", "\\bpublic\\b",
- "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
- "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
- "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
- "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b",
- "\\bvoid\\b", "\\bvolatile\\b", "\\bforeach\\b"};
-
- for (const QString &pattern : keywordPatterns)
- {
- addPattern(pattern, m_keywordFormat);
- }
-
- m_iterationFormat.setForeground(Qt::darkMagenta);
- m_iterationFormat.setFontWeight(QFont::Bold);
- QStringList iterationPatterns = {"\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
- for (const QString &pattern : iterationPatterns)
- {
- addPattern(pattern, m_iterationFormat);
- }
-}
-
-void Syntax::initCommentRules()
-{
- // Single line comment format expression
- m_singleLineCommentFormat.setForeground(Qt::darkGray);
- addPattern("//[^\n]*", m_singleLineCommentFormat);
-
- // TO-DO: Add multi-line comment support
-}
-
-void Syntax::initQuotationRules()
-{
- // Double quotation mark for string
- m_quotationMark.setForeground(Qt::darkGreen);
- addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
-
- // TO-DO: Add single quotation mark for character
-}
-
-void Syntax::initFunctionRules()
-{
- // Function format expression
- m_functionFormat.setFontItalic(true);
- m_functionFormat.setForeground(Qt::darkYellow);
- addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", m_functionFormat);
-}
-
-void Syntax::initParenthesisRules()
-{
- // Color pattern for parenthesis
- QColor parenthesisColor("#6495ED");
- m_parenthesisFormat.setForeground(parenthesisColor);
- addPattern("[()]", m_parenthesisFormat);
-}
-
-// Regex for single character format 'a', '\n', etc.
-void Syntax::initCharRules()
-{
- m_charFormat.setForeground(Qt::darkCyan);
- addPattern("'(\\\\.|[^'])'", m_charFormat);
-}
-
-void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
-{
- SyntaxRule rule;
- rule.m_pattern = QRegularExpression(pattern);
- rule.m_format = format;
- m_syntaxRules.append(rule);
-}
-
-void Syntax::highlightBlock(const QString &text)
-{
- for (const SyntaxRule &rule : m_syntaxRules)
- {
- QRegularExpressionMatchIterator matchIterator = rule.m_pattern.globalMatch(text);
- while (matchIterator.hasNext())
- {
- QRegularExpressionMatch match = matchIterator.next();
- setFormat(match.capturedStart(), match.capturedLength(), rule.m_format);
- }
- }
-}
diff --git a/src/Syntax/Syntax.cpp b/src/Syntax/Syntax.cpp
new file mode 100644
index 0000000..1f5a582
--- /dev/null
+++ b/src/Syntax/Syntax.cpp
@@ -0,0 +1,22 @@
+#include "Syntax/Syntax.h"
+
+void Syntax::highlightBlock(const QString &text)
+{
+ for (const SyntaxRule &rule : m_syntaxRules)
+ {
+ QRegularExpressionMatchIterator matchIterator = rule.m_pattern.globalMatch(text);
+ while (matchIterator.hasNext())
+ {
+ QRegularExpressionMatch match = matchIterator.next();
+ setFormat(match.capturedStart(), match.capturedLength(), rule.m_format);
+ }
+ }
+}
+
+void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
+{
+ SyntaxRule rule;
+ rule.m_pattern = QRegularExpression(pattern);
+ rule.m_format = format;
+ m_syntaxRules.append(rule);
+}
\ No newline at end of file
From d515736c884edf4ca4516d5bfe19df8b33ffeebb Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:23:13 -0700
Subject: [PATCH 083/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Implement=20Synt?=
=?UTF-8?q?axCpp=20class=20for=20C++=20syntax=20highlighting=20with=20keyw?=
=?UTF-8?q?ord,=20function,=20comment,=20quotation,=20parenthesis,=20and?=
=?UTF-8?q?=20character=20rules?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Syntax/SyntaxCpp.cpp | 91 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
create mode 100644 src/Syntax/SyntaxCpp.cpp
diff --git a/src/Syntax/SyntaxCpp.cpp b/src/Syntax/SyntaxCpp.cpp
new file mode 100644
index 0000000..e1159df
--- /dev/null
+++ b/src/Syntax/SyntaxCpp.cpp
@@ -0,0 +1,91 @@
+#include "Syntax/SyntaxCpp.h"
+
+#include
+#include
+
+SyntaxCpp::SyntaxCpp(QTextDocument *parent) : Syntax(parent)
+{
+ qDebug() << "SyntaxCpp highlighter created";
+ initKeywordRules();
+ initFunctionRules();
+ initParenthesisRules();
+ initCharRules();
+
+ // Keep these two calls are at the end
+ // to correctly apply the rules for strings and comments
+ initCommentRules();
+ initQuotationRules();
+}
+
+void SyntaxCpp::initKeywordRules()
+{
+ // Keyword format
+ m_keywordFormat.setForeground(Qt::blue);
+ m_keywordFormat.setFontWeight(QFont::Bold);
+
+ QStringList keywordPatterns = {
+ "\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
+ "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b",
+ "\\bfriend\\b", "\\binline\\b", "\\bint\\b",
+ "\\blong\\b", "\\bnamespace\\b", "\\boperator\\b",
+ "\\bprivate\\b", "\\bprotected\\b", "\\bpublic\\b",
+ "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
+ "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
+ "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
+ "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b",
+ "\\bvoid\\b", "\\bvolatile\\b", "\\bforeach\\b"};
+
+ for (const QString &pattern : keywordPatterns)
+ {
+ addPattern(pattern, m_keywordFormat);
+ }
+
+ m_iterationFormat.setForeground(Qt::darkMagenta);
+ m_iterationFormat.setFontWeight(QFont::Bold);
+ QStringList iterationPatterns = {"\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
+ for (const QString &pattern : iterationPatterns)
+ {
+ addPattern(pattern, m_iterationFormat);
+ }
+}
+
+void SyntaxCpp::initCommentRules()
+{
+ // Single line comment format expression
+ m_singleLineCommentFormat.setForeground(Qt::darkGray);
+ addPattern("//[^\n]*", m_singleLineCommentFormat);
+
+ // TO-DO: Add multi-line comment support
+}
+
+void SyntaxCpp::initQuotationRules()
+{
+ // Double quotation mark for string
+ m_quotationMark.setForeground(Qt::darkGreen);
+ addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
+
+ // TO-DO: Add single quotation mark for character
+}
+
+void SyntaxCpp::initFunctionRules()
+{
+ // Function format expression
+ m_functionFormat.setFontItalic(true);
+ m_functionFormat.setForeground(Qt::darkYellow);
+ addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", m_functionFormat);
+}
+
+void SyntaxCpp::initParenthesisRules()
+{
+ // Color pattern for parenthesis
+ QColor parenthesisColor("#6495ED");
+ m_parenthesisFormat.setForeground(parenthesisColor);
+ addPattern("[()]", m_parenthesisFormat);
+}
+
+// Regex for single character format 'a', '\n', etc.
+void SyntaxCpp::initCharRules()
+{
+ m_charFormat.setForeground(Qt::darkCyan);
+ addPattern("'(\\\\.|[^'])'", m_charFormat);
+}
\ No newline at end of file
From c4ec1a04798ec302dd1daa16913221984d195c52 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:23:36 -0700
Subject: [PATCH 084/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Add=20foundation?=
=?UTF-8?q?=20SyntaxGo=20implementation=20for=20Go=20syntax=20highlighting?=
=?UTF-8?q?=20with=20quotation=20rules?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Syntax/SyntaxGo.cpp | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 src/Syntax/SyntaxGo.cpp
diff --git a/src/Syntax/SyntaxGo.cpp b/src/Syntax/SyntaxGo.cpp
new file mode 100644
index 0000000..b90b9d7
--- /dev/null
+++ b/src/Syntax/SyntaxGo.cpp
@@ -0,0 +1,18 @@
+#include "Syntax/SyntaxGo.h"
+
+#include
+#include
+
+SyntaxGo::SyntaxGo(QTextDocument *parent) : Syntax(parent)
+{
+ qDebug() << "SyntaxGo highlighter created";
+ initQuotationRules();
+}
+
+void SyntaxGo::initQuotationRules()
+{
+ // Double quotation mark for string
+ m_quotationMark.setForeground(Qt::darkGreen);
+ addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
+ // TO-DO: Add single quotation mark for character
+}
\ No newline at end of file
From b3d0340c35821321bfe1b304c9e217ca36f8f349 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:23:48 -0700
Subject: [PATCH 085/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Add=20QSyntaxHig?=
=?UTF-8?q?hlighter=20member=20to=20FileManager=20for=20syntax=20highlight?=
=?UTF-8?q?ing=20support?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/FileManager.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/FileManager.h b/include/FileManager.h
index bccf188..178e8f3 100644
--- a/include/FileManager.h
+++ b/include/FileManager.h
@@ -2,6 +2,7 @@
#include
#include
+#include
class CodeEditor;
class MainWindow;
@@ -51,5 +52,6 @@ public slots:
CodeEditor *m_editor;
MainWindow *m_mainWindow;
+ QSyntaxHighlighter *m_currentHighlighter = nullptr;
QString m_currentFileName;
};
From d9ed3f002162ce185bb99156fee88f977bf86622 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:24:00 -0700
Subject: [PATCH 086/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Remove=20unused?=
=?UTF-8?q?=20Syntax=20member=20from=20MainWindow=20class?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/MainWindow.h | 1 -
src/MainWindow.cpp | 8 +++-----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 591a273..30c5a8c 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -45,7 +45,6 @@ private slots:
void createAppActions(QMenu *appMenu);
std::unique_ptr m_editor;
- std::unique_ptr m_syntax;
std::unique_ptr m_tree;
FileManager *m_fileManager;
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 1e1b2a6..1bde3a0 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,5 +1,4 @@
#include "MainWindow.h"
-#include "Syntax.h"
#include "Tree.h"
#include "CodeEditor.h"
#include "FileManager.h"
@@ -13,10 +12,9 @@
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
- m_editor(std::make_unique(this)),
- m_syntax(std::make_unique(m_editor->document())),
- m_tree(nullptr),
- m_fileManager(&FileManager::getInstance())
+ m_editor(std::make_unique(this)),
+ m_tree(nullptr),
+ m_fileManager(&FileManager::getInstance())
{
m_fileManager->initialize(m_editor.get(), this);
setWindowTitle("CodeAstra ~ Code Editor");
From 70cd4fb07c19fc8799f7b6afea58a13200add6b6 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:24:10 -0700
Subject: [PATCH 087/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Add=20SyntaxMana?=
=?UTF-8?q?ger=20class=20for=20dynamic=20syntax=20highlighter=20creation?=
=?UTF-8?q?=20based=20on=20file=20extensions?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/SyntaxManager.h | 53 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 include/SyntaxManager.h
diff --git a/include/SyntaxManager.h b/include/SyntaxManager.h
new file mode 100644
index 0000000..35243ce
--- /dev/null
+++ b/include/SyntaxManager.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "Syntax/SyntaxCpp.h"
+#include "Syntax/SyntaxGo.h"
+// #include "Syntax/SyntaxPy.h" // Uncomment when implemented
+// #include "Syntax/SyntaxEx.h" // Uncomment when implemented
+
+#include
+#include
+#include
+
+/**
+ * @class SyntaxManager
+ * @brief A utility class for creating syntax highlighters based on file extensions.
+ *
+ * This class provides a static method to create appropriate syntax highlighters
+ * for different programming languages based on the file extension. If a syntax
+ * highlighter for a specific file type is not implemented, it returns a nullptr.
+ */
+class SyntaxManager
+{
+public:
+ static std::unique_ptr createSyntaxHighlighter(const QString &extension, QTextDocument *doc)
+ {
+ qDebug() << "Creating highlighter for extension:" << extension;
+ if (extension == "cpp" || extension == "h" || extension == "c")
+ {
+ qDebug() << "C/C++ syntax highlighter selected.";
+ return std::make_unique(doc);
+ }
+ else if (extension == "py")
+ {
+ qDebug() << "Python syntax highlighter not implemented.";
+ // return std::make_unique(doc);
+ }
+ else if (extension == "go")
+ {
+ qDebug() << "Go syntax highlighter selected.";
+ return std::make_unique(doc);
+ }
+ else if (extension == "ex")
+ {
+ qDebug() << "Elixir syntax highlighter not implemented.";
+ // return std::make_unique(doc);
+ }
+ else
+ {
+ qDebug() << "No syntax highlighter available for" << extension << "file type.";
+ }
+
+ return nullptr;
+ }
+};
From 7f67166d31fcae4a49b7e5acf6bcf62b5b808916 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:24:26 -0700
Subject: [PATCH 088/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Integrate=20dyna?=
=?UTF-8?q?mic=20syntax=20highlighting=20in=20FileManager=20for=20loaded?=
=?UTF-8?q?=20files?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/FileManager.cpp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/FileManager.cpp b/src/FileManager.cpp
index 6f6c89e..f05f3fa 100644
--- a/src/FileManager.cpp
+++ b/src/FileManager.cpp
@@ -1,6 +1,7 @@
#include "FileManager.h"
#include "CodeEditor.h"
#include "MainWindow.h"
+#include "SyntaxManager.h"
#include
#include
@@ -116,6 +117,11 @@ void FileManager::loadFileInEditor(const QString &filePath)
if (m_editor)
{
m_editor->setPlainText(in.readAll());
+
+ delete m_currentHighlighter;
+
+ // Create and assign a new syntax highlighter based on language extension
+ m_currentHighlighter = SyntaxManager::createSyntaxHighlighter(getFileExtension(), m_editor->document()).release();
}
else
{
@@ -130,7 +136,7 @@ void FileManager::loadFileInEditor(const QString &filePath)
}
else
{
- qWarning() << "MainWindow is initialized in FileManager.";
+ qWarning() << "MainWindow is not initialized in FileManager.";
}
}
From a71c04f8e032a02473bb6d86fec6a096dd4445a1 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:24:37 -0700
Subject: [PATCH 089/160] =?UTF-8?q?=E2=9C=A8=20Feature:=20Organize=20synta?=
=?UTF-8?q?x-related=20files=20into=20a=20dedicated=20Syntax=20directory?=
=?UTF-8?q?=20and=20update=20CMakeLists.txt?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
CMakeLists.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7d76fa..47f31ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,15 +54,20 @@ find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Widgets Test REQUIRED)
add_library(${TARGET_NAME}
src/MainWindow.cpp
src/CodeEditor.cpp
- src/Syntax.cpp
src/Tree.cpp
src/FileManager.cpp
+ src/Syntax/Syntax.cpp
+ src/Syntax/SyntaxCpp.cpp
+ src/Syntax/SyntaxGo.cpp
include/MainWindow.h
include/CodeEditor.h
- include/Syntax.h
include/Tree.h
include/LineNumberArea.h
include/FileManager.h
+ include/SyntaxManager.h
+ include/Syntax/SyntaxCpp.h
+ include/Syntax/SyntaxGo.h
+ include/Syntax/Syntax.h
)
# Create the executable for the application
From 884ce777aacfefac5f40d38d1835e22d0df3d019 Mon Sep 17 00:00:00 2001
From: Chris
Date: Thu, 27 Mar 2025 15:27:57 -0700
Subject: [PATCH 090/160] =?UTF-8?q?=E2=9C=A8=20Update=20README.md=20to=20i?=
=?UTF-8?q?nclude=20supported=20languages=20for=20syntax=20highlighting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/README.md b/README.md
index 3a0d99e..d68f055 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,13 @@ Please, check the [wiki](https://github.com/sandbox-science/CodeAstra/wiki) for
- [ ] Create a new file ~ in progress
- [x] File tree navigation
- [ ] Syntax highlighting ~ in progress
+ - Supported Languagues:
+ - [ ] C/C++ (**in progress**)
+ - [ ] Golang (**in progress**)
+ - [ ] Python (**Backlog**)
+ - [ ] Elixir (**Backlog**)
+ - more to come ... ([contribution welcomed](https://github.com/sandbox-science/CodeAstra/issues/4))
+
- [ ] Plugin system
## To-Do
From 8200c9beec55590a6312066dfedc5af7c66eeb47 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:07:22 -0700
Subject: [PATCH 091/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Remove=20obsole?=
=?UTF-8?q?te=20syntax=20highlighter=20classes=20for=20C++,=20Go,=20and=20?=
=?UTF-8?q?general=20syntax?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Syntax/Syntax.cpp | 22 ----------
src/Syntax/SyntaxCpp.cpp | 91 ----------------------------------------
src/Syntax/SyntaxGo.cpp | 18 --------
3 files changed, 131 deletions(-)
delete mode 100644 src/Syntax/Syntax.cpp
delete mode 100644 src/Syntax/SyntaxCpp.cpp
delete mode 100644 src/Syntax/SyntaxGo.cpp
diff --git a/src/Syntax/Syntax.cpp b/src/Syntax/Syntax.cpp
deleted file mode 100644
index 1f5a582..0000000
--- a/src/Syntax/Syntax.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "Syntax/Syntax.h"
-
-void Syntax::highlightBlock(const QString &text)
-{
- for (const SyntaxRule &rule : m_syntaxRules)
- {
- QRegularExpressionMatchIterator matchIterator = rule.m_pattern.globalMatch(text);
- while (matchIterator.hasNext())
- {
- QRegularExpressionMatch match = matchIterator.next();
- setFormat(match.capturedStart(), match.capturedLength(), rule.m_format);
- }
- }
-}
-
-void Syntax::addPattern(const QString &pattern, const QTextCharFormat &format)
-{
- SyntaxRule rule;
- rule.m_pattern = QRegularExpression(pattern);
- rule.m_format = format;
- m_syntaxRules.append(rule);
-}
\ No newline at end of file
diff --git a/src/Syntax/SyntaxCpp.cpp b/src/Syntax/SyntaxCpp.cpp
deleted file mode 100644
index e1159df..0000000
--- a/src/Syntax/SyntaxCpp.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "Syntax/SyntaxCpp.h"
-
-#include
-#include
-
-SyntaxCpp::SyntaxCpp(QTextDocument *parent) : Syntax(parent)
-{
- qDebug() << "SyntaxCpp highlighter created";
- initKeywordRules();
- initFunctionRules();
- initParenthesisRules();
- initCharRules();
-
- // Keep these two calls are at the end
- // to correctly apply the rules for strings and comments
- initCommentRules();
- initQuotationRules();
-}
-
-void SyntaxCpp::initKeywordRules()
-{
- // Keyword format
- m_keywordFormat.setForeground(Qt::blue);
- m_keywordFormat.setFontWeight(QFont::Bold);
-
- QStringList keywordPatterns = {
- "\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
- "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b",
- "\\bfriend\\b", "\\binline\\b", "\\bint\\b",
- "\\blong\\b", "\\bnamespace\\b", "\\boperator\\b",
- "\\bprivate\\b", "\\bprotected\\b", "\\bpublic\\b",
- "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
- "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
- "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
- "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b",
- "\\bvoid\\b", "\\bvolatile\\b", "\\bforeach\\b"};
-
- for (const QString &pattern : keywordPatterns)
- {
- addPattern(pattern, m_keywordFormat);
- }
-
- m_iterationFormat.setForeground(Qt::darkMagenta);
- m_iterationFormat.setFontWeight(QFont::Bold);
- QStringList iterationPatterns = {"\\bfor\\b", "\\bwhile\\b", "\\bdo\\b", "\\bif\\b", "\\belse\\b"};
- for (const QString &pattern : iterationPatterns)
- {
- addPattern(pattern, m_iterationFormat);
- }
-}
-
-void SyntaxCpp::initCommentRules()
-{
- // Single line comment format expression
- m_singleLineCommentFormat.setForeground(Qt::darkGray);
- addPattern("//[^\n]*", m_singleLineCommentFormat);
-
- // TO-DO: Add multi-line comment support
-}
-
-void SyntaxCpp::initQuotationRules()
-{
- // Double quotation mark for string
- m_quotationMark.setForeground(Qt::darkGreen);
- addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
-
- // TO-DO: Add single quotation mark for character
-}
-
-void SyntaxCpp::initFunctionRules()
-{
- // Function format expression
- m_functionFormat.setFontItalic(true);
- m_functionFormat.setForeground(Qt::darkYellow);
- addPattern("\\b(?!for\\b|if\\b|else\\b|while\\b|do\\b)[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()", m_functionFormat);
-}
-
-void SyntaxCpp::initParenthesisRules()
-{
- // Color pattern for parenthesis
- QColor parenthesisColor("#6495ED");
- m_parenthesisFormat.setForeground(parenthesisColor);
- addPattern("[()]", m_parenthesisFormat);
-}
-
-// Regex for single character format 'a', '\n', etc.
-void SyntaxCpp::initCharRules()
-{
- m_charFormat.setForeground(Qt::darkCyan);
- addPattern("'(\\\\.|[^'])'", m_charFormat);
-}
\ No newline at end of file
diff --git a/src/Syntax/SyntaxGo.cpp b/src/Syntax/SyntaxGo.cpp
deleted file mode 100644
index b90b9d7..0000000
--- a/src/Syntax/SyntaxGo.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "Syntax/SyntaxGo.h"
-
-#include
-#include
-
-SyntaxGo::SyntaxGo(QTextDocument *parent) : Syntax(parent)
-{
- qDebug() << "SyntaxGo highlighter created";
- initQuotationRules();
-}
-
-void SyntaxGo::initQuotationRules()
-{
- // Double quotation mark for string
- m_quotationMark.setForeground(Qt::darkGreen);
- addPattern("\"(\\\\.|[^\"\\\\])*\"", m_quotationMark);
- // TO-DO: Add single quotation mark for character
-}
\ No newline at end of file
From 27b36c9686c23c261ff9a9e8f1a7110095c241ab Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:07:34 -0700
Subject: [PATCH 092/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Remove=20obsole?=
=?UTF-8?q?te=20syntax=20highlighter=20classes=20for=20C++=20and=20Go?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/Syntax/SyntaxCpp.h | 36 ------------------------------------
include/Syntax/SyntaxGo.h | 25 -------------------------
2 files changed, 61 deletions(-)
delete mode 100644 include/Syntax/SyntaxCpp.h
delete mode 100644 include/Syntax/SyntaxGo.h
diff --git a/include/Syntax/SyntaxCpp.h b/include/Syntax/SyntaxCpp.h
deleted file mode 100644
index d67a23b..0000000
--- a/include/Syntax/SyntaxCpp.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-/**
- * @class SyntaxCpp
- * @brief A syntax highlighter class for C/C++ code, inheriting from the Syntax base class.
- *
- * This class provides syntax highlighting for C and C++ code by defining various
- * QTextCharFormat rules for different C++ language elements.
- */
-class SyntaxCpp : public Syntax
-{
-public:
- SyntaxCpp(QTextDocument *parent = nullptr);
-
-private:
- QTextCharFormat m_keywordFormat;
- QTextCharFormat m_singleLineCommentFormat;
- QTextCharFormat m_quotationMark;
- QTextCharFormat m_functionFormat;
- QTextCharFormat m_parenthesisFormat;
- QTextCharFormat m_charFormat;
- QTextCharFormat m_iterationFormat;
-
- // Initialization functions for different syntax highlighting rules
- void initKeywordRules();
- void initCommentRules();
- void initFunctionRules();
- void initParenthesisRules();
- void initCharRules();
- void initQuotationRules();
-};
diff --git a/include/Syntax/SyntaxGo.h b/include/Syntax/SyntaxGo.h
deleted file mode 100644
index 5dc9644..0000000
--- a/include/Syntax/SyntaxGo.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-/**
- * @class SyntaxGo
- * @brief A syntax highlighter class for Go code, inheriting from the Syntax base class.
- *
- * This class provides syntax highlighting for Golang code by defining
- * various QTextCharFormat rules for different Go language elements.
- */
-class SyntaxGo : public Syntax
-{
-public:
- SyntaxGo(QTextDocument *parent = nullptr);
-
-private:
- QTextCharFormat m_quotationMark;
-
- // Initialization functions for different syntax highlighting rules
- void initQuotationRules();
-};
From 221d8eba1bfdeae5c8efe7f9563d2ec5fc766385 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:07:53 -0700
Subject: [PATCH 093/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Update=20Syntax?=
=?UTF-8?q?=20class=20constructor=20to=20accept=20YAML=20configuration=20a?=
=?UTF-8?q?nd=20remove=20unnecessary=20using=20declaration?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/Syntax/Syntax.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/Syntax/Syntax.h b/include/Syntax/Syntax.h
index c3efe17..25eb89c 100644
--- a/include/Syntax/Syntax.h
+++ b/include/Syntax/Syntax.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
/**
* @class Syntax
@@ -20,9 +21,8 @@ class Syntax : public QSyntaxHighlighter
Q_OBJECT
public:
- using QSyntaxHighlighter::QSyntaxHighlighter;
-
- virtual ~Syntax() = default;
+ Syntax(QTextDocument *parent, const YAML::Node &config);
+ ~Syntax() = default;
protected:
/**
@@ -58,4 +58,6 @@ class Syntax : public QSyntaxHighlighter
* @param format The text format to apply to matches of the pattern.
*/
void addPattern(const QString &pattern, const QTextCharFormat &format);
+
+ void loadSyntaxRules(const YAML::Node &config);
};
\ No newline at end of file
From 4fb7f24d9f20bc85568679431be5f0791e5bf23c Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:10:31 -0700
Subject: [PATCH 094/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Simplify=20Synt?=
=?UTF-8?q?axManager=20class=20by=20consolidating=20highlighter=20creation?=
=?UTF-8?q?=20logic=20and=20updating=20documentation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
include/SyntaxManager.h | 55 ++++++++++++++---------------------------
1 file changed, 18 insertions(+), 37 deletions(-)
diff --git a/include/SyntaxManager.h b/include/SyntaxManager.h
index 35243ce..9e41f3b 100644
--- a/include/SyntaxManager.h
+++ b/include/SyntaxManager.h
@@ -1,53 +1,34 @@
#pragma once
-#include "Syntax/SyntaxCpp.h"
-#include "Syntax/SyntaxGo.h"
-// #include "Syntax/SyntaxPy.h" // Uncomment when implemented
-// #include "Syntax/SyntaxEx.h" // Uncomment when implemented
+#include "syntax/Syntax.h"
#include
#include
#include
+#include
+
/**
* @class SyntaxManager
- * @brief A utility class for creating syntax highlighters based on file extensions.
+ * @brief Manages the creation of syntax highlighters for different file types.
+ *
+ * The SyntaxManager class provides functionality to create syntax highlighters
+ * based on file extensions. It supports dynamic creation of highlighters by
+ * utilizing configuration data and applies them to QTextDocument objects.
*
- * This class provides a static method to create appropriate syntax highlighters
- * for different programming languages based on the file extension. If a syntax
- * highlighter for a specific file type is not implemented, it returns a nullptr.
+ * @note This class is designed to work with the Qt framework and YAML configuration.
*/
class SyntaxManager
{
public:
- static std::unique_ptr createSyntaxHighlighter(const QString &extension, QTextDocument *doc)
- {
- qDebug() << "Creating highlighter for extension:" << extension;
- if (extension == "cpp" || extension == "h" || extension == "c")
- {
- qDebug() << "C/C++ syntax highlighter selected.";
- return std::make_unique(doc);
- }
- else if (extension == "py")
- {
- qDebug() << "Python syntax highlighter not implemented.";
- // return std::make_unique(doc);
- }
- else if (extension == "go")
- {
- qDebug() << "Go syntax highlighter selected.";
- return std::make_unique(doc);
- }
- else if (extension == "ex")
- {
- qDebug() << "Elixir syntax highlighter not implemented.";
- // return std::make_unique(doc);
- }
- else
- {
- qDebug() << "No syntax highlighter available for" << extension << "file type.";
- }
+ /**
+ * @brief Creates a syntax highlighter based on the file extension.
+ * @param extension The file extension (e.g., "cpp", "py").
+ * @param doc The QTextDocument to which the highlighter will be applied.
+ * @return A unique pointer to the appropriate syntax highlighter, or nullptr if not available.
+ */
+ static std::unique_ptr createSyntaxHighlighter(const QString &extension, QTextDocument *doc);
- return nullptr;
- }
+private:
+ static std::unique_ptr createHighlighter(QTextDocument *doc, const std::vector &config, const QString &extension);
};
From c4d4ad9c1abd1c3aa107d90482380f410e061a57 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:10:44 -0700
Subject: [PATCH 095/160] =?UTF-8?q?=E2=9C=A8=20Refactor:=20Consolidate=20t?=
=?UTF-8?q?est=20executable=20definitions=20and=20ensure=20proper=20linkin?=
=?UTF-8?q?g=20for=20yaml-cpp?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/CMakeLists.txt | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 48b3ff8..9f7c693 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -2,22 +2,19 @@
enable_testing()
# Add individual test executables
-add_executable(test_mainwindow
- test_mainwindow.cpp
-)
-
-# Add test_tree executable
-add_executable(test_tree
- test_tree.cpp
-)
+add_executable(test_mainwindow test_mainwindow.cpp)
+add_executable(test_tree test_tree.cpp)
+add_executable(test_syntax test_syntax.cpp)
-# Link the test with the CodeAstra library and necessary Qt libraries
-target_link_libraries(test_mainwindow PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test)
-target_link_libraries(test_tree PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test)
+# Make sure the test executables link with the necessary libraries
+target_link_libraries(test_mainwindow PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test yaml-cpp)
+target_link_libraries(test_tree PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test yaml-cpp)
+target_link_libraries(test_syntax PRIVATE ${TARGET_NAME} Qt6::Widgets Qt6::Test yaml-cpp)
# Register each test with CTest
add_test(NAME test_mainwindow COMMAND test_mainwindow)
add_test(NAME test_tree COMMAND test_tree)
+add_test(NAME test_syntax COMMAND test_tree)
# Set the runtime output directory for the test executables
set_target_properties(test_mainwindow PROPERTIES
@@ -26,10 +23,29 @@ set_target_properties(test_mainwindow PROPERTIES
set_target_properties(test_tree PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
)
+set_target_properties(test_syntax PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/tests
+)
set_property(SOURCE test_mainwindow.cpp PROPERTY SKIP_AUTOMOC OFF)
set_property(SOURCE test_tree.cpp PROPERTY SKIP_AUTOMOC OFF)
+set_property(SOURCE test_syntax.cpp PROPERTY SKIP_AUTOMOC OFF)
# Include directories for tests
target_include_directories(test_mainwindow PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_include_directories(test_tree PRIVATE ${CMAKE_SOURCE_DIR}/include)
+target_include_directories(test_syntax PRIVATE ${CMAKE_SOURCE_DIR}/include)
+
+# Ensure proper linking directories are set for yaml-cpp
+target_include_directories(test_mainwindow PRIVATE /opt/homebrew/include)
+target_include_directories(test_tree PRIVATE /opt/homebrew/include)
+target_include_directories(test_syntax PRIVATE /opt/homebrew/include)
+
+target_link_directories(test_mainwindow PRIVATE /opt/homebrew/lib)
+target_link_directories(test_tree PRIVATE /opt/homebrew/lib)
+target_link_directories(test_syntax PRIVATE /opt/homebrew/lib)
+
+# Link the libraries explicitly for both main executable and tests
+target_link_libraries(test_mainwindow PRIVATE /opt/homebrew/lib/libyaml-cpp.dylib)
+target_link_libraries(test_tree PRIVATE /opt/homebrew/lib/libyaml-cpp.dylib)
+target_link_libraries(test_syntax PRIVATE /opt/homebrew/lib/libyaml-cpp.dylib)
From 0edee19154ce3fac9616d5d4738ac7f5dd12d76d Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:12:35 -0700
Subject: [PATCH 096/160] :white_check_mark: Test: Add unit tests for Syntax
class to validate loading of syntax rules from YAML configuration
---
tests/test_syntax.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
create mode 100644 tests/test_syntax.cpp
diff --git a/tests/test_syntax.cpp b/tests/test_syntax.cpp
new file mode 100644
index 0000000..e851b75
--- /dev/null
+++ b/tests/test_syntax.cpp
@@ -0,0 +1,105 @@
+#include
+#include "syntax/Syntax.h"
+
+#include
+#include
+#include
+
+// Helper function to create a YAML node for testing
+YAML::Node createTestConfig()
+{
+ YAML::Node config;
+ YAML::Node keywords = config["keywords"];
+
+ YAML::Node category1;
+ YAML::Node rule1;
+ rule1["regex"] = "\\bint\\b";
+ rule1["color"] = "#ff0000";
+ rule1["bold"] = true;
+ rule1["italic"] = false;
+ category1.push_back(rule1);
+
+ YAML::Node rule2;
+ rule2["regex"] = "\\bfloat\\b";
+ rule2["color"] = "#00ff00";
+ rule2["bold"] = false;
+ rule2["italic"] = true;
+ category1.push_back(rule2);
+
+ keywords["types"] = category1;
+
+ return config;
+}
+
+class TestSyntax : public QObject
+{
+ Q_OBJECT
+
+protected:
+ QTextDocument *document;
+ Syntax *syntax;
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void testLoadValidSyntaxRules();
+ void testLoadEmptySyntaxRules();
+ void testLoadMissingKeywords();
+};
+
+void TestSyntax::initTestCase()
+{
+ qDebug() << "Initializing TestSyntax tests...";
+ document = new QTextDocument();
+ syntax = new Syntax(document, YAML::Node());
+}
+
+void TestSyntax::cleanupTestCase()
+{
+ qDebug() << "Cleaning up TestSyntax tests...";
+}
+
+void TestSyntax::testLoadEmptySyntaxRules()
+{
+ YAML::Node config;
+ syntax->loadSyntaxRules(config);
+
+ // Verify that no rules were loaded
+ QVERIFY(syntax->m_syntaxRules.isEmpty());
+}
+
+void TestSyntax::testLoadValidSyntaxRules()
+{
+ YAML::Node config = createTestConfig();
+ syntax->loadSyntaxRules(config);
+
+ // Verify that the rules were loaded correctly
+ QVERIFY(syntax->m_syntaxRules.size() == 2);
+
+ // Check the first rule
+ const auto &rule1 = syntax->m_syntaxRules[0];
+ QCOMPARE_EQ(rule1.m_pattern.pattern(), "\\bint\\b");
+ QCOMPARE_EQ(rule1.m_format.foreground().color(), QColor("#ff0000"));
+ QCOMPARE_EQ(rule1.m_format.fontWeight(), QFont::Bold);
+ QCOMPARE_NE(rule1.m_format.fontItalic(), true);
+
+ // Check the second rule
+ const auto &rule2 = syntax->m_syntaxRules[1];
+ QCOMPARE_EQ(rule2.m_pattern.pattern(), "\\bfloat\\b");
+ QCOMPARE_EQ(rule2.m_format.foreground().color(), QColor("#00ff00"));
+ QCOMPARE_EQ(rule2.m_format.fontWeight(), QFont::Normal);
+ QCOMPARE_EQ(rule2.m_format.fontItalic(), true);
+}
+
+void TestSyntax::testLoadMissingKeywords()
+{
+ YAML::Node config;
+ config["other_section"] = YAML::Node();
+ syntax->loadSyntaxRules(config);
+
+ // Verify that no rules were loaded
+ QVERIFY(syntax->m_syntaxRules.isEmpty());
+}
+
+QTEST_MAIN(TestSyntax)
+#include "test_syntax.moc"
\ No newline at end of file
From 67e2423cc50c74e7792a33ec4c4691ef312a5769 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:13:09 -0700
Subject: [PATCH 097/160] =?UTF-8?q?=E2=9C=A8=20Add=20syntax=20configuratio?=
=?UTF-8?q?n=20files=20for=20C++,=20Go,=20Markdown,=20Python,=20and=20YAML?=
=?UTF-8?q?=20with=20keyword=20highlighting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
config/cpp.syntax.yaml | 32 ++++++++++++++++++++++++++++++++
config/go.syntax.yaml | 12 ++++++++++++
config/markdown.syntax.yaml | 7 +++++++
config/python.syntax.yaml | 21 +++++++++++++++++++++
config/yaml.syntax.yaml | 19 +++++++++++++++++++
5 files changed, 91 insertions(+)
create mode 100644 config/cpp.syntax.yaml
create mode 100644 config/go.syntax.yaml
create mode 100644 config/markdown.syntax.yaml
create mode 100644 config/python.syntax.yaml
create mode 100644 config/yaml.syntax.yaml
diff --git a/config/cpp.syntax.yaml b/config/cpp.syntax.yaml
new file mode 100644
index 0000000..f97b264
--- /dev/null
+++ b/config/cpp.syntax.yaml
@@ -0,0 +1,32 @@
+extensions: [cpp, c, h, hpp]
+
+keywords:
+ keyword:
+ - regex: "\\b(char|class|const|double|enum|explicit|friend|inline|int|long|namespace|operator|private|protected|public|short|signals|signed|slots|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|foreach)\\b"
+ color: "#003478"
+ bold: "true"
+ - regex: "\\b(for|while|do|if|else)\\b"
+ color: "#D9001D"
+ - regex: "(?
Date: Fri, 28 Mar 2025 17:13:54 -0700
Subject: [PATCH 098/160] :recycle: Refactor: Update CMake configuration to
improve YAML file handling and ensure proper linking of Qt components
---
CMakeLists.txt | 60 +++++++++++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 15 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 47f31ad..dba7f2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Set default build output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
+set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
# Detect operating system
if(WIN32)
@@ -47,8 +48,24 @@ endif()
# Set Qt path for find_package
set(CMAKE_PREFIX_PATH ${Qt_DIR})
-# Find Qt Widgets
-find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Widgets Test REQUIRED)
+# Find Qt components
+find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Core Widgets Test)
+
+# Locate yaml-cpp
+if(APPLE)
+ set(yaml-cpp_DIR "/opt/homebrew/Cellar/yaml-cpp/0.8.0/lib/cmake/yaml-cpp")
+endif()
+find_package(yaml-cpp REQUIRED CONFIG)
+
+# Copy YAML files to the build directory (non-macOS case)
+set(YAML_SOURCE_DIR ${CMAKE_SOURCE_DIR}/config)
+set(YAML_DEST_DIR ${CMAKE_BINARY_DIR}/config)
+file(MAKE_DIRECTORY ${YAML_DEST_DIR})
+file(GLOB YAML_FILES "${YAML_SOURCE_DIR}/*.yaml")
+
+foreach(YAML_FILE ${YAML_FILES})
+ file(COPY ${YAML_FILE} DESTINATION ${YAML_DEST_DIR})
+endforeach()
# Create the CodeAstra library
add_library(${TARGET_NAME}
@@ -56,27 +73,34 @@ add_library(${TARGET_NAME}
src/CodeEditor.cpp
src/Tree.cpp
src/FileManager.cpp
- src/Syntax/Syntax.cpp
- src/Syntax/SyntaxCpp.cpp
- src/Syntax/SyntaxGo.cpp
+ src/Syntax.cpp
+ src/SyntaxManager.cpp
include/MainWindow.h
include/CodeEditor.h
include/Tree.h
include/LineNumberArea.h
include/FileManager.h
- include/SyntaxManager.h
- include/Syntax/SyntaxCpp.h
- include/Syntax/SyntaxGo.h
- include/Syntax/Syntax.h
+ include/syntaxManager.h
+ include/syntax/Syntax.h
)
+# Link YAML-CPP to the CodeAstra library
+target_link_libraries(${TARGET_NAME} PRIVATE yaml-cpp)
+
# Create the executable for the application
-add_executable(${EXECUTABLE_NAME}
- src/main.cpp
-)
+add_executable(${EXECUTABLE_NAME} src/main.cpp)
+
+# Ensure YAML config files are copied into macOS app bundle
+# if(APPLE)
+# add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD
+# COMMAND ${CMAKE_COMMAND} -E make_directory "$/Contents/Resources/config"
+# COMMAND ${CMAKE_COMMAND} -E copy_directory "${YAML_SOURCE_DIR}" "$/Contents/Resources/config"
+# COMMENT "Copying YAML config files into macOS app bundle..."
+# )
+# endif()
# Link the main executable with the CodeAstra library and Qt libraries
-target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${TARGET_NAME} Qt${QT_MAJOR_VERSION}::Widgets)
+target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${TARGET_NAME} Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Widgets)
# Add the tests subdirectory
add_subdirectory(tests)
@@ -90,7 +114,7 @@ if(MSVC)
target_compile_options(${EXECUTABLE_NAME} PRIVATE /W4 /WX)
elseif(APPLE)
target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
- set_target_properties(${EXECUTABLE_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
+ # set_target_properties(${EXECUTABLE_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
else()
target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()
@@ -108,4 +132,10 @@ set_target_properties(${EXECUTABLE_NAME} PROPERTIES
)
# Link necessary Qt libraries to CodeAstra library
-target_link_libraries(${TARGET_NAME} PRIVATE Qt${QT_MAJOR_VERSION}::Widgets)
\ No newline at end of file
+target_link_libraries(${TARGET_NAME} PRIVATE Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Widgets)
+
+# Ensure correct linking of yaml-cpp (macOS)
+if(APPLE)
+ target_include_directories(${EXECUTABLE_NAME} PRIVATE /opt/homebrew/include)
+ target_link_directories(${EXECUTABLE_NAME} PRIVATE /opt/homebrew/lib)
+endif()
\ No newline at end of file
From 7de9a8b223fd795e440c982b14eadd42d9de21a3 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:14:10 -0700
Subject: [PATCH 099/160] :recycle: Update: Enhance output messages in Makefile
for clarity during build and uninstall processes
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 92474bb..10cfe39 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ all: build install
# Run CMake to build the project
build:
- @echo "Building project with CMake..."
+ @echo "Building $(PROJECT) with CMake..."
@mkdir -p $(BUILD_DIR)
@cd $(BUILD_DIR) && cmake $(CMAKE_OPTIONS)
@@ -21,7 +21,7 @@ clean:
# Uninstalling the software
uninstall: clean
- @echo "Uninstalling the software..."
+ @echo "Uninstalling $(PROJECT)..."
@rm -rf $(EXECUTABLE).app $(EXECUTABLE)d.app
@OS_NAME=$(shell uname -s 2>/dev/null || echo "Windows"); \
if [ "$$OS_NAME" = "Darwin" ]; then \
From 2fe8aa5822a377d15cd91e7f72ade44454adeefc Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:14:20 -0700
Subject: [PATCH 100/160] :recycle: Update: Add libyaml-cpp-dev to Dockerfile
dependencies for YAML support
---
Dockerfile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 7c3b361..b138b66 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -13,7 +13,8 @@ RUN apt-get install -y --no-install-recommends \
qt6-base-dev \
x11-utils \
x11-xserver-utils \
- xvfb
+ xvfb \
+ libyaml-cpp-dev
RUN rm -rf /var/lib/apt/lists/*
# Copy CodeAstra into the container
From d1f7288763357d846c7b8a85df53e92bd3a8f270 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:26:24 -0700
Subject: [PATCH 101/160] :fire: Remove: Delete Syntax class header file as
part of codebase cleanup
---
include/Syntax/Syntax.h | 63 -----------------------------------------
1 file changed, 63 deletions(-)
delete mode 100644 include/Syntax/Syntax.h
diff --git a/include/Syntax/Syntax.h b/include/Syntax/Syntax.h
deleted file mode 100644
index 25eb89c..0000000
--- a/include/Syntax/Syntax.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-/**
- * @class Syntax
- * @brief A custom syntax highlighter class that extends QSyntaxHighlighter to provide
- * syntax highlighting functionality based on user-defined rules.
- *
- * This class allows you to define syntax highlighting rules using regular expressions
- * and associated text formats. It applies these rules to text blocks to highlight
- * specific patterns.
- *
- * @note This class inherits the constructor from QSyntaxHighlighter.
- */
-class Syntax : public QSyntaxHighlighter
-{
- Q_OBJECT
-
-public:
- Syntax(QTextDocument *parent, const YAML::Node &config);
- ~Syntax() = default;
-
-protected:
- /**
- * @brief Highlights the given text block based on the defined syntax rules.
- *
- * @param text The text block to be highlighted.
- */
- void highlightBlock(const QString &text) override;
-
-public:
- /**
- * @struct SyntaxRule
- * @brief Represents a single syntax highlighting rule.
- *
- * A syntax rule consists of a regular expression pattern and a text format
- * to apply to matching text.
- */
- struct SyntaxRule
- {
- QRegularExpression m_pattern;
- QTextCharFormat m_format;
- };
-
- QVector m_syntaxRules;
-
- /**
- * @brief Adds a new syntax highlighting rule.
- *
- * This method allows you to define a new rule by specifying a regular expression
- * pattern and the corresponding text format.
- *
- * @param pattern The regular expression pattern for the rule.
- * @param format The text format to apply to matches of the pattern.
- */
- void addPattern(const QString &pattern, const QTextCharFormat &format);
-
- void loadSyntaxRules(const YAML::Node &config);
-};
\ No newline at end of file
From 90eb445434d14145cee395ad4c2bbf67561b0227 Mon Sep 17 00:00:00 2001
From: Chris
Date: Fri, 28 Mar 2025 17:27:08 -0700
Subject: [PATCH 102/160] :recycle: Refactor: Moved Syntax.h out of the syntax
directory (removed directory)
---
include/Syntax.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 include/Syntax.h
diff --git a/include/Syntax.h b/include/Syntax.h
new file mode 100644
index 0000000..25eb89c
--- /dev/null
+++ b/include/Syntax.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/**
+ * @class Syntax
+ * @brief A custom syntax highlighter class that extends QSyntaxHighlighter to provide
+ * syntax highlighting functionality based on user-defined rules.
+ *
+ * This class allows you to define syntax highlighting rules using regular expressions
+ * and associated text formats. It applies these rules to text blocks to highlight
+ * specific patterns.
+ *
+ * @note This class inherits the constructor from QSyntaxHighlighter.
+ */
+class Syntax : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ Syntax(QTextDocument *parent, const YAML::Node &config);
+ ~Syntax() = default;
+
+protected:
+ /**
+ * @brief Highlights the given text block based on the defined syntax rules.
+ *
+ * @param text The text block to be highlighted.
+ */
+ void highlightBlock(const QString &text) override;
+
+public:
+ /**
+ * @struct SyntaxRule
+ * @brief Represents a single syntax highlighting rule.
+ *
+ * A syntax rule consists of a regular expression pattern and a text format
+ * to apply to matching text.
+ */
+ struct SyntaxRule
+ {
+ QRegularExpression m_pattern;
+ QTextCharFormat m_format;
+ };
+
+ QVector m_syntaxRules;
+
+ /**
+ * @brief Adds a new syntax highlighting rule.
+ *
+ * This method allows you to define a new rule by specifying a regular expression
+ * pattern and the corresponding text format.
+ *
+ * @param pattern The regular expression pattern for the rule.
+ * @param format The text format to apply to matches of the pattern.
+ */
+ void addPattern(const QString &pattern, const QTextCharFormat &format);
+
+ void loadSyntaxRules(const YAML::Node &config);
+};
\ No newline at end of file
From b4e531ff7fe7470dc364ac5c5a8f516f82f2ab70 Mon Sep 17 00:00:00 2001
From: Chris