← Back to team overview

kicad-developers team mailing list archive

[PATCH] DRC: do not close and reopen progress dialog

 

I'm running into an extremely irritating UI bug with DRC on this big
board - halfway through DRC, the progress dialog is torn down and
reopened. DRC is taking two full minutes with this board, which means I
invariably do something else while it runs - and when it pops up the
second progress dialog, that dialog receives any spacebar key press I
may have been making whilst typing, cancelling DRC. I did it three times
in a row earlier today. I wanted to throw my workstation out the window.

This patch fixes that. The DRC task creates a single progress bar dialog
and hands it to anything that needs it, keeping it open until the end.

-- 
Chris
>From aa10c0a898acd6b20caf09378803b6aa7f6590b1 Mon Sep 17 00:00:00 2001
From: Chris Pavlina <pavlinac@xxxxxxxxxxxx>
Date: Thu, 11 Aug 2016 15:03:03 -0400
Subject: [PATCH] DRC: do not close and reopen progress dialog

---
 include/wxPcbStruct.h                      |  6 ++-
 pcbnew/drc.cpp                             | 71 ++++++++++++++++++------------
 pcbnew/drc_stuff.h                         |  5 ++-
 pcbnew/zones_by_polygon_fill_functions.cpp | 34 +++++++++-----
 4 files changed, 74 insertions(+), 42 deletions(-)

diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h
index 887e7f3..fe46542 100644
--- a/include/wxPcbStruct.h
+++ b/include/wxPcbStruct.h
@@ -63,6 +63,7 @@ class REPORTER;
 struct PARSE_ERROR;
 struct IO_ERROR;
 class FP_LIB_TABLE;
+class wxProgressDialog;
 
 namespace PCB { struct IFACE; }     // KIFACE_I is in pcbnew.cpp
 
@@ -1416,8 +1417,11 @@ public:
      * @param aActiveWindow = the current active window, if a progress bar is shown
      *                      = NULL to do not display a progress bar
      * @param aVerbose = true to show error messages
+     * @param aProgressDialog = if non-NULL, use this progress dialog instead of
+     *      creating one.
      */
-    int Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose = true );
+    int Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose = true,
+            wxProgressDialog *aProgressDialog = NULL );
 
 
     /**
diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp
index c2c6e1a..08eb86f 100644
--- a/pcbnew/drc.cpp
+++ b/pcbnew/drc.cpp
@@ -1,10 +1,9 @@
-
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
  * Copyright (C) 2014 Dick Hollenbeck, dick@xxxxxxxxxxx
- * Copyright (C) 2016 KiCad Developers, see change_log.txt for contributors.
+ * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -187,6 +186,11 @@ void DRC::RunTests( wxTextCtrl* aMessages )
     // ( the board can be reloaded )
     m_pcb = m_pcbEditorFrame->GetBoard();
 
+    wxProgressDialog *progressDialog = new wxProgressDialog( _( "Design Rule Check" ), wxEmptyString,
+            100, aMessages ? aMessages->GetParent() : m_pcbEditorFrame,
+            wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
+
+
     // Ensure ratsnest is up to date:
     if( (m_pcb->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
     {
@@ -213,7 +217,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
         // update the m_drcDialog listboxes
         updatePointers();
 
-        return;
+        goto out;
     }
 
     // test pad to pad clearances, nothing to do with tracks, vias or zones.
@@ -235,7 +239,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
         wxSafeYield();
     }
 
-    testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
+    testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true, progressDialog );
 
     // Before testing segments and unconnected, refill all zones:
     // this is a good caution, because filled areas can be outdated.
@@ -246,7 +250,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
     }
 
     m_pcbEditorFrame->Fill_All_Zones( aMessages ? aMessages->GetParent() : m_pcbEditorFrame,
-                                  false );
+                                  false, progressDialog );
 
     // test zone clearances to other zones
     if( aMessages )
@@ -299,6 +303,9 @@ void DRC::RunTests( wxTextCtrl* aMessages )
         // to unnecessarily scroll.
         aMessages->AppendText( _( "Finished" ) );
     }
+
+out:
+    progressDialog->Destroy();
 }
 
 
@@ -491,46 +498,52 @@ void DRC::testPad2Pad()
 }
 
 
-void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar )
+void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar,
+        wxProgressDialog *aProgressDialog )
 {
     wxProgressDialog * progressDialog = NULL;
-    const int delta = 500;  // This is the number of tests between 2 calls to the
+    const int delta = 256;  // This is the number of tests between 2 calls to the
                             // progress bar
-    int count = 0;
+    int n_tracks = 0;
     for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
-        count++;
+        n_tracks++;
 
-    int deltamax = count/delta;
+    int deltamax = n_tracks/delta;
 
     if( aShowProgressBar && deltamax > 3 )
     {
-        progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
-                                               deltamax, aActiveWindow,
-                                               wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
-                                               wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
-        progressDialog->Update( 0, wxEmptyString );
+        if( aProgressDialog )
+        {
+            progressDialog = aProgressDialog;
+        }
+        else
+        {
+            progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
+                    deltamax, aActiveWindow,
+                    wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
+                    wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
+        }
+        progressDialog->Update( 0, _( "Checking track clearances..." ) );
+        progressDialog->SetRange( deltamax );
     }
 
-    int ii = 0;
-    count = 0;
+    int i_track = 0;
 
     for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
     {
-        if ( ii++ > delta )
+        ++i_track;
+        if ( i_track % delta == 0 && progressDialog )
         {
-            ii = 0;
-            count++;
+            wxString msg;
+            msg.Printf( _( "Checking track clearances (%d/%d)..." ), i_track, n_tracks );
+            if( !progressDialog->Update( i_track / delta, msg ) )
+                break;  // Aborted by user
 
-            if( progressDialog )
-            {
-                if( !progressDialog->Update( count, wxEmptyString ) )
-                    break;  // Aborted by user
 #ifdef __WXMAC__
-                // Work around a dialog z-order issue on OS X
-                if( count == deltamax )
-                    aActiveWindow->Raise();
+            if( i_track > n_track - delta )
+                aActiveWindow->Raise();
 #endif
-            }
+
         }
 
         if( !doTrackDrc( segm, segm->Next(), true ) )
@@ -542,7 +555,7 @@ void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar )
         }
     }
 
-    if( progressDialog )
+    if( progressDialog && !aProgressDialog )
         progressDialog->Destroy();
 }
 
diff --git a/pcbnew/drc_stuff.h b/pcbnew/drc_stuff.h
index 9a5e147..3b1693a 100644
--- a/pcbnew/drc_stuff.h
+++ b/pcbnew/drc_stuff.h
@@ -91,6 +91,7 @@ class TRACK;
 class MARKER_PCB;
 class DRC_ITEM;
 class NETCLASS;
+class wxProgressDialog;
 
 
 /**
@@ -274,8 +275,10 @@ private:
      * @param aActiveWindow = the active window ued as parent for the progress bar
      * @param aShowProgressBar = true to show a progress bar
      * (Note: it is shown only if there are many tracks)
+     * @param aProgressDialog = an existing wxProgressDialog, or NULL to create one
      */
