OSDN Git Service

Consolidate GUI implementation for package list view management.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 3 Dec 2012 13:17:30 +0000 (13:17 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 3 Dec 2012 13:17:30 +0000 (13:17 +0000)
ChangeLog
src/guimain.h
src/pkgdata.cpp
src/pkglist.cpp
src/pkglist.h

index 5238ee1..16c6de9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2012-12-03  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Consolidate GUI implementation for package list view management.
+
+       * src/pkglist.h (pkgListViewMaker::GetTitle): Disused overloaded
+       method; remove all declarations.
+       (pkgListViewMaker::GetVersionString): Disused method; remove
+       declaration.
+       (pkgListViewMaker::GetItem): New private inline method; declare it.
+       (pkgListViewMaker::UpdateItem): New private method; declare it.
+       (pkgListViewMaker::UpdateListView): New public method; declare it.
+       (pkgListViewMaker::MarkScheduledActions): Likewise.
+
+       * src/guimain.h (AppWindowMaker::MarkSchedule): New public inline
+       method; declare it, but defer implementation to...
+
+       * src/pkgdata.cpp (AppWindowMaker::MarkSchedule): ...here; not used
+       elsewhere, it is derived from, and replaces...
+       (pkgMarkSchedule): ...this function; factor out redundant code, in
+       favour of delegation to pkgListViewMaker::MarkScheduledActions(), with
+       following call to AppWindowMaker::UpdatePackageMenuBindings(); update
+       calling function references...
+       (AppWindowMaker::UnmarkSelectedPackage): ...here, and...
+       (AppWindowMaker::Schedule): ...here.
+
+       * src/pkglist.cpp (pkgVersionString): New static function; implement
+       it as a local replacement for...
+       (pkgListViewMaker::GetVersionString): ...this defunct class method.
+       (pkgGetTitle): New overloaded static function; implement two variants,
+       as local replacements for...
+       (pkgListViewMaker::GetTitle): ...this defunct overloaded class method.
+       (pkgListViewMaker::UpdateItem): Implement it; factor code from...
+       (pkgListViewMaker::InsertItem): ...here, whence use it.
+       (pkgListViewMaker::MarkScheduledActions): Implement it.
+       (pkgListViewMaker::UpdateListView): Implement it.
+       (pkgListViewMaker::pkgListViewMaker): Remove references to...
+       (LVIF_TEXT): ...this.
+
 2012-11-30  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Increase width of window sash bars by 50%.
index d75bef0..3af6023 100644 (file)
@@ -169,6 +169,7 @@ class AppWindowMaker: public WTK::MainWindowMaker
     void InitPackageListView( void );
     void UpdatePackageMenuBindings( void );
     void Schedule( unsigned long, const char * = NULL, const char * = NULL );
+    inline void MarkSchedule( pkgActionItem * );
     void UnmarkSelectedPackage( void );
 
     DataSheetMaker *DataSheet;
index 3326124..c46431e 100644 (file)
@@ -986,88 +986,15 @@ void AppWindowMaker::UpdatePackageMenuBindings()
   }
 }
 
