Skip to content

Commit

Permalink
open file file content goes into default tab
Browse files Browse the repository at this point in the history
Signed-off-by: Remisa Yousefvand <[email protected]>
  • Loading branch information
yousefvand committed Aug 12, 2024
1 parent d857443 commit e421e3d
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 52 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ else()
else()
add_executable(Notepad--
${PROJECT_SOURCES}
CodeEditor.h CodeEditor.cpp
codeeditor.h codeeditor.cpp
document.h document.cpp
)
endif()
Expand Down
42 changes: 21 additions & 21 deletions CMakeLists.txt.user
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 14.0.1, 2024-08-12T04:29:33. -->
<!-- Written by QtCreator 14.0.1, 2024-08-12T16:37:31. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
Expand Down Expand Up @@ -102,13 +102,13 @@
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_BUILD_TYPE:STRING=Debug
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/data/Code/Qt/Notepad--/build/Desktop-Debug</value>
Expand Down Expand Up @@ -159,13 +159,13 @@
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_BUILD_TYPE:STRING=Release
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/data/Code/Qt/Notepad--/build/Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
Expand Down Expand Up @@ -215,13 +215,13 @@
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/data/Code/Qt/Notepad--/build/Desktop-RelWithDebInfo</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
Expand Down Expand Up @@ -269,13 +269,13 @@
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/data/Code/Qt/Notepad--/build/Desktop-Profile</value>
Expand Down Expand Up @@ -324,13 +324,13 @@
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_BUILD_TYPE:STRING=MinSizeRel
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/data/Code/Qt/Notepad--/build/Desktop-MinSizeRel</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
Expand Down
145 changes: 145 additions & 0 deletions codeeditor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#include "codeeditor.h"
#include <QPainter>
#include <QTextBlock>

CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent), lineNumberArea(new LineNumberArea(this))
{
// Set text color to black
QPalette p = this->palette();
p.setColor(QPalette::Text, Qt::black);
this->setPalette(p);

// Set background color to white
this->setStyleSheet("QPlainTextEdit { background-color: white; }");

// Set a monospaced font
QFont font;
font.setFamily("Sans Serif"); // Monospaced font
font.setFixedPitch(true);
font.setPointSize(12); // Adjust size if necessary
this->setFont(font);

connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);

updateLineNumberAreaWidth(0);
highlightCurrentLine();
}

int CodeEditor::lineNumberAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}

// Ensure there's enough space for numbers
int space = 5 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;

return space;
}

void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
{
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}

void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
if (dy)
lineNumberArea->scroll(0, dy);
else
lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());

if (rect.contains(viewport()->rect()))
updateLineNumberAreaWidth(0);
}

void CodeEditor::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);

QRect cr = contentsRect();
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}

void CodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;

if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;

QColor lineColor = QColor(Qt::yellow).lighter(160);

selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}

setExtraSelections(extraSelections);
}

void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(lineNumberArea);
painter.fillRect(event->rect(), Qt::lightGray);

QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = static_cast<int>(blockBoundingGeometry(block).translated(contentOffset()).top());
int bottom = top + static_cast<int>(blockBoundingRect(block).height());

// Get the current line number
int currentLineNumber = textCursor().blockNumber();

// Loop through each block and draw line numbers
while (block.isValid() && top <= event->rect().bottom()) {
if (block.isVisible() && bottom >= event->rect().top()) {
QString number = QString::number(blockNumber + 1);

// Check if this is the current line
if (blockNumber == currentLineNumber) {
// Set bold font for the current line number
QFont boldFont = painter.font();
boldFont.setBold(true);
painter.setFont(boldFont);
painter.setPen(Qt::blue); // Optional: change color for current line number
} else {
// Use normal font for other line numbers
painter.setFont(QFont());
painter.setPen(Qt::black);
}

// Draw the line number
painter.drawText(-5, top, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight | Qt::AlignVCenter, number);

// Check if the block has wrapped lines
QTextLayout *layout = block.layout();
for (int i = 0; i < layout->lineCount(); ++i) {
QTextLine line = layout->lineAt(i);
int lineTop = top + static_cast<int>(line.y());
int lineBottom = lineTop + static_cast<int>(line.height());

// If the line is within the visible area and it's not the first line, draw a return symbol
if (i > 0 && lineTop >= event->rect().top() && lineBottom <= event->rect().bottom()) {
painter.setPen(Qt::black); // Set color to black for the return symbol
painter.drawText(-5, lineTop, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight | Qt::AlignVCenter, "");
}
}
}

block = block.next();
top = bottom;
bottom = top + static_cast<int>(blockBoundingRect(block).height());
++blockNumber;
}
}
55 changes: 55 additions & 0 deletions codeeditor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef CODEEDITOR_H
#define CODEEDITOR_H

