Workbench creation/it


Questa pagina spiega come aggiungere un nuovo ambiente di lavoro (Workbench) all'interfaccia di FreeCAD. Gli Workbenches sono dei contenitori per i comandi di FreeCAD. Essi possono essere codificati in python, in C++, o in una combinazione di entrambi, con il vantaggio di unire la velocità di C++ alla flessibilità di python. In tutti i casi, il vostro ambiente di lavoro sarà comunque lanciato da un insieme di due file python.

La struttura del workbench

Fondamentalmente è semplice: serve una cartella, con un nome a piacere, inserita nella directory Mod, contenente un file Init.py e, facoltativamente, un file InitGui.py. Il file Init viene sempre eseguito all'avvio FreeCAD, e il file InitGui.py viene eseguito immediatamente dopo, ma solo quando FreeCAD si avvia in modalità GUI, non in modalità console. Questo è tutto ciò che serve a FreeCAD per trovare il vostro ambiente di lavoro in fase di avvio e aggiungerlo alla sua interfaccia.

All'interno questi file si può fare quello che si vuole. Di solito vengono utilizzati in questo modo:

Struttura del workbench in C++

Per codificare l'ambiente in python, non è necessario usare particolari attenzioni, è possibile inserire semplicemente gli altri file python insieme ai file Init.py e InitGui.py. Invece, quando si lavora in C++ si deve avere maggiori attenzioni, e iniziare rispettando una regola fondamentale di FreeCAD: separare la parte App dell'ambiente, quella che può essere eseguita in modalità console, senza alcun elemento GUI, dalla parte Gui, che è quella che viene caricata solo quando FreeCAD funziona completo del suo ambiente GUI. Quindi, quando si crea un ambiente in C++, in realtà si creano probabilmente due moduli, un App e un Gui. Questi due moduli devono naturalmente essere richiamabili in python. Ogni modulo di FreeCAD (App o Gui) consiste, per lo meno, di un modulo con un file init. Questo è un tipico file AppMyModuleGui.cpp:

extern "C" {
    void MyModuleGuiExport initMyModuleGui()  
    {
         if (!Gui::Application::Instance) {
            PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application.");
            return;
        }
        try {
            // import other modules this one depends on
            Base::Interpreter().runString("import PartGui");
            // run some python code in the console
            Base::Interpreter().runString("print('welcome to my module!')");
        }
        catch(const Base::Exception& e) {
            PyErr_SetString(PyExc_ImportError, e.what());
            return;
        }
        (void) Py_InitModule("MyModuleGui", MyModuleGui_Import_methods);   /* mod name, table ptr */
        Base::Console().Log("Loading GUI of MyModule... done\n");
    
        // initializes the FreeCAD commands (in another cpp file)
        CreateMyModuleCommands();
    
        // initializes workbench and object definitions
        MyModuleGui::Workbench::init();
        MyModuleGui::ViewProviderSomeCustomObject::init();
    
         // add resources and reloads the translators
        loadMyModuleResource();
    }
} 

Il file Init.py

# FreeCAD init script of XXX module  

#***************************************************************************
#*   (c) John Doe john@doe.com 2015                                        *   
#*                                                                         *
#*   This file is part of the FreeCAD CAx development system.              *
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   FreeCAD is distributed in the hope that it will be useful,            *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Lesser General Public License for more details.                   *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with FreeCAD; if not, write to the Free Software        *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************/

FreeCAD.addImportType("My own format (*.own)","importOwn")
FreeCAD.addExportType("My own format (*.own)","importOwn")
print "I am executing some stuff here when FreeCAD starts!" 

Per il proprio ambiente è possibile scegliere liberamente qualsiasi licenza, ma se a un certo punto si desidera vederlo integrato e distribuito con il codice sorgente di FreeCAD si deve essere consapevoli che la licenza deve essere LGPL2+, come nell'esempio precedente. Le funzioni FreeCAD.addImportType() e addEXportType() permettono di assegnare il nome e l'estensione di un tipo di file, e un modulo python responsabile della sua importazione. Nell'esempio precedente, un modulo "importOwn.py" gestisce i file .own. Per ulteriori esempi, vedere la pagina degli esempi di codice.

Ambienti di lavoro in Python

