Add tab created time tooltip for new opened untitled tab
Note: while create the new tab (empty & clean), there will be a created time displayed. When the document is modified and period backup feature is enabled, a new created time will be assigned and displayed. However, the time of the first modification which makes empty document dirty will be remained as the tab creation time, even with several modification afterward. Fix #15563, close #15651
This commit is contained in:
parent
8baa1553fc
commit
fc051a1231
|
@ -190,7 +190,7 @@ public:
|
|||
bool fileSaveAs(BufferID id = BUFFER_INVALID, bool isSaveCopy = false);
|
||||
bool fileDelete(BufferID id = BUFFER_INVALID);
|
||||
bool fileRename(BufferID id = BUFFER_INVALID);
|
||||
bool fileRenameUntitled(BufferID id, const wchar_t* tabNewName);
|
||||
bool fileRenameUntitledPluginAPI(BufferID id, const wchar_t* tabNewName);
|
||||
|
||||
bool switchToFile(BufferID buffer); //find buffer in active view then in other view.
|
||||
//@}
|
||||
|
|
|
@ -3150,7 +3150,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
case NPPM_SETUNTITLEDNAME:
|
||||
{
|
||||
if (!wParam || !lParam) return FALSE;
|
||||
return fileRenameUntitled(reinterpret_cast<BufferID>(wParam), reinterpret_cast<const wchar_t*>(lParam));
|
||||
return fileRenameUntitledPluginAPI(reinterpret_cast<BufferID>(wParam), reinterpret_cast<const wchar_t*>(lParam));
|
||||
}
|
||||
|
||||
case NPPM_GETBOOKMARKID:
|
||||
|
|
|
@ -1949,7 +1949,8 @@ bool Notepad_plus::fileRename(BufferID id)
|
|||
scnN.nmhdr.idFrom = (uptr_t)bufferID;
|
||||
|
||||
bool success = false;
|
||||
bool isFileExisting = doesFileExist(buf->getFullPathName());
|
||||
wstring oldFileNamePath = buf->getFullPathName();
|
||||
bool isFileExisting = doesFileExist(oldFileNamePath.c_str());
|
||||
if (isFileExisting)
|
||||
{
|
||||
CustomFileDialog fDlg(_pPublicInterface->getHSelf());
|
||||
|
@ -1977,16 +1978,16 @@ bool Notepad_plus::fileRename(BufferID id)
|
|||
// We are just going to rename the tab nothing else
|
||||
// So just rename the tab and rename the backup file too if applicable
|
||||
|
||||
std::wstring staticName = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-newname", L"New name");
|
||||
wstring staticName = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-newname", L"New name");
|
||||
|
||||
StringDlg strDlg;
|
||||
std::wstring title = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-title", L"Rename Current Tab");
|
||||
wstring title = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-title", L"Rename Current Tab");
|
||||
strDlg.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), title.c_str(), staticName.c_str(), buf->getFileName(), langNameLenMax - 1, filenameReservedChars.c_str(), true);
|
||||
|
||||
wchar_t *tabNewName = reinterpret_cast<wchar_t *>(strDlg.doDialog());
|
||||
if (tabNewName)
|
||||
{
|
||||
std::wstring tabNewNameStr = tabNewName;
|
||||
wstring tabNewNameStr = tabNewName;
|
||||
trim(tabNewNameStr); // No leading and tailing space allowed
|
||||
|
||||
BufferID sameNamedBufferId = _pDocTab->findBufferByName(tabNewNameStr.c_str());
|
||||
|
@ -2023,18 +2024,21 @@ bool Notepad_plus::fileRename(BufferID id)
|
|||
bool isSnapshotMode = NppParameters::getInstance().getNppGUI().isSnapshotMode();
|
||||
if (isSnapshotMode)
|
||||
{
|
||||
std::wstring oldBackUpFile = buf->getBackupFileName();
|
||||
wstring oldBackUpFileName = buf->getBackupFileName();
|
||||
if (oldBackUpFileName.empty())
|
||||
return success;
|
||||
|
||||
// Change the backup file name and let MainFileManager decide the new filename
|
||||
buf->setBackupFileName(L"");
|
||||
wstring newBackUpFileName = oldBackUpFileName;
|
||||
|
||||
// Create new backup
|
||||
buf->setModifiedStatus(true);
|
||||
bool bRes = MainFileManager.backupCurrentBuffer();
|
||||
size_t index = newBackUpFileName.find_last_of(oldFileNamePath) - oldFileNamePath.length() + 1;
|
||||
newBackUpFileName.replace(index, oldFileNamePath.length(), tabNewNameStr);
|
||||
|
||||
// Delete old backup
|
||||
if (bRes)
|
||||
::DeleteFile(oldBackUpFile.c_str());
|
||||
if (doesFileExist(newBackUpFileName.c_str()))
|
||||
::ReplaceFile(newBackUpFileName.c_str(), oldBackUpFileName.c_str(), nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS | REPLACEFILE_IGNORE_ACL_ERRORS, 0, 0);
|
||||
else
|
||||
::MoveFileEx(oldBackUpFileName.c_str(), newBackUpFileName.c_str(), MOVEFILE_REPLACE_EXISTING);
|
||||
|
||||
buf->setBackupFileName(newBackUpFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2043,17 +2047,17 @@ bool Notepad_plus::fileRename(BufferID id)
|
|||
return success;
|
||||
}
|
||||
|
||||
bool Notepad_plus::fileRenameUntitled(BufferID id, const wchar_t* tabNewName)
|
||||
bool Notepad_plus::fileRenameUntitledPluginAPI(BufferID id, const wchar_t* tabNewName)
|
||||
{
|
||||
BufferID bufferID = id;
|
||||
if (id == BUFFER_INVALID)
|
||||
{
|
||||
bufferID = _pEditView->getCurrentBufferID();
|
||||
}
|
||||
|
||||
Buffer* buf = MainFileManager.getBufferByID(bufferID);
|
||||
|
||||
bool isFileExisting = doesFileExist(buf->getFullPathName());
|
||||
if (isFileExisting) return false;
|
||||
if (!buf->isUntitled()) return false;
|
||||
|
||||
// We are just going to rename the tab nothing else
|
||||
// So just rename the tab and rename the backup file too if applicable
|
||||
|
@ -2076,37 +2080,39 @@ bool Notepad_plus::fileRenameUntitled(BufferID id, const wchar_t* tabNewName)
|
|||
sameNamedBufferId = _pNonDocTab->findBufferByName(tabNewNameStr.c_str());
|
||||
}
|
||||
|
||||
if (sameNamedBufferId == BUFFER_INVALID)
|
||||
if (sameNamedBufferId != BUFFER_INVALID) return false;
|
||||
|
||||
|
||||
SCNotification scnN{};
|
||||
scnN.nmhdr.code = NPPN_FILEBEFORERENAME;
|
||||
scnN.nmhdr.hwndFrom = _pPublicInterface->getHSelf();
|
||||
scnN.nmhdr.idFrom = (uptr_t)bufferID;
|
||||
_pluginsManager.notify(&scnN);
|
||||
|
||||
buf->setFileName(tabNewNameStr.c_str());
|
||||
|
||||
scnN.nmhdr.code = NPPN_FILERENAMED;
|
||||
_pluginsManager.notify(&scnN);
|
||||
|
||||
bool isSnapshotMode = NppParameters::getInstance().getNppGUI().isSnapshotMode();
|
||||
if (isSnapshotMode)
|
||||
{
|
||||
SCNotification scnN{};
|
||||
scnN.nmhdr.code = NPPN_FILEBEFORERENAME;
|
||||
scnN.nmhdr.hwndFrom = _pPublicInterface->getHSelf();
|
||||
scnN.nmhdr.idFrom = (uptr_t)bufferID;
|
||||
_pluginsManager.notify(&scnN);
|
||||
wstring oldName = buf->getFullPathName();
|
||||
wstring oldBackUpFileName = buf->getBackupFileName();
|
||||
if (oldBackUpFileName.empty())
|
||||
return false;
|
||||
|
||||
buf->setFileName(tabNewNameStr.c_str());
|
||||
wstring newBackUpFileName = oldBackUpFileName;
|
||||
|
||||
scnN.nmhdr.code = NPPN_FILERENAMED;
|
||||
_pluginsManager.notify(&scnN);
|
||||
size_t index = newBackUpFileName.find_last_of(oldName) - oldName.length() + 1;
|
||||
newBackUpFileName.replace(index, oldName.length(), tabNewNameStr);
|
||||
|
||||
bool isSnapshotMode = NppParameters::getInstance().getNppGUI().isSnapshotMode();
|
||||
if (isSnapshotMode)
|
||||
{
|
||||
std::wstring oldBackUpFile = buf->getBackupFileName();
|
||||
if (doesFileExist(newBackUpFileName.c_str()))
|
||||
::ReplaceFile(newBackUpFileName.c_str(), oldBackUpFileName.c_str(), nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS | REPLACEFILE_IGNORE_ACL_ERRORS, 0, 0);
|
||||
else
|
||||
::MoveFileEx(oldBackUpFileName.c_str(), newBackUpFileName.c_str(), MOVEFILE_REPLACE_EXISTING);
|
||||
|
||||
// Change the backup file name and let MainFileManager decide the new filename
|
||||
buf->setBackupFileName(L"");
|
||||
|
||||
// Create new backup
|
||||
buf->setModifiedStatus(true);
|
||||
bool bRes = MainFileManager.backupCurrentBuffer();
|
||||
|
||||
// Delete old backup
|
||||
if (bRes)
|
||||
{
|
||||
::DeleteFile(oldBackUpFile.c_str());
|
||||
}
|
||||
}
|
||||
buf->setBackupFileName(newBackUpFileName);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -995,14 +995,27 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
else
|
||||
return FALSE;
|
||||
|
||||
Buffer * buf = MainFileManager.getBufferByID(idd);
|
||||
Buffer* buf = MainFileManager.getBufferByID(idd);
|
||||
if (buf == nullptr)
|
||||
return FALSE;
|
||||
|
||||
tipTmp = buf->getFullPathName();
|
||||
|
||||
wstring tabCreatedTime = buf->tabCreatedTimeString();
|
||||
if (!tabCreatedTime.empty())
|
||||
{
|
||||
tipTmp += L"\r";
|
||||
tipTmp += tabCreatedTime;
|
||||
SendMessage(lpttt->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, 200);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(lpttt->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, -1);
|
||||
}
|
||||
|
||||
if (tipTmp.length() >= tipMaxLen)
|
||||
return FALSE;
|
||||
|
||||
wcscpy_s(docTip, tipTmp.c_str());
|
||||
lpttt->lpszText = docTip;
|
||||
return TRUE;
|
||||
|
|
|
@ -398,46 +398,51 @@ int64_t Buffer::getFileLength() const
|
|||
return -1;
|
||||
}
|
||||
|
||||
wstring Buffer::getTimeString(FILETIME rawtime) const
|
||||
{
|
||||
wstring result;
|
||||
SYSTEMTIME utcSystemTime, localSystemTime;
|
||||
FileTimeToSystemTime(&rawtime, &utcSystemTime);
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &utcSystemTime, &localSystemTime);
|
||||
|
||||
const size_t dateTimeStrLen = 256;
|
||||
wchar_t bufDate[dateTimeStrLen] = { '\0' };
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, bufDate, dateTimeStrLen);
|
||||
result += bufDate;
|
||||
result += ' ';
|
||||
|
||||
wchar_t bufTime[dateTimeStrLen] = { '\0' };
|
||||
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, bufTime, dateTimeStrLen);
|
||||
result += bufTime;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
wstring Buffer::getFileTime(fileTimeType ftt) const
|
||||
{
|
||||
wstring result;
|
||||
wstring filePath;
|
||||
|
||||
if (_currentStatus != DOC_UNNAMED)
|
||||
WIN32_FILE_ATTRIBUTE_DATA attributes{};
|
||||
if (GetFileAttributesEx(_currentStatus == DOC_UNNAMED ? _backupFileName.c_str() : _fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA attributes{};
|
||||
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||
FILETIME rawtime;
|
||||
switch (ftt)
|
||||
{
|
||||
FILETIME rawtime;
|
||||
switch (ftt)
|
||||
{
|
||||
case ft_created:
|
||||
rawtime = attributes.ftCreationTime;
|
||||
break;
|
||||
case ft_modified:
|
||||
rawtime = attributes.ftLastWriteTime;
|
||||
break;
|
||||
default:
|
||||
rawtime = attributes.ftLastAccessTime;
|
||||
break;
|
||||
}
|
||||
|
||||
SYSTEMTIME utcSystemTime, localSystemTime;
|
||||
FileTimeToSystemTime(&rawtime, &utcSystemTime);
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &utcSystemTime, &localSystemTime);
|
||||
|
||||
const size_t dateTimeStrLen = 256;
|
||||
wchar_t bufDate[dateTimeStrLen] = {'\0'};
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, bufDate, dateTimeStrLen);
|
||||
result += bufDate;
|
||||
result += ' ';
|
||||
|
||||
wchar_t bufTime[dateTimeStrLen] = {'\0'};
|
||||
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &localSystemTime, nullptr, bufTime, dateTimeStrLen);
|
||||
result += bufTime;
|
||||
case ft_created:
|
||||
rawtime = attributes.ftCreationTime;
|
||||
break;
|
||||
case ft_modified:
|
||||
rawtime = attributes.ftLastWriteTime;
|
||||
break;
|
||||
default:
|
||||
rawtime = attributes.ftLastAccessTime;
|
||||
break;
|
||||
}
|
||||
|
||||
return getTimeString(rawtime);
|
||||
}
|
||||
return result;
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
|
||||
|
@ -779,7 +784,10 @@ BufferID FileManager::loadFile(const wchar_t* filename, Document doc, int encodi
|
|||
{
|
||||
newBuf->_backupFileName = backupFileName;
|
||||
if (!doesFileExist(fullpath))
|
||||
{
|
||||
newBuf->_currentStatus = DOC_UNNAMED;
|
||||
newBuf->setTabCreatedTimeStringFromBakFile();
|
||||
}
|
||||
}
|
||||
|
||||
const FILETIME zeroTimeStamp = {};
|
||||
|
@ -1085,7 +1093,8 @@ bool FileManager::backupCurrentBuffer()
|
|||
::MoveFileEx(fullpathTemp.c_str(), fullpath, MOVEFILE_REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
buffer->setModifiedStatus(false);
|
||||
buffer->setTabCreatedTimeStringFromBakFile();
|
||||
|
||||
result = true; //all done
|
||||
}
|
||||
}
|
||||
|
@ -1365,6 +1374,7 @@ BufferID FileManager::newEmptyDocument()
|
|||
|
||||
BufferID id = newBuf;
|
||||
newBuf->_id = id;
|
||||
newBuf->setTabCreatedTimeStringWithCurrentTime();
|
||||
_buffers.push_back(newBuf);
|
||||
++_nbBufs;
|
||||
++_nextBufferID;
|
||||
|
@ -1432,6 +1442,7 @@ BufferID FileManager::bufferFromDocument(Document doc, bool isMainEditZone)
|
|||
newBuf->_id = id;
|
||||
const NewDocDefaultSettings& ndds = (nppParamInst.getNppGUI()).getNewDocDefaultSettings();
|
||||
newBuf->_lang = ndds._lang;
|
||||
newBuf->setTabCreatedTimeStringWithCurrentTime();
|
||||
_buffers.push_back(newBuf);
|
||||
++_nbBufs;
|
||||
|
||||
|
|
|
@ -277,6 +277,20 @@ public:
|
|||
bool getNeedReload() const { return _needReloading; }
|
||||
void setNeedReload(bool reload) { _needReloading = reload; }
|
||||
|
||||
std::wstring tabCreatedTimeString() const { return _tabCreatedTimeString; }
|
||||
void setTabCreatedTimeStringFromBakFile() {
|
||||
if (_currentStatus == DOC_UNNAMED)
|
||||
_tabCreatedTimeString = getFileTime(Buffer::ft_created); // while DOC_UNNAMED, getFileTime will retrieve time from backup file
|
||||
}
|
||||
void setTabCreatedTimeStringWithCurrentTime() {
|
||||
if (_currentStatus == DOC_UNNAMED)
|
||||
{
|
||||
FILETIME now{};
|
||||
GetSystemTimeAsFileTime(&now);
|
||||
_tabCreatedTimeString = getTimeString(now);
|
||||
}
|
||||
}
|
||||
|
||||
size_t docLength() const {
|
||||
assert(_pManager != nullptr);
|
||||
return _pManager->docLength(_id);
|
||||
|
@ -286,6 +300,7 @@ public:
|
|||
|
||||
enum fileTimeType { ft_created, ft_modified, ft_accessed };
|
||||
std::wstring getFileTime(fileTimeType ftt) const;
|
||||
std::wstring getTimeString(FILETIME rawtime) const;
|
||||
|
||||
Lang * getCurrentLang() const;
|
||||
|
||||
|
@ -391,6 +406,8 @@ private:
|
|||
wchar_t * _fileName = nullptr; // points to filename part in _fullPathName
|
||||
bool _needReloading = false; // True if Buffer needs to be reloaded on activation
|
||||
|
||||
std::wstring _tabCreatedTimeString;
|
||||
|
||||
long _recentTag = -1;
|
||||
static long _recentTagCtr;
|
||||
|
||||
|
|
Loading…
Reference in New Issue