← Back to team overview

kicad-developers team mailing list archive

[PATCH] Add progress reporting for GerbView file loading

 

Hi all,

This patch adds the progress reporter dialog to GerbView file loading, when
loading multiple files and the total load time goes over 1 second.  I've
also done some refactoring to share code between loading multiple files via
a gerber job file and via the regular open dialog.

-Jon
From d968f0a64200fd483b03c52f4efdfb25f8f51e60 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Tue, 20 Feb 2018 21:58:53 -0500
Subject: [PATCH] Add progress reporting for GerbView file loading

---
 common/widgets/progress_reporter.cpp |  4 +--
 gerbview/files.cpp                   | 51 +++++++++++++++++++++++++++++++-----
 gerbview/gerbview_frame.h            |  9 +++++++
 gerbview/job_file_reader.cpp         | 39 +++------------------------
 include/widgets/progress_reporter.h  |  4 ++-
 5 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/common/widgets/progress_reporter.cpp b/common/widgets/progress_reporter.cpp
index ddd46668b..213c8a93f 100644
--- a/common/widgets/progress_reporter.cpp
+++ b/common/widgets/progress_reporter.cpp
@@ -100,7 +100,7 @@ bool PROGRESS_REPORTER::KeepRefreshing( bool aWait )
 
 
 WX_PROGRESS_REPORTER::WX_PROGRESS_REPORTER( wxWindow* aParent, const wxString& aTitle,
-                                            int aNumPhases ) :
+                                            int aNumPhases, bool aCanAbort ) :
     PROGRESS_REPORTER( aNumPhases ),
     wxProgressDialog( aTitle, wxT( "" ), 1, aParent,
                       // wxPD_APP_MODAL |   // Don't use; messes up OSX when called from
@@ -108,7 +108,7 @@ WX_PROGRESS_REPORTER::WX_PROGRESS_REPORTER( wxWindow* aParent, const wxString& a
                       wxPD_AUTO_HIDE |      // *MUST* use; otherwise wxWidgets will spin
                                             // up another event loop on completion which
                                             // causes all sorts of grief
-                      wxPD_CAN_ABORT |
+                      ( aCanAbort ? wxPD_CAN_ABORT : 0 ) |
                       wxPD_ELAPSED_TIME )
 {
 }
diff --git a/gerbview/files.cpp b/gerbview/files.cpp
index f659ae123..76f7e06ed 100644
--- a/gerbview/files.cpp
+++ b/gerbview/files.cpp
@@ -39,8 +39,10 @@
 #include <gerbview_frame.h>
 #include <gerbview_id.h>
 #include <gerber_file_image.h>
+#include <gerber_file_image_list.h>
 #include <gerbview_layer_widget.h>
 #include <wildcards_and_files_ext.h>
+#include <widgets/progress_reporter.h>
 
 // HTML Messages used more than one time:
 #define MSG_NO_MORE_LAYER\
@@ -216,6 +218,15 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
     // Set the busy cursor
     wxBusyCursor wait;
 
+    return loadListOfGerberFiles( currentPath, filenamesList );
+}
+
+
+bool GERBVIEW_FRAME::loadListOfGerberFiles( const wxString& aPath,
+                                            const wxArrayString& aFilenameList )
+{
+    wxFileName filename;
+
     // Read gerber files: each file is loaded on a new GerbView layer
     bool success = true;
     int layer = GetActiveLayer();
@@ -224,12 +235,30 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
     wxString msg;
     WX_STRING_REPORTER reporter( &msg );
 
-    for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ )
+    // Show progress dialog after 1 second of loading
+    static const long long progressShowDelay = 1000;
+
+    auto startTime = wxGetUTCTimeMillis();
+    std::unique_ptr<WX_PROGRESS_REPORTER> progress = nullptr;
+
+    for( unsigned ii = 0; ii < aFilenameList.GetCount(); ii++ )
     {
-        filename = filenamesList[ii];
+        if( !progress && wxGetUTCTimeMillis() - startTime > progressShowDelay )
+        {
+            progress = std::make_unique<WX_PROGRESS_REPORTER>( this,
+                            _( "Loading Gerber files..." ), 1, false );
+            progress->SetMaxProgress( aFilenameList.GetCount() - 1 );
+            progress->Report( _("Loading Gerber files..." ) );
+        }
+        else if( progress )
+        {
+            progress->KeepRefreshing();
+        }
+
+        filename = aFilenameList[ii];
 
         if( !filename.IsAbsolute() )
-            filename.SetPath( currentPath );
+            filename.SetPath( aPath );
 
         m_lastFileName = filename.GetFullPath();
 
@@ -241,16 +270,16 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
 
             layer = getNextAvailableLayer( layer );
 
-            if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 )
+            if( layer == NO_AVAILABLE_LAYERS && ii < aFilenameList.GetCount()-1 )
             {
                 success = false;
                 reporter.Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR );
 
                 // Report the name of not loaded files:
                 ii += 1;