-EXTERN_C void pkgMarkSchedule( HWND pkglist, pkgActionItem *actions )
+inline void AppWindowMaker::MarkSchedule( pkgActionItem *pending_actions )
 {
-  /* Helper routine to update the status icons within the package
-   * list view, to reflect scheduled actions in respect of the package
-   * associated with each.
+  /* Helper routine to update the status icons within the package list view,
+   * reflecting any scheduled action in respect of the package associated with
+   * each, and updating the menu bindings to match.
    */
-  LVITEM lookup;
-  lookup.iItem = 0;
-  lookup.iSubItem = 0;
-  lookup.mask = LVIF_IMAGE | LVIF_PARAM;
-  while( ListView_GetItem( pkglist, &lookup ) )
-  {
-    /* Traverse the displayed list of packages from top to bottom...
-     */
-    unsigned long op;
-    pkgActionItem *ref = actions->GetReference( (pkgXmlNode *)(lookup.lParam));
-    if( ref != NULL )
-    {
-      if( (op = ref->HasAttribute( ACTION_MASK )) != 0UL )
-      {
-       /* ...identifying any action scheduled on each package,
-        * and selecting the appropriate list view icon...
-        */
-       switch( op )
-       {
-         case ACTION_INSTALL:
-           /*
-            * ...for packages scheduled for installation...
-            *
-            * FIXME: we should also consider that such packages
-            * may have been scheduled for reinstallation.
-            */
-           lookup.iImage = PKGSTATE( AVAILABLE_INSTALL );
-           break;
-
-         case ACTION_UPGRADE:
-           /*
-            * ...for packages scheduled for upgrade...
-            */
-           lookup.iImage = PKGSTATE( UPGRADE );
-           break;
-
-         case ACTION_REMOVE:
-           /*
-            * ...for packages scheduled for removal.
-            */
-           lookup.iImage = PKGSTATE( REMOVE );
-       }
-      }
-      else
-      { /* A previously scheduled action has been cancelled;
-        * retrieve the package release status attributes, so
-        * we may reinstate the appropriate unmarked icon.
-        */
-       pkgActionItem avail;
-       pkgXmlNode *rel = ref->Selection();
-       if( rel == NULL ) rel = ref->Selection( to_remove );
-       if( (rel = pkgGetStatus( rel->GetParent(), &avail )) == NULL )
-         /*
-          * For a package which has not been installed, this
-          * indicates an available package...
-          */
-         lookup.iImage = PKGSTATE( AVAILABLE );
-
-       else
-       { /* ...while for an installed package, it indicates
-          * currency or upgradeability, as appropriate.
-          */
-         pkgSpecs current( rel );
-         pkgSpecs latest( avail.Selection() );
-         lookup.iImage = (latest > current) ? PKGSTATE( INSTALLED_OLD )
-           : PKGSTATE( INSTALLED_CURRENT );
-       }
-      }
-      /* Apply the new icon selection...
-       */
-      ListView_SetItem( pkglist, &lookup );
-    }
-    /* ...and move on to the next list view entry.
-     */
-    lookup.iItem++;
-  }
+  pkgListViewMaker pkglist( PackageListView );
+  pkglist.MarkScheduledActions( pending_actions );
+  UpdatePackageMenuBindings();
 }
 
 void AppWindowMaker::Schedule
@@ -1152,8 +1079,7 @@ void AppWindowMaker::Schedule
      * the resultant schedule of actions, and update the list
      * view state icons to reflect the pending actions.
      */
-    pkgMarkSchedule( PackageListView, pkgData->Schedule( action, pkgname ) );
-    UpdatePackageMenuBindings();
+    MarkSchedule( pkgData->Schedule( action, pkgname ) );
   }
 }
 
@@ -1195,8 +1121,7 @@ void AppWindowMaker::UnmarkSelectedPackage( void )
      * may have changed, so refresh the icon associations and the
      * package menu bindings accordingly.
      */
-    pkgMarkSchedule( PackageListView, pkgData->Schedule() );
-    UpdatePackageMenuBindings();
+    MarkSchedule( pkgData->Schedule() );
   }
 }
 
index dd54d33..057368a 100644 (file)
@@ -7,9 +7,9 @@
  * Copyright (C) 2012, MinGW Project
  *
  *
- * Implementation of the methods for the pkgListViewMaker class, to
- * support the display of the package list in the mingw-get graphical
- * user interface.
+ * Implementation of the methods for the pkgListViewMaker class, and
+ * its AppWindowMaker client API, to support the display of the package
+ * list in the mingw-get graphical user interface.
  *
  *
  * This is free software.  Permission is granted to copy, modify and
@@ -31,6 +31,7 @@
 #include "guimain.h"
 #include "pkgbase.h"
 #include "pkglist.h"
+#include "pkgtask.h"
 #include "pkgkeys.h"
 #include "pkginfo.h"
 
@@ -114,13 +115,124 @@ void AppWindowMaker::UpdatePackageList()
   delete dir;
 }
 
