+2012-10-27 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ Initiate progress metering for catalogue load and update operations.
+
+ * src/guidata.rc (IDD_REPO_UPDATE): New dialogue template; define it.
+ (IDM_REPO_UPDATE): Enable selection from "Repository" drop-down menu.
+
+ * src/guimain.h (IDD_REPO_UPDATE, IDD_CLOSE_OPTIONS):
+ (IDD_AUTO_CLOSE_OPTION, IDD_PROGRESS_BAR, IDD_PROGRESS_MSG): New
+ resource identification manifest constants; define them.
+ (pkgXmlNode, pkgProgressMeter): Add forward class declarations.
+ (AppWindowMaker::AttachedProgressMeter): New private data; define...
+ (AppWindowMaker::AppWindowMaker): ...and initialise it.
+ (AppWindowMaker::AttachProgressMeter): New public method; declare it.
+ (AppWindowMaker::DetachProgressMeter): Likewise.
+ (AppWindowMaker::LoadPackageData, AppWindowMaker::ClearPackageList):
+ (AppWindowMaker::UpdatePackageList): Make them public.
+
+ * src/pkgbase.h (pkgProgressMeter): New abstract class; declare it.
+ (AppWindowMaker) [GUIMAIN_H undefined]: Add forward class declaration.
+ (pkgXmlDocument::progress_meter): New private data member; declare...
+ (pkgXmlDocument::pkgXmlDocument): ...and initialise it.
+ (pkgXmlDocument::ProgressMeter, pkgXmlDocument::AttachProgressMeter):
+ (pkgXmlDocument::DetachProgressMeter): New public inline methods;
+ implement them.
+
+ * src/pkgview.cpp (WTK::GenericDialogue): Delete disused reference.
+ (AppWindowMaker::OnCommand): Factor out implementation; relocate it...
+ * src/guixmld.cpp: ...to here; thus it may utilise dependants of...
+ (ProgressMeterMaker): ...this new locally implemented class.
+ (AppWindowMaker::AttachProgressMeter): Implement it.
+ (AppWindowMaker::AttachProgressMeter): Likewise.
+ (pkgProgressMeter::~pkgProgressMeter): Likewise.
+ (pkgUpdate, pkgInvokeUpdate): New static functions; implement them.
+ (AppWindowMaker::Invoked): Replace direct call to LoadPackageData by
+ an indirect invocation, via a progress metering dialogue box using...
+ (pkgInitDataLoad): ...this new static callback function, invoking...
+ (pkgInvokeInitDataLoad): ...this new static thread function, whence...
+ (AppWindowMaker::LoadPackageData): ...this; add hook-up call to...
+ (pkgXmlDocument::AttachProgressMeter): ...incorporate this.
+
+ * src/pkgbind.cpp (pkgRepository::total, pkgRepository::count): New
+ private static properties; declare and instantiate them; provide...
+ (pkgRepository::Reset, pkgRepository::IncrementTotal): ...new public
+ static methods to manipulate them; declare and implement them inline.
+ (pkgRepository::GetPackageList): Use them to manage updates to the
+ pkgProgressMeter class instance, if any, which has been bound to
+ the controlling pkgXmlDocument class instance, when invoking...
+ (pkgXmlXmlDocument::BindRepositories): ...this.
+
2012-10-18 Keith Marshall <keithmarshall@users.sourceforge.net>
Associate DMH message boxes with active dialogues.
*/
POPUP "&Repository"
BEGIN
- MENUITEM "&Update Catalogue", IDM_REPO_UPDATE, GRAYED
+ MENUITEM "&Update Catalogue", IDM_REPO_UPDATE
MENUITEM SEPARATOR
MENUITEM "&Quit\tAlt+F4", IDM_REPO_QUIT
END
ID_PKGSTATE_REMOVE ICON DISCARDABLE "state12.ico"
ID_PKGSTATE_PURGE ICON DISCARDABLE "state13.ico"
+/* Template for progress meter dialogue box.
+ */
+IDD_REPO_UPDATE DIALOG DISCARDABLE 10, 20, 270, 60
+CAPTION "Update Package Catalogue"
+STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_CAPTION | WS_DLGFRAME
+FONT 10, "Verdana"
+BEGIN
+ GROUPBOX "Actions", IDD_CLOSE_OPTIONS, 5, 31, 260, 25
+ DEFPUSHBUTTON "Close", IDOK, 219, 39, 40, 12, WS_GROUP | WS_DISABLED
+ AUTOCHECKBOX "Close dialogue automatically, when update is complete.", \
+ IDD_AUTO_CLOSE_OPTION, 10, 41, 200, 11
+ CONTROL "", IDD_PROGRESS_BAR, PROGRESS_CLASS, WS_CHILD \
+ | PBS_SMOOTH, 6, 20, 258, 10
+ LTEXT "", IDD_PROGRESS_MSG, 7, 6, 256, 12
+END
+
/* $RCSfile$: end of file */
#define IDM_HELP_ABOUT 603
#define IDD_HELP_ABOUT 603
+#define IDD_REPO_UPDATE 610
+#define IDD_CLOSE_OPTIONS 611
+#define IDD_AUTO_CLOSE_OPTION 612
+#define IDD_PROGRESS_BAR 613
+#define IDD_PROGRESS_MSG 614
+
#define ID_PKGLIST_TABLE_HEADINGS 1024
#define ID_PKGNAME_COLUMN_HEADING 1025
#define ID_PKGTYPE_COLUMN_HEADING 1026
#include <wtklite.h>
#include <commctrl.h>
+class pkgXmlNode;
class pkgXmlDocument;
+class pkgProgressMeter;
class DataSheetMaker;
class AppWindowMaker;
{
public:
AppWindowMaker( HINSTANCE inst ): WTK::MainWindowMaker( inst ),
- pkgData( NULL ), DefaultFont( (HFONT)(GetStockObject( DEFAULT_GUI_FONT )) ){}
+ pkgData( NULL ), DefaultFont( (HFONT)(GetStockObject( DEFAULT_GUI_FONT )) ),
+ AttachedProgressMeter( NULL ){}
~AppWindowMaker(){ /* delete ChildWindows; */ DeleteObject( DefaultFont ); }
HWND Create( const char *, const char * );
inline long AdjustLayout( void ){ return OnSize( 0, 0, 0 ); }
int Invoked( void );
+ void LoadPackageData( bool = false );
+ void ClearPackageList( void ){ ListView_DeleteAllItems( PackageListView ); }
+ void UpdatePackageList( void );
+
+ inline pkgProgressMeter *AttachProgressMeter( pkgProgressMeter * );
+ inline void DetachProgressMeter( pkgProgressMeter * );
+
private:
virtual long OnCreate();
virtual long OnCommand( WPARAM );
WTK::SashWindowMaker *HorizontalSash, *VerticalSash;
pkgXmlDocument *pkgData;
- void LoadPackageData( bool = false );
+ pkgProgressMeter *AttachedProgressMeter;
HFONT DefaultFont;
HWND PackageListView;
void InitPackageListView( void );
- void ClearPackageList( void ){ ListView_DeleteAllItems( PackageListView ); }
- void UpdatePackageList( void );
DataSheetMaker *DataSheet;
WTK::ChildWindowMaker *TabDataPane;
#include <unistd.h>
#include <wtkexcept.h>
-int AppWindowMaker::Invoked( void )
+class ProgressMeterMaker: public pkgProgressMeter
{
- /* Override for the WTK::MainWindowMaker::Invoked() method; it
- * provides the hook for the initial loading of the XML database,
- * and creation of the display controls through which its content
- * will be presented to the user, prior to invocation of the main
- * window's message loop.
- *
- * The data displays depend on the MS-Windows Common Controls API;
- * initialise all components of this up front.
+ /* A locally defined class, supporting progress metering
+ * for package catalogue update and load operations.
*/
- InitCommonControls();
+ public:
+ ProgressMeterMaker( HWND, HWND, AppWindowMaker * );
+
+ virtual int Annotate( const char *, ... );
+ virtual void SetRange( int, int );
+ virtual void SetValue( int );
+
+ protected:
+ HWND message_line, progress_bar;
+};
- /* Load the data from the XML catalogue files, and construct the
- * initial view of the available package list.
+inline
+pkgProgressMeter *AppWindowMaker::AttachProgressMeter( pkgProgressMeter *meter )
+{
+ /* A local helper method for attaching a progress meter to the
+ * controlling class instance for the main application window.
*/
- LoadPackageData();
- InitPackageListView();
+ if( AttachedProgressMeter == NULL )
+ AttachedProgressMeter = meter;
+ return AttachedProgressMeter;
+}
- /* Initialise the data-sheet tab control, displaying the default
- * "no package selected" message.
+inline void AppWindowMaker::DetachProgressMeter( pkgProgressMeter *meter )
+{
+ /* A local helper method for detaching a progress meter from the
+ * controlling class instance for the main application window.
*/
- InitPackageTabControl();
+ if( meter == AttachedProgressMeter )
+ {
+ pkgData->DetachProgressMeter( meter );
+ AttachedProgressMeter = NULL;
+ }
+}
- /* Force a layout adjustment, to ensure that the displayed
- * data controls are correctly populated.
+/* We need to provide a destructor for the abstract base class, from which
+ * our progress meters are derived; here is as good a place as any.
+ */
+pkgProgressMeter::~pkgProgressMeter(){ referrer->DetachProgressMeter( this ); }
+
+/* We must also provide the implementation of our local progress meter class.
+ */
+ProgressMeterMaker::ProgressMeterMaker
+( HWND annotation, HWND indicator, AppWindowMaker *owner ):
+pkgProgressMeter( owner ), message_line( annotation ), progress_bar( indicator )
+{
+ /* Constructor creates an instance of the progress meter class, attaching it
+ * to the main application window, with an initial metering range of 0..100%,
+ * and a starting indicated completion state of 0%.
*/
- AdjustLayout();
+ owner->AttachProgressMeter( this );
+ SetRange( 0, 100 );
+ SetValue( 0 );
+}
- /* Finally, we may delegate all further processing to the main
- * window's message loop.
+int ProgressMeterMaker::Annotate( const char *fmt, ... )
+{
+ /* Method to add a printf() style annotation to the progress meter dialogue.
*/
- return WTK::MainWindowMaker::Invoked();
+ va_list argv;
+ va_start( argv, fmt );
+ char annotation[1 + vsnprintf( NULL, 0, fmt, argv )];
+ int len = vsnprintf( annotation, sizeof( annotation ), fmt, argv );
+ va_end( argv );
+
+ SendMessage( message_line, WM_SETTEXT, 0, (LPARAM)(annotation) );
+ return len;
}
+void ProgressMeterMaker::SetRange( int min, int max )
+{
+ /* Method to adjust the range of the progress meter, to represent any
+ * arbitrary range of discrete values, rather than percentage units.
+ */
+ SendMessage( progress_bar, PBM_SETRANGE, 0, MAKELPARAM( min, max ) );
+}
+
+void ProgressMeterMaker::SetValue( int value )
+{
+ /* Method to update the indicated completion state of a progress meter,
+ * to represent any arbitrary value within its assigned metering range.
+ */
+ SendMessage( progress_bar, PBM_SETPOS, value, 0 );
+}
+
+/* Implementation of service routines, for loading the package catalogue
+ * from its defining collection of XML files.
+ */
void AppWindowMaker::LoadPackageData( bool force_update )
{
/* Helper method to load the package database from its
/* Establish the repository URI references, for retrieval
* of the downloadable catalogue files, and load them...
*/
+ pkgData->AttachProgressMeter( AttachedProgressMeter );
if( pkgData->BindRepositories( force_update ) == NULL )
/*
* ...once again, bailing out on failure.
pkgData->LoadSystemMap();
}
+static void pkgInvokeInitDataLoad( void *window )
+{
+ /* Thread procedure for performing the initial catalogue load, on
+ * application start-up. This will load from locally cached data
+ * files, when available; however, it will also initiate a download
+ * from the remote repository, for any file which is missing from
+ * the local cache. Since this may be a time consuming process,
+ * we subject it to progress metering, to ensure that the user is
+ * not left staring at an apparently hung, blank window.
+ */
+ HWND msg = GetDlgItem( (HWND)(window), IDD_PROGRESS_MSG );
+ HWND dlg = GetDlgItem( (HWND)(window), IDD_PROGRESS_BAR );
+ AppWindowMaker *app = GetAppWindow( GetParent( (HWND)(window) ));
+ SendMessage( (HWND)(window),
+ WM_SETTEXT, 0, (LPARAM)("Loading Package Catalogue")
+ );
+ ProgressMeterMaker ui( msg, dlg, app );
+
+ /* For this activity, we request automatic dismissal of the dialogue,
+ * when loading has been completed; the user will have an opportunity
+ * to countermand this choice, if loading is delayed by the required
+ * download of any missing local catalogue file.
+ */
+ dlg = GetDlgItem( (HWND)(window), IDD_AUTO_CLOSE_OPTION );
+ SendMessage( dlg, WM_SETTEXT, 0,
+ (LPARAM)("Close dialogue automatically, when loading is complete.")
+ );
+ CheckDlgButton( (HWND)(window), IDD_AUTO_CLOSE_OPTION, BST_CHECKED );
+
+ /* We've now set up the initial state for the progress meter dialogue;
+ * proceed to load, (and perhaps download), the XML data files.
+ */
+ app->LoadPackageData( false );
+
+ /* When loading has been completed, automatically dismiss the dialogue...
+ */
+ if( IsDlgButtonChecked( (HWND)(window), IDD_AUTO_CLOSE_OPTION ) )
+ SendMessage( (HWND)(window), WM_COMMAND, (WPARAM)(IDOK), 0 );
+
+ /* ...unless the user has countermanded the automatic dismissal request...
+ */
+ else
+ { /* ...in which case, we activate the manual dismissal button...
+ */
+ if( (dlg = GetDlgItem( (HWND)(window), IDOK )) != NULL )
+ EnableWindow( dlg, TRUE );
+
+ /* ...and notify the user that it must be clicked to continue.
+ */
+ ui.Annotate( "Data has been loaded; please close this dialogue to continue." );
+ }
+}
+
+static int CALLBACK pkgInitDataLoad
+( HWND window, unsigned int msg, WPARAM wParam, LPARAM lParam )
+{
+ /* Handler for the initial catalogue loading progress dialogue.
+ */
+ switch( msg )
+ {
+ /* We need to handle only two classes of windows messages
+ * on behalf of this dialogue box...
+ */
+ case WM_INITDIALOG:
+ /*
+ * ...viz. on initial dialogue box creation, we delegate the actual
+ * activity, of loading the catalogue, to this background thread...
+ */
+ _beginthread( pkgInvokeInitDataLoad, 0, (void *)(window) );
+ return TRUE;
+
+ case WM_COMMAND:
+ if( LOWORD( wParam ) == IDOK )
+ {
+ /* ...then we wait for a notification that the dialogue may be
+ * closed, (which isn't permitted until the thread completes).
+ */
+ EndDialog( window, 0 );
+ return TRUE;
+ }
+ }
+ /* Any other messages, which are directed to this dialogue box, may be
+ * safely ignored.
+ */
+ return FALSE;
+}
+
+static void pkgInvokeUpdate( void *window )
+{
+ /* Thread procedure for performing a package catalogue update.
+ * This will download catalogue files from the remote repository,
+ * and integrate them into the locally cached catalogue XML file
+ * set. Since this is normally a time consuming process, we must
+ * subject it to progress metering, to ensure that the user is
+ * not left staring at an apparently hung, blank window.
+ */
+ HWND msg = GetDlgItem( (HWND)(window), IDD_PROGRESS_MSG );
+ HWND dlg = GetDlgItem( (HWND)(window), IDD_PROGRESS_BAR );
+ AppWindowMaker *app = GetAppWindow( GetParent( (HWND)(window) ));
+ ProgressMeterMaker ui( msg, dlg, app );
+
+ /* After setting up the progress meter, we clear out any data
+ * which was previously loaded into the package list, reload it
+ * with the "forced download" option, and refresh the display.
+ */
+ app->ClearPackageList();
+ app->LoadPackageData( true );
+ app->UpdatePackageList();
+
+ /* During the update, the user may have selected the option for
+ * automatic dismissal of the dialogue box on completion...
+ */
+ if( IsDlgButtonChecked( (HWND)(window), IDD_AUTO_CLOSE_OPTION ) )
+ /*
+ * ...in which case, we dismiss it without further ado...
+ */
+ SendMessage( (HWND)(window), WM_COMMAND, (WPARAM)(IDOK), 0 );
+
+ else
+ { /* ...otherwise, we activate the manual dismissal button...
+ */
+ if( (dlg = GetDlgItem( (HWND)(window), IDOK )) != NULL )
+ EnableWindow( dlg, TRUE );
+
+ /* ...and notify the user that it must be clicked to continue.
+ */
+ ui.Annotate( "Update is complete; please close this dialogue to continue." );
+ }
+}
+
+static int CALLBACK pkgUpdate
+( HWND window, unsigned int msg, WPARAM wParam, LPARAM lParam )
+{
+ /* Handler for the package catalogue update dialogue box, as
+ * invoked by the "Update catalogue" menu pick, (or equivalent
+ * tool-bar button selection).
+ */
+ switch( msg )
+ {
+ /* We need to handle only two classes of windows messages
+ * on behalf of this dialogue box...
+ */
+ case WM_INITDIALOG:
+ /*
+ * ...viz. on initial dialogue box creation, we delegate the actual
+ * activity, of updating the catalogue, to this background thread...
+ */
+ _beginthread( pkgInvokeUpdate, 0, (void *)(window) );
+ return TRUE;
+
+ case WM_COMMAND:
+ if( LOWORD( wParam ) == IDOK )
+ {
+ /* ...then we wait for a notification that the dialogue may be
+ * closed, (which isn't permitted until the thread completes).
+ */
+ EndDialog( window, 0 );
+ return TRUE;
+ }
+ }
+ /* Any other messages, which are directed to this dialogue box, may be
+ * safely ignored.
+ */
+ return FALSE;
+}
+
+int AppWindowMaker::Invoked( void )
+{
+ /* Override for the WTK::MainWindowMaker::Invoked() method; it
+ * provides the hook for the initial loading of the XML database,
+ * and creation of the display controls through which its content
+ * will be presented to the user, prior to invocation of the main
+ * window's message loop.
+ *
+ * The data displays depend on the MS-Windows Common Controls API;
+ * initialise all components of this up front.
+ */
+ InitCommonControls();
+
+ /* Load the data from the XML catalogue files, and construct
+ * the initial view of the available package list; this activity
+ * is invoked in a background thread, initiated from a progress
+ * dialogue derived from the "Update Catalogue" template.
+ */
+ DialogBox( AppInstance,
+ MAKEINTRESOURCE( IDD_REPO_UPDATE ), AppWindow, pkgInitDataLoad
+ );
+ InitPackageListView();
+
+ /* Initialise the data-sheet tab control, displaying the default
+ * "no package selected" message.
+ */
+ InitPackageTabControl();
+
+ /* Force a layout adjustment, to ensure that the displayed
+ * data controls are correctly populated.
+ */
+ AdjustLayout();
+
+ /* Finally, we may delegate all further processing to the main
+ * window's message loop.
+ */
+ return WTK::MainWindowMaker::Invoked();
+}
+
+long AppWindowMaker::OnCommand( WPARAM cmd )
+{
+ /* Handler for WM_COMMAND messages which are directed to the
+ * top level application window.
+ */
+ switch( cmd )
+ { case IDM_HELP_ABOUT:
+ /*
+ * This request is initiated by selecting "About mingw-get"
+ * from the "Help" menu; we respond by displaying the "about"
+ * dialogue box.
+ */
+ WTK::GenericDialogue( AppInstance, AppWindow, IDD_HELP_ABOUT );
+ break;
+
+ case IDM_REPO_UPDATE:
+ /*
+ * This request is initiated by selecting "Update Catalogue"
+ * from the "Repository" menu; we respond by initiating a progress
+ * dialogue, from which a background thread is invoked to download
+ * fresh copies of the package catalogue files from the remote
+ * repository, and consolidate them into the local catalogue.
+ */
+ DialogBox(
+ AppInstance, MAKEINTRESOURCE( IDD_REPO_UPDATE ), AppWindow, pkgUpdate
+ );
+ break;
+
+ case IDM_REPO_QUIT:
+ /*
+ * This request is initiated by selecting the "Quit" option
+ * from the "Repository" menu; we respond by sending a WM_QUIT
+ * message, to terminate the current application instance.
+ */
+ SendMessage( AppWindow, WM_CLOSE, 0, 0L );
+ break;
+ }
+ /* Any other message is silently ignored.
+ */
+ return EXIT_SUCCESS;
+}
+
/* $RCSfile$: end of file */
class pkgSpecs;
class pkgDirectory;
+#ifndef GUIMAIN_H
+class AppWindowMaker;
+#endif
+
+class pkgProgressMeter
+{
+ /* An abstract base class, from which the controller class
+ * for a progress meter dialogue window may be derived.
+ */
+ public:
+ virtual void SetValue( int ) = 0;
+ virtual void SetRange( int, int ) = 0;
+ virtual int Annotate( const char *, ... ) = 0;
+
+ protected:
+ AppWindowMaker *referrer;
+ pkgProgressMeter( AppWindowMaker *ref = NULL ): referrer( ref ){}
+ ~pkgProgressMeter();
+};
+
class pkgXmlNode : public TiXmlElement
{
/* A minimal emulation of the wxXmlNode class, founded on
public:
/* Constructors...
*/
- inline pkgXmlDocument(){}
- inline pkgXmlDocument( const char* name )
+ inline pkgXmlDocument(): progress_meter( NULL ){}
+ inline pkgXmlDocument( const char* name ): progress_meter( NULL )
{
/* tinyxml has a similar constructor, but unlike wxXmlDocument,
* it DOES NOT automatically load the document; force it.
{
actions->GetScheduledSourceArchives( category );
}
+
+ /* Facility for monitoring of XML document processing operations.
+ */
+ private:
+ pkgProgressMeter* progress_meter;
+
+ public:
+ inline pkgProgressMeter *ProgressMeter( void )
+ {
+ return progress_meter;
+ }
+ inline pkgProgressMeter *AttachProgressMeter( pkgProgressMeter *attachment )
+ {
+ if( progress_meter == NULL )
+ progress_meter = attachment;
+ return progress_meter;
+ }
+ inline void DetachProgressMeter( pkgProgressMeter *attachment )
+ {
+ if( attachment == progress_meter )
+ progress_meter = NULL;
+ }
};
EXTERN_C const char *xmlfile( const char*, const char* = NULL );
* $Id$
*
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009, 2010, 2011, MinGW Project
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
*
*
* Implementation of repository binding for the pkgXmlDocument class.
* of package lists, from any specified repository.
*/
public:
+ static void Reset( void ){ count = total = 0; }
+ static void IncrementTotal( void ){ ++total; }
+
pkgRepository( pkgXmlDocument*, pkgXmlNode*, pkgXmlNode*, bool );
~pkgRepository(){};
pkgXmlNode *dbase;
pkgXmlNode *repository;
pkgXmlDocument *owner;
+ static int count, total;
bool force_update;
};
+/* Don't forget that we MUST explicitly allocate static storage for
+ * static property values declared within the pkgRepository class.
+ */
+int pkgRepository::count;
+int pkgRepository::total;
+
pkgRepository::pkgRepository
/*
* Constructor...
{
/* Check for a locally cached copy of the "package-list" file...
*/
+ const char *mode = "Loading";
+ const char *fmt = "%s catalogue: %s.xml; (item %d of %d)\n";
if( force_update || (access( dfile, F_OK ) != 0) )
{
/* When performing an "update", or if no local copy is available...
* Force a "sync", to fetch a copy from the public host.
*/
- dmh_printf( "Update catalogue: %s.xml\n", dname );
+ const char *mode = force_update ? "Updating" : "Downloading";
+ if( owner->ProgressMeter() != NULL )
+ /*
+ * Progress of the "update" is being metered; annotate the
+ * metering display accordingly...
+ */
+ owner->ProgressMeter()->Annotate( fmt, mode, dname, ++count, total );
+
+ else
+ /* Progress is not being explicitly metered, but the user
+ * may still appreciate a minimal progress report...
+ */
+ dmh_printf( fmt, mode, dname, ++count, total );
+
+ /* During the actual fetch, collect any generated diagnostics
+ * for the current catalogue file into a message digest, so
+ * that the GUI may present them in a single message box.
+ */
+ dmh_control( DMH_BEGIN_DIGEST );
owner->SyncRepository( dname, repository );
}
+ else if( owner->ProgressMeter() != NULL )
+ /*
+ * This is a simple request to load a local copy of the
+ * catalogue file; progress metering is in effect, so we
+ * annotate the metering display accordingly...
+ */
+ owner->ProgressMeter()->Annotate( fmt, mode, dname, ++count, total );
+
+ else if( pkgOptions()->Test( OPTION_VERBOSE ) > 1 )
+ /*
+ * Similarly, this is a request to load a local copy of
+ * the catalogue; progress metering is not in effect, but
+ * the user has requested verbose diagnostics, so issue
+ * a diagnostic progress report.
+ */
+ dmh_printf( fmt, mode, dname, ++count, total );
/* We SHOULD now have a locally cached copy of the package-list;
* attempt to merge it into the active profile database...
/* We successfully loaded the XML catalogue; refer to its
* root element...
*/
- if( pkgOptions()->Test( OPTION_VERBOSE ) > 1 )
- dmh_printf( "Load catalogue: %s.xml\n", dname );
pkgXmlNode *catalogue, *pkglist;
if( (catalogue = merge.GetRoot()) != NULL )
{
/* Recursively incorporate any additional package lists,
* which may be specified within the current catalogue...
*/
- GetPackageList( catalogue->FindFirstAssociate( package_list_key ) );
+ catalogue = catalogue->FindFirstAssociate( package_list_key );
+ if( (pkglist = catalogue) != NULL )
+ do {
+ /* ...updating the total catalogue reference count,
+ * to include all extra catalogue files specified.
+ */
+ ++total;
+ pkglist = pkglist->FindNextAssociate( package_list_key );
+ } while( pkglist != NULL );
+
+ /* Flush any message digest which has been accumulated
+ * for the last catalogue processed...
+ */
+ dmh_control( DMH_END_DIGEST );
+ if( owner->ProgressMeter() != NULL )
+ {
+ /* ...and update the progress meter display, if any,
+ * to reflect current progress.
+ */
+ owner->ProgressMeter()->SetRange( 0, total );
+ owner->ProgressMeter()->SetValue( count );
+ }
+ /* Proceed to process the embedded catalogues.
+ */
+ GetPackageList( catalogue );
}
}
else
free( (void *)(dfile) );
}
}
+ /* Ensure that any accumulated diagnostics, pertaining to catalogue
+ * processing, have been displayed before wrapping up.
+ */
+ dmh_control( DMH_END_DIGEST );
}
void pkgRepository::GetPackageList( pkgXmlNode *catalogue )
/* Sanity check passed...
* Walk the XML data tree, selecting "repository" specifications...
*/
+ pkgRepository::Reset();
pkgXmlNode *repository = dbase->FindFirstAssociate( repository_key );
while( repository != NULL )
{
pkgRepository client( this, dbase, repository, force_update );
pkgXmlNode *catalogue = repository->FindFirstAssociate( package_list_key );
if( catalogue == NULL )
- /*
- * This repository specification doesn't identify any named
+ {
+ /* This repository specification doesn't identify any named
* package list, so try the default, (which is named to match
* the XML key name for the "package-list" element)...
*/
+ pkgRepository::IncrementTotal();
client.GetPackageList( package_list_key );
-
+ }
else
- /* At least one package list catalogue is specified; load it,
+ { /* At least one package list catalogue is specified; load it,
* and any others which are explicitly identified...
*/
+ pkgXmlNode *ref = catalogue;
+ do { pkgRepository::IncrementTotal();
+ ref = ref->FindNextAssociate( package_list_key );
+ } while( ref != NULL );
+
client.GetPackageList( catalogue );
+ }
/* Similarly, a complete distribution may draw from an arbitrary set
* of distinct repositories; move on, to process the next repository
*
*/
#include "guimain.h"
+#include "pkgbase.h"
#include "dmh.h"
-using WTK::GenericDialogue;
+using WTK::StringResource;
using WTK::HorizontalSashWindowMaker;
using WTK::VerticalSashWindowMaker;
-using WTK::StringResource;
/* The main application window is divided into two
* horizontally adjustable sash panes; the following
return EXIT_SUCCESS;
}
-long AppWindowMaker::OnCommand( WPARAM cmd )
-{
- /* Handler for WM_COMMAND messages which are directed to the
- * top level application window.
- */
- switch( cmd )
- {
- case IDM_HELP_ABOUT:
- /*
- * This request is initiated by selecting "About mingw-get"
- * from the "Help" menu; we respond by displaying the "about"
- * dialogue box.
- */
- GenericDialogue( AppInstance, AppWindow, IDD_HELP_ABOUT );
- break;
-
- case IDM_REPO_QUIT:
- /*
- * This request is initiated by selecting the "Quit" option
- * from the "Repository" menu; we respond by sending a WM_QUIT
- * message, to terminate the current application instance.
- */
- SendMessage( AppWindow, WM_CLOSE, 0, 0L );
- break;
- }
- return EXIT_SUCCESS;
-}
-
#if 0
/* FIXME: this stub implementation has been superseded by an
* alternative implementation in pkgdata.cpp; eventually, this