class MyWorkbench (Workbench):

    MenuText = "My Workbench"
    ToolTip = "A description of my workbench"
    Icon = """paste here the contents of a 16x16 xpm icon"""

    def Initialize(self):
        "This function is executed when FreeCAD starts"
        import MyModuleA, MyModuleB # import here all the needed files that create your FreeCAD commands
        self.list = ["MyCommand1, MyCommand2"] # A list of command names created in the line above
        self.appendToolbar("My Commands",self.list) # creates a new toolbar with your commands
        self.appendMenu("My New Menu",self.list) # creates a new menu
        self.appendMenu(["An existing Menu","My submenu"],self.list) # appends a submenu to an existing menu

    def Activated(self):
        "This function is executed when the workbench is activated"
        return

    def Deactivated(self):
        "This function is executed when the workbench is deactivated"
        return

    def ContextMenu(self, recipient):
        "This is executed whenever the user right-clicks on screen"
        # "recipient" will be either "view" or "tree"
        self.appendContextMenu("My commands",self.list) # add commands to the context menu

    def GetClassName(self): 
        # this function is mandatory if this is a full python workbench
        return "Gui::PythonWorkbench"
       
Gui.addWorkbench(MyWorkbench())

Oltre a questo, si può fare tutto quello che si vuole: si potrebbe mettere tutto il codice del workbench all'interno di InitGui.py se si vuole, ma di solito è più conveniente posizionare le diverse funzioni dell'ambiente in file separati. Così i file sono più piccoli e più facili da leggere. Poi si importano i file nel file InitGui.py. È possibile organizzare i file nel modo desiderato, un buon esempio di organizzazione è un file per ogni comando di FreeCAD che si aggiunge.

Workbench in C++

Quando si vuole codificare l'ambiente in C ++, probabilmente si vuole anche codificare la definizione dell'ambiente stesso in C ++ (anche se non è necessario: si potrebbe anche codificare solo gli strumenti in C++, e lasciare la definizione dell'ambiente in python). In tal caso, il file InitGui.py diventa molto semplice: Può contenere una sola riga:

import MyModuleGui 

dove MyModule è l'ambiente completo in C++, inclusi i comandi e la definizione dell'ambiente.

La codificazione dei workbenches in C++ funziona in modo molto simile. Questo è un tipico file Workbench.cpp da includere nella parte Gui del modulo:

namespace MyModuleGui {
    class MyModuleGuiExport Workbench : public Gui::StdWorkbench
    {
        TYPESYSTEM_HEADER();

    public:
        Workbench();
        virtual ~Workbench();

        virtual void activated();
        virtual void deactivated();

    protected:
        Gui::ToolBarItem* setupToolBars() const;
        Gui::MenuItem*    setupMenuBar() const;
    };
} 

I comandi di FreeCAD

I comandi FreeCAD sono gli elementi di base dell'interfaccia di FreeCAD. Possono apparire come un pulsanti sulla barra degli strumenti, e come voce di menu. Ma sono lo stesso comando. Un comando è una semplice classe Python, che deve contenere un paio di attributi predefiniti e le funzioni che definiscono il nome del comando, la sua icona, e cosa fare quando viene attivato il comando.

Definizione dei comandi Python

class My_Command_Class():
    """My new command"""

    def GetResources(self):
        return {'Pixmap'  : 'My_Command_Icon', # the name of a svg file available in the resources
                'Accel' : "Shift+S", # a default shortcut (optional)
                'MenuText': "My New Command"
                'ToolTip' : "What my new command does"}

    def Activated(self):
        "Do something here"
        return

    def IsActive(self):
        """Here you can define if the command must be active or not (greyed) if certain conditions
        are met or not. This function is optional."""
        return True

FreeCADGui.addCommand('My_Command',My_Command_Class()) 

Definizione dei comandi C++

Allo stesso modo, è possibile codificare i comandi in C++, in genere hanno un file Commands.cpp nel modulo Gui. Questo è un tipico file Commands.cpp:

DEF_STD_CMD_A(CmdMyCommand);

CmdMyCommand::CmdMyCommand()
  :Command("My_Command")
{
  sAppModule    = "MyModule";
  sGroup        = QT_TR_NOOP("MyModule");
  sMenuText     = QT_TR_NOOP("Runs my command...");
  sToolTipText  = QT_TR_NOOP("Describes what my command does");
  sWhatsThis    = QT_TR_NOOP("Describes what my command does");
  sStatusTip    = QT_TR_NOOP("Describes what my command does");
  sPixmap       = "some_svg_icon_from_my_resource";
}

void CmdMyCommand::activated(int iMsg)
{
    openCommand("My Command");
    doCommand(Doc,"print('Hello, world!')");
    commitCommand();
    updateActive();
}

bool CmdMyCommand::isActive(void)
{
  if( getActiveGuiDocument() )
    return true;
  else
    return false;
}

void CreateMyModuleCommands(void)
{
    Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
    rcCmdMgr.addCommand(new CmdMyCommand());
} 


Online version: "http://www.freecadweb.org/wiki/index.php?title=Workbench_creation/it&oldid=189376"

Navigation menu