From b584aa5ae4abf7ff9de7611b3f49aea92191bcca Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Tue, 19 Feb 2008 19:44:33 +0000 Subject: [PATCH] Introduce automatism for calling the updatecheck dialog. User can set the interval how often this is done in preferences dialog (default interval: 3 days, can be completely disabled). The automatic calling of this dialog should not disturb anyone as it's closed immediately if there are no updates available or if a developer version with an unknown revision is used. Some GUI controls on the dialog had to be moved around as well as some lines of code so everything works well with the automatic dialog closing. --- components/heidisql/include/const.inc | 5 +++ source/main.pas | 23 +++++++++- source/options.dfm | 39 +++++++++++++++-- source/options.pas | 19 ++++++++ source/updatecheck.dfm | 37 +++++++++------- source/updatecheck.pas | 62 ++++++++++++++++++++------- 6 files changed, 149 insertions(+), 36 deletions(-) diff --git a/components/heidisql/include/const.inc b/components/heidisql/include/const.inc index 971e93c4..47f30b6e 100644 --- a/components/heidisql/include/const.inc +++ b/components/heidisql/include/const.inc @@ -149,6 +149,11 @@ const REGNAME_CSV_LOWPRIO = 'CSVImportLowPriority'; REGNAME_CSV_REPLACE = 'CSVImportReplace'; REGNAME_CSV_IGNORE = 'CSVImportIgnore'; + REGNAME_DO_UPDATECHECK = 'Updatecheck'; + DEFAULT_DO_UPDATECHECK = True; + REGNAME_UPDATECHECK_INTERVAL = 'UpdatecheckInterval'; + DEFAULT_UPDATECHECK_INTERVAL = 3; + REGNAME_LAST_UPDATECHECK = 'UpdatecheckLastrun'; REGPREFIX_COLWIDTHS = 'ColWidths_'; REGPREFIX_COLSVISIBLE = 'ColsVisible_'; diff --git a/source/main.pas b/source/main.pas index ae928d84..82930d05 100644 --- a/source/main.pas +++ b/source/main.pas @@ -17,7 +17,7 @@ uses ActnList, ImgList, Registry, ShellApi, ToolWin, Clipbrd, db, DBCtrls, SynMemo, synedit, SynEditTypes, ZDataSet, ZSqlProcessor, HeidiComp, sqlhelp, MysqlQueryThread, Childwin, VirtualTrees, TntDBGrids, - StrUtils; + StrUtils, DateUtils; type TMainForm = class(TForm) @@ -487,7 +487,28 @@ var parHost, parPort, parUser, parPass, parDatabase, parTimeout, parCompress, parSortDatabases, parDescription : String; reg : TRegistry; + LastUpdatecheck : TDateTime; + UpdatecheckInterval : Integer; + DefaultLastrunDate : String; + frm : TfrmUpdateCheck; begin + // Do an updatecheck if checked in settings + if GetRegValue(REGNAME_DO_UPDATECHECK, DEFAULT_DO_UPDATECHECK) then begin + DefaultLastrunDate := '2000-01-01'; + try + LastUpdatecheck := StrToDateTime( GetRegValue(REGNAME_LAST_UPDATECHECK, DefaultLastrunDate) ); + except + LastUpdatecheck := StrToDateTime( DefaultLastrunDate ); + end; + UpdatecheckInterval := GetRegValue(REGNAME_UPDATECHECK_INTERVAL, DEFAULT_UPDATECHECK_INTERVAL); + if DaysBetween(Now, LastUpdatecheck) >= UpdatecheckInterval then begin + frm := TfrmUpdateCheck.Create(Self); + frm.AutoClose := True; + frm.ShowModal; + FreeAndNil(frm); + end; + end; + // Check commandline if parameters were passed. Otherwise show connections windows curParam := 1; while curParam <= ParamCount do diff --git a/source/options.dfm b/source/options.dfm index 4cab9464..1211f4ce 100644 --- a/source/options.dfm +++ b/source/options.dfm @@ -80,7 +80,7 @@ object optionsform: Toptionsform OnClick = Modified end object updownLogSQLNum: TUpDown - Left = 120 + Left = 114 Top = 101 Width = 17 Height = 21 @@ -93,7 +93,7 @@ object optionsform: Toptionsform OnChanging = anyUpDownLimitChanging end object editLogSQLNum: TEdit - Left = 67 + Left = 61 Top = 101 Width = 53 Height = 21 @@ -150,6 +150,37 @@ object optionsform: Toptionsform TabOrder = 8 OnChanging = anyUpDownLimitChanging end + object chkUpdatecheck: TCheckBox + Left = 16 + Top = 199 + Width = 268 + Height = 17 + Caption = 'Automatically check for updates / Interval [days]:' + Checked = True + State = cbChecked + TabOrder = 9 + OnClick = chkUpdatecheckClick + end + object editUpdatecheckInterval: TEdit + Left = 302 + Top = 197 + Width = 43 + Height = 21 + TabOrder = 10 + Text = '0' + end + object updownUpdatecheckInterval: TUpDown + Left = 345 + Top = 197 + Width = 16 + Height = 21 + Associate = editUpdatecheckInterval + Min = 1 + Max = 999 + Position = 1 + TabOrder = 11 + OnChanging = anyUpDownLimitChanging + end end object TabSheet2: TTabSheet BorderWidth = 5 @@ -674,7 +705,7 @@ object optionsform: Toptionsform end object ColorDialog1: TColorDialog Options = [cdFullOpen, cdSolidColor] - Left = 109 - Top = 229 + Left = 1 + Top = 274 end end diff --git a/source/options.pas b/source/options.pas index fb7ee727..18b0a36b 100644 --- a/source/options.pas +++ b/source/options.pas @@ -92,6 +92,9 @@ type editLogSnip: TEdit; updownLogSnip: TUpDown; labelSqlSnipHint: TLabel; + chkUpdatecheck: TCheckBox; + editUpdatecheckInterval: TEdit; + updownUpdatecheckInterval: TUpDown; procedure ButtonCancelClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure Modified(Sender: TObject); @@ -104,6 +107,7 @@ type procedure anyUpDownLimitChanging(Sender: TObject; var AllowChange: Boolean); procedure btnOpenLogFolderClick(Sender: TObject); + procedure chkUpdatecheckClick(Sender: TObject); private { Private declarations } public @@ -181,6 +185,8 @@ begin reg.WriteInteger(REGNAME_DATAFONTSIZE, UpDownDataFontSize.Position); reg.WriteBool(REGNAME_REMEMBERFILTERS, chkRememberFilters.Checked); reg.WriteBool(REGNAME_LOGTOFILE, chkLogToFile.Checked); + reg.WriteBool(REGNAME_DO_UPDATECHECK, chkUpdatecheck.Checked); + reg.WriteInteger(REGNAME_UPDATECHECK_INTERVAL, updownUpdatecheckInterval.Position); // Close registry key reg.CloseKey; @@ -268,6 +274,9 @@ begin CheckBoxLimit.OnClick(self); updownLogSQLNum.Position := Mainform.GetRegValue(REGNAME_LOGSQLNUM, DEFAULT_LOGSQLNUM); updownLogSnip.Position := Mainform.GetRegValue(REGNAME_LOGSQLWIDTH, DEFAULT_LOGSQLWIDTH); + chkUpdatecheck.Checked := Mainform.GetRegValue(REGNAME_DO_UPDATECHECK, DEFAULT_DO_UPDATECHECK); + updownUpdatecheckInterval.Position := Mainform.GetRegValue(REGNAME_UPDATECHECK_INTERVAL, DEFAULT_UPDATECHECK_INTERVAL); + // Default Column-Width in DBGrids: updownDefaultColWidth.Position := Mainform.GetRegValue(REGNAME_DEFAULTCOLWIDTH, DEFAULT_DEFAULTCOLWIDTH); // Color-coding: @@ -378,4 +387,14 @@ begin ShellExec( '', DirnameSessionLogs ); end; +{** + Updatecheck checkbox was clicked +} +procedure Toptionsform.chkUpdatecheckClick(Sender: TObject); +begin + updownUpdatecheckInterval.Enabled := chkUpdatecheck.Checked; + editUpdatecheckInterval.Enabled := chkUpdatecheck.Checked; + Modified(sender); +end; + end. diff --git a/source/updatecheck.dfm b/source/updatecheck.dfm index 8de8f2e9..8dded478 100644 --- a/source/updatecheck.dfm +++ b/source/updatecheck.dfm @@ -4,7 +4,7 @@ object frmUpdateCheck: TfrmUpdateCheck BorderStyle = bsDialog Caption = 'Check for updates ...' ClientHeight = 273 - ClientWidth = 362 + ClientWidth = 384 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -13,27 +13,30 @@ object frmUpdateCheck: TfrmUpdateCheck Font.Style = [] OldCreateOrder = False Position = poMainFormCenter + OnCreate = FormCreate OnShow = FormShow DesignSize = ( - 362 + 384 273) PixelsPerInch = 96 TextHeight = 13 object lblStatus: TLabel Left = 8 - Top = 245 - Width = 245 - Height = 13 + Top = 240 + Width = 256 + Height = 28 Anchors = [akLeft, akRight, akBottom] AutoSize = False Caption = 'lblStatus' + Layout = tlCenter + WordWrap = True end object btnCancel: TButton - Left = 226 + Left = 270 Top = 240 - Width = 128 + Width = 106 Height = 25 - Anchors = [akLeft, akRight, akBottom] + Anchors = [akRight, akBottom] Cancel = True Caption = 'Cancel' Default = True @@ -43,18 +46,19 @@ object frmUpdateCheck: TfrmUpdateCheck object groupBuild: TGroupBox Left = 8 Top = 123 - Width = 346 + Width = 368 Height = 110 Anchors = [akLeft, akTop, akRight, akBottom] Caption = 'Nightly build' + Enabled = False TabOrder = 1 DesignSize = ( - 346 + 368 110) object btnBuild: TButton Left = 6 Top = 78 - Width = 333 + Width = 355 Height = 25 Anchors = [akLeft, akRight, akBottom] Caption = 'Download nightly build' @@ -65,7 +69,7 @@ object frmUpdateCheck: TfrmUpdateCheck object memoBuild: TMemo Left = 6 Top = 16 - Width = 333 + Width = 355 Height = 60 Anchors = [akLeft, akTop, akRight, akBottom] BorderStyle = bsNone @@ -80,18 +84,19 @@ object frmUpdateCheck: TfrmUpdateCheck object groupRelease: TGroupBox Left = 8 Top = 8 - Width = 346 + Width = 368 Height = 110 Anchors = [akLeft, akTop, akRight] Caption = 'Official release' + Enabled = False TabOrder = 2 DesignSize = ( - 346 + 368 110) object btnRelease: TButton Left = 6 Top = 78 - Width = 333 + Width = 355 Height = 25 Anchors = [akLeft, akRight, akBottom] Caption = 'Download new release' @@ -102,7 +107,7 @@ object frmUpdateCheck: TfrmUpdateCheck object memoRelease: TMemo Left = 6 Top = 16 - Width = 333 + Width = 355 Height = 60 Anchors = [akLeft, akTop, akRight, akBottom] BorderStyle = bsNone diff --git a/source/updatecheck.pas b/source/updatecheck.pas index 9a2d9cb3..92046cd7 100644 --- a/source/updatecheck.pas +++ b/source/updatecheck.pas @@ -4,7 +4,7 @@ interface uses Windows, Messages, SysUtils, Classes, Forms, - Dialogs, StdCtrls, ExtActns, IniFiles, Controls, Graphics; + Dialogs, StdCtrls, ExtActns, IniFiles, Controls, Graphics, Registry; type TfrmUpdateCheck = class(TForm) @@ -16,6 +16,7 @@ type lblStatus: TLabel; memoRelease: TMemo; memoBuild: TMemo; + procedure FormCreate(Sender: TObject); procedure btnBuildClick(Sender: TObject); procedure btnReleaseClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -27,6 +28,8 @@ type procedure ReadCheckFile; public { Public declarations } + AutoClose: Boolean; // Automatically close dialog after detecting no available downloads + CurrentRevision: Integer; end; implementation @@ -38,6 +41,14 @@ uses helpers, main; {$I const.inc} +{** + Set defaults +} +procedure TfrmUpdateCheck.FormCreate(Sender: TObject); +begin + // Should be false by default. Callers can set this to True after Create() + AutoClose := False; +end; {** Update status text @@ -55,14 +66,15 @@ end; procedure TfrmUpdateCheck.FormShow(Sender: TObject); var TempPath: array[0..MAX_PATH] of Char; + reg : TRegistry; begin Status('Initiating ... '); Caption := 'Check for '+APPNAME+' updates ...'; + CurrentRevision := StrToIntDef(AppRevision, 0); // Init GUI controls btnRelease.Enabled := False; btnBuild.Enabled := False; - btnCancel.Enabled := False; memoRelease.Clear; memoBuild.Clear; @@ -76,16 +88,41 @@ begin // Download the check file Screen.Cursor := crHourglass; - Status('Downloading check file ...'); try + Status('Downloading check file ...'); CheckfileDownload.ExecuteTarget(nil); + Status('Reading check file ...'); ReadCheckFile; - DeleteFile(CheckfileDownload.Filename); - finally - FreeAndNil(CheckfileDownload); - Screen.Cursor := crDefault; - btnCancel.Enabled := True; + if (not groupRelease.Enabled) and (not groupBuild.Enabled) then begin + // Developer versions probably have "unknown" (0) as revision, + // which makes it impossible to compare the revisions. + if CurrentRevision = 0 then + Status('Error: Cannot determine current revision. Using a developer version?') + else + Status('Your '+APPNAME+' is up-to-date (no update available).'); + end else + Status('Updates available.'); + // Remember when we did the updatecheck to enable the automatic interval + reg := TRegistry.Create; + reg.OpenKey(REGPATH, true); + reg.WriteString(REGNAME_LAST_UPDATECHECK, DateTimeToStr(Now)); + reg.CloseKey; + FreeAndNil(reg); + except + // Do not popup errors, just display them in the status label + On E:Exception do + Status(E.Message); end; + if FileExists(CheckfileDownload.Filename) then + DeleteFile(CheckfileDownload.Filename); + FreeAndNil(CheckfileDownload); + Screen.Cursor := crDefault; + + // For automatic updatechecks this dialog should close if no updates are available. + // Using PostMessage, as Self.Close or ModalResult := mrCancel does not work + // as expected in FormShow + if AutoClose and (not groupRelease.Enabled) and (not groupBuild.Enabled) then + PostMessage(Self.Handle, WM_CLOSE, 0, 0); end; @@ -103,8 +140,6 @@ const INISECT_RELEASE = 'Release'; INISECT_BUILD = 'Build'; begin - Status('Reading check file ...'); - // Read [Release] section of check file Ini := TIniFile.Create(CheckfileDownload.Filename); if Ini.SectionExists(INISECT_RELEASE) then begin @@ -118,7 +153,7 @@ begin memoRelease.Lines.Add( 'Note: ' + Note ); btnRelease.Caption := 'Download version ' + ReleaseVersion; // Enable the download button if the current version is outdated - groupRelease.Enabled := ReleaseRevision > StrToIntDef(AppRevision, 0); + groupRelease.Enabled := (CurrentRevision > 0) and (ReleaseRevision > CurrentRevision); btnRelease.Enabled := groupRelease.Enabled; memoRelease.Enabled := groupRelease.Enabled; if not memoRelease.Enabled then @@ -141,7 +176,7 @@ begin // A new release should have priority over a new nightly build. // So the user should not be able to download a newer build here // before having installed the new release. - groupBuild.Enabled := (BuildRevision > StrToIntDef(AppRevision, 0)) and (not btnRelease.Enabled); + groupBuild.Enabled := (CurrentRevision > 0) and (BuildRevision > CurrentRevision) and (not btnRelease.Enabled); btnBuild.Enabled := groupBuild.Enabled; memoBuild.Enabled := groupBuild.Enabled; if not memoBuild.Enabled then @@ -149,9 +184,6 @@ begin else memoBuild.Font.Color := clWindowText; end; - - // Clear status label - Status(''); end;