+static char *pkgGetTitle( pkgXmlNode *pkg, const pkgXmlNode *xml_root )
+{
+  /* A private helper method, to retrieve the title attribute
+   * associated with the description for the nominated package.
+   *
+   * Note: this should really return a const char *, but then
+   * we would need to cast it to non-const for mapping into the
+   * ill-formed structure of Microsoft's LVITEM, so we may just
+   * as well return the non-const result anyway.
+   */
+  pkgXmlNode *desc = pkg->FindFirstAssociate( description_key );
+  while( desc != NULL )
+  {
+    /* Handling it internally as the const which it should be...
+     */
+    const char *title;
+    if( (title = desc->GetPropVal( title_key, NULL )) != NULL )
+      /*
+       * As soon as we find a description element with an
+       * assigned title attribute, immediately return it,
+       * (with the required cast to non-const).
+       */
+      return (char *)(title);
+
+    /* If we haven't yet found any title attribute, check for any
+     * further description elements at the current XML nesting level.
+     */
+    desc = desc->FindNextAssociate( description_key );
+  }
+
+  /* If we've exhausted all description elements at the current XML
+   * nesting level, without finding a title attribute, and we haven't
+   * checked all enclosing levels back to the document root...
+   */
+  if( pkg != xml_root )
+    /*
+     * ...then continue the search in the immediately enclosing level.
+     */
+    return pkgGetTitle( pkg->GetParent(), xml_root );
+
+  /* If we get to here, then we've searched all levels back to the
+   * document root, and have failed to find any title attribute; we
+   * have nothing to return.
+   */
+  return NULL;
+}
+
+static inline char *pkgGetTitle( pkgXmlNode *pkg )
+{
+  /* Overload the preceding function, to automatically generate
+   * the required reference to the XML document root.
+   */
+  return pkgGetTitle( pkg->GetParent(), pkg->GetDocumentRoot() );
+}
+
+static inline
+char *version_string_copy( char *buf, const char *text, int fill = 0 )
+{
+  /* Local helper function to construct a package version string
+   * from individual version specific elements of the tarname.
+   */
+  if( text != NULL )
+  {
+    /* First, if a fill character is specified, copy it as the
+     * first character of the result; (we assume that we are
+     * appending to a previously constructed result, and that
+     * this is the field separator character).
+     */
+    if( fill != 0 ) *buf++ = fill;
+
+    /* Now, append "text" up to, and including its final NUL
+     * terminator; (note that we do NOT guard against buffer
+     * overrun, as we have complete control over the calling
+     * context, where we allocated a result buffer at least
+     * as long as the tarname string from which the composed
+     * version string is extracted, and the composed result
+     * can never exceed the original length of this).
+     */
+    do { if( (*buf = *text) != '\0' ) ++buf; } while( *text++ != '\0' );
+  }
+  /* Finally, we return a pointer to the terminating NUL of
+   * the result, so as to facilitate appending further text.
+   */
+  return buf;
+}
+
+static char *pkgVersionString( char *buf, pkgSpecs *pkg )
+{
+  /* Helper method to construct a fully qualified version string
+   * from the decomposed package tarname form in a pkgSpecs structure.
+   *
+   * We begin with the concatenation of package version and build ID
+   * fields, retrieved from the pkgSpecs representation...
+   */
+  char *update = version_string_copy( buf, pkg->GetPackageVersion() );
+  update = version_string_copy( update, pkg->GetPackageBuild(), '-' );
+  if( pkg->GetSubSystemVersion() != NULL )
+  {
+    /* ...then, we append the sub-system ID, if applicable...
+     */
+    update = version_string_copy( update, pkg->GetSubSystemName(), '-' );
+    update = version_string_copy( update, pkg->GetSubSystemVersion(), '-' );
+    update = version_string_copy( update, pkg->GetSubSystemBuild(), '-' );
+  }
+  /* ...and finally, we return a pointer to the buffer in which
+   * we constructed the fully qualified version string.
+   */
+  return buf;
+}
+
 pkgListViewMaker::pkgListViewMaker( HWND pane ): ListView( pane )
 {
   /* Constructor: initialise the invariant parameters within the
    * embedded W32API ListView control structure.
    */
   content.stateMask = 0;
-  content.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
+  content.mask = LVIF_PARAM | LVIF_IMAGE | LVIF_STATE;
+  content.iSubItem = 0;
   content.iItem = -1;
 }
 
