aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ui/CMakeLists.txt1
-rw-r--r--src/ui/FindWidget.cpp52
-rw-r--r--src/ui/FindWidget.h8
-rw-r--r--src/ui/details/VerifyDetailsDialog.h2
-rw-r--r--src/ui/encoding/TextEncodingDetect.cpp313
-rw-r--r--src/ui/encoding/TextEncodingDetect.h85
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp33
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp8
-rw-r--r--src/ui/thread/FileReadThread.cpp24
-rw-r--r--src/ui/thread/FileReadThread.h2
-rw-r--r--src/ui/widgets/EditorPage.cpp154
-rw-r--r--src/ui/widgets/InfoBoardWidget.h2
-rw-r--r--src/ui/widgets/PlainTextEditorPage.cpp257
-rw-r--r--src/ui/widgets/PlainTextEditorPage.h (renamed from src/ui/widgets/EditorPage.h)27
-rw-r--r--src/ui/widgets/TextEdit.cpp60
-rw-r--r--src/ui/widgets/TextEdit.h6
-rw-r--r--ui/FilePage.ui15
-rw-r--r--ui/PlainTextEditor.ui79
18 files changed, 869 insertions, 259 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 59cc99bf..32edb262 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -10,6 +10,7 @@ aux_source_directory(./settings UI_SOURCE)
aux_source_directory(./thread UI_SOURCE)
aux_source_directory(./details UI_SOURCE)
aux_source_directory(./data_struct UI_SOURCE)
+aux_source_directory(./encoding UI_SOURCE)
if (SMTP_SUPPORT)
aux_source_directory(./smtp UI_SOURCE)
diff --git a/src/ui/FindWidget.cpp b/src/ui/FindWidget.cpp
index 6326b119..b95859a1 100644
--- a/src/ui/FindWidget.cpp
+++ b/src/ui/FindWidget.cpp
@@ -26,8 +26,8 @@
namespace GpgFrontend::UI {
-FindWidget::FindWidget(QWidget* parent, QTextEdit* edit) : QWidget(parent) {
- mTextpage = edit;
+FindWidget::FindWidget(QWidget* parent, PlainTextEditorPage* edit)
+ : QWidget(parent), mTextpage(edit) {
findEdit = new QLineEdit(this);
auto* closeButton = new QPushButton(
this->style()->standardIcon(QStyle::SP_TitleBarCloseButton), QString(),
@@ -55,12 +55,13 @@ FindWidget::FindWidget(QWidget* parent, QTextEdit* edit) : QWidget(parent) {
}
void FindWidget::setBackground() {
- QTextCursor cursor = mTextpage->textCursor();
+ auto cursor = mTextpage->getTextPage()->textCursor();
// if match is found set background of QLineEdit to white, otherwise to red
QPalette bgPalette(findEdit->palette());
if (!findEdit->text().isEmpty() &&
- mTextpage->document()->find(findEdit->text()).position() < 0) {
+ mTextpage->getTextPage()->document()->find(findEdit->text()).position() <
+ 0) {
bgPalette.setColor(QPalette::Base, "#ececba");
} else {
bgPalette.setColor(QPalette::Base, Qt::white);
@@ -69,45 +70,45 @@ void FindWidget::setBackground() {
}
void FindWidget::slotFindNext() {
- QTextCursor cursor = mTextpage->textCursor();
- cursor = mTextpage->document()->find(findEdit->text(), cursor,
- QTextDocument::FindCaseSensitively);
+ QTextCursor cursor = mTextpage->getTextPage()->textCursor();
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
// if end of document is reached, restart search from beginning
if (cursor.position() == -1) {
- cursor = mTextpage->document()->find(findEdit->text(), cursor,
- QTextDocument::FindCaseSensitively);
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
}
// cursor should not stay at -1, otherwise text is not editable
// todo: check how gedit handles this
if (cursor.position() != -1) {
- mTextpage->setTextCursor(cursor);
+ mTextpage->getTextPage()->setTextCursor(cursor);
}
this->setBackground();
}
void FindWidget::slotFind() {
- QTextCursor cursor = mTextpage->textCursor();
+ QTextCursor cursor = mTextpage->getTextPage()->textCursor();
if (cursor.anchor() == -1) {
- cursor = mTextpage->document()->find(findEdit->text(), cursor,
- QTextDocument::FindCaseSensitively);
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
} else {
- cursor = mTextpage->document()->find(findEdit->text(), cursor.anchor(),
- QTextDocument::FindCaseSensitively);
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), cursor.anchor(), QTextDocument::FindCaseSensitively);
}
// if end of document is reached, restart search from beginning
if (cursor.position() == -1) {
- cursor = mTextpage->document()->find(findEdit->text(), cursor,
- QTextDocument::FindCaseSensitively);
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), cursor, QTextDocument::FindCaseSensitively);
}
// cursor should not stay at -1, otherwise text is not editable
// todo: check how gedit handles this
if (cursor.position() != -1) {
- mTextpage->setTextCursor(cursor);
+ mTextpage->getTextPage()->setTextCursor(cursor);
}
this->setBackground();
}
@@ -117,19 +118,20 @@ void FindWidget::slotFindPrevious() {
flags |= QTextDocument::FindBackward;
flags |= QTextDocument::FindCaseSensitively;
- QTextCursor cursor = mTextpage->textCursor();
- cursor = mTextpage->document()->find(findEdit->text(), cursor, flags);
+ QTextCursor cursor = mTextpage->getTextPage()->textCursor();
+ cursor = mTextpage->getTextPage()->document()->find(findEdit->text(), cursor,
+ flags);
// if begin of document is reached, restart search from end
if (cursor.position() == -1) {
- cursor =
- mTextpage->document()->find(findEdit->text(), QTextCursor::End, flags);
+ cursor = mTextpage->getTextPage()->document()->find(
+ findEdit->text(), QTextCursor::End, flags);
}
// cursor should not stay at -1, otherwise text is not editable
// todo: check how gedit handles this
if (cursor.position() != -1) {
- mTextpage->setTextCursor(cursor);
+ mTextpage->getTextPage()->setTextCursor(cursor);
}
this->setBackground();
}
@@ -150,11 +152,11 @@ void FindWidget::keyPressEvent(QKeyEvent* e) {
}
void FindWidget::slotClose() {
- QTextCursor cursor = mTextpage->textCursor();
+ QTextCursor cursor = mTextpage->getTextPage()->textCursor();
if (cursor.position() == -1) {
cursor.setPosition(0);
- mTextpage->setTextCursor(cursor);
+ mTextpage->getTextPage()->setTextCursor(cursor);
}
mTextpage->setFocus();
close();
diff --git a/src/ui/FindWidget.h b/src/ui/FindWidget.h
index e4cbdaab..bc412012 100644
--- a/src/ui/FindWidget.h
+++ b/src/ui/FindWidget.h
@@ -26,7 +26,7 @@
#define FINDWIDGET_H
#include "ui/GpgFrontendUI.h"
-#include "ui/widgets/EditorPage.h"
+#include "ui/widgets/PlainTextEditorPage.h"
namespace GpgFrontend::UI {
@@ -42,7 +42,7 @@ class FindWidget : public QWidget {
*
* @param parent The parent widget
*/
- explicit FindWidget(QWidget* parent, QTextEdit* edit);
+ explicit FindWidget(QWidget* parent, PlainTextEditorPage* edit);
private:
void keyPressEvent(QKeyEvent* e) override;
@@ -53,8 +53,8 @@ class FindWidget : public QWidget {
*/
void setBackground();
- QTextEdit* mTextpage; /** Textedit associated to the notification */
- QLineEdit* findEdit; /** Label holding the text shown in infoBoard */
+ PlainTextEditorPage* mTextpage; /** Textedit associated to the notification */
+ QLineEdit* findEdit; /** Label holding the text shown in infoBoard */
private slots:
diff --git a/src/ui/details/VerifyDetailsDialog.h b/src/ui/details/VerifyDetailsDialog.h
index 5de648f6..21affdb4 100644
--- a/src/ui/details/VerifyDetailsDialog.h
+++ b/src/ui/details/VerifyDetailsDialog.h
@@ -26,7 +26,7 @@
#define __VERIFYDETAILSDIALOG_H__
#include "ui/GpgFrontendUI.h"
-#include "ui/widgets/EditorPage.h"
+#include "ui/widgets/PlainTextEditorPage.h"
#include "ui/widgets/VerifyKeyDetailBox.h"
namespace GpgFrontend::UI {
diff --git a/src/ui/encoding/TextEncodingDetect.cpp b/src/ui/encoding/TextEncodingDetect.cpp
new file mode 100644
index 00000000..22ae5897
--- /dev/null
+++ b/src/ui/encoding/TextEncodingDetect.cpp
@@ -0,0 +1,313 @@
+//
+// Copyright 2015-2016 Jonathan Bennett <[email protected]>
+//
+// https://www.autoitscript.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Includes
+#include "TextEncodingDetect.h"
+
+using namespace AutoIt::Common;
+
+static const unsigned char TextEncodingDetect_UTF16_BOM_LE[] = {
+ (unsigned char)(0xFF), (unsigned char)(0xFE)};
+static const unsigned char TextEncodingDetect_UTF16_BOM_BE[] = {
+ (unsigned char)(0xFE), (unsigned char)(0xFF)};
+static const unsigned char TextEncodingDetect_UTF8_BOM[] = {
+ (unsigned char)(0xEF), (unsigned char)(0xBB), (unsigned char)(0xBF)};
+
+const unsigned char *TextEncodingDetect::utf16_bom_le_ =
+ TextEncodingDetect_UTF16_BOM_LE;
+const unsigned char *TextEncodingDetect::utf16_bom_be_ =
+ TextEncodingDetect_UTF16_BOM_BE;
+const unsigned char *TextEncodingDetect::utf8_bom_ =
+ TextEncodingDetect_UTF8_BOM;
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructor()
+// Default constructor
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::TextEncodingDetect() {
+ // By default, assume nulls can't appear in ANSI/ASCII/UTF8 text files
+ null_suggests_binary_ = true;
+
+ // Set defaults for utf16 detection based the use of odd/even nulls
+ utf16_expected_null_percent_ = 70;
+ utf16_unexpected_null_percent_ = 10;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Set the percentages used in utf16 detection using nulls.
+///////////////////////////////////////////////////////////////////////////////
+
+void TextEncodingDetect::SetUtf16UnexpectedNullPercent(int percent) {
+ if (percent > 0 && percent < 100) utf16_expected_null_percent_ = percent;
+}
+
+void TextEncodingDetect::SetUtf16ExpectedNullPercent(int percent) {
+ if (percent > 0 && percent < 100) utf16_unexpected_null_percent_ = percent;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Simple function to return the length of the BOM for a particular encoding
+// mode.
+///////////////////////////////////////////////////////////////////////////////
+
+int TextEncodingDetect::GetBOMLengthFromEncodingMode(Encoding encoding) {
+ int length = 0;
+
+ if (encoding == UTF16_BE_BOM || encoding == UTF16_LE_BOM)
+ length = 2;
+ else if (encoding == UTF8_BOM)
+ length = 3;
+
+ return length;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains a valid BOM and returns the encoding based on it.
+// Returns encoding "None" if there is no BOM.
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::Encoding TextEncodingDetect::CheckBOM(
+ const unsigned char *pBuffer, size_t size) {
+ // Check for BOM
+ if (size >= 2 && pBuffer[0] == utf16_bom_le_[0] &&
+ pBuffer[1] == utf16_bom_le_[1]) {
+ return UTF16_LE_BOM;
+ } else if (size >= 2 && pBuffer[0] == utf16_bom_be_[0] &&
+ pBuffer[1] == utf16_bom_be_[1]) {
+ return UTF16_BE_BOM;
+ } else if (size >= 3 && pBuffer[0] == utf8_bom_[0] &&
+ pBuffer[1] == utf8_bom_[1] && pBuffer[2] == utf8_bom_[2]) {
+ return UTF8_BOM;
+ } else {
+ return None;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains a valid BOM and returns the encoding based on it.
+// If it doesn't contain a BOM it tries to guess what the encoding is or
+// "None" if it just looks like binary data.
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::Encoding TextEncodingDetect::DetectEncoding(
+ const unsigned char *pBuffer, size_t size) const {
+ // First check if we have a BOM and return that if so
+ Encoding encoding = CheckBOM(pBuffer, size);
+ if (encoding != None) return encoding;
+
+ // Now check for valid UTF8
+ encoding = CheckUTF8(pBuffer, size);
+ if (encoding != None) return encoding;
+
+ // Now try UTF16
+ encoding = CheckUTF16NewlineChars(pBuffer, size);
+ if (encoding != None) return encoding;
+
+ encoding = CheckUTF16ASCII(pBuffer, size);
+ if (encoding != None) return encoding;
+
+ // ANSI or None (binary) then
+ if (!DoesContainNulls(pBuffer, size))
+ return ANSI;
+ else {
+ // Found a null, return based on the preference in null_suggests_binary_
+ if (null_suggests_binary_)
+ return None;
+ else
+ return ANSI;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains valid utf8. Returns:
+// None - not valid utf8
+// UTF8_NOBOM - valid utf8 encodings and multibyte sequences
+// ASCII - Only data in the 0-127 range.
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::Encoding TextEncodingDetect::CheckUTF8(
+ const unsigned char *pBuffer, size_t size) const {
+ // UTF8 Valid sequences
+ // 0xxxxxxx ASCII
+ // 110xxxxx 10xxxxxx 2-byte
+ // 1110xxxx 10xxxxxx 10xxxxxx 3-byte
+ // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4-byte
+ //
+ // Width in UTF8
+ // Decimal Width
+ // 0-127 1 byte
+ // 194-223 2 bytes
+ // 224-239 3 bytes
+ // 240-244 4 bytes
+ //
+ // Subsequent chars are in the range 128-191
+
+ bool only_saw_ascii_range = true;
+ size_t pos = 0;
+ int more_chars;
+
+ while (pos < size) {
+ unsigned char ch = pBuffer[pos++];
+
+ if (ch == 0 && null_suggests_binary_) {
+ return None;
+ } else if (ch <= 127) {
+ // 1 byte
+ more_chars = 0;
+ } else if (ch >= 194 && ch <= 223) {
+ // 2 Byte
+ more_chars = 1;
+ } else if (ch >= 224 && ch <= 239) {
+ // 3 Byte
+ more_chars = 2;
+ } else if (ch >= 240 && ch <= 244) {
+ // 4 Byte
+ more_chars = 3;
+ } else {
+ return None; // Not utf8
+ }
+
+ // Check secondary chars are in range if we are expecting any
+ while (more_chars && pos < size) {
+ only_saw_ascii_range = false; // Seen non-ascii chars now
+
+ ch = pBuffer[pos++];
+ if (ch < 128 || ch > 191) return None; // Not utf8
+
+ --more_chars;
+ }
+ }
+
+ // If we get to here then only valid UTF-8 sequences have been processed
+
+ // If we only saw chars in the range 0-127 then we can't assume UTF8 (the
+ // caller will need to decide)
+ if (only_saw_ascii_range)
+ return ASCII;
+ else
+ return UTF8_NOBOM;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains text that looks like utf16 by scanning for
+// newline chars that would be present even in non-english text.
+// Returns:
+// None - not valid utf16
+// UTF16_LE_NOBOM - looks like utf16 le
+// UTF16_BE_NOBOM - looks like utf16 be
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::Encoding TextEncodingDetect::CheckUTF16NewlineChars(
+ const unsigned char *pBuffer, size_t size) {
+ if (size < 2) return None;
+
+ // Reduce size by 1 so we don't need to worry about bounds checking for pairs
+ // of bytes
+ size--;
+
+ int le_control_chars = 0;
+ int be_control_chars = 0;
+ unsigned char ch1, ch2;
+
+ size_t pos = 0;
+ while (pos < size) {
+ ch1 = pBuffer[pos++];
+ ch2 = pBuffer[pos++];
+
+ if (ch1 == 0) {
+ if (ch2 == 0x0a || ch2 == 0x0d) ++be_control_chars;
+ } else if (ch2 == 0) {
+ if (ch1 == 0x0a || ch1 == 0x0d) ++le_control_chars;
+ }
+
+ // If we are getting both LE and BE control chars then this file is not
+ // utf16
+ if (le_control_chars && be_control_chars) return None;
+ }
+
+ if (le_control_chars)
+ return UTF16_LE_NOBOM;
+ else if (be_control_chars)
+ return UTF16_BE_NOBOM;
+ else
+ return None;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains text that looks like utf16. This is done based
+// the use of nulls which in ASCII/script like text can be useful to identify.
+// Returns:
+// None - not valid utf16
+// UTF16_LE_NOBOM - looks like utf16 le
+// UTF16_BE_NOBOM - looks like utf16 be
+///////////////////////////////////////////////////////////////////////////////
+
+TextEncodingDetect::Encoding TextEncodingDetect::CheckUTF16ASCII(
+ const unsigned char *pBuffer, size_t size) const {
+ int num_odd_nulls = 0;
+ int num_even_nulls = 0;
+
+ // Get even nulls
+ size_t pos = 0;
+ while (pos < size) {
+ if (pBuffer[pos] == 0) num_even_nulls++;
+
+ pos += 2;
+ }
+
+ // Get odd nulls
+ pos = 1;
+ while (pos < size) {
+ if (pBuffer[pos] == 0) num_odd_nulls++;
+
+ pos += 2;
+ }
+
+ double even_null_threshold = (num_even_nulls * 2.0) / size;
+ double odd_null_threshold = (num_odd_nulls * 2.0) / size;
+ double expected_null_threshold = utf16_expected_null_percent_ / 100.0;
+ double unexpected_null_threshold = utf16_unexpected_null_percent_ / 100.0;
+
+ // Lots of odd nulls, low number of even nulls
+ if (even_null_threshold < unexpected_null_threshold &&
+ odd_null_threshold > expected_null_threshold)
+ return UTF16_LE_NOBOM;
+
+ // Lots of even nulls, low number of odd nulls
+ if (odd_null_threshold < unexpected_null_threshold &&
+ even_null_threshold > expected_null_threshold)
+ return UTF16_BE_NOBOM;
+
+ // Don't know
+ return None;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Checks if a buffer contains any nulls. Used to check for binary vs text data.
+///////////////////////////////////////////////////////////////////////////////
+
+bool TextEncodingDetect::DoesContainNulls(const unsigned char *pBuffer,
+ size_t size) {
+ size_t pos = 0;
+ while (pos < size) {
+ if (pBuffer[pos++] == 0) return true;
+ }
+
+ return false;
+}
diff --git a/src/ui/encoding/TextEncodingDetect.h b/src/ui/encoding/TextEncodingDetect.h
new file mode 100644
index 00000000..6d861716
--- /dev/null
+++ b/src/ui/encoding/TextEncodingDetect.h
@@ -0,0 +1,85 @@
+#pragma once
+#ifndef TEXT_ENCODING_DETECT_H_
+#define TEXT_ENCODING_DETECT_H_
+
+//
+// Copyright 2015 Jonathan Bennett <[email protected]>
+//
+// https://www.autoitscript.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Includes
+#include <stddef.h>
+
+namespace AutoIt::Common {
+class TextEncodingDetect {
+ public:
+ enum Encoding {
+ None, // Unknown or binary
+ ANSI, // 0-255
+ ASCII, // 0-127
+ UTF8_BOM, // UTF8 with BOM
+ UTF8_NOBOM, // UTF8 without BOM
+ UTF16_LE_BOM, // UTF16 LE with BOM
+ UTF16_LE_NOBOM, // UTF16 LE without BOM
+ UTF16_BE_BOM, // UTF16-BE with BOM
+ UTF16_BE_NOBOM, // UTF16-BE without BOM
+ };
+
+ TextEncodingDetect();
+ ~TextEncodingDetect() = default;
+
+ static Encoding CheckBOM(
+ const unsigned char *pBuffer,
+ size_t size); // Just check if there is a BOM and return
+ Encoding DetectEncoding(const unsigned char *pBuffer, size_t size)
+ const; // Check BOM and also guess if there is no BOM
+ static int GetBOMLengthFromEncodingMode(
+ Encoding encoding); // Just return the BOM length of a given mode
+
+ void SetNullSuggestsBinary(bool null_suggests_binary) {
+ null_suggests_binary_ = null_suggests_binary;
+ }
+ void SetUtf16UnexpectedNullPercent(int percent);
+ void SetUtf16ExpectedNullPercent(int percent);
+
+ private:
+ TextEncodingDetect(const TextEncodingDetect &);
+ const TextEncodingDetect &operator=(const TextEncodingDetect &);
+
+ static const unsigned char *utf16_bom_le_;
+ static const unsigned char *utf16_bom_be_;
+ static const unsigned char *utf8_bom_;
+
+ bool null_suggests_binary_;
+ int utf16_expected_null_percent_;
+ int utf16_unexpected_null_percent_;
+
+ Encoding CheckUTF8(const unsigned char *pBuffer,
+ size_t size) const; // Check for valid UTF8 with no BOM
+ static Encoding CheckUTF16NewlineChars(
+ const unsigned char *pBuffer,
+ size_t size); // Check for valid UTF16 with no BOM via control chars
+ Encoding CheckUTF16ASCII(const unsigned char *pBuffer, size_t size)
+ const; // Check for valid UTF16 with no BOM via null distribution
+ static bool DoesContainNulls(const unsigned char *pBuffer,
+ size_t size); // Check for nulls
+};
+
+} // namespace AutoIt::Common
+
+//////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index d2ad177a..593fe6fe 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -69,7 +69,8 @@ void MainWindow::slotEncrypt() {
process_operation(this, _("Symmetrically Encrypting"), [&]() {
try {
- auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ auto buffer =
+ edit->curTextPage()->getTextPage()->toPlainText().toStdString();
error = GpgFrontend::BasicOperator::GetInstance().EncryptSymmetric(
buffer, tmp, result);
} catch (const std::runtime_error& e) {
@@ -94,7 +95,8 @@ void MainWindow::slotEncrypt() {
process_operation(this, _("Encrypting"), [&]() {
try {
- auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ auto buffer =
+ edit->curTextPage()->getTextPage()->toPlainText().toStdString();
error = GpgFrontend::BasicOperator::GetInstance().Encrypt(
std::move(keys), buffer, tmp, result);
} catch (const std::runtime_error& e) {
@@ -114,7 +116,8 @@ void MainWindow::slotEncrypt() {
infoBoard->resetOptionActionsMenu();
#ifdef SMTP_SUPPORT
if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR)
- send_an_email(this, infoBoard, edit->curTextPage()->toPlainText());
+ send_an_email(this, infoBoard,
+ edit->curTextPage()->getTextPage()->toPlainText());
#endif
} else {
QMessageBox::critical(this, _("Error"),
@@ -157,7 +160,11 @@ void MainWindow::slotSign() {
process_operation(this, _("Signing"), [&]() {
try {
- auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ auto buffer = edit->curTextPage()
+ ->getTextPage()
+ ->toPlainText()
+ .toUtf8()
+ .toStdString();
error = GpgFrontend::BasicOperator::GetInstance().Sign(
std::move(keys), buffer, tmp, GPGME_SIG_MODE_CLEAR, result);
} catch (const std::runtime_error& e) {
@@ -183,7 +190,7 @@ void MainWindow::slotDecrypt() {
if (edit->tabCount() == 0 || edit->slotCurPageTextEdit() == nullptr) return;
auto decrypted = std::make_unique<ByteArray>();
- QByteArray text = edit->curTextPage()->toPlainText().toUtf8();
+ QByteArray text = edit->curTextPage()->getTextPage()->toPlainText().toUtf8();
if (text.trimmed().startsWith(GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD)) {
QMessageBox::critical(
@@ -234,7 +241,7 @@ void MainWindow::slotFind() {
void MainWindow::slotVerify() {
if (edit->tabCount() == 0 || edit->slotCurPageTextEdit() == nullptr) return;
- auto text = edit->curTextPage()->toPlainText().toUtf8();
+ auto text = edit->curTextPage()->getTextPage()->toPlainText().toUtf8();
// TODO(Saturneric) PreventNoDataErr
auto sig_buffer = std::make_unique<ByteArray>();
@@ -317,7 +324,11 @@ void MainWindow::slotEncryptSign() {
auto tmp = std::make_unique<ByteArray>();
process_operation(this, _("Encrypting and Signing"), [&]() {
try {
- auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ auto buffer = edit->curTextPage()
+ ->getTextPage()
+ ->toPlainText()
+ .toUtf8()
+ .toStdString();
error = GpgFrontend::BasicOperator::GetInstance().EncryptSign(
std::move(keys), std::move(signer_keys), buffer, tmp, encr_result,
sign_result);
@@ -352,7 +363,8 @@ void MainWindow::slotEncryptSign() {
infoBoard->resetOptionActionsMenu();
#ifdef SMTP_SUPPORT
if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR)
- send_an_email(this, infoBoard, edit->curTextPage()->toPlainText(), false);
+ send_an_email(this, infoBoard,
+ edit->curTextPage()->getTextPage()->toPlainText(), false);
#endif
#ifdef ADVANCE_SUPPORT
@@ -376,7 +388,7 @@ void MainWindow::slotEncryptSign() {
void MainWindow::slotDecryptVerify() {
if (edit->tabCount() == 0 || edit->slotCurPageTextEdit() == nullptr) return;
- QString plainText = edit->curTextPage()->toPlainText();
+ QString plainText = edit->curTextPage()->getTextPage()->toPlainText();
#ifdef ADVANCE_SUPPORT
if (plainText.trimmed().startsWith(
@@ -453,7 +465,8 @@ void MainWindow::slotAppendSelectedKeys() {
auto key_ids = mKeyList->getSelected();
GpgKeyImportExporter::GetInstance().ExportKeys(key_ids, exported);
- edit->curTextPage()->append(QString::fromStdString(*exported));
+ edit->curTextPage()->getTextPage()->appendPlainText(
+ QString::fromStdString(*exported));
}
void MainWindow::slotCopyMailAddressToClipboard() {
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index 0c0204f4..9f40ec9d 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -41,7 +41,7 @@ void MainWindow::slotStartWizard() {
void MainWindow::slotImportKeyFromEdit() {
if (edit->tabCount() == 0 || edit->slotCurPageTextEdit() == nullptr) return;
CommonUtils::GetInstance()->slotImportKeys(
- this, edit->curTextPage()->toPlainText().toStdString());
+ this, edit->curTextPage()->getTextPage()->toPlainText().toStdString());
}
void MainWindow::slotOpenKeyManagement() {
@@ -139,7 +139,7 @@ void MainWindow::slotCleanDoubleLinebreaks() {
return;
}
- QString content = edit->curTextPage()->toPlainText();
+ QString content = edit->curTextPage()->getTextPage()->toPlainText();
content.replace("\n\n", "\n");
edit->slotFillTextEditWithText(content);
}
@@ -149,7 +149,7 @@ void MainWindow::slotAddPgpHeader() {
return;
}
- QString content = edit->curTextPage()->toPlainText().trimmed();
+ QString content = edit->curTextPage()->getTextPage()->toPlainText().trimmed();
content.prepend("\n\n").prepend(GpgConstants::PGP_CRYPT_BEGIN);
content.append("\n").append(GpgConstants::PGP_CRYPT_END);
@@ -162,7 +162,7 @@ void MainWindow::slotCutPgpHeader() {
return;
}
- QString content = edit->curTextPage()->toPlainText();
+ QString content = edit->curTextPage()->getTextPage()->toPlainText();
int start = content.indexOf(GpgConstants::PGP_CRYPT_BEGIN);
int end = content.indexOf(GpgConstants::PGP_CRYPT_END);
diff --git a/src/ui/thread/FileReadThread.cpp b/src/ui/thread/FileReadThread.cpp
index 270f50e7..04f713bd 100644
--- a/src/ui/thread/FileReadThread.cpp
+++ b/src/ui/thread/FileReadThread.cpp
@@ -29,39 +29,41 @@
namespace GpgFrontend::UI {
-FileReadThread::FileReadThread(std::string path) : path(std::move(path)) {}
+FileReadThread::FileReadThread(std::string path) : path(std::move(path)) {
+ qRegisterMetaType<std::string>("std::string");
+}
void FileReadThread::run() {
- LOG(INFO) << "Started";
+ LOG(INFO) << "started";
boost::filesystem::path read_file_path(this->path);
if (is_regular_file(read_file_path)) {
- LOG(INFO) << "Read Open";
+ LOG(INFO) << "read open";
- auto fp = fopen(read_file_path.string().c_str(), "r");
+ auto fp = fopen(read_file_path.string().c_str(), "rb");
size_t read_size;
- LOG(INFO) << "Thread Start Reading";
+ LOG(INFO) << "thread start reading";
- char buffer[8192];
+ char buffer[4096];
while ((read_size = fread(buffer, sizeof(char), sizeof buffer, fp)) > 0) {
// Check isInterruptionRequested
if (QThread::currentThread()->isInterruptionRequested()) {
- LOG(INFO) << "Read Thread isInterruptionRequested ";
+ LOG(INFO) << "thread is interruption requested ";
fclose(fp);
return;
}
- LOG(INFO) << "Read Thread Read block size " << read_size;
+ LOG(INFO) << "block size " << read_size;
std::string buffer_str(buffer, read_size);
- emit sendReadBlock(QString::fromStdString(buffer_str));
+ emit sendReadBlock(buffer_str);
#ifdef RELEASE
QThread::msleep(32);
#else
- QThread::msleep(48);
+ QThread::msleep(128);
#endif
}
fclose(fp);
emit readDone();
- LOG(INFO) << "Thread End Reading";
+ LOG(INFO) << "thread end reading";
}
}
diff --git a/src/ui/thread/FileReadThread.h b/src/ui/thread/FileReadThread.h
index 46ed6cbc..65982848 100644
--- a/src/ui/thread/FileReadThread.h
+++ b/src/ui/thread/FileReadThread.h
@@ -37,7 +37,7 @@ class FileReadThread : public QThread {
signals:
- void sendReadBlock(const QString& block);
+ void sendReadBlock(const std::string& block);
void readDone();
diff --git a/src/ui/widgets/EditorPage.cpp b/src/ui/widgets/EditorPage.cpp
deleted file mode 100644
index 8c26fe71..00000000
--- a/src/ui/widgets/EditorPage.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * 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.
- *
- * Foobar 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 Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * 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/EditorPage.h"
-
-#include <boost/filesystem.hpp>
-#include <utility>
-
-#include "ui/thread/FileReadThread.h"
-
-namespace GpgFrontend::UI {
-
-EditorPage::EditorPage(QString filePath, QWidget* parent)
- : QWidget(parent), full_file_path_(std::move(filePath)) {
- // Set the Textedit properties
- textPage = new QTextEdit();
- textPage->setAcceptRichText(false);
-
- // Set the layout style
- mainLayout = new QVBoxLayout();
- mainLayout->setSpacing(0);
- mainLayout->addWidget(textPage);
- mainLayout->setContentsMargins(0, 0, 0, 0);
- setLayout(mainLayout);
-
- textPage->setFocus();
-
- // Front in same width
- this->setFont({"Courier"});
- this->setAttribute(Qt::WA_DeleteOnClose);
-}
-
-const QString& EditorPage::getFilePath() const { return full_file_path_; }
-
-QTextEdit* EditorPage::getTextPage() { return textPage; }
-
-void EditorPage::setFilePath(const QString& filePath) {
- full_file_path_ = filePath;
-}
-
-void EditorPage::showNotificationWidget(QWidget* widget,
- const char* className) {
- widget->setProperty(className, true);
- mainLayout->addWidget(widget);
-}
-
-void EditorPage::closeNoteByClass(const char* className) {
- QList<QWidget*> widgets = findChildren<QWidget*>();
- for (QWidget* widget : widgets) {
- if (widget->property(className) == true) {
- widget->close();
- }
- }
-}
-
-void EditorPage::slotFormatGpgHeader() {
- QString content = 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 || signMarked) {
- return;
- }
-
- signMarked = 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(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 EditorPage::ReadFile() {
- LOG(INFO) << "Called";
-
- read_done_ = false;
-
- auto text_page = this->getTextPage();
- text_page->setReadOnly(true);
- auto thread = new FileReadThread(this->full_file_path_.toStdString());
-
- connect(thread, &FileReadThread::sendReadBlock, this,
- &EditorPage::slotInsertText);
-
- connect(thread, &FileReadThread::readDone, this, [=]() {
- LOG(INFO) << "thread read done";
- text_page->document()->setModified(false);
- text_page->setReadOnly(false);
- });
-
- connect(thread, &FileReadThread::finished, this, [=]() {
- LOG(INFO) << "thread finished";
- thread->deleteLater();
- read_done_ = true;
- read_hread_ = nullptr;
- });
-
- connect(this, &EditorPage::destroyed, [=]() {
- LOG(INFO) << "request interruption for read thread";
- thread->requestInterruption();
- read_hread_ = nullptr;
- });
- this->read_hread_ = thread;
- thread->start();
-}
-
-void EditorPage::slotInsertText(const QString& text) {
- this->getTextPage()->insertPlainText(text);
-}
-void EditorPage::PrepareToDestroy() {
- if (read_hread_) {
- read_hread_->requestInterruption();
- read_hread_ = nullptr;
- }
-}
-
-} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/InfoBoardWidget.h b/src/ui/widgets/InfoBoardWidget.h
index 8d37be6c..816da849 100644
--- a/src/ui/widgets/InfoBoardWidget.h
+++ b/src/ui/widgets/InfoBoardWidget.h
@@ -25,7 +25,7 @@
#ifndef __VERIFYNOTIFICATION_H__
#define __VERIFYNOTIFICATION_H__
-#include "EditorPage.h"
+#include "PlainTextEditorPage.h"
#include "gpg/result_analyse/VerifyResultAnalyse.h"
#include "ui/details/VerifyDetailsDialog.h"
diff --git a/src/ui/widgets/PlainTextEditorPage.cpp b/src/ui/widgets/PlainTextEditorPage.cpp
new file mode 100644
index 00000000..1a99c2a6
--- /dev/null
+++ b/src/ui/widgets/PlainTextEditorPage.cpp
@@ -0,0 +1,257 @@
+/**
+ * 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.
+ *
+ * Foobar 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 Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * 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 <boost/filesystem.hpp>
+#include <boost/format.hpp>
+#include <utility>
+
+#include "ui/encoding/TextEncodingDetect.h"
+#include "ui/thread/FileReadThread.h"
+#include "ui_PlainTextEditor.h"
+
+namespace GpgFrontend::UI {
+
+PlainTextEditorPage::PlainTextEditorPage(QString filePath, QWidget* parent)
+ : QWidget(parent),
+ ui(std::make_shared<Ui_PlainTextEditor>()),
+ full_file_path_(std::move(filePath)) {
+ 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_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::slotFormatGpgHeader() {
+ 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 || signMarked) {
+ return;
+ }
+
+ signMarked = 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::sendReadBlock, this,
+ &PlainTextEditorPage::slotInsertText);
+
+ connect(thread, &FileReadThread::readDone, 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";
+ 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::slotInsertText(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
diff --git a/src/ui/widgets/EditorPage.h b/src/ui/widgets/PlainTextEditorPage.h
index d1bc1ac2..24823c06 100644
--- a/src/ui/widgets/EditorPage.h
+++ b/src/ui/widgets/PlainTextEditorPage.h
@@ -28,12 +28,7 @@
#include "gpg/GpgConstants.h"
#include "ui/GpgFrontendUI.h"
-QT_BEGIN_NAMESPACE
-class QVBoxLayout;
-class QHBoxLayout;
-class QString;
-class QLabel;
-QT_END_NAMESPACE
+class Ui_PlainTextEditor;
namespace GpgFrontend::UI {
@@ -41,7 +36,7 @@ namespace GpgFrontend::UI {
* @brief Class for handling a single tab of the tabwidget
*
*/
-class EditorPage : public QWidget {
+class PlainTextEditorPage : public QWidget {
Q_OBJECT
public:
/**
@@ -50,7 +45,8 @@ class EditorPage : public QWidget {
* @param filePath Path of the file handled in this tab
* @param parent Pointer to the parent widget
*/
- explicit EditorPage(QString filePath = "", QWidget* parent = nullptr);
+ explicit PlainTextEditorPage(QString filePath = "",
+ QWidget* parent = nullptr);
/**
* @details Get the filepath of the currently activated tab.
@@ -67,7 +63,7 @@ class EditorPage : public QWidget {
/**
* @details Return pointer tp the textedit of the currently activated tab.
*/
- QTextEdit* getTextPage();
+ QPlainTextEdit* getTextPage();
/**
* @details Show additional widget at buttom of currently active tab
@@ -91,12 +87,17 @@ class EditorPage : public QWidget {
void PrepareToDestroy();
private:
- QTextEdit* textPage; /** The textedit of the tab */
- QVBoxLayout* mainLayout; /** The layout for the tab */
+ std::shared_ptr<Ui_PlainTextEditor> ui;
QString full_file_path_; /** The path to the file handled in the tab */
bool signMarked{}; /** true, if the signed header is marked, false if not */
bool read_done_ = false;
- QThread* read_hread_ = nullptr;
+ QThread* read_thread_ = nullptr;
+ bool binary_mode_ = false;
+ size_t read_bytes_ = 0;
+
+ void detect_encoding(const std::string& data);
+
+ void detect_cr_lf(const QString& data);
private slots:
@@ -105,7 +106,7 @@ class EditorPage : public QWidget {
*/
void slotFormatGpgHeader();
- void slotInsertText(const QString& text);
+ void slotInsertText(const std::string& data);
};
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index be6ec181..a8ff8d73 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -50,7 +50,7 @@ TextEdit::TextEdit(QWidget* parent) : QWidget(parent) {
void TextEdit::slotNewTab() {
QString header = _("untitled") + QString::number(++countPage) + ".txt";
- auto* page = new EditorPage();
+ auto* page = new PlainTextEditorPage();
auto index = tabWidget->addTab(page, header);
tabWidget->setTabIcon(index, QIcon(":file.png"));
tabWidget->setCurrentIndex(tabWidget->count() - 1);
@@ -80,11 +80,11 @@ void TextEdit::slotOpenFile(QString& path) {
LOG(INFO) << "path" << path.toStdString();
auto result = file.open(QIODevice::ReadOnly | QIODevice::Text);
if (result) {
- auto* page = new EditorPage(path);
+ auto* page = new PlainTextEditorPage(path);
connect(page->getTextPage()->document(),
&QTextDocument::modificationChanged, this,
&TextEdit::slotShowModified);
-
+
QApplication::setOverrideCursor(Qt::WaitCursor);
auto index = tabWidget->addTab(page, strippedName(path));
tabWidget->setTabIcon(index, QIcon(":file.png"));
@@ -111,7 +111,7 @@ void TextEdit::slotOpen() {
QFile file(fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- auto* page = new EditorPage(fileName);
+ auto* page = new PlainTextEditorPage(fileName);
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
@@ -165,7 +165,7 @@ bool TextEdit::saveFile(const QString& fileName) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- EditorPage* page = slotCurPageTextEdit();
+ PlainTextEditorPage* page = slotCurPageTextEdit();
QTextStream outputStream(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
@@ -197,7 +197,7 @@ bool TextEdit::slotSaveAs() {
return true;
}
- EditorPage* page = slotCurPageTextEdit();
+ PlainTextEditorPage* page = slotCurPageTextEdit();
QString path;
if (!page->getFilePath().isEmpty()) {
path = page->getFilePath();
@@ -250,7 +250,7 @@ void TextEdit::removeTab(int index) {
* If it returns false, the close event should be aborted.
*/
bool TextEdit::maybeSaveCurrentTab(bool askToSave) {
- EditorPage* page = slotCurPageTextEdit();
+ PlainTextEditorPage* page = slotCurPageTextEdit();
// if this page is no textedit, there should be nothing to save
if (page == nullptr) {
return true;
@@ -352,13 +352,8 @@ bool TextEdit::maybeSaveAnyTab() {
return false;
}
-QTextEdit* TextEdit::curTextPage() const {
- auto* curTextPage = qobject_cast<EditorPage*>(tabWidget->currentWidget());
- if (curTextPage != nullptr) {
- return curTextPage->getTextPage();
- } else {
- return nullptr;
- }
+PlainTextEditorPage* TextEdit::curTextPage() const {
+ return qobject_cast<PlainTextEditorPage*>(tabWidget->currentWidget());
}
FilePage* TextEdit::curFilePage() const {
@@ -372,8 +367,9 @@ FilePage* TextEdit::curFilePage() const {
int TextEdit::tabCount() const { return tabWidget->count(); }
-EditorPage* TextEdit::slotCurPageTextEdit() const {
- auto* curPage = qobject_cast<EditorPage*>(tabWidget->currentWidget());
+PlainTextEditorPage* TextEdit::slotCurPageTextEdit() const {
+ auto* curPage =
+ qobject_cast<PlainTextEditorPage*>(tabWidget->currentWidget());
return curPage;
}
@@ -387,7 +383,7 @@ void TextEdit::slotQuote() const {
return;
}
- QTextCursor cursor(curTextPage()->document());
+ QTextCursor cursor(curTextPage()->getTextPage()->document());
// beginEditBlock and endEditBlock() let operation look like single undo/redo
// operation
@@ -405,10 +401,10 @@ void TextEdit::slotQuote() const {
}
void TextEdit::slotFillTextEditWithText(const QString& text) const {
- QTextCursor cursor(curTextPage()->document());
+ QTextCursor cursor(curTextPage()->getTextPage()->document());
cursor.beginEditBlock();
- this->curTextPage()->selectAll();
- this->curTextPage()->insertPlainText(text);
+ this->curTextPage()->getTextPage()->selectAll();
+ this->curTextPage()->getTextPage()->insertPlainText(text);
cursor.endEditBlock();
}
@@ -425,7 +421,7 @@ void TextEdit::loadFile(const QString& fileName) {
}
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
- curTextPage()->setPlainText(in.readAll());
+ curTextPage()->getTextPage()->setPlainText(in.readAll());
QApplication::restoreOverrideCursor();
slotCurPageTextEdit()->setFilePath(fileName);
tabWidget->setTabText(tabWidget->currentIndex(), strippedName(fileName));
@@ -445,7 +441,7 @@ void TextEdit::slotPrint() {
#ifndef QT_NO_PRINTER
QTextDocument* document;
if (curTextPage() != nullptr) {
- document = curTextPage()->document();
+ document = curTextPage()->getTextPage()->document();
}
QPrinter printer;
@@ -464,7 +460,7 @@ void TextEdit::slotShowModified() const {
QString title = tabWidget->tabText(index);
// if doc is modified now, add leading * to title,
// otherwise remove the leading * from the title
- if (curTextPage()->document()->isModified()) {
+ if (curTextPage()->getTextPage()->document()->isModified()) {
tabWidget->setTabText(index, title.prepend("* "));
} else {
tabWidget->setTabText(index, title.remove(0, 2));
@@ -494,7 +490,7 @@ QHash<int, QString> TextEdit::unsavedDocuments() const {
// gedit like "unsaved changed"-dialog
for (int i = 0; i < tabWidget->count(); i++) {
- auto* ep = qobject_cast<EditorPage*>(tabWidget->widget(i));
+ auto* ep = qobject_cast<PlainTextEditorPage*>(tabWidget->widget(i));
if (ep != nullptr && ep->ReadDone() &&
ep->getTextPage()->document()->isModified()) {
QString doc_name = tabWidget->tabText(i);
@@ -513,7 +509,7 @@ void TextEdit::slotCut() const {
return;
}
- curTextPage()->cut();
+ curTextPage()->getTextPage()->cut();
}
void TextEdit::slotCopy() const {
@@ -522,7 +518,7 @@ void TextEdit::slotCopy() const {
}
if (curTextPage() != nullptr) {
- curTextPage()->copy();
+ curTextPage()->getTextPage()->copy();
}
}
@@ -531,7 +527,7 @@ void TextEdit::slotPaste() const {
return;
}
- curTextPage()->paste();
+ curTextPage()->getTextPage()->paste();
}
void TextEdit::slotUndo() const {
@@ -539,7 +535,7 @@ void TextEdit::slotUndo() const {
return;
}
- curTextPage()->undo();
+ curTextPage()->getTextPage()->undo();
}
void TextEdit::slotRedo() const {
@@ -547,7 +543,7 @@ void TextEdit::slotRedo() const {
return;
}
- curTextPage()->redo();
+ curTextPage()->getTextPage()->redo();
}
void TextEdit::slotZoomIn() const {
@@ -556,7 +552,7 @@ void TextEdit::slotZoomIn() const {
}
if (curTextPage() != nullptr) {
- curTextPage()->zoomIn();
+ curTextPage()->getTextPage()->zoomIn();
}
}
@@ -566,7 +562,7 @@ void TextEdit::slotZoomOut() const {
}
if (curTextPage() != nullptr) {
- curTextPage()->zoomOut();
+ curTextPage()->getTextPage()->zoomOut();
}
}
@@ -574,7 +570,7 @@ void TextEdit::slotSelectAll() const {
if (tabWidget->count() == 0 || curTextPage() == nullptr) {
return;
}
- curTextPage()->selectAll();
+ curTextPage()->getTextPage()->selectAll();
}
void TextEdit::slotFilePagePathChanged(const QString& path) const {
diff --git a/src/ui/widgets/TextEdit.h b/src/ui/widgets/TextEdit.h
index e877ccc1..c1f44969 100644
--- a/src/ui/widgets/TextEdit.h
+++ b/src/ui/widgets/TextEdit.h
@@ -26,9 +26,9 @@
#define __TEXTEDIT_H__
#include "ui/QuitDialog.h"
-#include "ui/widgets/EditorPage.h"
#include "ui/widgets/FilePage.h"
#include "ui/widgets/HelpPage.h"
+#include "ui/widgets/PlainTextEditorPage.h"
namespace GpgFrontend::UI {
/**
@@ -66,7 +66,7 @@ class TextEdit : public QWidget {
* @return \li reference to QTextEdit if tab has one
* \li 0 otherwise (e.g. if helppage)
*/
- [[nodiscard]] QTextEdit* curTextPage() const;
+ [[nodiscard]] PlainTextEditorPage* curTextPage() const;
[[nodiscard]] FilePage* curFilePage() const;
@@ -84,7 +84,7 @@ class TextEdit : public QWidget {
* @details Return pointer to the currently activated text edit tab page.
*
*/
- EditorPage* slotCurPageTextEdit() const;
+ PlainTextEditorPage* slotCurPageTextEdit() const;
/**
* @details Return pointer to the currently activated file treeview tab page.
diff --git a/ui/FilePage.ui b/ui/FilePage.ui
index cb4517b1..4467e154 100644
--- a/ui/FilePage.ui
+++ b/ui/FilePage.ui
@@ -26,6 +26,21 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
diff --git a/ui/PlainTextEditor.ui b/ui/PlainTextEditor.ui
new file mode 100644
index 00000000..bcccdee1
--- /dev/null
+++ b/ui/PlainTextEditor.ui
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PlainTextEditor</class>
+ <widget class="QWidget" name="PlainTextEditor">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1007</width>
+ <height>701</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPlainTextEdit" name="textPage"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>12</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="loadingLabel">
+ <property name="text">
+ <string>Loading...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="characterLabel">
+ <property name="text">
+ <string>Character</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lfLabel">
+ <property name="text">
+ <string>LF</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="encodingLabel">
+ <property name="text">
+ <string>UTF-8</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>