-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
open file file content goes into default tab
Signed-off-by: Remisa Yousefvand <[email protected]>
- Loading branch information
1 parent
d857443
commit e421e3d
Showing
7 changed files
with
300 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.