Menu

Diff of /trunk/Src/UUpdateCheckers.pas [000000] .. [r2883]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/trunk/Src/UUpdateCheckers.pas
@@ -0,0 +1,263 @@
+{
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at http://mozilla.org/MPL/2.0/
+ *
+ * Copyright (C) 2013, Peter Johnson (www.delphidabbler.com).
+ *
+ * $Rev$
+ * $Date$
+ *
+ * Implements thread classes that check online to find if updates to the
+ * CodeSnip program or online database are available. Also implements a manager
+ * class for these threads.
+}
+
+
+unit UUpdateCheckers;
+
+
+interface
+
+
+uses
+  // Delphi
+  ExtActns,
+  // Project
+  Notifications.UData, Notifications.URecorderThread, UThreadGroup;
+
+
+type
+  ///  <summary>Thread that checks online to find if a new version of CodeSnip
+  ///  is available.</summary>
+  ///  <remarks>
+  ///  <para>No check is made if the user has switched the facility off in
+  ///  preferences.</para>
+  ///  <para>The thread fails silently as if no update is available if any
+  ///  errors occur when accessing the internet or web service.</para>
+  ///  <para>If an update is found a notification containing the details is
+  ///  placed in the notification queue to await display.</para>
+  ///  </remarks>
+  TProgramUpdateCheckerThread = class(TNotificationRecorderThread)
+  strict private
+    var
+      ///  <summary>Action that causes a web page to be displayed from where
+      ///  a program update can be downloaded.</summary>
+      ///  <remarks>This action is executed when the user clicks the 'task
+      ///  button' in any program update notification window.</remarks>
+      fDownloadAction: TBrowseURL;
+  strict protected
+    ///  <summary>Finds if an update of the CodeSnip program is available and
+    ///  creates a notification containing information about it if so.
+    ///  </summary>
+    ///  <param name="N">TNotificationData [out] If an update is available this
+    ///  parameter contains information about the update to be added to the
+    ///  notification queue. If no update is available this value is undefined.
+    ///  </param>
+    ///  <returns>Boolean. True if an update is a available and a notification
+    ///  record was created or False if no update is available.</returns>
+    ///  <remarks>False is also returned if an error was encountered or if the
+    ///  user has disabled automatic checking for program updates.</remarks>
+    function GetNotification(out N: TNotificationData): Boolean; override;
+  public
+    ///  <summary>Creates the and initialises the thread instance.</summary>
+    ///  <param name="StartDelay">Cardinal [in] Number of milliseconds to delay
+    ///  the start of the thread's execution. Passing 0 indicates no delay.
+    ///  Non-zero delays are rounded up to the nearest 1/5th second.</param>
+    constructor Create(StartDelay: Cardinal = 0);
+    ///  <summary>Destroys thread object instance.</summary>
+    destructor Destroy; override;
+  end;
+
+type
+  ///  <summary>Thread that checks online to find if a new version of the online
+  ///  code snippets database is available.</summary>
+  ///  <remarks>
+  ///  <para>No check is made if the user has switched the facility off in
+  ///  preferences.</para>
+  ///  <para>The thread fails silently as if no update is available if any
+  ///  errors occur when accessing the internet or web service.</para>
+  ///  <para>If an update is found a notification containing the details is
+  ///  placed in the notification queue to await display.</para>
+  ///  </remarks>
+  TDatabaseUpdateCheckerThread = class(TNotificationRecorderThread)
+  strict protected
+    ///  <summary>Checks if the local copy of the online database is up to date
+    ///  and creates a notification containing information about it if so.
+    ///  </summary>
+    ///  <param name="N">TNotificationData [out] If an update is available this
+    ///  parameter contains information about the update to be added to the
+    ///  notification queue. If no update is available this value is undefined.
+    ///  </param>
+    ///  <returns>Boolean. True if an update is a available and a notification
+    ///  record was created or False if no update is available.</returns>
+    ///  <remarks>False is also returned if an error was encountered or if the
+    ///  user has disabled automatic checking for database updates.</remarks>
+    function GetNotification(out N: TNotificationData): Boolean; override;
+  end;
+
+type
+  ///  <summary>Manages creation and lifetime of the background threads that
+  ///  check for and notify program and online code snippets database updates.
+  ///  </summary>
+  TUpdateCheckerMgr = class(TObject)
+  strict private
+    var
+      ///  <summary>Manages the lifetime of the update threads.</summary>
+      fThreads: TThreadGroup;
+  public
+    ///  <summary>Creates new object instance and creates and initialises the
+    ///  update checker threads.</summary>
+    ///  <remarks>The threads are created suspended.</remarks>
+    constructor Create;
+    ///  <summary>Destroys object instance and update checker threads.</summary>
+    ///  <remarks>Waits for any non-terminated threads to complete.</remarks>
+    destructor Destroy; override;
+    ///  <summary>Starts the update checker threads.</summary>
+    procedure StartThreads;
+    ///  <summary>Signals the update checker threads to terminate.</summary>
+    ///  <remarks>Does not wait for the threads to complete.</remarks>
+    procedure StopThreads;
+  end;
+
+
+implementation
+
+
+uses
+  // Delphi
+  SysUtils, Classes,
+  // Project
+  FmUpdateDlg, UAppInfo, UPreferences, UProgramUpdateChecker, UUpdateMgr;
+
+
+{ TProgramUpdateCheckerThread }
+
+constructor TProgramUpdateCheckerThread.Create(StartDelay: Cardinal);
+begin
+  inherited Create(StartDelay);
+  fDownloadAction := TBrowseURL.Create(nil);
+end;
+
+destructor TProgramUpdateCheckerThread.Destroy;
+begin
+  fDownloadAction.Free;
+  inherited;
+end;
+
+function TProgramUpdateCheckerThread.GetNotification(out N: TNotificationData):
+  Boolean;
+resourcestring
+  sTitle = 'Program Update Available';
+  sContent = 'CodeSnip version %s is available for download.';
+  sDownloadPrompt = 'Download Now';
+const
+  HelpKeyword = 'ProgramUpdateNotification';
+var
+  UpdateChecker: TProgramUpdateChecker;
+  Content: TArray<string>;
+  TaskCallback: TProc;
+begin
+  try
+    if not Preferences.AutoCheckProgramUpdates then
+      Exit(False);
+    UpdateChecker := TProgramUpdateChecker.Create;
+    try
+      if not UpdateChecker.Execute('Auto') then
+        Exit(False);
+      fDownloadAction.URL := UpdateChecker.DownloadURL;
+      Content := TArray<string>.Create(
+        Format(sContent, [string(UpdateChecker.LatestVersion)])
+      );
+      TaskCallback :=
+        procedure
+        begin
+          fDownloadAction.Execute;
+        end;
+      N := TNotificationData.Create(
+        sTitle, Content, HelpKeyword, TaskCallback, sDownloadPrompt
+      );
+      Result := True;
+    finally
+      UpdateChecker.Free;
+    end;
+  except
+    // Swallow any exception and return false to indicate "no update"
+    Result := False;
+  end;
+end;
+
+{ TDatabaseUpdateCheckerThread }
+
+function TDatabaseUpdateCheckerThread.GetNotification(
+  out N: TNotificationData): Boolean;
+resourcestring
+  sTitle = 'Database Update Available';
+  sContent1 = 'The online Code Snippets Database has been updated.';
+  sContent2 = 'You can update your local copy of the database to reflect the '
+    + 'changes.';
+  sUpdatePrompt = 'Update Now';
+const
+  HelpKeyword = 'DatabaseUpdateNotification';
+var
+  UpdateMgr: TUpdateMgr;
+  Content: TArray<string>;
+  TaskCallback: TProc;
+begin
+  try
+    if not Preferences.AutoCheckDatabaseUpdates then
+      Exit(False);
+    UpdateMgr := TUpdateMgr.Create(TAppInfo.AppDataDir);
+    try
+      if UpdateMgr.CheckForUpdates in [uqUpToDate, uqError] then
+        Exit(False);
+      Content := TArray<string>.Create(sContent1, sContent2);
+      TaskCallback :=
+        procedure
+        begin
+          TUpdateDlg.Execute(nil);
+        end;
+      N := TNotificationData.Create(
+        sTitle, Content, HelpKeyword, TaskCallback, sUpdatePrompt
+      );
+      Result := True;
+    finally
+      UpdateMgr.Free;
+    end
+  except
+    // Swallow any exception and return false to indicate "no update"
+    Result := False;
+  end;
+end;
+
+{ TUpdateCheckerMgr }
+
+constructor TUpdateCheckerMgr.Create;
+begin
+  inherited Create;
+  fThreads := TThreadGroup.Create;
+  fThreads.Add([
+    TProgramUpdateCheckerThread.Create(10000),  // begins work after 10s delay
+    TDatabaseUpdateCheckerThread.Create(20000)  // begins work after 20s delay
+  ]);
+  fThreads.SetPriorities(tpLowest);
+end;
+
+destructor TUpdateCheckerMgr.Destroy;
+begin
+  fThreads.Free;
+  inherited;
+end;
+
+procedure TUpdateCheckerMgr.StartThreads;
+begin
+  fThreads.Start;
+end;
+
+procedure TUpdateCheckerMgr.StopThreads;
+begin
+  fThreads.Terminate;
+end;
+
+end.
+
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.