diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index f2668b9..14bb7a7 100644 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Debug --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -159,14 +159,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Release --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} /data/Code/Qt/Notepad--/build/Desktop-Release @@ -215,14 +215,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} /data/Code/Qt/Notepad--/build/Desktop-RelWithDebInfo @@ -269,14 +269,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} 0 /data/Code/Qt/Notepad--/build/Desktop-Profile @@ -324,14 +324,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=MinSizeRel --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_BUILD_TYPE:STRING=MinSizeRel +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} /data/Code/Qt/Notepad--/build/Desktop-MinSizeRel diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0852004 --- /dev/null +++ b/LICENSE @@ -0,0 +1,174 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3, which is displayed below. + This license makes reference to the version 3 of the GNU General + Public License, which you can find in the LICENSE file. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright © 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies of this +licensedocument, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + + As used herein, “this License” refers to version 3 of the GNU Lesser +General Public License, and the “GNU GPL” refers to version 3 of the +GNU General Public License. + + “The Library” refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An “Application” is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A “Combined Work” is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the “Linked +Version”. + + The “Minimal Corresponding Source” for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The “Corresponding Application Code” for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort + to ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this + license document. + +4. Combined Works. + + You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of +the Library contained in the Combined Work and reverse engineering for +debugging such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this + license document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of + this License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (a) uses at run + time a copy of the Library already present on the user's + computer system, and (b) will operate properly with a modified + version of the Library that is interface-compatible with the + Linked Version. + + e) Provide Installation Information, but only if you would + otherwise be required to provide such information under section 6 + of the GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the Application + with a modified version of the Linked Version. (If you use option + 4d0, the Installation Information must accompany the Minimal + Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in + the manner specified by section 6 of the GNU GPL for conveying + Corresponding Source.) + +5. Combined Libraries. + + You may place library facilities that are a work based on the Library +side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities, conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of + it is a work based on the Library, and explaining where to find + the accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +as you received it specifies that a certain numbered version of the +GNU Lesser General Public License “or any later version” applies to +it, you have the option of following the terms and conditions either +of that published version or of any later version published by the +Free Software Foundation. If the Library as you received it does not +specify a version number of the GNU Lesser General Public License, +you may choose any version of the GNU Lesser General Public License +ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the Library. diff --git a/README.md b/README.md index f156221..85d252b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Notepad-- +![gui](assets/lgplv3.png) + A simple light text editor. Notepadqq was my choice editor. Unfortunately it doesn't maintain anymore. I tried to help but there was old PRs and plenty of unanswered issues. The project was a mix of C++/Qt/Javascript/HTML,CSS,Python... It is a while I didn't code in C++ and my knowledge of Qt is a little. All that said this is a **toy** project, at least for a while. The -- (minus minus) indicates that this is a minimalistic project. I will design GUI just like Notepadqq so there is no new GUI learning. For now I just release for Linux which has Qt6 installed (dynamic compile). diff --git a/assets/lgplv3.png b/assets/lgplv3.png new file mode 100644 index 0000000..012f011 Binary files /dev/null and b/assets/lgplv3.png differ diff --git a/document.cpp b/document.cpp index baacd2c..c89c10c 100644 --- a/document.cpp +++ b/document.cpp @@ -1,11 +1,14 @@ #include "document.h" #include "codeeditor.h" +#include "languages/languagemanager.h" #include #include #include #include #include #include +#include +#include Document::Document(const QString &filePath, QWidget *parent) : QWidget(parent), m_filePath(filePath), m_fileSize(0), m_startPointer(0), m_endPointer(0), syntaxHighlighter(nullptr) { @@ -73,24 +76,24 @@ void Document::openFile(const QString &filePath) { setFilePath(filePath); m_fileSize = m_file.size(); - m_startPointer = 0; - m_endPointer = qMin(m_fileSize, m_startPointer + 1024 * 1024); // Load first 1MB - loadContent(); + // Load the entire file content for simplicity + QByteArray content = m_file.readAll(); + editor->setPlainText(QString::fromUtf8(content)); + editor->moveCursor(QTextCursor::Start); // Calculate the original hash of the file asynchronously QtConcurrent::run([this]() { m_originalHash = calculateMD5Stream(&m_file); + qDebug() << "Original MD5 calculated:" << m_originalHash.toHex(); }); -} -void Document::loadContent() { - if (!m_file.isOpen()) return; + m_file.close(); +} - m_file.seek(m_startPointer); - QByteArray content = m_file.read(m_endPointer - m_startPointer); - editor->setPlainText(QString::fromUtf8(content)); - editor->moveCursor(QTextCursor::Start); +void Document::trackChanges() { + // Basic change tracking (full document, for simplicity) + m_currentText = editor->toPlainText(); } void Document::updatePointers() { @@ -113,9 +116,33 @@ void Document::updatePointers() { } } -void Document::trackChanges() { - m_currentText = editor->toPlainText(); - m_changedSegments[m_startPointer] = m_currentText; +void Document::loadContent() { + if (!m_file.isOpen()) { + qDebug() << "File is not open, cannot load content."; + return; + } + + // Calculate the size of the portion to read + qint64 bytesToRead = m_endPointer - m_startPointer; + + // Ensure the reading is within bounds + if (m_startPointer < 0 || m_startPointer >= m_fileSize || bytesToRead <= 0) { + qDebug() << "Invalid pointers or no data to read."; + return; + } + + m_file.seek(m_startPointer); // Seek to the start pointer + + QByteArray content = m_file.read(bytesToRead); + if (content.isEmpty()) { + qDebug() << "No content read from the file."; + return; + } + + editor->setPlainText(QString::fromUtf8(content)); // Set content to the editor + editor->moveCursor(QTextCursor::Start); // Move cursor to the start of the document + + qDebug() << "File content loaded successfully. Start pointer:" << m_startPointer << ", End pointer:" << m_endPointer; } void Document::saveFile() { @@ -130,16 +157,15 @@ void Document::saveFile() { return; } - // Use QTextStream for writing QTextStream out(&file); - out << editor->toPlainText(); // Write the entire content of the editor to the file - - // After saving, calculate the new hash asynchronously - QtConcurrent::run([this]() { - m_originalHash = calculateMD5Stream(&m_file); - }); + out << editor->toPlainText(); file.close(); + + // Recalculate and store the MD5 hash of the saved file + m_originalHash = calculateMD5Stream(&file); + + qDebug() << "File saved. New MD5:" << m_originalHash.toHex(); } void Document::saveFileAs(const QString &newFilePath) { @@ -152,31 +178,34 @@ void Document::saveFileAs(const QString &newFilePath) { QByteArray Document::calculateMD5Stream(QFile *file) { QCryptographicHash hash(QCryptographicHash::Md5); - file->seek(0); + if (!file->isOpen()) { + if (!file->open(QIODevice::ReadOnly)) { + qDebug() << "Failed to open file for MD5 calculation:" << file->errorString(); + return QByteArray(); + } + } + + file->seek(0); // Ensure we start from the beginning of the file - QByteArray buffer; + // Read the entire file content and update the hash while (!file->atEnd()) { - buffer = file->read(1024 * 1024); // Read in chunks + QByteArray buffer = file->read(1024 * 1024); // Read in chunks (1MB here) hash.addData(buffer); } - return hash.result(); + file->close(); // Close the file if it was opened here + return hash.result(); // Return the calculated MD5 hash } QByteArray Document::calculateModifiedMD5() { - QString currentContent = editor->toPlainText(); - QCryptographicHash hash(QCryptographicHash::Md5); - hash.addData(currentContent.toUtf8()); - return hash.result(); + QFile file(m_filePath); + return calculateMD5Stream(&file); } bool Document::closeDocument() { - // Special case: if the document is empty, allow closing without checking the hash - if (editor->toPlainText().isEmpty() && m_filePath.isEmpty()) { - return true; - } - QByteArray currentHash = calculateModifiedMD5(); + qDebug() << "Original MD5:" << m_originalHash.toHex(); + qDebug() << "Current MD5:" << currentHash.toHex(); if (currentHash != m_originalHash) { QMessageBox::StandardButton reply; @@ -185,20 +214,16 @@ bool Document::closeDocument() { QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); if (reply == QMessageBox::Save) { - QString savePath = QFileDialog::getSaveFileName(this, tr("Save File As"), "", tr("Text Files (*.txt);;All Files (*)")); - if (savePath.isEmpty()) { - return false; // User canceled the Save As dialog, don't close the document - } - saveFileAs(savePath); + saveFile(); return true; } else if (reply == QMessageBox::Discard) { - return true; // Allow closing without saving + return true; } else { - return false; // Cancel closing + return false; } } - return true; // No unsaved changes, allow closing + return true; } void Document::goToLineNumberInEditor() { @@ -210,20 +235,18 @@ void Document::goToLineNumberInEditor() { QTextCursor cursor = editor->textCursor(); cursor.movePosition(QTextCursor::Start); // Move to the start of the editor - // Move the cursor down to the desired line number for (int i = 1; i < lineNumber; ++i) { cursor.movePosition(QTextCursor::Down); - // Check if the cursor has moved to the end of the document if (cursor.atEnd()) { QMessageBox::warning(this, tr("Line Number Out of Bounds"), tr("The specified line number is outside the bounds of the file.")); - return; // Exit if the line number is out of bounds + return; } } editor->setTextCursor(cursor); - editor->ensureCursorVisible(); // Ensure the cursor is visible after moving + editor->ensureCursorVisible(); } } diff --git a/examples/1GBfile.sh b/examples/1GBfile.sh index 7641cce..69bf450 100755 --- a/examples/1GBfile.sh +++ b/examples/1GBfile.sh @@ -1,16 +1,7 @@ #!/usr/bin/env bash -file="1GB.txt" +output_file="1GB.txt" -# Define the size in byte -s (1 GB) size=$((1 * 1024 * 1024 * 1024)) - -# Generate the random file < /dev/urandom -tr -dc 'a-zA-Z0-9 ' | head -c "$size" > "$file" +base64 /dev/urandom | head -c 1073741824 > "$output_file" echo "Done!" - - - - -