1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Bug 2125: Displaying current version on the New version notification + Contents of About dialog can be copied to the clipboard using Ctrl+C

https://winscp.net/tracker/2125

Source commit: 50ae66db19efb1f756ea809faad22a8067d53bff
This commit is contained in:
Martin Prikryl
2022-11-01 12:01:32 +00:00
parent a11d0a7530
commit e78ae6176e
15 changed files with 243 additions and 38 deletions

View File

@@ -3224,6 +3224,116 @@ UnicodeString __fastcall FormatDateTimeSpan(const UnicodeString TimeFormat, TDat
return Result;
}
//---------------------------------------------------------------------------
UnicodeString FormatRelativeTime(const TDateTime & ANow, const TDateTime & AThen, bool DateOnly)
{
UnicodeString Result;
if (DateOnly)
{
if (IsSameDay(AThen, ANow - 1))
{
Result = LoadStrPart(TIME_RELATIVE, 3);
}
else if (IsSameDay(AThen, ANow))
{
Result = LoadStrPart(TIME_RELATIVE, 2);
}
}
if (Result.IsEmpty())
{
int Part, Num;
Num = YearsBetween(ANow, AThen);
if (Num > 1)
{
Part = 18;
}
else if (Num == 1)
{
Part = 17;
}
else
{
Num = MonthsBetween(ANow, AThen);
if (Num > 1)
{
Part = 16;
}
else if (Num == 1)
{
Part = 15;
}
else
{
Num = DaysBetween(ANow, AThen);
if (Num > 1)
{
Part = 12;
}
else if (Num == 1)
{
Part = 11;
}
else
{
Num = static_cast<int>(HoursBetween(ANow, AThen));
if (Num > 1)
{
Part = 10;
}
else if (Num == 1)
{
Part = 9;
}
else
{
Num = static_cast<int>(MinutesBetween(ANow, AThen));
if (Num > 1)
{
Part = 8;
}
else if (Num == 1)
{
Part = 7;
}
else
{
Num = static_cast<int>(SecondsBetween(ANow, AThen));
if (Num > 1)
{
Part = 6;
}
else if (Num == 1)
{
Part = 5;
}
else if (Num == 0)
{
Part = 1;
}
else
{
DebugFail();
Part = -1;
}
}
}
}
}
}
if (DebugAlwaysTrue(Part >= 0))
{
Result = FORMAT(LoadStrPart(TIME_RELATIVE, Part), (abs(Num)));
}
else
{
Result = FormatDateTime(L"ddddd", AThen);
}
}
return Result;
}
//---------------------------------------------------------------------------
UnicodeString __fastcall ExtractFileBaseName(const UnicodeString & Path)
{
return ChangeFileExt(ExtractFileName(Path), L"");
@@ -4347,3 +4457,8 @@ void NotImplemented()
DebugFail();
throw Exception(L"Not implemented");
}
//---------------------------------------------------------------------------
UnicodeString GetDividerLine()
{
return UnicodeString::StringOfChar(L'-', 27);
}

View File