@@ -164,36 +276,52 @@ EXTERN_C pkgXmlNode *pkgGetStatus( pkgXmlNode *pkg, pkgActionItem *avail )
 void pkgListViewMaker::InsertItem( pkgXmlNode *pkg, char *class_name )
 {
   /* Private method to add a single package record, as an individual
-   * row item, to the displayed list view table.
+   * row item, to the displayed list view table; begin by filling in
+   * the appropriate fields within the "content" structure...
    */
+  content.iItem++;
   content.state = 0;
-  content.iItem += 1;
-  content.iSubItem = 0;
   content.lParam = (unsigned long)(pkg);
-  content.pszText = "";
 
+  /* ...then delegate the actual entry construction to...
+   */
+  UpdateItem( class_name, true );
+}
+
+inline bool pkgListViewMaker::GetItem( void )
+{
+  /* An inline helper method to load the content structure from the
+   * next available item, if any, in the package list view; returns
+   * true when content is successfully loaded, else returns false.
+   */
+  content.iItem++; return ListView_GetItem( ListView, &content );
+}
+
+void pkgListViewMaker::UpdateItem( char *class_name, bool new_entry )
+{
   /* Assign a temporary action item, through which we may identify
    * the latest available, and currently installed (if any), version
    * attributes for the package under consideration.
    */
   pkgActionItem avail;
-  pkgXmlNode *rel = pkgGetStatus( pkg, &avail );
+  pkgXmlNode *package = (pkgXmlNode *)(content.lParam);
+  pkgXmlNode *installed = pkgGetStatus( package, &avail );
 
   /* Decompose the package tarname identifier for the latest available
    * release, into its individual package specification properties.
    */
-  pkgSpecs latest( pkg = avail.Selection() );
+  pkgSpecs latest( package = avail.Selection() );
 
   /* Allocate a temporary working text buffer, in which to format
    * package property values for display...
    */
-  size_t len = strlen( pkg->GetPropVal( tarname_key, value_none ) );
-  if( rel != NULL )
+  size_t len = strlen( package->GetPropVal( tarname_key, value_none ) );
+  if( installed != NULL )
   {
     /* ...ensuring that it is at least as large as the longer of the
      * latest or installed release tarname.
      */
-    size_t altlen = strlen( rel->GetPropVal( tarname_key, value_none ) );
+    size_t altlen = strlen( installed->GetPropVal( tarname_key, value_none ) );
     if( altlen > len ) len = altlen;
   }
   char buf[1 + len];
@@ -201,162 +329,75 @@ void pkgListViewMaker::InsertItem( pkgXmlNode *pkg, char *class_name )
   /* Choose a suitable icon for representation of the installation
    * status of the package under consideration...
    */
-  if( rel != NULL )
+  if( installed != NULL )
   {
     /* ...noting that, when it is already installed...
      */
-    pkgSpecs current( rel );
-    if( latest > current )
-      /*
-       * ...and, when the latest available is NEWER than the
-       * installed version, then we choose the icon indicating
-       * an installed package with an available update...
-       */
-      content.iImage = PKGSTATE( INSTALLED_OLD );
-
-    else
-      /* ...or, when the latest available is NOT NEWER than
-       * the installed version, then we choose the alternative
-       * icon, simply indicating an installed package...
-       */
-      content.iImage = PKGSTATE( INSTALLED_CURRENT );
+    pkgSpecs current( installed );
+    content.iImage = (latest > current)
+      ? /* ...and, when the latest available is NEWER than the
+        * installed version, then we choose the icon indicating
+        * an installed package with an available update...
+        */
+       PKGSTATE( INSTALLED_OLD )
+
+      : /* ...or, when the latest available is NOT NEWER than
+        * the installed version, then we choose the alternative
+        * icon, simply indicating an installed package...
+        */
+       PKGSTATE( INSTALLED_CURRENT );
 
     /* ...and also, load the version identification string for
      * the installed version into the working text buffer.
      */
-    GetVersionString( buf, &current );
+    pkgVersionString( buf, &current );
   }
   else
-    /* Alternatively, for any package which is not recorded as
+  { /* Alternatively, for any package which is not recorded as
      * installed, choose the icon indicating an available, but
-     * not (yet) installed package.
+     * not (yet) installed package...
      */
     content.iImage = PKGSTATE( AVAILABLE );
 
-  /* Add the package identification record, as a list item...
-   */
-  ListView_InsertItem( ListView, &content );
-  /*
-   * ...and fill in the text for the package name and class columns.
-   */
-  ListView_SetItemText( ListView, content.iItem, 1, package_name );
-  ListView_SetItemText( ListView, content.iItem, 2, class_name );
-
-  /* When an installed package release has been identified...
-   */
-  if( rel != NULL )
-    /*
-     * ...fill in the version identificaton text appropriately.
+    /* ...and mark the list view column entry, for the installed
+     * version, as empty.
      */
-    ListView_SetItemText( ListView, content.iItem, 3, buf );
+    *buf = '\0';
+  }
 