#include <QPlainTextEdit>

class QPaintEvent;
class QResizeEvent;
class QSize;
class QWidget;

class LineNumberArea;

class CodeEditor : public QPlainTextEdit
{
Q_OBJECT

public:
CodeEditor(QWidget *parent = nullptr);

void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();

protected:
void resizeEvent(QResizeEvent *event) override;

private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateLineNumberArea(const QRect &rect, int dy);

private:
QWidget *lineNumberArea;
};

class LineNumberArea : public QWidget
{
public:
LineNumberArea(CodeEditor *editor) : QWidget(editor), codeEditor(editor) {}

QSize sizeHint() const override
{
return QSize(codeEditor->lineNumberAreaWidth(), 0);
}

protected:
void paintEvent(QPaintEvent *event) override
{
codeEditor->lineNumberAreaPaintEvent(event);
}

private:
CodeEditor *codeEditor;
};

#endif // CODEEDITOR_H
47 changes: 33 additions & 14 deletions document.cpp
Original file line number Diff line number Diff line change
@@ -1,54 +1,73 @@
#include "document.h"
#include "codeeditor.h" // Updated to match the new filename
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QFileInfo>
#include <QVBoxLayout>

Document::Document(QWidget *parent) : QWidget(parent), filePath("") {
Document::Document(const QString &filePath, QWidget *parent)
: QWidget(parent), m_filePath(filePath), m_content("") {
editor = new CodeEditor(this); // Initialize the CodeEditor
QVBoxLayout *layout = new QVBoxLayout(this); // Create a vertical layout
layout->addWidget(editor); // Add the editor to the layout
setLayout(layout); // Set the layout for this Document widget

if (!filePath.isEmpty()) {
openFile(filePath); // Open the file if a path is provided
}
}

Document::Document(const QString &filePath, QWidget *parent) : QWidget(parent), filePath(filePath) {
editor = new CodeEditor(this); // Initialize the CodeEditor
QVBoxLayout *layout = new QVBoxLayout(this); // Create a vertical layout
layout->addWidget(editor); // Add the editor to the layout
setLayout(layout); // Set the layout for this Document widget
openFile(filePath); // Open the file
// Getter for m_filePath
QString Document::filePath() const {
return m_filePath;
}

// Setter for m_filePath
void Document::setFilePath(const QString &path) {
m_filePath = path;
}

// Getter for m_content
QString Document::content() const {
return m_content;
}

// Setter for m_content
void Document::setContent(const QString &content) {
m_content = content;
editor->setPlainText(content); // Update the editor with the new content
}

void Document::openFile(const QString &filePath) {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
QString content = in.readAll();
editor->setPlainText(content); // Set the editor's content
this->filePath = filePath; // Set file path
m_content = in.readAll();
editor->setPlainText(m_content); // Set the editor's content
m_filePath = filePath; // Set file path
} else {
QMessageBox::warning(this, tr("Error"), tr("Cannot open file: ") + file.errorString());
}
}

void Document::saveFile() {
if (filePath.isEmpty()) {
if (m_filePath.isEmpty()) {
QMessageBox::warning(this, tr("Error"), tr("No file path associated with this document."));
return; // No path to save
}

QFile file(filePath);
QFile file(m_filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << editor->toPlainText(); // Get text from editor
file.close();
m_content = editor->toPlainText(); // Update m_content
} else {
QMessageBox::warning(this, tr("Error"), tr("Cannot save file: ") + file.errorString());
}
}

void Document::saveFileAs(const QString &newFilePath) {
filePath = newFilePath; // Update the current file path
m_filePath = newFilePath; // Update the current file path
saveFile(); // Call saveFile to handle the saving
}
Loading

0 comments on commit e421e3d

Please sign in to comment.