diff options
Diffstat (limited to 'src/ui/widgets/PlainTextEditorPage.cpp')
-rw-r--r-- | src/ui/widgets/PlainTextEditorPage.cpp | 189 |
1 files changed, 114 insertions, 75 deletions
diff --git a/src/ui/widgets/PlainTextEditorPage.cpp b/src/ui/widgets/PlainTextEditorPage.cpp index c70991b9..7eb682cc 100644 --- a/src/ui/widgets/PlainTextEditorPage.cpp +++ b/src/ui/widgets/PlainTextEditorPage.cpp @@ -24,14 +24,16 @@ * */ -#include "ui/widgets/PlainTextEditorPage.h" - -#include <encoding-detect/TextEncodingDetect.h> +#include "PlainTextEditorPage.h" #include <boost/format.hpp> +#include <string> #include <utility> -#include "ui/thread/FileReadThread.h" +#include "core/function/CharsetOperator.h" +#include "core/thread/FileReadTask.h" +#include "core/thread/Task.h" +#include "core/thread/TaskRunnerGetter.h" #include "ui_PlainTextEditor.h" namespace GpgFrontend::UI { @@ -42,8 +44,6 @@ PlainTextEditorPage::PlainTextEditorPage(QString file_path, QWidget *parent) 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); @@ -52,21 +52,26 @@ PlainTextEditorPage::PlainTextEditorPage(QString file_path, QWidget *parent) this->setAttribute(Qt::WA_DeleteOnClose); this->ui_->characterLabel->setText(_("0 character")); - this->ui_->lfLabel->setText(_("None")); - this->ui_->encodingLabel->setText(_("Binary")); + this->ui_->lfLabel->setText(_("lf")); + this->ui_->encodingLabel->setText(_("utf-8")); connect(ui_->textPage, &QPlainTextEdit::textChanged, this, [=]() { + // if file is loading 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...")); + if (full_file_path_.isEmpty()) { + read_done_ = true; + ui_->loadingLabel->setHidden(true); + } else { + read_done_ = false; + ui_->loadingLabel->setText(_("Loading...")); + ui_->loadingLabel->setHidden(false); + } } const QString &PlainTextEditorPage::GetFilePath() const { @@ -75,6 +80,26 @@ const QString &PlainTextEditorPage::GetFilePath() const { QPlainTextEdit *PlainTextEditorPage::GetTextPage() { return ui_->textPage; } +bool PlainTextEditorPage::WillCharsetChange() const { + // detect if the line-ending will change + if (is_crlf_) return true; + + // detect if the charset of the file will change + if (charset_name_ != "UTF-8" && charset_name_ != "ISO-8859-1") + return true; + else + return false; +} + +void PlainTextEditorPage::NotifyFileSaved() { + this->is_crlf_ = false; + this->charset_confidence_ = 100; + this->charset_name_ = "UTF-8"; + + this->ui_->lfLabel->setText(_("lf")); + this->ui_->encodingLabel->setText(_("UTF-8")); +} + void PlainTextEditorPage::SetFilePath(const QString &filePath) { full_file_path_ = filePath; } @@ -140,37 +165,34 @@ void PlainTextEditorPage::ReadFile() { 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); + const auto target_path = this->full_file_path_.toStdString(); + + auto *task_runner = + GpgFrontend::Thread::TaskRunnerGetter::GetInstance().GetTaskRunner(); + + auto *read_task = new FileReadTask(target_path); + connect(read_task, &FileReadTask::SignalFileBytesRead, this, + &PlainTextEditorPage::slot_insert_text, Qt::QueuedConnection); + connect(this, &PlainTextEditorPage::SignalUIBytesDisplayed, read_task, + &FileReadTask::SignalFileBytesReadNext, Qt::QueuedConnection); + + connect(read_task, &FileReadTask::SignalTaskFinished, this, + []() { LOG(INFO) << "read thread closed"; }); + connect(this, &PlainTextEditorPage::close, read_task, + &FileReadTask::SignalTaskFinished); + connect(read_task, &FileReadTask::SignalFileBytesReadEnd, this, [=]() { + // set the UI + if (!binary_mode_) text_page->setReadOnly(false); + this->read_done_ = true; + this->ui_->textPage->setEnabled(true); text_page->document()->setModified(false); - ui_->textPage->blockSignals(false); - ui_->textPage->document()->blockSignals(false); - ui_->loadingLabel->setHidden(true); + this->ui_->textPage->blockSignals(false); + this->ui_->textPage->document()->blockSignals(false); + this->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(); + task_runner->PostTask(read_task); } std::string binary_to_string(const std::string &source) { @@ -181,17 +203,19 @@ std::string binary_to_string(const std::string &source) { return ss.str(); } -void PlainTextEditorPage::slot_insert_text(const std::string &data) { +void PlainTextEditorPage::slot_insert_text(QByteArray bytes_data) { + std::string data = bytes_data.toStdString(); 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 + // 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_) { + if (!binary_mode_ && !read_done_) { detect_encoding(data); } if (binary_mode_) { + // change formery displayed text to binary format if (if_last_binary_mode != binary_mode_) { auto text_buffer = ui_->textPage->document()->toRawText().toLocal8Bit().toStdString(); @@ -200,60 +224,75 @@ void PlainTextEditorPage::slot_insert_text(const std::string &data) { binary_to_string(text_buffer).c_str()); this->ui_->lfLabel->setText("None"); } + + // insert new data this->GetTextPage()->insertPlainText(binary_to_string(data).c_str()); + // update the size of the file auto str = boost::format(_("%1% byte(s)")) % read_bytes_; this->ui_->characterLabel->setText(str.str().c_str()); } else { - this->GetTextPage()->insertPlainText(data.c_str()); + // detect crlf/lf line ending + detect_cr_lf(data); + + // when reding from a text file + // try convert the any of thetext to utf8 + std::string utf8_data; + if (!read_done_ && charset_confidence_ > 25) { + CharsetOperator::Convert2Utf8(data, utf8_data, charset_name_); + } else { + // when editing a text file, do nothing. + utf8_data = data; + } + + // insert the text to the text page + this->GetTextPage()->insertPlainText(utf8_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; } + QTimer::singleShot(25, this, &PlainTextEditorPage::SignalUIBytesDisplayed); + LOG(INFO) << "end"; } 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()); + // skip the binary data to avoid the false detection of the encoding + if (binary_mode_) return; + + // detect the encoding + auto charset = CharsetOperator::Detect(data); + this->charset_name_ = std::get<0>(charset).c_str(); + this->language_name_ = std::get<1>(charset).c_str(); + this->charset_confidence_ = std::get<2>(charset); - if (encoding == AutoIt::Common::TextEncodingDetect::None) { + // probably there is no need to detect the encoding again + if (this->charset_confidence_ < 10) { 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)")); + } + + if (binary_mode_) { + // hide the line ending label, when the file is binary + this->ui_->lfLabel->setHidden(true); + this->ui_->encodingLabel->setText(_("binary")); + } else { + ui_->encodingLabel->setText(this->charset_name_.c_str()); } } -void PlainTextEditorPage::detect_cr_lf(const QString &data) { +void PlainTextEditorPage::detect_cr_lf(const std::string &data) { if (binary_mode_) { - this->ui_->lfLabel->setText("None"); return; } - if (data.contains("\r\n")) { - this->ui_->lfLabel->setText("CRLF"); + + // if contain crlf, set the label to crlf + if (is_crlf_) return; + + if (data.find("\r\n") != std::string::npos) { + this->ui_->lfLabel->setText("crlf"); + is_crlf_ = true; } else { - this->ui_->lfLabel->setText("LF"); + this->ui_->lfLabel->setText("lf"); } } |