← Back to team overview

kicad-developers team mailing list archive

Re: Current state of ActionPlugin

 

Dear All,

A quick update on this feature. I use it since it's committed and it
look to work as expected.

 I advance on my side to provide a undo/redo feature.
You will find attached a patch for that.
For the moment it's a request for comments.

 It successfully undo/redo multiples actions (modify elements, adding
items and remove items).
 Of course care must be taken if the python script delete elements
(Example: use "RemoveNative" instead of "Remove") but the undo/redo work.

Regards,
Le 23/01/2017 à 16:25, Nick Østergaard a écrit :
> Ok, feel free to remind me later then.
> 
> 2017-01-23 14:30 GMT+01:00 Wayne Stambaugh <stambaughw@xxxxxxxxx>:
>> On 1/23/2017 8:30 AM, jp charras wrote:
>>> Le 23/01/2017 à 14:19, Nick Østergaard a écrit :
>>>> Should it be enabled in the windows nightlies now or should we wait a bit?
>>>>
>>>
>>> Before enabling it, please wait for a few tests from devs and J-S.
>>> Perhaps also a bit of doc and 2 or 3 samples which do not delete anything (could be in demos) is
>>> welcome.
>>> This is in the J-S Reynaud's hands.
>>
>> I concur.  I think it would be wise to allow our python devs to test it
>> for a while be for we make it available for general testing.
>>
>>>
>>>
>>>> 2017-01-23 14:13 GMT+01:00 jp charras <jp.charras@xxxxxxxxxx>:
>>>>> Le 18/01/2017 à 18:00, Jean-Samuel Reynaud a écrit :
>>>>>> Just to know if this patch is now acceptable ? Did you plan to commit it ?
>>>>>>
>>>>>> Thanks,
>>>>>> Le 17/01/2017 à 19:46, Jean-Samuel Reynaud a écrit :
>>>>>>>> yes i was trying to subtly imply that :)
>>>>>>> ok, find attached the patch with the about box updated ;)
>>>>>>>
>>>>>>> Regards,
>>>>>>>
>>>>>
>>>>> I committed the patch ( with fixes, see comments) in rev:
>>>>> 2b5769c0a8568e421c2152177a8f1c27d9bf9cb5
>>>>>
>>>>> Jean-Samuel, thanks, and please carefully test this rev, to be sure I did not break anything.
>>>>>
>>>>> The action plugin feature must be currently seen as an experimental feature, for developers, because
>>>>> it can easily break a board.
>>>>> It is enabled if the option -DKICAD_SCRIPTING_ACTION_MENU=ON is added to the cmake command line.
>>>>>
>>>>> I am thinking this feature need to be tested, and enhancements added (especially if a script deletes
>>>>> a board item), and this is the reason I see it as currently experimental.
>>>>>
>>>>> However, now it exists, it can be tested.
>>>>>
>>>>>
>>>>> --
>>>>> Jean-Pierre CHARRAS
>>>>>
>>>>> _______________________________________________
>>>>> Mailing list: https://launchpad.net/~kicad-developers
>>>>> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>>>>> Unsubscribe : https://launchpad.net/~kicad-developers
>>>>> More help   : https://help.launchpad.net/ListHelp
>>>>
>>>
>>>
>>
>> _______________________________________________
>> Mailing list: https://launchpad.net/~kicad-developers
>> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~kicad-developers
>> More help   : https://help.launchpad.net/ListHelp
> 
> _______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers
> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~kicad-developers
> More help   : https://help.launchpad.net/ListHelp
> 

diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp
index 7118f7f..26cf1b8 100644
--- a/pcbnew/swig/pcbnew_action_plugins.cpp
+++ b/pcbnew/swig/pcbnew_action_plugins.cpp
@@ -36,6 +36,8 @@
 #include <class_board.h>
 #include <class_module.h>
 #include <class_track.h>
+#include <class_drawsegment.h>
+#include <class_zone.h>
 #include <board_commit.h>
 #include <kicad_device_context.h>
 
