OSDN Git Service

Implement GUI bindings for package download agent.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 10 Dec 2012 15:41:21 +0000 (15:41 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 10 Dec 2012 15:41:21 +0000 (15:41 +0000)
ChangeLog
Makefile.in
src/guidata.rc
src/guimain.h
src/guixmld.cpp
src/pkgbase.h
src/pkginet.cpp
src/pkginet.h [new file with mode: 0644]
src/pkgnget.cpp [new file with mode: 0644]

index dd587d3..5a2d54b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2012-12-10  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Implement GUI bindings for package download agent.
+
+       * src/guimain.h (IDD_PROGRESS_VAL, IDD_PROGRESS_MAX):
+       (IDD_PROGRESS_PCT): New manifest resource IDs; define them.  They will
+       be used to identify dialogue controls, to be associated with...
+       (IDD_APPLY_DOWNLOAD): ...this new dialogue template ID; define it.
+       (AppWindowMaker::DownloadArchiveFiles): New inline method; declare it.
+
+       * src/guidata.rc (IDD_APPLY_DOWNLOAD): Implement dialogue template.
+
+       * src/pkgbase.h (pkgActionItem::DownloadArchiveFiles): New public
+       inline method; declare it.  It overloads an existing private method of
+       the same name, which it subsequently invokes.
+
+       * src/pkginet.h: New header file; it declares...
+       (pkgInvokeDownload): ...this new extern "C" function prototype, and...
+       (pkgDownloadMeter): ...this abstract class; it is factored from its
+       original implementation in pkginet.cpp, augmented by addition of...
+       (pkgDownloadMeter::primary): New static member variable; declare it.
+       (pkgDownloadMeter::UseGUI): New public method; implement it inline.
+       (pkgDownloadMeter::ResetGUI): New public method; declare it, providing
+       a do-nothing inline default implementation.  Any derived class, which
+       supports GUI capability, should override this.
+
+       * src/pkgnget.cpp: New file; it implements...
+       (pkgDownloadMeterGUI): New class, derived from pkgDownloadMeter.
+       (pkgActionItem::DownloadArchiveFiles): New overloaded inline method.
+       (AppWindowMaker::DownloadArchiveFiles): New inline method.
+       (pkgInvokeDownload): New dialogue box worker thread handler.
+
+       * src/pkginet.cpp: Include pkginet.h; hence...
+       (pkgDownloadMeter): ...remove redundant class declaration.
+       (pkgDownloadMeter::primary): Define and initialise it.
+       (pkgInternetStreamingAgent::Get) [pkgDownloadMeter::UseGUI]: Delegate
+       progress metering to referenced pkgDownloadMeterGUI class instance.
+       [! pkgDownloadMeter::UseGUI]: Continue to use the existing built-in
+       pkgDownloadMeterTTY mechanism.
+       (pkgActionItem::DownloadSingleArchive) [ACTION_DOWLOAD_FAILED]: Assert
+       this initially; subsequently clear it on successful completion.
+       (pkgActionItem::DownloadArchiveFiles): Collect diagnostic messages
+       into a single DMH_BEGIN_DIGEST ... DMH_END_DIGEST group.
+
+       * src/guixmld.cpp: Include pkginet.h; it is required by...
+       (AppWindowMaker::OnCommand) [IDD_REPO_APPLY]: Use pkgInvokeDownload.
+
+       * Makefile.in (GUIMAIN_OBJECTS): Include pkgnget.$OBJEXT
+
 2012-12-08  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Implement "Discard" handler for GUI "Apply Changes" dialogue.
index 9e84a12..db410e4 100644 (file)
@@ -91,7 +91,8 @@ CLI_EXE_OBJECTS  =   \
 
 GUIMAIN_OBJECTS  =   \
    guimain.$(OBJEXT) guidata.$(OBJEXT) guixmld.$(OBJEXT) guidmh.$(OBJEXT) \
-   approot.$(OBJEXT) pkgview.$(OBJEXT) pkglist.$(OBJEXT) pkgdata.$(OBJEXT)
+   approot.$(OBJEXT) pkgview.$(OBJEXT) pkglist.$(OBJEXT) pkgdata.$(OBJEXT) \
+   pkgnget.$(OBJEXT)
 
 GUIMAIN_LIBS = -lwtklite -lcomctl32
 
index 9a8e037..5956998 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2012, MinGW Project
+ * Copyright (C) 2012, MinGW.org Project
  *
  *
  * Resource definitions for the mingw-get GUI implementation.
@@ -173,4 +173,21 @@ BEGIN
   EDITTEXT                             IDD_APPLY_INSTALLS_PACKAGES, 7, 148, 292, 36, WS_VSCROLL | ES_VT100
 END
 
+/* Template for GUI styled package download monitoring dialogue box.
+ */
+IDD_APPLY_DOWNLOAD DIALOG DISCARDABLE  10, 20, 280, 52
+CAPTION                                        "Download Package"
+STYLE                                  DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_CAPTION | WS_DLGFRAME
+FONT                                   10, "Verdana"
+BEGIN
+  LTEXT                                "Connecting...", IDD_PROGRESS_MSG, 7, 6, 266, 10
+  CONTROL                              "", IDD_PROGRESS_VAL, "STATIC", SS_CTEXTBOX, 6, 20, 100, 10
+  CTEXT                                        "of", IDD_PROGRESS_TXT, 106, 20, 18, 10
+  CONTROL                              "", IDD_PROGRESS_MAX, "STATIC", SS_CTEXTBOX, 124, 20, 100, 10
+  CTEXT                                        ":", IDD_PROGRESS_TXT, 224, 20, 10, 10
+  CONTROL                              "", IDD_PROGRESS_PCT, "STATIC", SS_CTEXTBOX, 234, 20, 40, 10
+  CONTROL                              "", IDD_PROGRESS_BAR, PROGRESS_CLASS, WS_CHILD \
+                                       | PBS_SMOOTH, 6, 35, 268, 10
+END
+
 /* $RCSfile$: end of file */
index 6a383af..f326a14 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2012, MinGW Project
+ * Copyright (C) 2012, MinGW.org Project
  *
  *
  * Resource definitions and window management class declarations for
 #define IDD_AUTO_CLOSE_OPTION           612
 #define IDD_PROGRESS_BAR                613
 #define IDD_PROGRESS_MSG                614
+#define IDD_PROGRESS_VAL                615
+#define IDD_PROGRESS_MAX                616
+#define IDD_PROGRESS_PCT                617
 #define IDD_PROGRESS_TXT                618
 
 #define IDD_APPLY_APPROVE               630
+#define IDD_APPLY_DOWNLOAD              631
 
 #define IDD_APPLY_REMOVES_PACKAGES      633
 #define IDD_APPLY_REMOVES_SUMMARY       634
@@ -173,6 +177,7 @@ class AppWindowMaker: public WTK::MainWindowMaker
     inline void DetachProgressMeter( pkgProgressMeter * );
 
     inline unsigned long EnumerateActions( int = 0 );
+    inline void DownloadArchiveFiles( void );
 
   private:
     virtual long OnCreate();
index 93e12d7..9c3a7df 100644 (file)
@@ -26,6 +26,7 @@
  */
 #include "guimain.h"
 #include "pkgbase.h"
+#include "pkginet.h"
 #include "pkgkeys.h"
 #include "pkglist.h"
 #include "pkgtask.h"
@@ -621,10 +622,10 @@ long AppWindowMaker::OnCommand( WPARAM cmd )
           * download any required packages, and invoke the scheduled
           * remove, upgrade, or install actions.
           *
-          * FIXME: the pkgInvokeDownload() and pkgApplyChanges() thread
-          * handlers have yet to be implemented.
+          * FIXME: the pkgInvokeDownload() thread handler has yet to
+          * be implemented.
           */
-//       DispatchDialogueThread( IDD_APPLY_DOWNLOAD, pkgInvokeDownload );
+         DispatchDialogueThread( IDD_APPLY_DOWNLOAD, pkgInvokeDownload );
 //       DispatchDialogueThread( IDD_APPLY_MONITORED, pkgApplyChanges );
 
          /* After applying changes, we fall through...
index 97f1223..7d2618c 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009, 2010, 2011, 2012, MinGW Project
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
  *
  *
  * Public interface for the package directory management routines;
@@ -336,9 +336,10 @@ class pkgActionItem
     void GetSourceArchive( pkgXmlNode*, unsigned long );
     void GetScheduledSourceArchives( unsigned long );
 
-    /* Method for processing all scheduled actions.
+    /* Methods for processing all scheduled actions.
      */
     void Execute();
+    inline void DownloadArchiveFiles( void );
 
     /* Method to manipulate error trapping, control, and state
      * flags for the schedule of actions.
index 12b5775..65c821f 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009, 2010, 2011, 2012, MinGW Project
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
  *
  *
  * Implementation of the package download machinery for mingw-get.
 #include "debug.h"
 
 #include "pkgbase.h"
+#include "pkginet.h"
 #include "pkgkeys.h"
 #include "pkgtask.h"
 
-class pkgDownloadMeter
-{
-  /* Abstract base class, from which facilities for monitoring the
-   * progress of file downloads may be derived.
-   */
-  public:
-    /* The working method to refresh the download progress display;
-     * each derived class MUST furnish an implementation for this.
-     */
-    virtual int Update( unsigned long length ) = 0;
-
-  protected:
-    /* Storage for the expected size of the active download...
-     */
-    unsigned long content_length;
-
-    /* ...and a method to format it for human readable display.
-     */
-    int SizeFormat( char*, unsigned long );
-};
+/* This static member variable of the pkgDownloadMeter class
+ * provides a mechanism for communicating with a pre-existing
+ * download monitoring dialogue, such as is employed in the GUI.
+ * We MUST define it, and we also initialise it to NULL.  While
+ * it remains thus, (as it always does in the CLI), no attempt
+ * will be made to access any pre-existing dialogue, and local
+ * monitoring objects will be employed; the GUI sets this to
+ * refer to its dialogue, when this is activated.
+ */
+pkgDownloadMeter *pkgDownloadMeter::primary = NULL;
 
 class pkgDownloadMeterTTY : public pkgDownloadMeter
 {
@@ -602,12 +593,33 @@ int pkgInternetStreamingAgent::Get( const char *from_url )
        /* With the download transaction fully specified, we may
         * request processing of the file transfer...
         */
-       pkgDownloadMeterTTY download_meter
-         (
-           from_url, pkgDownloadAgent.QueryContentLength( dl_host )
-         );
-       dl_meter = &download_meter;
-       dl_status = TransferData( fd );
+       if( (dl_meter = pkgDownloadMeter::UseGUI()) != NULL )
+       {
+         /* ...with progress monitoring delegated to the GUI's
+          * dialogue box, when running under its auspices...
+          */
+         dl_meter->ResetGUI(
+             filename, pkgDownloadAgent.QueryContentLength( dl_host )
+           );
+         dl_status = TransferData( fd );
+       }
+       else
+       { /* ...otherwise creating our own TTY progress monitor,
+          * when running under the auspices of the CLI.
+          */
+         pkgDownloadMeterTTY download_meter(
+             from_url, pkgDownloadAgent.QueryContentLength( dl_host )
+           );
+         dl_meter = &download_meter;
+
+         /* Note that the following call MUST be kept within the
+          * scope in which the progress monitor was created; thus,
+          * it CANNOT be factored out of this "else" block scope,
+          * even though it also appears at the end of the scope
+          * of the preceding "if" block.
+          */
+         dl_status = TransferData( fd );
+       }
       }
       else DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_INTERNET_REQUESTS ),
          dmh_printf( "OpenURL:error:%d\n", GetLastError() )