-  /* Finally, fill in the text for the latest version identification
-   * and package description columns.
+  /* When compiling a new list entry...
    */
-  ListView_SetItemText( ListView, content.iItem, 4, GetVersionString( buf, &latest ) );
-  ListView_SetItemText( ListView, content.iItem, 5, GetTitle( avail.Selection()) );
-}
-
-char *pkgListViewMaker::GetTitle( pkgXmlNode *pkg, const pkgXmlNode *xml_root )
-{
-  /* A private helper method, to retrieve the title attribute
-   * associated with the description for the nominated package.
-   *
-   * Note: this should really return a const char *, but then
-   * we would need to cast it to non-const for mapping into the
-   * ill-formed structure of Microsoft's LVITEM, so we may just
-   * as well return the non-const result anyway.
-   */
-  pkgXmlNode *desc = pkg->FindFirstAssociate( description_key );
-  while( desc != NULL )
+  if( new_entry )
   {
-    /* Handling it internally as the const which it should be...
-     */
-    const char *title;
-    if( (title = desc->GetPropVal( title_key, NULL )) != NULL )
-      /*
-       * As soon as we find a description element with an
-       * assigned title attribute, immediately return it,
-       * (with the required cast to non-const).
-       */
-      return (char *)(title);
-
-    /* If we haven't yet found any title attribute, check for any
-     * further description elements at the current XML nesting level.
+    /* ...add the package identification record, as a new item...
      */
-    desc = desc->FindNextAssociate( description_key );
-  }
-
-  /* If we've exhausted all description elements at the current XML
-   * nesting level, without finding a title attribute, and we haven't
-   * checked all enclosing levels back to the document root...
-   */
-  if( pkg != xml_root )
+    ListView_InsertItem( ListView, &content );
     /*
-     * ...then continue the search in the immediately enclosing level.
+     * ...and fill in the text for the package name, class name,
+     * and package description columns...
      */
-    return GetTitle( pkg->GetParent() );
-
-  /* If we get to here, then we've searched all levels back to the
-   * document root, and have failed to find any title attribute; we
-   * have nothing to return.
-   */
-  return NULL;
-}
-
-static inline
-char *version_string_copy( char *buf, const char *text, int fill = 0 )
-{
-  /* Local helper function to construct a package version string
-   * from individual version specific elements of the tarname.
-   */
-  if( text != NULL )
-  {
-    /* First, if a fill character is specified, copy it as the
-     * first character of the result; (we assume that we are
-     * appending to a previously constructed result, and that
-     * this is the field separator character).
+    ListView_SetItemText( ListView, content.iItem, 1, package_name );
+    ListView_SetItemText( ListView, content.iItem, 2, class_name );
+    ListView_SetItemText( ListView, content.iItem, 5, pkgGetTitle( package ) );
+  }
+  else
+    /* ...otherwise, this is simply a request to update an
+     * existing item, in place; do so.  (Note that, in this
+     * case, we DO NOT touch the package name, class name,
+     * or package description column content).
      */
-    if( fill != 0 ) *buf++ = fill;
+    ListView_SetItem( ListView, &content );
 
-    /* Now, append "text" up to, and including its final NUL
-     * terminator; (note that we do NOT guard against buffer
-     * overrun, as we have complete control over the calling
-     * context, where we allocated a result buffer at least
-     * as long as the tarname string from which the composed
-     * version string is extracted, and the composed result
-     * can never exceed the original length of this).
-     */
-    do { if( (*buf = *text) != '\0' ) ++buf; } while( *text++ != '\0' );
-  }
-  /* Finally, we return a pointer to the terminating NUL of
-   * the result, so as to facilitate appending further text.
+  /* Always fill in the text, as established above, in the
+   * column which identifies the currently installed version,
+   * if any, or clear it if the package is not installed.
    */
-  return buf;
-}
+  ListView_SetItemText( ListView, content.iItem, 3, buf );
 
