From b76bf9e4dfefc33b12505b0f147c09196ce94d1d Mon Sep 17 00:00:00 2001 From: Don HO Date: Fri, 20 Dec 2019 00:38:57 +0100 Subject: [PATCH] Make doSaveOrNot dialog simpler when there's a single file to save When there are several files to save, the same doSaveOrNot dialog which cotains 5 buttons (Yes, No, Cancel, Yes to All and No to All) is shown. But if there is only one file to save, then it's better to not show Yes to All and No to All buttons to make a consistent user interface. Fix #7762 --- PowerEditor/src/Notepad_plus.cpp | 15 ++++++++ PowerEditor/src/NppIO.cpp | 38 ++++++++++++++++--- PowerEditor/src/ScitillaComponent/Buffer.cpp | 10 +++++ PowerEditor/src/ScitillaComponent/Buffer.h | 3 +- PowerEditor/src/localization.cpp | 39 ++++++++++++++++++++ PowerEditor/src/localization.h | 2 + 6 files changed, 100 insertions(+), 7 deletions(-) diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index b1b7f9b9..e0e529a4 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -1884,6 +1884,21 @@ int Notepad_plus::doSaveOrNot(const TCHAR* fn, bool isMulti) ::SendMessage(_pPublicInterface->getHSelf(), WM_SIZE, 0, 0); } + if (!isMulti) + { + generic_string title, msg; + + if (!_nativeLangSpeaker.getDoSaveOrNotStrings(title, msg)) + { + title = TEXT("Save"); + msg = TEXT("Save file \"$STR_REPLACE$\" ?"); + } + + msg = stringReplace(msg, TEXT("$STR_REPLACE$"), fn); + + return ::MessageBox(_pPublicInterface->getHSelf(), msg.c_str(), title.c_str(), MB_YESNOCANCEL | MB_ICONQUESTION | MB_APPLMODAL); + } + DoSaveOrNotBox doSaveOrNotBox; doSaveOrNotBox.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), fn, isMulti); doSaveOrNotBox.doDialog(_nativeLangSpeaker.isRTL()); diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 4af2fc7c..8b0e68c5 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -959,7 +959,8 @@ bool Notepad_plus::fileCloseAll(bool doDeleteBackup, bool isSnapshotMode) } else { - res = doSaveOrNot(buf->getFullPathName(), true); + size_t nbDirtyFiles = MainFileManager.getNbDirtyBuffers(); + res = doSaveOrNot(buf->getFullPathName(), nbDirtyFiles > 1); } if (res == IDYES) @@ -1040,7 +1041,8 @@ bool Notepad_plus::fileCloseAll(bool doDeleteBackup, bool isSnapshotMode) } else { - res = doSaveOrNot(buf->getFullPathName(), true); + size_t nbDirtyFiles = MainFileManager.getNbDirtyBuffers(); + res = doSaveOrNot(buf->getFullPathName(), nbDirtyFiles > 1); } if (res == IDYES) @@ -1096,6 +1098,17 @@ bool Notepad_plus::fileCloseAllGiven(const std::vector& krvecBufferIndexes) bool saveToAll = false; std::vector bufferIndexesToClose; + // Count the number of dirty file + size_t nbDirtyFiles = 0; + for (const auto& index : krvecBufferIndexes) + { + BufferID id = _pDocTab->getBufferByIndex(index); + Buffer* buf = MainFileManager.getBufferByID(id); + + if (buf->isDirty()) + ++nbDirtyFiles; + } + for (const auto& index : krvecBufferIndexes) { BufferID id = _pDocTab->getBufferByIndex(index); @@ -1126,8 +1139,9 @@ bool Notepad_plus::fileCloseAllGiven(const std::vector& krvecBufferIndexes) * IDNO : No * IDIGNORE : No To All * IDCANCEL : Cancel Opration - */ - int res = saveToAll ? IDYES : doSaveOrNot(buf->getFullPathName(), true); + */ + + int res = saveToAll ? IDYES : doSaveOrNot(buf->getFullPathName(), nbDirtyFiles > 1); if (res == IDYES || res == IDRETRY) { @@ -1245,7 +1259,13 @@ bool Notepad_plus::fileCloseAllButCurrent() } else { - res = doSaveOrNot(buf->getFullPathName(), true); + size_t nbDirtyFiles = MainFileManager.getNbDirtyBuffers(); + + // if current file is dirty, if should be removed from dirty files to make nbDirtyFiles accurate + Buffer* currentBuf = MainFileManager.getBufferByID(current); + nbDirtyFiles -= currentBuf->isDirty() ? 1 : 0; + + res = doSaveOrNot(buf->getFullPathName(), nbDirtyFiles > 1); } if (res == IDYES) @@ -1309,7 +1329,13 @@ bool Notepad_plus::fileCloseAllButCurrent() } else { - res = doSaveOrNot(buf->getFullPathName(), true); + size_t nbDirtyFiles = MainFileManager.getNbDirtyBuffers(); + + // if current file is dirty, if should be removed from dirty files to make nbDirtyFiles accurate + Buffer* currentBuf = MainFileManager.getBufferByID(current); + nbDirtyFiles -= currentBuf->isDirty() ? 1 : 0; + + res = doSaveOrNot(buf->getFullPathName(), nbDirtyFiles > 1); } diff --git a/PowerEditor/src/ScitillaComponent/Buffer.cpp b/PowerEditor/src/ScitillaComponent/Buffer.cpp index 980c0159..59869b94 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.cpp +++ b/PowerEditor/src/ScitillaComponent/Buffer.cpp @@ -533,6 +533,16 @@ void FileManager::checkFilesystemChanges(bool bCheckOnlyCurrentBuffer) } } +size_t FileManager::getNbDirtyBuffers() const +{ + size_t nb_dirtyBufs = 0; + for (size_t i = 0; i < _nbBufs; ++i) + { + if (_buffers[i]->_isDirty) + ++nb_dirtyBufs; + } + return nb_dirtyBufs; +} int FileManager::getBufferIndexByID(BufferID id) { diff --git a/PowerEditor/src/ScitillaComponent/Buffer.h b/PowerEditor/src/ScitillaComponent/Buffer.h index 9803b4c7..132035d3 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.h +++ b/PowerEditor/src/ScitillaComponent/Buffer.h @@ -76,7 +76,8 @@ public: //void activateBuffer(int index); void checkFilesystemChanges(bool bCheckOnlyCurrentBuffer); - size_t getNbBuffers() { return _nbBufs; }; + size_t getNbBuffers() const { return _nbBufs; }; + size_t getNbDirtyBuffers() const; int getBufferIndexByID(BufferID id); Buffer * getBufferByIndex(size_t index); Buffer * getBufferByID(BufferID id) {return static_cast(id);} diff --git a/PowerEditor/src/localization.cpp b/PowerEditor/src/localization.cpp index 01cb181c..4c961738 100644 --- a/PowerEditor/src/localization.cpp +++ b/PowerEditor/src/localization.cpp @@ -1048,6 +1048,45 @@ TiXmlNodeA * NativeLangSpeaker::searchDlgNode(TiXmlNodeA *node, const char *dlgT return NULL; } +bool NativeLangSpeaker::getDoSaveOrNotStrings(generic_string& title, generic_string& msg) +{ + if (!_nativeLangA) return false; + + TiXmlNodeA *dlgNode = _nativeLangA->FirstChild("Dialog"); + if (!dlgNode) return false; + + dlgNode = searchDlgNode(dlgNode, "DoSaveOrNot"); + if (!dlgNode) return false; + + const char *title2set = (dlgNode->ToElement())->Attribute("title"); + if (!title2set || !title2set[0]) return false; + + WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); + const wchar_t *titleW = wmc.char2wchar(title2set, _nativeLangEncoding); + title = titleW; + + for (TiXmlNodeA *childNode = dlgNode->FirstChildElement("Item"); + childNode; + childNode = childNode->NextSibling("Item")) + { + TiXmlElementA *element = childNode->ToElement(); + int id; + const char *sentinel = element->Attribute("id", &id); + const char *name = element->Attribute("name"); + if (sentinel && (name && name[0])) + { + if (id == 1761) + { + const wchar_t *msgW = wmc.char2wchar(name, _nativeLangEncoding); + msg = msgW; + + return true; + } + } + } + return false; +} + bool NativeLangSpeaker::changeDlgLang(HWND hDlg, const char *dlgTagName, char *title, size_t titleMaxSize) { if (title) diff --git a/PowerEditor/src/localization.h b/PowerEditor/src/localization.h index 42021ae9..b5533c3b 100644 --- a/PowerEditor/src/localization.h +++ b/PowerEditor/src/localization.h @@ -67,6 +67,8 @@ public: void changePrefereceDlgLang(PreferenceDlg & preference); void changePluginsAdminDlgLang(PluginsAdminDlg & pluginsAdminDlg); + bool getDoSaveOrNotStrings(generic_string& title, generic_string& msg); + bool isRTL() const { return _isRTL; };