@@ -194,6 +194,7 @@ void SetStringValueEvenIfEmpty(TStrings * Strings, const UnicodeString & Name, c
UnicodeString __fastcall GetAncestorProcessName(int Levels = 1);
UnicodeString GetAncestorProcessNames();
void NotImplemented();
UnicodeString GetDividerLine();
//---------------------------------------------------------------------------
struct TSearchRecSmart : public TSearchRec
{
@@ -267,6 +268,7 @@ int __fastcall TimeToMSec(TDateTime T);
int __fastcall TimeToSeconds(TDateTime T);
int __fastcall TimeToMinutes(TDateTime T);
UnicodeString __fastcall FormatDateTimeSpan(const UnicodeString TimeFormat, TDateTime DateTime);
UnicodeString FormatRelativeTime(const TDateTime & ANow, const TDateTime & AThen, bool DateOnly);
TStrings * TlsCipherList();
//---------------------------------------------------------------------------
template<class MethodT>

View File

@@ -17,6 +17,7 @@
#include <shlobj.h>
#include <System.IOUtils.hpp>
#include <System.StrUtils.hpp>
#include <System.DateUtils.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
@@ -1000,38 +1001,40 @@ bool __fastcall TConfiguration::GetIsUnofficial()
#endif
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TConfiguration::GetVersionStr()
UnicodeString TConfiguration::FormatVersionStr(bool Verbose)
{
TGuard Guard(FCriticalSection);
try
{
UnicodeString BuildStr;
if (!IsUnofficial)
if (!IsUnofficial || Verbose)
{
BuildStr = LoadStr(VERSION_BUILD);
}
else
{
#ifdef _DEBUG
BuildStr = LoadStr(VERSION_DEBUG_BUILD);
#else
BuildStr = LoadStr(VERSION_DEV_BUILD);
#endif
if (!IsUnofficial)
{
BuildStr = LoadStr(VERSION_BUILD);
}
else
{
#ifdef _DEBUG
BuildStr = LoadStr(VERSION_DEBUG_BUILD);
#else
BuildStr = LoadStr(VERSION_DEV_BUILD);
#endif
}
int Build = LOWORD(FixedApplicationInfo->dwFileVersionLS);
if (Build > 0)
{
BuildStr += L" " + IntToStr(Build);
}
}
int Build = LOWORD(FixedApplicationInfo->dwFileVersionLS);
if (Build > 0)
{
BuildStr += L" " + IntToStr(Build);
}
UnicodeString BuildDate = __DATE__;
UnicodeString MonthStr = CutToChar(BuildDate, L' ', true);
UnicodeString BuildDateStr = __DATE__;
UnicodeString MonthStr = CutToChar(BuildDateStr, L' ', true);
int Month = ParseShortEngMonthName(MonthStr);
int Day = StrToInt(CutToChar(BuildDate, L' ', true));
int Year = StrToInt(Trim(BuildDate));
UnicodeString DateStr = FORMAT(L"%d-%2.2d-%2.2d", (Year, Month, Day));
AddToList(BuildStr, DateStr, L" ");
int Day = StrToInt(CutToChar(BuildDateStr, L' ', true));
int Year = StrToInt(Trim(BuildDateStr));
TDateTime BuildDate = EncodeDateVerbose(static_cast<Word>(Year), static_cast<Word>(Month), static_cast<Word>(Day));
UnicodeString FullVersion = Version;
@@ -1043,11 +1046,34 @@ UnicodeString __fastcall TConfiguration::GetVersionStr()
FullVersion += L" " + AReleaseType;
}
UnicodeString Result = FMTLOAD(VERSION2, (FullVersion, BuildStr));
UnicodeString Fmt;
UnicodeString DateStr;
if (Verbose)
{
DateStr = FormatDateTime(L"yyyy-mm-dd", BuildDate);
Fmt = LoadStr(VERSION2);
}
else
{
TDateTime ANow = Now();
if (BuildDate < ANow)
{
DateStr = FormatRelativeTime(ANow, BuildDate, true);
}
else
{
DateStr = FormatDateTime(L"ddddd", BuildDate);
}
#ifndef BUILD_OFFICIAL
Result += L" " + LoadStr(VERSION_DONT_DISTRIBUTE);
#endif
Fmt = L"%s (%s)";
}
AddToList(BuildStr, DateStr, L" ");
UnicodeString Result = FORMAT(Fmt, (FullVersion, BuildStr));
if (!IsUnofficial && Verbose)
{
Result += L" " + LoadStr(VERSION_DONT_DISTRIBUTE);
}
return Result;
}
@@ -1057,6 +1083,11 @@ UnicodeString __fastcall TConfiguration::GetVersionStr()
}
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TConfiguration::GetVersionStr()
{
return FormatVersionStr(true);
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TConfiguration::GetFileVersion(const UnicodeString & FileName)
{
UnicodeString Result;

View File

@@ -270,6 +270,7 @@ public:
bool RegistryPathExists(const UnicodeString & RegistryPath);
bool HasLocalPortNumberLimits();
virtual UnicodeString TemporaryDir(bool Mask = false) = 0;
UnicodeString FormatVersionStr(bool IncludeOfficialBuildNumber);
TStoredSessionList * __fastcall SelectFilezillaSessionsForImport(
TStoredSessionList * Sessions, UnicodeString & Error);

View File

@@ -397,3 +397,43 @@ void __fastcall TAboutDialog::Dispatch(void * Message)
}
}
//---------------------------------------------------------------------------
void __fastcall TAboutDialog::FormKeyDown(TObject *, WORD & Key, TShiftState Shift)
{
if ((Key == L'C') && Shift.Contains(ssCtrl))
{
if ((FThirdPartyWebBrowser != NULL) &&
FThirdPartyWebBrowser->Focused() &&
(FThirdPartyWebBrowser->SelLength() > 0))
{
// Let the browser handle the Ctrl+C
}
else
{
UnicodeString Text =
ApplicationLabel->Caption + sLineBreak +
VersionLabel->Caption + sLineBreak +
sLineBreak +
WinSCPCopyrightLabel->Caption + sLineBreak +
HomepageLabel->Caption + sLineBreak +
sLineBreak +
ProductSpecificMessageLabel->Caption + sLineBreak +
ForumUrlLabel->Caption + sLineBreak;
UnicodeString ThirdPartyText;
if ((FThirdPartyWebBrowser != NULL) &&
CopyTextFromBrowser(FThirdPartyWebBrowser, ThirdPartyText))
{
Text +=
sLineBreak +
GetDividerLine() + sLineBreak +
Label3->Caption + sLineBreak +
ThirdPartyText + sLineBreak;
}
TInstantOperationVisualizer Visualizer;
CopyToClipboard(Text);
Key = 0;
}
}
}
//---------------------------------------------------------------------------

View File

@@ -10,8 +10,10 @@ object AboutDialog: TAboutDialog
ClientWidth = 410
Color = clBtnFace
ParentFont = True
KeyPreview = True
OldCreateOrder = True
Position = poOwnerFormCenter
OnKeyDown = FormKeyDown
DesignSize = (
410
501)

View File

@@ -39,6 +39,7 @@ __published:
void __fastcall OKButtonMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y);
void __fastcall IconPaintBoxPaint(TObject *Sender);
void __fastcall FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift);
private:
TConfiguration * FConfiguration;
TNotifyEvent FOnRegistrationLink;