-                while( ii < filenamesList.GetCount() )
+                while( ii < aFilenameList.GetCount() )
                 {
-                    filename = filenamesList[ii++];
+                    filename = aFilenameList[ii++];
                     wxString txt;
                     txt.Printf( MSG_NOT_LOADED,
                                 GetChars( filename.GetFullName() ) );
@@ -261,10 +290,15 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
 
             SetActiveLayer( layer, false );
         }
+
+        if( progress )
+            progress->AdvanceProgress();
     }
 
     if( !success )
     {
+        wxSafeYield();  // Allows slice of time to redraw the screen
+                        // to refresh widgets, before displaying messages
         HTML_MESSAGE_BOX mbox( this, _( "Errors" ) );
         mbox.ListSet( msg );
         mbox.ShowModal();
@@ -272,11 +306,14 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
 
     Zoom_Automatique( false );
 
+    GetImagesList()->SortImagesByZOrder();
+
     // Synchronize layers tools with actual active layer:
     ReFillLayerWidget();
     SetActiveLayer( GetActiveLayer() );
     m_LayersManager->UpdateLayerIcons();
-    syncLayerBox();
+    syncLayerBox( true );
+
     return success;
 }
 
diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h
index 729541d94..ca7e35d12 100644
--- a/gerbview/gerbview_frame.h
+++ b/gerbview/gerbview_frame.h
@@ -216,6 +216,15 @@ private:
     /// Updates the GAL with display settings changes
     void applyDisplaySettingsToGAL();
 
+    /**
+     * Loads a list of Gerber files and updates the view based on them
+     * @param aPath is the base path for the filenames if they are relative
+     * @param aFilenameList is a list of filenames to load
+     * @return true if every file loaded successfully
+     */
+    bool                loadListOfGerberFiles( const wxString& aPath,
+                                               const wxArrayString& aFilenameList );
+
 public:
     GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent );
     ~GERBVIEW_FRAME();
diff --git a/gerbview/job_file_reader.cpp b/gerbview/job_file_reader.cpp
index 80f54ee38..b5c919e80 100644
--- a/gerbview/job_file_reader.cpp
+++ b/gerbview/job_file_reader.cpp
@@ -144,6 +144,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
 {
     wxFileName filename = aFullFileName;
     wxString currentPath;
+    bool success = true;
 
     if( !filename.IsOk() )
     {
@@ -189,41 +190,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
 
             wxArrayString& gbrfiles = gbjReader.GetGerberFiles();
 
-            wxFileName gbr_fn = filename;
-            bool read_ok;
-            int layer = 0;
-            SetActiveLayer( layer, false );
-
-            for( unsigned ii = 0; ii < gbrfiles.GetCount(); ii++ )
-            {
-                gbr_fn.SetFullName( gbrfiles[ii] );
-
-                if( gbr_fn.FileExists() )
-                {
-                    //LoadGerberFiles( gbr_fn.GetFullPath() );
-                    read_ok = Read_GERBER_File( gbr_fn.GetFullPath() );
-
-                    if( read_ok )
-                    {
-                        layer = getNextAvailableLayer( layer );
-                        SetActiveLayer( layer, false );
-                    }
-                }
-                else
-                    read_ok = false;
-
-                if( !read_ok )
-                {
-                    wxString err;
-                    err.Printf( _( "Can't load Gerber file:<br><i>%s</i><br>" ), gbr_fn.GetFullPath() );
-                    reporter.Report( err, REPORTER::RPT_WARNING );
-                }
-            }
-
-            GetImagesList()->SortImagesByZOrder();
-            ReFillLayerWidget();
-            syncLayerBox( true );
-            GetCanvas()->Refresh();
+            success = loadListOfGerberFiles( currentPath, gbrfiles );
         }
     }
 
@@ -238,7 +205,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
         mbox.ShowModal();
     }
 
-    return true;
+    return success;
 }
 
 
diff --git a/include/widgets/progress_reporter.h b/include/widgets/progress_reporter.h
index 2eff0f217..6594d388b 100644
--- a/include/widgets/progress_reporter.h
+++ b/include/widgets/progress_reporter.h
@@ -102,8 +102,10 @@ public:
      * aNumPhases = 1 is the usual progress bar
      * aNumPhases = n creates n virtual progress bar zones: a 0 to 100 percent width
      * of a virtual zone fills 0 to 1/n progress bar full size of the nth virtual zone index
+     * @param aCanAbort is true if the abort button should be shown
      */
-    WX_PROGRESS_REPORTER( wxWindow* aParent, const wxString& aTitle, int aNumPhases );
+    WX_PROGRESS_REPORTER( wxWindow* aParent, const wxString& aTitle, int aNumPhases,
+                          bool aCanAbort = true );
     ~WX_PROGRESS_REPORTER();
 
 private:
-- 
2.14.1


Follow ups