diff --git a/src/plugins/diffeditor/diffeditorconstants.h b/src/plugins/diffeditor/diffeditorconstants.h index e1c9870c980..8d5d635fa62 100644 --- a/src/plugins/diffeditor/diffeditorconstants.h +++ b/src/plugins/diffeditor/diffeditorconstants.h @@ -38,6 +38,7 @@ const char DIFF_EDITOR_MIMETYPE[] = "text/x-patch"; const char C_DIFF_EDITOR_DESCRIPTION[] = "DiffEditor.Description"; const char SIDE_BY_SIDE_VIEW_ID[] = "DiffEditor.SideBySide"; const char UNIFIED_VIEW_ID[] = "DiffEditor.Unified"; +const char SELECT_ENCODING[] = "DiffEditor.SelectEncoding"; const char G_TOOLS_DIFF[] = "QtCreator.Group.Tools.Options"; diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index f68143bbbaf..546fe9e27e0 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -31,7 +31,9 @@ #include #include +#include #include +#include #include #include @@ -314,10 +316,10 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const beginReload(); QString patch; ReadResult readResult = read(fileName, &patch, errorString); - if (readResult == TextFileFormat::ReadEncodingError) - return OpenResult::CannotHandle; - else if (readResult != TextFileFormat::ReadSuccess) + if (readResult == TextFileFormat::ReadIOError + || readResult == TextFileFormat::ReadMemoryAllocationError) { return OpenResult::ReadError; + } bool ok = false; QList fileDataList = DiffUtils::readPatch(patch, &ok); @@ -333,9 +335,29 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const setDiffFiles(fileDataList, fi.absolutePath()); } endReload(ok); + if (!ok && readResult == TextFileFormat::ReadEncodingError) + ok = selectEncoding(); return ok ? OpenResult::Success : OpenResult::CannotHandle; } +bool DiffEditorDocument::selectEncoding() +{ + Core::CodecSelector codecSelector(Core::ICore::dialogParent(), this); + switch (codecSelector.exec()) { + case Core::CodecSelector::Reload: { + setCodec(codecSelector.selectedCodec()); + QString errorMessage; + return reload(&errorMessage, Core::IDocument::FlagReload, Core::IDocument::TypeContents); + } + case Core::CodecSelector::Save: + setCodec(codecSelector.selectedCodec()); + return Core::EditorManager::saveDocument(this); + case Core::CodecSelector::Cancel: + break; + } + return false; +} + QString DiffEditorDocument::fallbackSaveAsFileName() const { const int maxSubjectLength = 50; diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h index dce11062604..a034feb4391 100644 --- a/src/plugins/diffeditor/diffeditordocument.h +++ b/src/plugins/diffeditor/diffeditordocument.h @@ -86,6 +86,7 @@ public: bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; OpenResult open(QString *errorString, const QString &fileName, const QString &realFileName) override; + bool selectEncoding(); State state() const { return m_state; } QString plainText() const; diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index c4f0ab5cb53..8c408ae3891 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -76,7 +77,7 @@ void DiffEditorWidgetController::setDocument(DiffEditorDocument *document) if (m_document) { disconnect(m_document, &IDocument::aboutToReload, this, &DiffEditorWidgetController::scheduleShowProgress); - disconnect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::hideProgress); + disconnect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::onDocumentReloadFinished); } const bool wasRunning = m_document && m_document->state() == DiffEditorDocument::Reloading; @@ -85,7 +86,8 @@ void DiffEditorWidgetController::setDocument(DiffEditorDocument *document) if (m_document) { connect(m_document, &IDocument::aboutToReload, this, &DiffEditorWidgetController::scheduleShowProgress); - connect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::hideProgress); + connect(m_document, &IDocument::reloadFinished, this, &DiffEditorWidgetController::onDocumentReloadFinished); + updateCannotDecodeInfo(); } const bool isRunning = m_document && m_document->state() == DiffEditorDocument::Reloading; @@ -123,6 +125,12 @@ void DiffEditorWidgetController::hideProgress() m_progressIndicator->hide(); } +void DiffEditorWidgetController::onDocumentReloadFinished() +{ + updateCannotDecodeInfo(); + hideProgress(); +} + void DiffEditorWidgetController::patch(bool revert, int fileIndex, int chunkIndex) { if (!m_document) @@ -294,6 +302,27 @@ void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int controller->requestChunkActions(menu, fileIndex, chunkIndex, selection); } +void DiffEditorWidgetController::updateCannotDecodeInfo() +{ + if (!m_document) + return; + + InfoBar *infoBar = m_document->infoBar(); + Id selectEncodingId(Constants::SELECT_ENCODING); + if (m_document->hasDecodingError()) { + if (!infoBar->canInfoBeAdded(selectEncodingId)) + return; + InfoBarEntry info(selectEncodingId, + tr("Error: Could not decode \"%1\" with \"%2\"-encoding.") + .arg(m_document->displayName(), + QString::fromLatin1(m_document->codec()->name()))); + info.setCustomButtonInfo(tr("Select Encoding"), [this]() { m_document->selectEncoding(); }); + infoBar->addInfo(info); + } else { + infoBar->removeInfo(selectEncodingId); + } +} + void DiffEditorWidgetController::sendChunkToCodePaster(int fileIndex, int chunkIndex) { if (!m_document) diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.h b/src/plugins/diffeditor/diffeditorwidgetcontroller.h index 4951ec1cb44..70c6aa4caee 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.h +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.h @@ -61,6 +61,7 @@ public: void addApplyAction(QMenu *menu, int fileIndex, int chunkIndex); void addRevertAction(QMenu *menu, int fileIndex, int chunkIndex); void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, const ChunkSelection &selection); + void updateCannotDecodeInfo(); ChunkData chunkData(int fileIndex, int chunkIndex) const; @@ -83,6 +84,7 @@ private: void scheduleShowProgress(); void showProgress(); void hideProgress(); + void onDocumentReloadFinished(); QWidget *m_diffEditorWidget = nullptr;