aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui/widgets/PlainTextEditorPage.cpp
diff options
context:
space:
mode:
authorSaturn&Eric <[email protected]>2022-03-19 07:55:26 +0000
committerGitHub <[email protected]>2022-03-19 07:55:26 +0000
commitd1e305cda3a8ddc066213f3309826caf29064423 (patch)
treefabeb080e66df2fe944011ba5690f680ebabe7b6 /src/ui/widgets/PlainTextEditorPage.cpp
parent<doc>(project): update README.md. (diff)
parentMerge branch 'main' into develop-2.0.5 (diff)
downloadGpgFrontend-d1e305cda3a8ddc066213f3309826caf29064423.tar.gz
GpgFrontend-d1e305cda3a8ddc066213f3309826caf29064423.zip
Merge pull request #49 from saturneric/develop-2.0.5
v2.0.5
Diffstat (limited to 'src/ui/widgets/PlainTextEditorPage.cpp')
-rw-r--r--src/ui/widgets/PlainTextEditorPage.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/ui/widgets/PlainTextEditorPage.cpp b/src/ui/widgets/PlainTextEditorPage.cpp
new file mode 100644
index 00000000..c70991b9
--- /dev/null
+++ b/src/ui/widgets/PlainTextEditorPage.cpp
@@ -0,0 +1,260 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]><[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/widgets/PlainTextEditorPage.h"
+
+#include <encoding-detect/TextEncodingDetect.h>
+
+#include <boost/format.hpp>
+#include <utility>
+
+#include "ui/thread/FileReadThread.h"
+#include "ui_PlainTextEditor.h"
+
+namespace GpgFrontend::UI {
+
+PlainTextEditorPage::PlainTextEditorPage(QString file_path, QWidget *parent)
+ : QWidget(parent),
+ ui_(std::make_shared<Ui_PlainTextEditor>()),
+ full_file_path_(std::move(file_path)) {
+ ui_->setupUi(this);
+
+ if (full_file_path_.isEmpty()) read_done_ = true;
+
+ ui_->textPage->setFocus();
+ ui_->loadingLabel->setHidden(true);
+
+ // Front in same width
+ this->setFont({"Courier"});
+ this->setAttribute(Qt::WA_DeleteOnClose);
+
+ this->ui_->characterLabel->setText(_("0 character"));
+ this->ui_->lfLabel->setText(_("None"));
+ this->ui_->encodingLabel->setText(_("Binary"));
+
+ connect(ui_->textPage, &QPlainTextEdit::textChanged, this, [=]() {
+ if (!read_done_) return;
+
+ auto text = ui_->textPage->document()->toPlainText();
+ auto str = boost::format(_("%1% character(s)")) % text.size();
+ this->ui_->characterLabel->setText(str.str().c_str());
+
+ detect_cr_lf(text);
+ detect_encoding(text.toStdString());
+ });
+
+ ui_->loadingLabel->setText(_("Loading..."));
+}
+
+const QString &PlainTextEditorPage::GetFilePath() const {
+ return full_file_path_;
+}
+
+QPlainTextEdit *PlainTextEditorPage::GetTextPage() { return ui_->textPage; }
+
+void PlainTextEditorPage::SetFilePath(const QString &filePath) {
+ full_file_path_ = filePath;
+}
+
+void PlainTextEditorPage::ShowNotificationWidget(QWidget *widget,
+ const char *className) {
+ widget->setProperty(className, true);
+ ui_->verticalLayout->addWidget(widget);
+}
+
+void PlainTextEditorPage::CloseNoteByClass(const char *className) {
+ QList<QWidget *> widgets = findChildren<QWidget *>();
+ for (QWidget *widget : widgets) {
+ if (widget->property(className) == true) {
+ widget->close();
+ }
+ }
+}
+
+void PlainTextEditorPage::slot_format_gpg_header() {
+ QString content = ui_->textPage->toPlainText();
+
+ // Get positions of the gpg-headers, if they exist
+ int start = content.indexOf(GpgFrontend::GpgConstants::PGP_SIGNED_BEGIN);
+ int startSig =
+ content.indexOf(GpgFrontend::GpgConstants::PGP_SIGNATURE_BEGIN);
+ int endSig = content.indexOf(GpgFrontend::GpgConstants::PGP_SIGNATURE_END);
+
+ if (start < 0 || startSig < 0 || endSig < 0 || sign_marked_) {
+ return;
+ }
+
+ sign_marked_ = true;
+
+ // Set the fontstyle for the header
+ QTextCharFormat signFormat;
+ signFormat.setForeground(QBrush(QColor::fromRgb(80, 80, 80)));
+ signFormat.setFontPointSize(9);
+
+ // set font style for the signature
+ QTextCursor cursor(ui_->textPage->document());
+ cursor.setPosition(startSig, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, endSig);
+ cursor.setCharFormat(signFormat);
+
+ // set the font style for the header
+ int headEnd = content.indexOf("\n\n", start);
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, headEnd);
+ cursor.setCharFormat(signFormat);
+}
+
+void PlainTextEditorPage::ReadFile() {
+ LOG(INFO) << "called";
+
+ read_done_ = false;
+ read_bytes_ = 0;
+ ui_->textPage->setEnabled(false);
+ ui_->textPage->setReadOnly(true);
+ ui_->textPage->blockSignals(true);
+ ui_->loadingLabel->setHidden(false);
+ ui_->textPage->document()->blockSignals(true);
+
+ auto text_page = this->GetTextPage();
+ text_page->setReadOnly(true);
+ auto thread = new FileReadThread(this->full_file_path_.toStdString());
+
+ connect(thread, &FileReadThread::SignalSendReadBlock, this,
+ &PlainTextEditorPage::slot_insert_text);
+
+ connect(thread, &FileReadThread::SignalReadDone, this, [=]() {
+ LOG(INFO) << "thread read done";
+ if (!binary_mode_) {
+ text_page->setReadOnly(false);
+ }
+ });
+
+ connect(thread, &FileReadThread::finished, this, [=]() {
+ LOG(INFO) << "thread finished";
+ thread->deleteLater();
+ read_done_ = true;
+ read_thread_ = nullptr;
+ ui_->textPage->setEnabled(true);
+ text_page->document()->setModified(false);
+ ui_->textPage->blockSignals(false);
+ ui_->textPage->document()->blockSignals(false);
+ ui_->loadingLabel->setHidden(true);
+ });
+
+ connect(this, &PlainTextEditorPage::destroyed, [=]() {
+ LOG(INFO) << "request interruption for read thread";
+ if (read_thread_ && thread->isRunning()) thread->requestInterruption();
+ read_thread_ = nullptr;
+ });
+ this->read_thread_ = thread;
+ thread->start();
+}
+
+std::string binary_to_string(const std::string &source) {
+ static char syms[] = "0123456789ABCDEF";
+ std::stringstream ss;
+ for (unsigned char c : source)
+ ss << syms[((c >> 4) & 0xf)] << syms[c & 0xf] << " ";
+ return ss.str();
+}
+
+void PlainTextEditorPage::slot_insert_text(const std::string &data) {
+ LOG(INFO) << "data size" << data.size();
+ read_bytes_ += data.size();
+ // If binary format is detected, the entire file is converted to binary format
+ // for display
+ bool if_last_binary_mode = binary_mode_;
+ if (!binary_mode_) {
+ detect_encoding(data);
+ }
+
+ if (binary_mode_) {
+ if (if_last_binary_mode != binary_mode_) {
+ auto text_buffer =
+ ui_->textPage->document()->toRawText().toLocal8Bit().toStdString();
+ ui_->textPage->clear();
+ this->GetTextPage()->insertPlainText(
+ binary_to_string(text_buffer).c_str());
+ this->ui_->lfLabel->setText("None");
+ }
+ this->GetTextPage()->insertPlainText(binary_to_string(data).c_str());
+
+ auto str = boost::format(_("%1% byte(s)")) % read_bytes_;
+ this->ui_->characterLabel->setText(str.str().c_str());
+ } else {
+ this->GetTextPage()->insertPlainText(data.c_str());
+
+ auto text = this->GetTextPage()->toPlainText();
+ auto str = boost::format(_("%1% character(s)")) % text.size();
+ this->ui_->characterLabel->setText(str.str().c_str());
+ detect_cr_lf(text);
+ }
+}
+
+void PlainTextEditorPage::PrepareToDestroy() {
+ if (read_thread_) {
+ read_thread_->requestInterruption();
+ read_thread_ = nullptr;
+ }
+}
+
+void PlainTextEditorPage::detect_encoding(const std::string &data) {
+ AutoIt::Common::TextEncodingDetect text_detect;
+ AutoIt::Common::TextEncodingDetect::Encoding encoding =
+ text_detect.DetectEncoding((unsigned char *)(data.data()), data.size());
+
+ if (encoding == AutoIt::Common::TextEncodingDetect::None) {
+ binary_mode_ = true;
+ ui_->encodingLabel->setText(_("Binary"));
+ } else if (encoding == AutoIt::Common::TextEncodingDetect::ASCII) {
+ ui_->encodingLabel->setText(_("ASCII(7 bits)"));
+ } else if (encoding == AutoIt::Common::TextEncodingDetect::ANSI) {
+ ui_->encodingLabel->setText(_("ASCII(8 bits)"));
+ } else if (encoding == AutoIt::Common::TextEncodingDetect::UTF8_BOM ||
+ encoding == AutoIt::Common::TextEncodingDetect::UTF8_NOBOM) {
+ ui_->encodingLabel->setText(_("UTF-8"));
+ } else if (encoding == AutoIt::Common::TextEncodingDetect::UTF16_LE_BOM ||
+ encoding == AutoIt::Common::TextEncodingDetect::UTF16_LE_NOBOM) {
+ ui_->encodingLabel->setText(_("UTF-16"));
+ } else if (encoding == AutoIt::Common::TextEncodingDetect::UTF16_BE_BOM ||
+ encoding == AutoIt::Common::TextEncodingDetect::UTF16_BE_NOBOM) {
+ ui_->encodingLabel->setText(_("UTF-16(BE)"));
+ }
+}
+
+void PlainTextEditorPage::detect_cr_lf(const QString &data) {
+ if (binary_mode_) {
+ this->ui_->lfLabel->setText("None");
+ return;
+ }
+ if (data.contains("\r\n")) {
+ this->ui_->lfLabel->setText("CRLF");
+ } else {
+ this->ui_->lfLabel->setText("LF");
+ }
+}
+
+} // namespace GpgFrontend::UI