View File

@@ -209,7 +209,7 @@ UnicodeString __fastcall TMessageForm::GetFormText()
{
UnicodeString DividerLine, ButtonCaptions;
DividerLine = UnicodeString::StringOfChar(L'-', 27) + sLineBreak;
DividerLine = GetDividerLine() + sLineBreak;
for (int i = 0; i < ComponentCount - 1; i++)
{
if (dynamic_cast<TButton*>(Components[i]) != NULL)
@@ -224,19 +224,13 @@ UnicodeString __fastcall TMessageForm::GetFormText()
{
MoreMessages = MessageMemo->Text + DividerLine;
}
else if (MessageBrowser != NULL)
else if ((MessageBrowser != NULL) && CopyTextFromBrowser(MessageBrowser, MoreMessages))
{
MessageBrowser->SelectAll();
MessageBrowser->CopyToClipBoard();
if (NonEmptyTextFromClipboard(MoreMessages))
if (!EndsStr(sLineBreak, MoreMessages))
{
if (!EndsStr(sLineBreak, MoreMessages))
{
MoreMessages += sLineBreak;
}
MoreMessages += DividerLine;
MoreMessages += sLineBreak;
}
MessageBrowser->DoCommand(L"UNSELECT");
MoreMessages += DividerLine;
}
UnicodeString MessageCaption = NormalizeNewLines(MessageText);
UnicodeString Result = FORMAT(L"%s%s%s%s%s%s%s%s%s%s%s", (DividerLine, Caption, sLineBreak,

View File

@@ -496,6 +496,7 @@
#define COPY_INFO_EXCLUDE_EMPTY_DIRS 566
#define PUBLIC_KEY_UPLOADED 567
#define PUBLIC_KEY_PERMISSIONS 568
#define TIME_RELATIVE 569
#define CORE_VARIABLE_STRINGS 600
#define PUTTY_BASED_ON 601

View File

@@ -465,6 +465,7 @@ BEGIN
COPY_INFO_EXCLUDE_EMPTY_DIRS, "Exclude empty directories"
PUBLIC_KEY_UPLOADED, "**Public key \"%s\" was installed.**\n\nYou can now login to the server using the key pair."
PUBLIC_KEY_PERMISSIONS, "Though potentially wrong permissions of \"%s\" file and/or its parent folder were detected. Please check them."
TIME_RELATIVE, "just now|today|yesterday|tomorrow|one second ago|%d seconds ago|one minute ago|%d minutes ago|one hour ago|%d hours ago|one day ago|%d days ago|one week ago|%d weeks ago|one month ago|%d months ago|one year ago|%d years ago"
CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"

View File

@@ -309,6 +309,7 @@
#define STORE_MIGRATION_LEARN 1596
#define MESSAGE_DISMISS 1597
#define USAGE_PASSWORDSFROMFILES 1598
#define UPDATE_CURRENT 1599
#define WIN_FORMS_STRINGS 1600
#define COPY_FILE 1605

View File

@@ -314,6 +314,7 @@ BEGIN
STORE_MIGRATION_LEARN, "Learn about transitioning from classic installation."
MESSAGE_DISMISS, "Dismiss"
USAGE_PASSWORDSFROMFILES, "Read all passwords from files"
UPDATE_CURRENT, "Your version: %s"
WIN_FORMS_STRINGS, "WIN_FORMS_STRINGS"
COPY_FILE, "%s file '%s' to %s:"

View File

@@ -1444,6 +1444,15 @@ void HideBrowserScrollbars(TWebBrowserEx * WebBrowser)
}
}
//---------------------------------------------------------------------------
bool CopyTextFromBrowser(TWebBrowserEx * WebBrowser, UnicodeString & Text)
{
WebBrowser->SelectAll();
WebBrowser->CopyToClipBoard();
bool Result = NonEmptyTextFromClipboard(Text);
WebBrowser->DoCommand(L"UNSELECT");
return Result;
}
//---------------------------------------------------------------------------
UnicodeString GenerateAppHtmlPage(TFont * Font, TPanel * Parent, const UnicodeString & Body, bool Seamless)
{
UnicodeString Result =

View File

@@ -58,6 +58,7 @@ void __fastcall NavigateBrowserToUrl(TWebBrowserEx * WebBrowser, const UnicodeSt
void ReadyBrowserForStreaming(TWebBrowserEx * WebBrowser);
void WaitBrowserToIdle(TWebBrowserEx * WebBrowser);
void HideBrowserScrollbars(TWebBrowserEx * WebBrowser);
bool CopyTextFromBrowser(TWebBrowserEx * WebBrowser, UnicodeString & Text);
UnicodeString GenerateAppHtmlPage(TFont * Font, TPanel * Parent, const UnicodeString & Body, bool Seamless);
void LoadBrowserDocument(TWebBrowserEx * WebBrowser, const UnicodeString & Document);
TComponent * __fastcall FindComponentRecursively(TComponent * Root, const UnicodeString & Name);

View File

@@ -1659,6 +1659,11 @@ bool __fastcall CheckForUpdates(bool CachedResults)
Message += L"\n\n" +
FMTLOAD(UPDATE_NEXT, (FormatDateTime("ddddd", Updates.LastCheck + Updates.Period)));
}
else if (New)
{
UnicodeString Version = Configuration->FormatVersionStr(false);
Message += L"\n\n" + FMTLOAD(UPDATE_CURRENT, (Version));
}
int Answers = qaOK |
// show "what's new" button only when change list URL was not provided in results