-char *pkgListViewMaker::GetVersionString( char *buf, pkgSpecs *pkg )
-{
-  /* Helper method to construct a fully qualified version string
-   * from the decomposed package tarname form in a pkgSpecs structure.
-   *
-   * We begin with the concatenation of package version and build ID
-   * fields, retrieved from the pkgSpecs representation...
+  /* Finally, fill in the text of the column which identifies
+   * the latest available version of the package.
    */
-  char *update = version_string_copy( buf, pkg->GetPackageVersion() );
-  update = version_string_copy( update, pkg->GetPackageBuild(), '-' );
-  if( pkg->GetSubSystemVersion() != NULL )
-  {
-    /* ...then, we append the sub-system ID, if applicable...
-     */
-    update = version_string_copy( update, pkg->GetSubSystemName(), '-' );
-    update = version_string_copy( update, pkg->GetSubSystemVersion(), '-' );
-    update = version_string_copy( update, pkg->GetSubSystemBuild(), '-' );
-  }
-  /* ...and finally, we return a pointer to the buffer in which
-   * we constructed the fully qualified version string.
-   */
-  return buf;
+  ListView_SetItemText( ListView, content.iItem, 4, pkgVersionString( buf, &latest ) );
 }
 
 void pkgListViewMaker::Dispatch( pkgXmlNode *package )
@@ -401,4 +442,72 @@ void pkgListViewMaker::Dispatch( pkgXmlNode *package )
   }
 }
 
+void pkgListViewMaker::MarkScheduledActions( pkgActionItem *schedule )
+{
+  /* Method to reassign icons to entries within the package list view,
+   * indicating any which have been marked for installation, upgrade,
+   * or removal of the associated package.
+   */
+  for( content.iItem = -1; GetItem(); )
+  {
+    /* Visiting every entry in the list...
+     */
+    pkgActionItem *ref;
+    if( (ref = schedule->GetReference( (pkgXmlNode *)(content.lParam) )) != NULL )
+    {
+      /* ...identify those which are associated with a scheduled action...
+       */
+      unsigned long opcode;
+      if( (opcode = ref->HasAttribute( ACTION_MASK )) == ACTION_INSTALL )
+      {
+       /* ...selecting the appropriate icon to mark those packages
+        * which have been scheduled for installation...
+        *
+        * FIXME: we should also consider that such packages
+        * may have been scheduled for reinstallation.
+        */
+       content.iImage = PKGSTATE( AVAILABLE_INSTALL );
+      }
+      else if( opcode == ACTION_UPGRADE )
+      {
+       /* ...those which have been scheduled for upgrade...
+        */
+       content.iImage = PKGSTATE( UPGRADE );
+      }
+      else if( opcode == ACTION_REMOVE )
+      {
+       /* ...and those which have been scheduled for removal.
+        */
+       content.iImage = PKGSTATE( REMOVE );
+      }
+      else
+      { /* Where a scheduled action is any other than those above,
+        * handle as if there was no scheduled action...
+        */
+       opcode = 0UL;
+       /*
+        * ...and ensure that the list view entry reflects the
+        * normal display state for the associated package.
+        */
+       UpdateItem( NULL );
+      }
+      if( opcode != 0UL )
+       /*
+        * Where an action mark is appropriate, ensure that it
+        * is applied to the list view entry.
+        */
+       ListView_SetItem( ListView, &content );
+    }
+  }
+}
+
+void pkgListViewMaker::UpdateListView( void )
+{
+  /* A simple helper method, to refresh the content of the
+   * package list view, resetting each item to its initial
+   * unmarked display state.
+   */
+  for( content.iItem = -1; GetItem(); ) UpdateItem( NULL );
+}
+
 /* $RCSfile$: end of file */
index 42cbb25..64c845c 100644 (file)
@@ -65,17 +65,15 @@ class pkgListViewMaker: public pkgDirectoryViewerEngine
   public:
     pkgListViewMaker( HWND );
     virtual void Dispatch( pkgXmlNode * );
+    virtual void MarkScheduledActions( pkgActionItem * );
+    virtual void UpdateListView( void );
 
   private:
     HWND ListView;
     LVITEM content;
-    char *GetTitle( pkgXmlNode *pkg )
-    {
-      return GetTitle( pkg, pkg->GetDocumentRoot() );
-    }
-    char *GetTitle( pkgXmlNode *, const pkgXmlNode * );
-    char *GetVersionString( char *, pkgSpecs * );
+    inline bool GetItem( void );
     void InsertItem( pkgXmlNode *, char * );
+    void UpdateItem( char *, bool = false );
     char *package_name;
 };