-    void testTracks( wxWindow * aActiveWindow, bool aShowProgressBar );
+    void testTracks( wxWindow * aActiveWindow, bool aShowProgressBar,
+            wxProgressDialog *aProgressDialog );
 
     void testPad2Pad();
 
diff --git a/pcbnew/zones_by_polygon_fill_functions.cpp b/pcbnew/zones_by_polygon_fill_functions.cpp
index 16e2088..2ee6c09 100644
--- a/pcbnew/zones_by_polygon_fill_functions.cpp
+++ b/pcbnew/zones_by_polygon_fill_functions.cpp
@@ -1,12 +1,8 @@
 /*
- * @file zones_by_polygon_fill_functions.cpp
- */
-
-/*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2009 Jean-Pierre Charras <jean-pierre.charras@xxxxxxxxxxxxxxxxx>
- * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
+ * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,6 +22,10 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+/*
+ * @file zones_by_polygon_fill_functions.cpp
+ */
+
 #include <wx/progdlg.h>
 
 #include <fctsys.h>
@@ -124,7 +124,8 @@ int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone )
 }
 
 
-int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
+int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose,
+        wxProgressDialog *aProgressDialog )
 {
     int errorLevel = 0;
     int areaCount = GetBoard()->GetAreaCount();
@@ -137,10 +138,21 @@ int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
     msg.Printf( FORMAT_STRING, 000, areaCount, wxT("XXXXXXXXXXXXXXXXX" ) );
 
     if( aActiveWindow )
-        progressDialog = new wxProgressDialog( _( "Fill All Zones" ), msg,
-                                     areaCount+2, aActiveWindow,
-                                     wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
-                                     wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
+    {
+        if( aProgressDialog )
+        {
+            progressDialog = aProgressDialog;
+        }
+        else
+        {
+            progressDialog = new wxProgressDialog( _( "Fill All Zones" ), msg,
+                    areaCount + 2, aActiveWindow,
+                    wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
+        }
+        progressDialog->Update( 0, msg );
+        progressDialog->SetRange( areaCount + 2 );
+    }
+
     // Display the actual message
     if( progressDialog )
         progressDialog->Update( 0, _( "Starting zone fill..." ) );
@@ -182,7 +194,7 @@ int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose )
 
     // Recalculate the active ratsnest, i.e. the unconnected links
     TestForActiveLinksInRatsnest( 0 );
-    if( progressDialog )
+    if( progressDialog && !aProgressDialog )
         progressDialog->Destroy();
     return errorLevel;
 }
-- 
2.9.2


Follow ups