Skip to content

UI Design #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

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.

![CodeAstra Demo](assets/demo_ui.png)

> [!TIP]
>
> Join the [Matrix Server](https://matrix.to/#/#codeastra:matrix.org) for CodeAstra development log and discussion.
Expand Down
Binary file added assets/demo_ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion config/cxx.syntax.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ keywords:
- 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" # Dark Blue
bold: true
- regex: "\\b(for|while|do|if|else)\\b"
- regex: "\\b(for|while|do|if|else|return)\\b"
color: "#D9001D" # Bright Red
- regex: "(?<!\\w)#include(?!\\w)"
color: "#800080" # Purple
Expand Down
3 changes: 3 additions & 0 deletions include/Tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ class Tree : public QObject
std::unique_ptr<QFileIconProvider> m_iconProvider;
std::unique_ptr<QFileSystemModel> m_model;
std::unique_ptr<QTreeView> m_tree;

protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
1 change: 1 addition & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>resources/app_icon.png</file>
<file>resources/themes/dark.qss</file>
</qresource>
</RCC>
178 changes: 178 additions & 0 deletions resources/themes/dark.qss
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
* {
font-family: 'Fira Code', 'Menlo', 'Monaco', "Consolas", "Courier New", "Monospace";
font-size: 13pt;
}

QMainWindow {
background-color: #1a1a1a;
color: #ffffff;
border-radius: 8px;
}

QStatusBar {
background-color: #252525;
color: #e0e0e0;
border-top: 1px solid #383838;
font-size: 11pt;
padding: 6px 10px;
}

QTreeView {
background-color: #1e1e1e;
color: #e0e0e0;
padding: 6px;
border-radius: 6px;
}

QTreeView::item {
padding: 2px 4px;
}

QTreeView::item:selected {
background: #2b5ea3;
color: white;
border-radius: 4px;
}

QTreeView::item:hover {
background: #3c3c3c;
}

QTreeView::item:focus {
outline: none;
}

QScrollBar:vertical, QScrollBar:horizontal {
background: #1e1e1e;
width: 12px;
margin: 0px;
}

QScrollBar::handle {
background: #666666;
border-radius: 6px;
margin: 2px;
}

QScrollBar::handle:hover {
background: #888888;
}

QMenuBar {
background-color: #252525;
color: white;
padding: 6px 10px;
}

QMenu {
background-color: #2d2d2d;
color: white;
border: 1px solid #444444;
border-radius: 6px;
padding: 4px;
}

QMenu::item {
padding: 6px 20px;
border-radius: 4px;
}

QMenu::item:selected {
background-color: #3c3c3c;
}

QMenu::item:hover {
background-color: #454545;
}

QPlainTextEdit, QLineEdit {
background-color: #1e1e1e;
color: #e0e0e0;
border-radius: 6px;
padding: 8px;
border: 1px solid #333333;
}

QPlainTextEdit {
selection-background-color: #2b5ea3;
selection-color: white;
}

QPlainTextEdit:focus, QTreeView:focus {
border: 1px solid #3d75c2;
}

QTabBar::tab {
background: #2d2d2d;
color: #d4d4d4;
padding: 8px 16px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
margin-right: 2px;
}

QTabBar::tab:selected {
background: #1e1e1e;
color: white;
border-top: 2px solid #3d75c2;
}

QTabBar::tab:hover {
background: #353535;
}

QToolTip {
background-color: #2d2d2d;
color: #e0e0e0;
border: 1px solid #444444;
padding: 6px;
border-radius: 6px;
}

QPushButton {
background-color: #2b5ea3;
color: white;
border-radius: 6px;
padding: 8px 16px;
border: none;
}

QPushButton:hover {
background-color: #3d75c2;
}

QPushButton:pressed {
background-color: #214a80;
}

QComboBox {
background-color: #2d2d2d;
color: #e0e0e0;
border-radius: 6px;
padding: 6px;
border: 1px solid #444444;
}

QComboBox:hover {
border: 1px solid #3d75c2;
}

QComboBox::drop-down {
border: none;
}

QCheckBox {
color: #e0e0e0;
spacing: 8px;
}

QCheckBox::indicator {
width: 18px;
height: 18px;
border-radius: 4px;
border: 1px solid #444444;
}

QCheckBox::indicator:checked {
background-color: #2b5ea3;
}
12 changes: 7 additions & 5 deletions src/CodeEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
}
else if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Slash)
{
addComment();
addComment();
return;
}
else if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Backspace)
{
moveCursor(QTextCursor::WordLeft, QTextCursor::KeepAnchor);
textCursor().removeSelectedText();
textCursor().deletePreviousChar();
QTextCursor cursor = textCursor();
cursor.movePosition(QTextCursor::WordLeft, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
setTextCursor(cursor);

return;
}
else
Expand Down Expand Up @@ -263,7 +265,7 @@ void CodeEditor::highlightCurrentLine()
QTextEdit::ExtraSelection selection;

QColor lineColor = QColor(Qt::lightGray).lighter(60);
lineColor.setAlpha(100);
lineColor.setAlpha(80);

selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
Expand Down
6 changes: 5 additions & 1 deletion src/FileManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,11 @@ OperationResult FileManager::newFile(const QFileInfo &pathInfo, QString newFileP
file.close();
}

FileManager::getInstance().setCurrentFileName(QString::fromStdString(filePath.string()));
QString fileName = QString::fromStdString(filePath.string());

FileManager::getInstance().setCurrentFileName(fileName);
FileManager::getInstance().loadFileInEditor(fileName);

return {true, filePath.filename().string() + " created successfully."};
}