@@ -682,8 +694,10 @@ void pkgActionItem::DownloadSingleArchive
   if(  ((flags & ACTION_DOWNLOAD) == ACTION_DOWNLOAD)
   &&   ((access( download.DestFile(), R_OK ) != 0) && (errno == ENOENT))  )
   {
-    /* ...if not, ask the download agent to fetch it...
+    /* ...if not, ask the download agent to fetch it,
+     * anticipating that this may fail...
      */
+    flags |= ACTION_DOWNLOAD_FAILED;
     const char *url_template = get_host_info( Selection(), uri_key );
     if( url_template != NULL )
     {
@@ -695,9 +709,9 @@ void pkgActionItem::DownloadSingleArchive
       mkpath( package_url, url_template, package_name, mirror );
       if( download.Get( package_url ) > 0 )
        /*
-        * Download was successful; clear the pending flag.
+        * Download was successful; clear the pending and failure flags.
         */
-       flags &= ~(ACTION_DOWNLOAD);
+       flags &= ~(ACTION_DOWNLOAD | ACTION_DOWNLOAD_FAILED);
       else
        /* Diagnose failure; leave pending flag set.
         */
@@ -728,8 +742,10 @@ void pkgActionItem::DownloadArchiveFiles( pkgActionItem *current )
    */
   while( current != NULL )
   {
-    /* ...while we haven't run off the end...
+    /* ...while we haven't run off the end, and collecting any diagnositic
+     * messages relating to any one package into a common digest...
      */
+    dmh_control( DMH_BEGIN_DIGEST );
     if( (current->flags & ACTION_INSTALL) == ACTION_INSTALL )
     {
       /* For all packages specified in the current action list,
@@ -755,9 +771,11 @@ void pkgActionItem::DownloadArchiveFiles( pkgActionItem *current )
         */
        current->DownloadSingleArchive( package_name, pkgArchivePath() );
     }
-    /* Repeat download action, for any additional packages specified
+    /* Flush out any diagnostics relating to the current package, then
+     * repeat the download action, for any additional packages specified
      * in the current "actions" list.
      */
+    dmh_control( DMH_END_DIGEST );
     current = current->next;
   }
 }
diff --git a/src/pkginet.h b/src/pkginet.h
new file mode 100644 (file)
index 0000000..4e4da0a
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef PKGINET_H
+/*
+ * pkginet.h
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
+ *
+ *
+ * Public declaration of the download metering class, and support
+ * functions provided by the internet download agent.
+ *
+ *
+ * This is free software.  Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#define PKGINET_H  1
+
+class pkgDownloadMeter
+{
+  /* Abstract base class, from which facilities for monitoring the
+   * progress of file downloads may be derived.
+   */
+  public:
+    /* Hooks for use in the implementation of the GUI download
+     * monitoring dialogue; in a CLI context, these effectively
+     * become no-ops.
+     */
+    static pkgDownloadMeter *UseGUI(){ return primary; }
+    virtual void ResetGUI( const char *, unsigned long ){}
+
+    /* The working method to refresh the download progress display;
+     * each derived class MUST furnish an implementation for this.
+     */
+    virtual int Update( unsigned long ) = 0;
+
+  protected:
+    /* Reference pointer to the primary instance of the download
+     * meter in the GUI; always set to NULL, in a CLI context.
+     */
+    static pkgDownloadMeter *primary;
+
+    /* Storage for the expected size of the active download...
+     */
+    unsigned long content_length;
+
+    /* ...and a method to format it for human readable display.
+     */
+    int SizeFormat( char *, unsigned long );
+};
+
+/* Entry point for the worker thread associated with the download
+ * monitoring dialogue, in the GUI context.
+ */
+EXTERN_C void pkgInvokeDownload( void * );
+
+#endif /* PKGINET_H: $RCSfile$: end of file */
diff --git a/src/pkgnget.cpp b/src/pkgnget.cpp
new file mode 100644 (file)
index 0000000..484accc
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * pkgnget.cpp
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW.org Project
+ *
+ *
+ * Implementation of the network download agent interface, through
+ * which the mingw-get GUI requests the services of the mingw-get DLL
+ * to get (download) package archives from internet repositories.
+ *
+ *
+ * This is free software.  Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#include "guimain.h"
+#include "pkgbase.h"
+#include "pkginet.h"
+
+class pkgDownloadMeterGUI: public pkgDownloadMeter
+{
+  /* A locally defined class, through which the download agent
+   * may transmit progress monitoring data to the designated GUI
+   * download monitoring dialogue box.
+   */
+  public:
+    pkgDownloadMeterGUI( HWND );
+
+    virtual void ResetGUI( const char *, unsigned long );
+    virtual int Update( unsigned long );
+
+    inline ~pkgDownloadMeterGUI();
+
+  private:
+    HWND file_name, file_size, copy_size, copy_frac, progress_bar;
+};
+
+/* Constructor...
+ */
+pkgDownloadMeterGUI::pkgDownloadMeterGUI( HWND dialogue )
+{
+  /* Establish the global reference, through which the download
+   * agent will obtain access to the GUI dialogue...
+   */
+  primary = this;
+
+  /* ...and store references to its data controls.
+   */
+  file_name = GetDlgItem( dialogue, IDD_PROGRESS_MSG );
+  file_size = GetDlgItem( dialogue, IDD_PROGRESS_MAX );
+  copy_size = GetDlgItem( dialogue, IDD_PROGRESS_VAL );
+  copy_frac = GetDlgItem( dialogue, IDD_PROGRESS_PCT );
+  progress_bar = GetDlgItem( dialogue, IDD_PROGRESS_BAR );
+}
+
+void pkgDownloadMeterGUI::ResetGUI( const char *filename, unsigned long size )
+{
+  /* Method to reset the displayed content of the dialogue box to
+   * an appropriate initial state, in preparation for monitoring the
+   * download of a new archive file; the name of this file, and its
+   * anticipated size are preset, as specified by the arguments.
+   */
+  char size_buf[12]; SizeFormat( size_buf, 0 );
+  SendMessage( file_name, WM_SETTEXT, 0, (LPARAM)(filename) );
+  SendMessage( copy_size, WM_SETTEXT, 0, (LPARAM)(size_buf) );
+  SizeFormat( size_buf, content_length = size );
+  SendMessage( file_size, WM_SETTEXT, 0, (LPARAM)(size_buf) );
+  SendMessage( copy_frac, WM_SETTEXT, 0, (LPARAM)("0 %") );
+  SendMessage( progress_bar, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
+  SendMessage( progress_bar, PBM_SETPOS, 0, 0 );
+}
+
+int pkgDownloadMeterGUI::Update( unsigned long count )
+{
+  /* Method to update the download progress report; the download
+   * agent invokes this after each block of archive data has been
+   * received from the repository host, so that this method may
+   * refresh the progress counters in the dialogue box.
+   */
+  char size_buf[12];
+
+  /* First, we update the display of the actual byte count...
+   */
+  SizeFormat( size_buf, count );
+  SendMessage( copy_size, WM_SETTEXT, 0, (LPARAM)(size_buf) );
+
+  /* ...then we convert that byte count to a percentage of
+   * the anticipated file size, using the result to update
+   * the percentage completed, and the progress bar.
+   */
+  count = (count * 100) / content_length;
+  if( snprintf( size_buf, sizeof( size_buf ), "%d %", count ) >= sizeof( size_buf ) )
+    strcpy( size_buf, "*** %" );
+  SendMessage( copy_frac, WM_SETTEXT, 0, (LPARAM)(size_buf) );
+  SendMessage( progress_bar, PBM_SETPOS, count, 0 );
+}
+
+/* Destructor...
+ */
+inline pkgDownloadMeterGUI::~pkgDownloadMeterGUI()
+{
+  /* This must reset the global reference pointer, so the download
+   * agent will not attempt to access a dialogue box which has been
+   * closed by the GUI application.
+   */
+  primary = NULL;
+}
+
+inline void pkgActionItem::DownloadArchiveFiles( void )
+{
+  /* Helper method, invoked by the GUI application, to initiate
+   * an in-order traversal of the schedule of actions...
+   */
+  pkgActionItem *current;
+  if( (current = this) != NULL )
+  {
+    /* ...ensuring that the traversal commences at the first of
+     * the scheduled actions...
+     */
+    while( current->prev != NULL ) current = current->prev;
+
+    /* ...to download all requisite archive files.
+     */
+    DownloadArchiveFiles( current );
+  }
+}
+
+inline void AppWindowMaker::DownloadArchiveFiles( void )
+{
+  /* Helper method to redirect a request to initiate package
+   * download, from the controlling application window object
+   * to its associated schedule of actions object.
+   */
+  pkgData->Schedule()->DownloadArchiveFiles();
+}
+
+EXTERN_C void pkgInvokeDownload( void *window )
+{
+  /* Worker thread procedure, invoked by the OnCommand() method
+   * of the application window object, when initiating the archive
+   * download process via the appropriate monitoring dialogue.
+   */
+  pkgDownloadMeterGUI metered( (HWND)(window) );
+  GetAppWindow( GetParent( (HWND)(window) ))->DownloadArchiveFiles();
+  SendMessage( (HWND)(window), WM_COMMAND, (WPARAM)(IDOK), 0 );
+}
+
+/* $RCSfile$: end of file */