@@ -176,14 +178,174 @@ void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent )
 
     if( actionPlugin )
     {
-        // TODO: Adding recovery point for jobs
-        // BOARD_COMMIT commit( this );
-        // commit.Push( _( "External plugin" ) );
+        PICKED_ITEMS_LIST itemsList;
+        BOARD* currentPcb = GetBoard();
 
-        actionPlugin->Run();
+        itemsList.m_Status = UR_CHANGED;
 
         OnModify();
 
+        // Append tracks:
+        for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
+        {
+            ITEM_PICKER picker( item, UR_CHANGED );
+            itemsList.PushItem( picker );
+        }
+
+        // Append modules:
+        for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
+        {
+            ITEM_PICKER picker( item, UR_CHANGED );
+            itemsList.PushItem( picker );
+        }
+
+        // Append drawings
+        for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
+        {
+            ITEM_PICKER picker( item, UR_CHANGED );
+            itemsList.PushItem( picker );
+        }
+
+        // Append zones outlines
+        for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
+        {
+            ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
+                            ii ), UR_CHANGED );
+            itemsList.PushItem( picker );
+        }
+
+        // Append zones segm:
+        for( BOARD_ITEM* item = currentPcb->m_Zone; item != NULL; item = item->Next() )
+        {
+            ITEM_PICKER picker( item, UR_CHANGED );
+            itemsList.PushItem( picker );
+        }
+
+        SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) );
+
+        itemsList.ClearItemsList();
+
+        // Execute plugin himself...
+        actionPlugin->Run();
+
+        currentPcb->m_Status_Pcb = 0;
+
+        // Get back the undo buffer to fix some modifications
+        PICKED_ITEMS_LIST* oldBuffer = GetScreen()->PopCommandFromUndoList();
+
+        // Try do discover what was modified
+
+        PICKED_ITEMS_LIST deletedItemsList;
+
+        // Found deleted modules
+        for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ )
+        {
+            BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i );
+            ITEM_PICKER picker( item, UR_DELETED );
+
+            wxASSERT( item );
+
+            switch( item->Type() )
+            {
+            case PCB_NETINFO_T:
+            case PCB_MARKER_T:
+            case PCB_MODULE_T:
+            case PCB_TRACE_T:
+            case PCB_VIA_T:
+            case PCB_LINE_T:
+            case PCB_TEXT_T:
+            case PCB_DIMENSION_T:
+            case PCB_TARGET_T:
+            case PCB_ZONE_T:
+                // If item has a list it's mean that the element is on the board
+                if( item->GetList() == NULL )
+                {
+                    deletedItemsList.PushItem( picker );
+                }
+
+                break;
+
+            case PCB_ZONE_AREA_T:
+            {
+                bool zoneFound = false;
+
+                for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
+                    zoneFound |= currentPcb->GetArea( ii ) == item;
+
+                if( !zoneFound )
+                {
+                    deletedItemsList.PushItem( picker );
+                }
+
+                break;
+            }
+
+            default:
+                wxString msg;
+                msg.Printf( wxT( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: "
+                                 "BOARD_ITEM type (%d) not handled" ),
+                        item->Type() );
+                wxFAIL_MSG( msg );
+                break;
+            }
+        }
+
+        // Mark deleted elements in undolist
+        for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ )
+        {
+            oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) );
+        }
+
+        // Find new modules
+        for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
+        {
+            if( !oldBuffer->ContainsItem( item ) )
+            {
+                ITEM_PICKER picker( item, UR_NEW );
+                oldBuffer->PushItem( picker );
+            }
+        }
+
+        for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
+        {
+            if( !oldBuffer->ContainsItem( item ) )
+            {
+                ITEM_PICKER picker( item, UR_NEW );
+                oldBuffer->PushItem( picker );
+            }
+        }
+
+        for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
+        {
+            if( !oldBuffer->ContainsItem( item ) )
+            {
+                ITEM_PICKER picker( item, UR_NEW );
+                oldBuffer->PushItem( picker );
+            }
+        }
+
+        for( BOARD_ITEM* item = currentPcb->m_Zone; item != NULL; item = item->Next() )
+        {
+            if( !oldBuffer->ContainsItem( item ) )
+            {
+                ITEM_PICKER picker( item, UR_NEW );
+                oldBuffer->PushItem( picker );
+            }
+        }
+
+        for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
+        {
+            if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) )
+            {
+                ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
+                                ii ), UR_NEW );
+                oldBuffer->PushItem( picker );
+            }
+        }
+
+
+        GetScreen()->PushCommandToUndoList( oldBuffer );
+
         if( IsGalCanvasActive() )
         {
             UseGalCanvas( GetGalCanvas() );
@@ -201,7 +363,7 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
 {
     wxMenu* actionMenu = GetMenuBar()->FindItem( ID_TOOLBARH_PCB_ACTION_PLUGIN )->GetSubMenu();
 
-    if( !actionMenu )   // Should not occur.
+    if( !actionMenu ) // Should not occur.
         return;
 
     // First, remove existing submenus, if they are too many
@@ -235,7 +397,7 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
     {
         wxMenuItem* item;
 
-        if( ii < (int)available_menus.size() )
+        if( ii < (int) available_menus.size() )
         {
             item = available_menus[ii];
             item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() );
@@ -248,9 +410,9 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
                     ACTION_PLUGINS::GetAction( ii )->GetDescription(),
                     KiBitmap( hammer_xpm ) );
 
-                Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
-                         (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
-                         PCB_EDIT_FRAME::OnActionPlugin );
+            Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
+                    (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
+                    PCB_EDIT_FRAME::OnActionPlugin );
         }
 
         ACTION_PLUGINS::SetActionMenu( ii, item->GetId() );

References