Expand Down
53 changes: 51 additions & 2 deletions src/Tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@
#include <filesystem>
#include <QMessageBox>
#include <QInputDialog>
#include <QApplication>
#include <QHeaderView>
#include <QMimeData>

Tree::Tree(QSplitter *splitter)
: QObject(splitter),
m_iconProvider(std::make_unique<QFileIconProvider>()),
m_model(std::make_unique<QFileSystemModel>()),
m_tree(std::make_unique<QTreeView>(splitter))
{
connect(m_tree.get(), &QTreeView::doubleClicked, this, &Tree::openFile);
connect(m_tree.get(), &QTreeView::clicked, this, &Tree::openFile);
}

Tree::~Tree() {}
Expand All @@ -33,18 +36,33 @@ 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);
m_model->setReadOnly(false);
}

void Tree::setupTree()
{
QFont baseFont = QApplication::font();
QFont treeFont = baseFont;
treeFont.setPointSize(baseFont.pointSize() - 1);

m_tree->setFont(treeFont);
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->setIndentation(16);
m_tree->setSortingEnabled(false);
m_tree->sortByColumn(1, Qt::AscendingOrder);
m_tree->setHeaderHidden(true);
m_tree->setUniformRowHeights(true);

// Configure file/folder drag & drop
m_tree->setDragDropMode(QAbstractItemView::InternalMove);
m_tree->setDragEnabled(true);
m_tree->setAcceptDrops(true);
m_tree->setDropIndicatorShown(true);
m_tree->setDefaultDropAction(Qt::MoveAction);
m_tree->setEditTriggers(QAbstractItemView::NoEditTriggers);

for (int i = 1; i <= m_model->columnCount(); ++i)
{
Expand All @@ -53,6 +71,37 @@ void Tree::setupTree()

m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_tree.get(), &QTreeView::customContextMenuRequested, this, &Tree::showContextMenu);

// Connect to dragEnter and dragMove events
m_tree->installEventFilter(this);
}

bool Tree::eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_tree.get())
{
if (event->type() == QEvent::DragEnter)
{
QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(event);
if (dragEvent->mimeData()->hasUrls())
{
dragEvent->acceptProposedAction();
return true;
}
}

else if (event->type() == QEvent::DragMove)
{
QDragMoveEvent *dragEvent = static_cast<QDragMoveEvent *>(event);
if (dragEvent->mimeData()->hasUrls())
{
dragEvent->acceptProposedAction();
return true;
}
}
}

return QObject::eventFilter(obj, event);
}

void Tree::openFile(const QModelIndex &index)
Expand Down
Loading
Loading