"""Subclass of ModelsView, which is generated by wxFormBuilder."""

import os
import wx
import wxx
import tran
import app
import model
import copy
import deco
import app.resources as rc
from app.ui.view import BaseView
from ctx import localcontext as context
from activity.models.ui import ui
from activity.models.ui import dlg as ui_dlg
import app.clipboard as clipboard


# all languages short-cut
ID_ADD_MEMBER_KEY = wx.ID_HIGHEST + 200
ID_ADD_METHOD_KEY = wx.ID_HIGHEST + 201
ID_ADD_ARGUMENT_KEY = wx.ID_HIGHEST + 202
ID_ADD_START_KEY = wx.ID_HIGHEST + 203
ID_ADD_END_KEY = wx.ID_HIGHEST + 204
ID_TREE_LEFT_KEY = wx.ID_HIGHEST + 205
ID_ADD_CLASS_KEY = wx.ID_HIGHEST + 206
ID_ADD_IMPORT_KEY = wx.ID_HIGHEST + 207
ID_ADD_INHERITANCE = wx.ID_HIGHEST + 208


# base class for clipboard data
class clip_item_model(object):
    """clipboard format"""

    def __init__(self, object):
        """
        Initialize clipboard data.
        The object is the selected data
        """
        # self.copyType = type(object)
        #self.copyArgs = object.get_kwargs()
        self.proj = object.project
        self.lang = self.proj._language
        self.type = type(object)
        self.args = object.get_kwargs()


CLIP_FORMAT_MODEL = clipboard.register(clip_item_model)


# Implementing ModelsView
class ModelsView(BaseView, ui.ModelsView):
    """Implements the view for model"""
    perspective = ''

    run_handler = True
    debug_handler = True

    # add folder
    _addFolderId = wx.Window.NewControlId()
    _addClassDiagramId = wx.Window.NewControlId()
    _addModuleId = wx.Window.NewControlId()
    _addNamespaceId = wx.Window.NewControlId()
    _addTypeId = wx.Window.NewControlId()
    _addEnumId = wx.Window.NewControlId()
    _addClassId = wx.Window.NewControlId()
    _addInheritanceId = wx.Window.NewControlId()
    _setFriendshipId = wx.Window.NewControlId()
    _addMemberId = wx.Window.NewControlId()
    _addConstructorId = wx.Window.NewControlId()
    _addMethodId = wx.Window.NewControlId()
    _addDestructorId = wx.Window.NewControlId()
    _addArgumentId = wx.Window.NewControlId()
    _addFunctionId = wx.Window.NewControlId()
    _addVariableId = wx.Window.NewControlId()
    _addVirtualMethodId = wx.Window.NewControlId()
    _addIsclassMethodId = wx.Window.NewControlId()
    _addRelationId = wx.Window.NewControlId()
    _applyRule3Id = wx.Window.NewControlId()
    _pyboostInterfaceId = wx.Window.NewControlId()
    _setPreferredCtorId = wx.Window.NewControlId()
    _addPyPackageId = wx.Window.NewControlId()
    _menuAddPythonId = wx.Window.NewControlId()
    _addPyModuleId = wx.Window.NewControlId()
    _addImportFolderId = wx.Window.NewControlId()
    _addPyImportId = wx.Window.NewControlId()
    _addPyClassId = wx.Window.NewControlId()
    _addPyInheritanceId = wx.Window.NewControlId()
    _addPyInitId = wx.Window.NewControlId()
    _addPyMethodId = wx.Window.NewControlId()
    _addPyArgumentId = wx.Window.NewControlId()
    _addargsId = wx.Window.NewControlId()
    _addkwargsId = wx.Window.NewControlId()
    _addPyMemberId = wx.Window.NewControlId()
    _addPyFunctionId = wx.Window.NewControlId()
    _addPyVariableId = wx.Window.NewControlId()
    _editDecoratorsId = wx.Window.NewControlId()
    _setPyEntryId = wx.Window.NewControlId()
    _projectContextsId = wx.Window.NewControlId()
    _projectLibrariesId = wx.Window.NewControlId()
    _projectExportId = wx.Window.NewControlId()

    #update_context : these properties will be used for update menus
    @property
    def can_paste(self):
        """Indicate if it's possible to paste'"""
        selected = self.selected
        if not selected or clipboard.info != CLIP_FORMAT_MODEL:
            return False
        data = clipboard.data
        if selected.project._language != data.lang:
            return False
        if data.lang == 'python':
            if data.type in [model.py.InitMethod, model.py.MemberData, model.py.MemberMethod]:
                return selected.inner_member_container is not None
            if data.type is model.py.Argument:
                return self.can_add_py_arg
            if data.type is model.py.ArgsArgument:
                return self.can_add_py_argargs
            if data.type is model.py.KwArgsArgument:
                return self.can_add_py_kwargs
            if data.type is model.py.Data:
                return self.can_add_py_variable
            if data.type is model.py.Function:
                return self.can_add_py_function
            if data.type is model.py.Import:
                return self.can_add_py_import
            if data.type is model.py.ImportsFolder:
                return self.can_add_py_imports_folder
            if data.type is model.py.Inheritance:
                return self.can_add_py_inheritance
            if data.type is model.py.Module:
                return self.can_add_py_module
            return False
        if data.lang != 'c++':
            return False
        # get the clipboard type specifier
        s_type = data.args.get('type', None)
        # kwnow types
        s_typenames = [x.name for x in selected.types]
        t_typenames = selected.template_types
        if data.type in [model.cc.Argument, model.cc.MemberData]:
            if not s_type:
                return False  # may be an exception, because that's not allowd
            if s_type.type_name in s_typenames:
                return True
            if s_type.type_name in t_typenames:
                return True
            return False
        if data.type is model.cc.Constructor:
            if data.args.get('parent', None) == selected.inner_class:
                return True
            return False
        if data.type in [model.cc.MemberMethod, model.cc.IsClassMethod]:
            if not selected.inner_member_container:
                return False
            if not s_type:
                return False  # may be an exception, because that's not allowd
            if s_type.type_name in s_typenames:
                return True
            if s_type.type_name in t_typenames:
                return True
            # check again the arguments
            childs = data.args.get('child_kwargs', {})
            if model.cc.Argument in childs:
                for arg in childs[model.cc.Argument]:
                    s_type = arg.get('type', None)
                    if not s_type:
                        return False
                    if s_type.type_name in s_typenames:
                        continue
                    if s_type.type_name in t_typenames:
                        continue
                    return False
            return True

    @property
    def can_cut(self):
        """return info about the feasibility of cut"""
        obj = self.selected
        return bool(obj and obj.can_delete and not obj in [
            model.Project, model.LibrariesFolder,
            model.cc.TypesFolder, model.cc.Inheritance,
            model.cc.RelationFrom, model.cc.RelationTo,
            model.cc.Class])

    @property
    def can_copy(self):
        """Inticate if it's possible to copy'"""
        selected = self.selected
        if not selected or selected.read_only:
            return False
        return type(selected) not in [
            model.Project, model.LibrariesFolder,
            model.cc.TypesFolder, model.cc.Inheritance,
            model.cc.RelationFrom, model.cc.RelationTo,
            model.cc.Class]

    @property
    def can_delete(self):
        """return info about if this can be deleted"""
        return bool(self.selected and self.selected.can_delete)

    @property
    def can_edit_open(self):
        """it's enabled editing?'"""
        selected = self.selected
        if not selected:
            return False
        if type(selected) in [model.cc.Constructor,
            model.cc.Destructor, model.cc.Function, model.cc.MemberMethod,
            model.py.InitMethod, model.py.MemberMethod, model.py.Function,
            model.cc.InitMethod, model.cc.IsClassMethod, model.ClassDiagram,
            model.py.Module]:
            return True
        return False

    @property
    def can_edit_context(self):
        """Is context editable?"""
        if not self.selected or type(self.selected) in [model.LibrariesFolder,
        model.cc.TypesFolder, model.cc.Type, model.cc.Namespace, model.cc.Argument]:
            return False
        return True

    @property
    def can_edit_user_sections(self):
        """The user sections is editable for selected object?"""
        selected = self.selected
        if not selected or selected.read_only:
            return False
        return type(selected) in [model.cc.Class, model.py.Class]

    @property
    def can_add_class(self):
        """Can be added class?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_class_container
        if not obj:
            return False
        return  obj.project._language == 'c++'

    @property
    def can_add_inheritance(self):
        """Can be added an inheritance?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_inheritance_container
        if not obj:
            return False
        return obj.project._language == 'c++'

    @property
    def can_add_destructor(self):
        """Can be added a destructor?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_member_container
        if not obj:
            return False
        obj = obj.inner_class
        if not obj:
            return False
        if not obj.project._language == 'c++':
            return False
        return not obj(model.cc.Destructor, filter=lambda x: x.inner_class == obj, cut=True)

    @property
    def can_add_py_class(self):
        """Can be added a class?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_class_container
        if not obj:
            return False
        return obj.project._language == 'python'

    @property
    def can_add_py_arg(self):
        """Can be add an argument?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_argument_container
        if not obj:
            return False
        return type(obj) in [model.py.Function, model.py.MemberMethod, model.py.InitMethod]

    @property
    def can_add_py_argargs(self):
        """Can add an 'args'?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_argument_container
        if not obj:
            return False
        if obj.project._language != 'python':
            return False
        return not obj[model.py.ArgsArgument]

    @property
    def can_add_py_kwargs(self):
        """Can add a kwargs?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_argument_container
        if not obj:
            return False
        if obj.project._language != 'python':
            return False
        return not obj[model.py.KwArgsArgument]

    @property
    def can_add_py_function(self):
        """Handle add python function"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_function_container
        if not obj:
            return False
        return obj.project._language == 'python'

    @property
    def can_add_py_variable(self):
        """can add a python variable at selected place?"""
        obj = self.selected
        if not obj:
            return False
        obj = self.selected.inner_variable_container
        if not obj:
            return False
        return obj.project._language == 'python'

    @property
    def can_add_py_imports_folder(self):
        """Can add an imports folder here?"""
        obj = self.selected
        if not obj:
            return False
        return obj.inner_import_container is not None

    @property
    def can_add_py_import(self):
        """can be added a python import at selected place?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_import_container
        if not obj:
            return False
        return obj.project._language == 'python'

    @property
    def can_add_py_inheritance(self):
        """can be added a python inheritance at selected place?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_inheritance_container
        if not obj:
            return False
        return obj.project._language == 'python'

    @property
    def can_add_py_module(self):
        """A module can be added here?"""
        obj = self.selected
        if not obj:
            return False
        obj = obj.inner_module_container
        if not obj:
            return False
        return obj.project._language == 'python'

    def __init__(self, parent, root=None):
        """Initializes the view"""
        super(ModelsView, self).__init__(parent)
        self.frame = parent
        self.imglist = rc.GetBitmapImageList()
        self.m_tree.SetImageList(self.imglist)
        self._create_menus()
        self._create_toolbars()
        self._bind_events()
        self._set_accelerators()
        self.m_tree.AddRoot('Projects')
        # when we create a models view, we need to update elements
        if root is None:
            # reload full stack
            theApp = context.app
            for wrk in theApp.workspaces:
                self.insert(wrk)
        # enhancement for popup subviews
        else:
            self.insert(root)

    def GetViewStatus(self):
        """Get working info about the view"""
        return str(self.m_tree.GetExpansionState())

    def SetViewStatus(self, status):
        """Set working info about the view"""
        try:
            l = eval(status)
            self.m_tree.SetExpansionState(l)
            return True
        except:
            return False

    def insert(self, element):
        """Nested insert elements in tree"""
        self.DoRenderAddElement(element)
        for cls in element._child:
            for k in element[cls]:
                self.insert(k)

    @deco.classproperty
    def name(cls):
        """returns the name of this view"""
        return 'Models'

    @classmethod
    def bitmap_index(cls):
        """return the bitmap index"""
        return rc.GetBitmapIndex('models')

    @classmethod
    def bitmap(cls):
        """return the bitmap"""
        return rc.GetBitmap('models')

    def _create_menus(self):
        """create the menu"""
        super(ModelsView, self)._create_menus()
        # the menu structure
        self._menu = wx.Menu()
        self._menuAdd = wx.Menu()
        # add project
        self._addProject = wx.MenuItem(self._menuAdd, app.ID_NEW_PROJECT, u"Project ...", u"Add new project", wx.ITEM_NORMAL)
        self._addProject.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_MENU))
        self._menuAdd.AppendItem(self._addProject)
        # add folder
        self._addFolder = wx.MenuItem(self._menuAdd, self._addFolderId,
            u"Folder ..." + u"\t" + u"Shift+Ctrl+F", u"add folder", wx.ITEM_NORMAL)
        self._addFolder.SetBitmap(wx.Bitmap(u"app/res/folder.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAdd.AppendItem(self._addFolder)

        self._addClassDiagram = wx.MenuItem(self._menuAdd, self._addClassDiagramId,
            u"Class diagram ...", u"add class diagram", wx.ITEM_NORMAL)
        self._addClassDiagram.SetBitmap(wx.Bitmap(u"app/res/classdiagram.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAdd.AppendItem(self._addClassDiagram)

        self._menu.AppendSubMenu(self._menuAdd, u"common")

        self._menuAddCC = wx.Menu()
        self._menuAddCCElements = wx.Menu()

        self._addModule = wx.MenuItem(self._menuAddCCElements, self._addModuleId,
            u"Module ...\tShift+Ctrl+M", u"add module", wx.ITEM_NORMAL)
        self._addModule.SetBitmap(wx.Bitmap(u"app/res/module.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addModule)

        self._addNamespace = wx.MenuItem(self._menuAddCCElements, self._addNamespaceId,
            u"Namespace ...\tShift+N", u"add namespace", wx.ITEM_NORMAL)
        self._addNamespace.SetBitmap(wx.Bitmap(u"app/res/namespace.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addNamespace)

        self._addType = wx.MenuItem(self._menuAddCCElements, self._addTypeId,
            u"Type ...\tCtrl+Alt+T", u"add type", wx.ITEM_NORMAL)
        self._addType.SetBitmap(wx.Bitmap(u"app/res/type.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addType)

        self._addEnum = wx.MenuItem(self._menuAddCCElements, self._addEnumId,
            u"Enum...\tShift+Ctrl+E", u"add enum", wx.ITEM_NORMAL)
        self._addEnum.SetBitmap(wx.Bitmap(u"app/res/enum.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addEnum)

        self._addClass = wx.MenuItem(self._menuAddCCElements, self._addClassId,
            u"Class ...\tCtrl+Alt+C", u"add class", wx.ITEM_NORMAL)
        self._addClass.SetBitmap(wx.Bitmap(u"app/res/class.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addClass)

        self._addInheritance = wx.MenuItem(self._menuAddCCElements, self._addInheritanceId,
            u"Inheritance ...\tCtrl+Alt+I", u"add inheritance", wx.ITEM_NORMAL)
        self._addInheritance.SetBitmap(wx.Bitmap(u"app/res/inheritance.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addInheritance)

        self._setFriendship = wx.MenuItem(self._menuAddCCElements, self._setFriendshipId,
            u"set friends ...", u"Select friend classes", wx.ITEM_NORMAL)
        self._setFriendship.SetBitmap(wx.Bitmap(u"app/res/friend.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._setFriendship)

        self._addMember = wx.MenuItem(self._menuAddCCElements, self._addMemberId,
            u"Member ...\tCtrl+Alt+M", u"add member", wx.ITEM_NORMAL)
        self._addMember.SetBitmap(wx.Bitmap(u"app/res/argument.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addMember)

        self._addConstructor = wx.MenuItem(self._menuAddCCElements, self._addConstructorId,
            u"Constructor\tCtrl+Alt+N", u"add constructor", wx.ITEM_NORMAL)
        self._addConstructor.SetBitmap(wx.Bitmap(u"app/res/constructor.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addConstructor)

        self._addMethod = wx.MenuItem(self._menuAddCCElements, self._addMethodId,
            u"Method ...\tCtrl+Alt+F", u"add method", wx.ITEM_NORMAL)
        self._addMethod.SetBitmap(wx.Bitmap(u"app/res/method.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addMethod)

        self._addDestructor = wx.MenuItem(self._menuAddCCElements, self._addDestructorId,
            u"Destructor ...\tCtrl+Alt+D", u"add destructor", wx.ITEM_NORMAL)
        self._addDestructor.SetBitmap(wx.Bitmap(u"app/res/destructor.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addDestructor)

        self._addArgument = wx.MenuItem(self._menuAddCCElements, self._addArgumentId,
            u"Argument ...\tCtrl+Shift+A", u"add argument", wx.ITEM_NORMAL)
        self._addArgument.SetBitmap(wx.Bitmap(u"app/res/argument.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addArgument)

        self._addFunction = wx.MenuItem(self._menuAddCCElements, self._addFunctionId,
            u"Function ...\tCtrl+F", u"add function", wx.ITEM_NORMAL)
        self._addFunction.SetBitmap(wx.Bitmap(u"app/res/function.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addFunction)

        self._addVariable = wx.MenuItem(self._menuAddCCElements, self._addVariableId,
            u"Variable ...\tCtrl+Alt+V", u"add variable", wx.ITEM_NORMAL)
        self._addVariable.SetBitmap(wx.Bitmap(u"app/res/data.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addVariable)

        self._addVirtualMethod = wx.MenuItem(self._menuAddCCElements, self._addVirtualMethodId,
            u"Virtual methods ...\tCtrl+Shift+V", u"show virtual methods dialog", wx.ITEM_NORMAL)
        self._addVirtualMethod.SetBitmap(wx.Bitmap(u"app/res/virtual.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCElements.AppendItem(self._addVirtualMethod)

        self._menuAddCC.AppendSubMenu(self._menuAddCCElements, u"Elements")

        self._menuAddCCGenerators = wx.Menu()
        self._addIsclassMethod = wx.MenuItem(self._menuAddCCGenerators, self._addIsclassMethodId,
            u"is_class methods ...\tCtrl+Shift+I", u"show is_class methods dialog", wx.ITEM_NORMAL)
        self._addIsclassMethod.SetBitmap(wx.Bitmap(u"app/res/is_class.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCGenerators.AppendItem(self._addIsclassMethod)

        self._addRelation = wx.MenuItem(self._menuAddCCGenerators, self._addRelationId,
            u"Relation ...\tCtrl+Alt+R", u"add relation", wx.ITEM_NORMAL)
        self._addRelation.SetBitmap(wx.Bitmap(u"app/res/relation.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCGenerators.AppendItem(self._addRelation)

        self._applyRule3 = wx.MenuItem(self._menuAddCCGenerators, self._applyRule3Id,
            u"Rule of three\tCtrl+3", u"apply rule of three", wx.ITEM_NORMAL)
        self._applyRule3.SetBitmap(wx.Bitmap(u"app/res/tres.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCGenerators.AppendItem(self._applyRule3)

        self._pyboostInterface = wx.MenuItem(self._menuAddCCGenerators, self._pyboostInterfaceId,
            u"boost.python interface...", u"create python interface using boost.python", wx.ITEM_NORMAL)
        self._pyboostInterface.SetBitmap(wx.Bitmap(u"app/res/pyboost.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCCGenerators.AppendItem(self._pyboostInterface)

        self._menuAddCC.AppendSubMenu(self._menuAddCCGenerators, u"Generators")

        self._setPreferredCtor = wx.MenuItem(self._menuAddCC, self._setPreferredCtorId,
            u"Set preferred ctor", u"set preferred constructor", wx.ITEM_NORMAL)
        self._menuAddCC.AppendItem(self._setPreferredCtor)

        self._menuAddCC.AppendSeparator()
        # project contexts
        self._projectContexts = wx.MenuItem(self._menuAddCC, self._projectContextsId,
            u"Project contexts", u"setup project contexts", wx.ITEM_NORMAL)
        self._projectContexts.SetBitmap(wx.Bitmap(u"app/res/context.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCC.AppendItem(self._projectContexts)
        # project libaries
        self._projectLibraries = wx.MenuItem(self._menuAddCC, self._projectLibrariesId,
            u"Project libraries", u"add/remove project libraries", wx.ITEM_NORMAL)
        self._projectLibraries.SetBitmap(wx.Bitmap(u"app/res/library.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddCC.AppendItem(self._projectLibraries)

        self._menu.AppendSubMenu(self._menuAddCC, u"c++")
        self._menuAddPython = wx.Menu()
        self._addPyPackage = wx.MenuItem(self._menuAddPython, self._addPyPackageId,
            u"package ...\tShift+Ctrl+P", u"Add oython package", wx.ITEM_NORMAL)
        self._addPyPackage.SetBitmap(wx.Bitmap(u"app/res/py_package.xpm", wx.BITMAP_TYPE_ANY))

        self._menuAddPython.AppendItem(self._addPyPackage)
        self._addPyModule = wx.MenuItem(self._menuAddPython, self._menuAddPythonId,
            u"Module ...\tShift+Ctrl+M", u"add module", wx.ITEM_NORMAL)
        self._addPyModule.SetBitmap(wx.Bitmap(u"app/res/py_module.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyModule)

        self._addImportFolder = wx.MenuItem(self._menuAddPython, self._addImportFolderId,
            u"imports folder", u"add python imports folder", wx.ITEM_NORMAL)
        self._addImportFolder.SetBitmap(wx.Bitmap(u"app/res/folderI.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addImportFolder)

        self._addPyImport = wx.MenuItem(self._menuAddPython, self._addPyImportId,
            u"import ...\tCtrl+I", u"add python import", wx.ITEM_NORMAL)
        self._addPyImport.SetBitmap(wx.Bitmap(u"app/res/import.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyImport)

        self._addPyClass = wx.MenuItem(self._menuAddPython, self._addPyClassId,
            u"Class ...\tCtrl+Alt+C", u"add class", wx.ITEM_NORMAL)
        self._addPyClass.SetBitmap(wx.Bitmap(u"app/res/py_class.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyClass)

        self._addPyInheritance = wx.MenuItem(self._menuAddPython, self._addPyInheritanceId,
            u"Inheritance ...\tCtrl+Alt+I", u"add inheritance", wx.ITEM_NORMAL)
        self._addPyInheritance.SetBitmap(wx.Bitmap(u"app/res/py_inheritance.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyInheritance)

        self._addPyInit = wx.MenuItem(self._menuAddPython, self._addPyInitId,
            u"init\tCtrl+Alt+N", u"add init", wx.ITEM_NORMAL)
        self._addPyInit.SetBitmap(wx.Bitmap(u"app/res/py_init.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyInit)

        self._addPyMethod = wx.MenuItem(self._menuAddPython, self._addPyMethodId,
            u"Method ...\tCtrl+Alt+F", u"add method", wx.ITEM_NORMAL)
        self._addPyMethod.SetBitmap(wx.Bitmap(u"app/res/py_method.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyMethod)

        self._addPyArgument = wx.MenuItem(self._menuAddPython, self._addPyArgumentId,
            u"Argument ...\tCtrl+Shift+A", u"add argument", wx.ITEM_NORMAL)
        self._addPyArgument.SetBitmap(wx.Bitmap(u"app/res/py_argument.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyArgument)

        self._addargs = wx.MenuItem(self._menuAddPython, self._addargsId,
            u"*args", u"add variable argument list", wx.ITEM_NORMAL)
        self._addargs.SetBitmap(wx.Bitmap(u"app/res/py_args.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addargs)

        self._addkwargs = wx.MenuItem(self._menuAddPython, self._addkwargsId,
            u"**kwargs", u"add variable argument list", wx.ITEM_NORMAL)
        self._addkwargs.SetBitmap(wx.Bitmap(u"app/res/py_kwargs.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addkwargs)

        self._addPyMember = wx.MenuItem(self._menuAddPython, self._addPyMemberId,
            u"Member ...\tCtrl+Alt+M", u"add member", wx.ITEM_NORMAL)
        self._addPyMember.SetBitmap(wx.Bitmap(u"app/res/py_member.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyMember)

        self._addPyFunction = wx.MenuItem(self._menuAddPython, self._addPyFunctionId,
            u"Function ...\tCtrl+F", u"add function", wx.ITEM_NORMAL)
        self._addPyFunction.SetBitmap(wx.Bitmap(u"app/res/py_function.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyFunction)

        self._addPyVariable = wx.MenuItem(self._menuAddPython, self._addPyVariableId,
            u"Variable ...\tCtrl+Alt+V", u"add variable", wx.ITEM_NORMAL)
        self._addPyVariable.SetBitmap(wx.Bitmap(u"app/res/py_variable.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._addPyVariable)

        self._editDecorators = wx.MenuItem(self._menuAddPython, self._editDecoratorsId,
            u"decorators ...", u"edit decorators", wx.ITEM_NORMAL)
        self._editDecorators.SetBitmap(wx.Bitmap(u"app/res/decorator.xpm", wx.BITMAP_TYPE_ANY))
        self._menuAddPython.AppendItem(self._editDecorators)

        self._menuAddPython.AppendSeparator()
        self._setPyEntry = wx.MenuItem(self._menuAddPython, self._setPyEntryId,
            u"entry point", wx.EmptyString, wx.ITEM_CHECK)
        self._menuAddPython.AppendItem(self._setPyEntry)
        self._setPyEntry.Enable(False)

        self._menu.AppendSubMenu(self._menuAddPython, u"python")
        self._menu.AppendSeparator()
        # export sources
        self._projectExport = wx.MenuItem(self._menu, self._projectExportId,
            u"Export sources", u"refresh files", wx.ITEM_NORMAL)
        self._projectExport.SetBitmap(wx.ArtProvider.GetBitmap(u"gtk-convert",
            wx.ART_TOOLBAR))
        self._menu.AppendItem(self._projectExport)
        self.RegisterMenu('Model', self._menu)

    def _create_toolbars(self):
        """Create the associated toolbars"""
        super(ModelsView, self)._create_toolbars()
        # common elements
        self._auiToolBarElements = wx.aui.AuiToolBar(self.frame, wx.ID_ANY, wx.DefaultPosition,
            wx.DefaultSize, wx.aui.AUI_TB_GRIPPER | wx.aui.AUI_TB_HORZ_LAYOUT)
        els = [self._addFolder, self._addClassDiagram, self._projectExport]
        bar = self._auiToolBarElements
        bar.SetMinSize(wx.Size(24, 24))
        for el in els:
            bar.AddTool(el.GetId(), el.GetLabel(), el.GetBitmap())
        bar.Realize()
        self.frame.m_mgr.AddPane(bar, wx.aui.AuiPaneInfo().Name(u"elements_toolbar").
            Top().Hide(). Caption(u"elements").PinButton(True).Gripper().Dock().Resizable().
            DockFixed(False).Row(1).Position(2).Layer(10).ToolbarPane())
        self.RegisterToolbar(bar)
        # c++ elements
        self._auiToolBarCC = wx.aui.AuiToolBar(self.frame, wx.ID_ANY, wx.DefaultPosition,
            wx.DefaultSize, wx.aui.AUI_TB_GRIPPER | wx.aui.AUI_TB_HORZ_LAYOUT)
        bar = self._auiToolBarCC
        els = [self._addModule, self._addNamespace, self._addType, self._addEnum,
            self._addClass, self._addInheritance, self._setFriendship, self._addMember,
            self._addMethod, self._addConstructor, self._addDestructor, self._addArgument,
            self._addFunction, self._addVariable, None, self._addRelation, self._projectContexts,
            self._projectLibraries]

        bar.SetMinSize(wx.Size(24, 24))
        for el in els:
            if el is None:
                bar.AddSeparator()
            else:
                bar.AddTool(el.GetId(), el.GetLabel(), el.GetBitmap())
        bar.Realize()
        self.frame.m_mgr.AddPane(bar, wx.aui.AuiPaneInfo().Name(u"cpp_toolbar").Top().
            Hide().Caption(u"c++").PinButton(True).Gripper().Dock().Resizable().
            DockFixed(False).Row(1).Position(3).Layer(10).ToolbarPane())
        self.RegisterToolbar(bar)
        # python elements
        self._auiToolBarPY = wx.aui.AuiToolBar(self.frame, wx.ID_ANY,
            wx.DefaultPosition, wx.DefaultSize,
            wx.aui.AUI_TB_GRIPPER | wx.aui.AUI_TB_HORZ_LAYOUT)
        bar = self._auiToolBarPY
        els = [self._addPyPackage, self._addPyModule, self._addPyClass,
            self._addPyInheritance, self._addPyMember, self._addPyMethod,
            self._addPyInit, self._addPyArgument, self._addPyFunction,
            self._addPyVariable]
        bar.SetMinSize(wx.Size(24, 24))
        for el in els:
            if el is None:
                bar.AddSeparator()
            else:
                bar.AddTool(el.GetId(), el.GetLabel(), el.GetBitmap())
        bar.Realize()
        self.frame.m_mgr.AddPane(bar, wx.aui.AuiPaneInfo().Name(u"python_toolbar").Top().
            Hide().Caption(u"python").PinButton(True).Gripper().Dock().Resizable().
            DockFixed(False).Row(1).Position(3).Layer(10).ToolbarPane())
        self.RegisterToolbar(bar)

    def _bind_events(self):
        """Binds the events to this pane"""
        # bind custom control events
        self.m_tree.Bind(wx.EVT_RIGHT_DOWN, self.OnTreeMenu)
        self.m_tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeOpenItem)
        self.m_tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged)
        self.m_tree.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnModelBeginDrag)
        self.m_tree.Bind(wx.EVT_TREE_END_DRAG, self.OnModelEndDrag)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateProjectContexts, id=self._projectContextsId)
        self.BindSpecial(wx.EVT_MENU, self.OnProjectContexts, id=self._projectContextsId)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateExportFiles, id=self._projectExportId)
        self.BindSpecial(wx.EVT_MENU, self.OnExportFiles, id=self._projectExportId)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateProjectLibraries, id=self._projectLibrariesId)
        self.BindSpecial(wx.EVT_MENU, self.OnProjectLibraries, id=self._projectLibrariesId)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateEditOpen, id=app.ID_EDIT_OPEN)
        self.BindSpecial(wx.EVT_MENU, self.OnEditOpen, id=app.ID_EDIT_OPEN)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateEditContext, id=app.ID_EDIT_CONTEXT)
        self.BindSpecial(wx.EVT_MENU, self.OnEditContext, id=app.ID_EDIT_CONTEXT)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateEditUserSections, id=app.ID_EDIT_USER_SECTIONS)
        self.BindSpecial(wx.EVT_MENU, self.OnEditUserSections, id=app.ID_EDIT_USER_SECTIONS)

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddFolder, id=self._addFolder.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddFolder, id=self._addFolder.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddClassDiagram, id=self._addClassDiagram.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddClassDiagram, id=self._addClassDiagram.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddModule, id=self._addModule.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddModule, id=self._addModule.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddNamespace, id=self._addNamespace.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddNamespace, id=self._addNamespace.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddType, id=self._addType.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddType, id=self._addType.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddEnum, id=self._addEnum.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddEnum, id=self._addEnum.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddClass, id=self._addClass.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddClass, id=self._addClass.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddInheritance, id=self._addInheritance.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddInheritance, id=self._addInheritance.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateSelectFriends, id=self._setFriendship.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnSelectFriends, id=self._setFriendship.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddMember, id=self._addMember.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddMember, id=self._addMember.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddConstructor, id=self._addConstructor.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddConstructor, id=self._addConstructor.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddMethod, id=self._addMethod.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddMethod, id=self._addMethod.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddDestructor, id=self._addDestructor.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddDestructor, id=self._addDestructor.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddArgument, id=self._addArgument.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddArgument, id=self._addArgument.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddFunction, id=self._addFunction.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddFunction, id=self._addFunction.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddVariable, id=self._addVariable.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddVariable, id=self._addVariable.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddVirtualMethods, id=self._addVirtualMethod.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddVirtualMethods, id=self._addVirtualMethod.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddIsClassMethod, id=self._addIsclassMethod.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddIsClassMethod, id=self._addIsclassMethod.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddRelation, id=self._addRelation.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddRelation, id=self._addRelation.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateRuleOfThree, id=self._applyRule3.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnRuleOfThree, id=self._applyRule3.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddBoostPython, id=self._pyboostInterface.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddBoostPython, id=self._pyboostInterface.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateSetPreferredCtor, id=self._setPreferredCtor.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnSetPreferredCtor, id=self._setPreferredCtor.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyPackage, id=self._addPyPackage.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyPackage, id=self._addPyPackage.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyModule, id=self._addPyModule.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyModule, id=self._addPyModule.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyImport, id=self._addPyImport.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyImport, id=self._addPyImport.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyClass, id=self._addPyClass.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyClass, id=self._addPyClass.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyInheritance, id=self._addPyInheritance.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyInheritance, id=self._addPyInheritance.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyInit, id=self._addPyInit.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyInit, id=self._addPyInit.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyMethod, id=self._addPyMethod.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyMethod, id=self._addPyMethod.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyArgument, id=self._addPyArgument.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyArgument, id=self._addPyArgument.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddArgArgs, id=self._addargs.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddArgArgs, id=self._addargs.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddArgKwArgs, id=self._addkwargs.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddArgKwArgs, id=self._addkwargs.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyMember, id=self._addPyMember.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyMember, id=self._addPyMember.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyFunction, id=self._addPyFunction.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyFunction, id=self._addPyFunction.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddPyVariable, id=self._addPyVariable.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddPyVariable, id=self._addPyVariable.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdatePySetEntry, id=self._setPyEntry.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnPySetEntry, id=self._setPyEntry.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateEditDecorators, id=self._editDecorators.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnEditDecorators, id=self._editDecorators.GetId())

        self.BindSpecial(wx.EVT_UPDATE_UI, self.OnUpdateAddImportsFolder, id=self._addImportFolder.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnAddImportsFolder, id=self._addImportFolder.GetId())

        #accelerator dispatchers
        self.Bind(wx.EVT_MENU, self.NodeOnAddMember, id=ID_ADD_MEMBER_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddMethod, id=ID_ADD_METHOD_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddArgument, id=ID_ADD_ARGUMENT_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddStart, id=ID_ADD_START_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddEnd, id=ID_ADD_END_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddClass, id=ID_ADD_CLASS_KEY)
        #self.Bind(wx.EVT_MENU, self.OnAddPyImport, id=ID_ADD_IMPORT_KEY)
        self.Bind(wx.EVT_MENU, self.NodeOnAddInheritance, id=ID_ADD_INHERITANCE)
        #self.m_tree.Bind(wx.EVT_TREE_ITEM_GETTOOLTIP,
        #    self.OnTreeModelTooltip)
        # avoid erratic release capture in dnd
        #self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, lambda x: None)
        super(ModelsView, self)._bind_events()

    def _set_accelerators(self):
        """Set the accelerator table"""
        ctrl_alt = wx.ACCEL_CTRL + wx.ACCEL_ALT
        ctrl_shf = wx.ACCEL_CTRL + wx.ACCEL_SHIFT
        aTable = wx.AcceleratorTable([
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_F1, wx.ID_FILE1),
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_F2, wx.ID_FILE2),
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_F3, wx.ID_FILE3),
        #overload menu accelerators
            wx.AcceleratorEntry(ctrl_alt, ord('M'), ID_ADD_MEMBER_KEY),
            wx.AcceleratorEntry(ctrl_alt, ord('F'), ID_ADD_METHOD_KEY),
            wx.AcceleratorEntry(ctrl_shf, ord('A'), ID_ADD_ARGUMENT_KEY),
            wx.AcceleratorEntry(ctrl_alt, ord('N'), ID_ADD_START_KEY),
            wx.AcceleratorEntry(ctrl_alt, ord('D'), ID_ADD_END_KEY),
            wx.AcceleratorEntry(ctrl_alt, ord('C'), ID_ADD_CLASS_KEY),
            wx.AcceleratorEntry(ctrl_alt, ord('I'), ID_ADD_INHERITANCE),
        #tree navigation facilities
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_LEFT, BaseView._leftKeyId)
        ])
        self.SetAcceleratorTable(aTable)

    def NodeOnAddClass(self, event):
        """Attempt to translate method"""
        if self.can_add_class:
            self.OnAddClass(event)
        elif self.can_add_py_class:
            self.OnAddPyClass(event)

    def NodeOnAddInheritance(self, event):
        """Attempt to translate method"""
        if self.can_add_inheritance:
            self.OnAddInheritance(event)
        elif self.can_add_py_inheritance:
            self.OnAddPyInheritance(event)

    def NodeOnAddMember(self, event):
        """Attempt to translate method"""
        s = self.selected
        if not s:
            return
        #determine languaje
        project = s.project
        if project is None:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            if s.outer_class:
                self.OnAddMember(event)
            else:
                self.OnAddVariable(event)
        else:
            if s.outer_class:
                self.OnAddPyMember(event)
            else:
                self.OnAddPyVariable(event)

    def NodeOnAddMethod(self, event):
        """Attempt to translate method"""
        s = self.selected
        if not s:
            return
        #determine languaje
        project = s.project
        if project is None:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            if s.outer_class:
                self.OnAddMethod(event)
            elif s.inner_function_container:
                self.OnAddFunction(event)
        else:
            if s.outer_class:
                self.OnAddPyMethod(event)
            elif s.inner_function_container:
                self.OnAddPyFunction(event)

    def NodeOnAddArgument(self, event):
        """Attempt to translate method"""
        s = self.selected
        if not s:
            return
        #determine languaje
        project = s.project
        if project is None:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            if s.inner_argument_container:
                self.OnAddArgument(event)
        else:
            if s.inner_argument_container:
                self.OnAddPyArgument(event)

    def NodeOnAddStart(self, event):
        """Attempt to translate method"""
        s = self.selected
        if not s:
            return
        #determine languaje
        project = s.project
        if project is None:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            if s.outer_class:
                self.OnAddConstructor(event)
        else:
            if s.outer_class:
                self.OnAddPyInit(event)

    def NodeOnAddEnd(self, event):
        """Attempt to translate method"""
        if self.can_add_destructor:
            self.OnAddDestructor(self)
        else:
            pass  # __del__ is disable because in python destructor is some delicated

    def TreeLeftKey(self, event):
        """If the selected node is expanded, simply collapse it.
        If not, navigate through parent"""
        if not self.selected:
            return
        if self.m_tree.IsExpanded(self.selected):
            self.m_tree.Collapse(self.selected)
        else:
            parent = self.selected.parent
            if self.m_tree.HoldsObject(parent):
                self.m_tree.SelectItem(parent)

    def OnTreeMenu(self, event):
        """Handles context tree popup menu"""
        (item, where) = self.m_tree.HitTest(event.GetPosition())
        if item is None:
            return
        self.m_tree.SelectItem(item)
        obj = self.selected
        if obj is None:
            return
        menu = wx.Menu()
        separator = False
        if self.can_edit_open:
            separator = True
            menu.Append(app.ID_EDIT_OPEN, "Open ...", "Edit user code.")
        if self.can_edit_user_sections:
            separator = True
            menu.Append(app.ID_EDIT_USER_SECTIONS,
                "edit user sections", "Edit user code in some sections of generated sources.")
        if self.can_edit_context:
            separator = True
            menu.Append(app.ID_EDIT_CONTEXT,
                "Select contexts ...", "Select applied contexts")
        # add elements filtering disabled
        if app.ui.clone_mnu(self._menuAdd, parent=menu, enabled=True, separator=separator):
            separator = False
        if app.ui.clone_mnu(self._menuAddCC, parent=menu, enabled=True, separator=separator):
            separator = False
        app.ui.clone_mnu(self._menuAddPython, parent=menu, enabled=True, separator=separator)
        if self.can_edit_properties:
            menu.AppendSeparator()
            app.ui.append_menuitem_copy(menu, self.frame.editProperties)
        self.PopupMenu(menu, event.GetPosition())
        menu.Destroy()

    def OnTreeOpenItem(self, event):
        """Handle open item"""
        obj = self.selected
        if obj is None:
            return
        if hasattr(obj, '_pane') and obj._pane is not None:
            self.frame.docBook.SetSelection(
                self.frame.docBook.GetPageIndex(obj._pane))
            return
        t = type(obj)
        handle_map = {
            self.OpenConstructor: [model.cc.Constructor],
            self.OpenMethod: [model.cc.MemberMethod, model.cc.IsClassMethod,
                model.cc.InitMethod, model.cc.ExitMethod, model.cc.Destructor,
                model.cc.Function],
            self.OpenPythonMethod: [model.py.MemberMethod, model.py.InitMethod,
                model.py.Function],
            self.OpenPythonModule: [model.py.Module],
            self.OpenClassDiagram: [model.ClassDiagram]}
        try:
            (x for x in handle_map if t in handle_map[x]).next()(obj)
        except:
            self.OnEditProperties(event)
        event.Skip()

    def OpenConstructor(self, constructor, view=None):
        """Open constructor code for editing"""
        from activity.models.ui import pane
        assert (not hasattr(constructor, '_pane') or constructor._pane is None)
        frame = self.frame
        p = pane.ConstructorPane(frame.docBook, frame, constructor)
        constructor._pane = p
        frame.docBook.AddPage(p, constructor.tab_label, True, bitmap=constructor.GetTabBitmap())

    def OpenMethod(self, method, view=None):
        """Open method code for editing"""
        from activity.models.ui import pane
        assert (not hasattr(method, '_pane') or method._pane is None)
        frame = self.frame
        p = pane.MethodPane(frame.docBook, frame, method)
        method._pane = p
        frame.docBook.AddPage(p, method.tab_label, True, bitmap=method.GetTabBitmap())

    def OpenPythonMethod(self, method, view=None):
        """Open method code for editing"""
        from activity.models.ui import pane
        assert (not hasattr(method, '_pane') or method._pane is None)
        frame = self.frame
        p = pane.PyMethodPane(frame.docBook, frame, method)
        method._pane = p
        frame.docBook.AddPage(p, method.tab_label, True, method.bitmap_index)

    def OpenPythonModule(self, module, view=None):
        """Open a module for editing"""
        from activity.models.ui import pane
        assert (not hasattr(module, '_pane') or module._pane is None)
        frame = self.frame
        p = pane.PyModulePane(frame.docBook, frame, module)
        module._pane = p
        frame.docBook.AddPage(p, module.tab_label, True, module.bitmap_index)

    def OpenClassDiagram(self, diag):
        """Open the class diagram for show"""
        from activity.models.ui import pane
        assert not hasattr(diag, '_pane') or diag._pane is None
        frame = self.frame
        p = pane.DiagramPane(frame.docBook, diag)
        diag._pane = p
        frame.docBook.AddPage(p, diag.tab_label, True, diag.bitmap_index)
        diag._pane.NotifyShow()

    def OnTreeSelChanged(self, event):
        """Handle select changed"""
        self.selected = self.m_tree.GetSelection()
        if not isinstance(self.selected, model.TComponent):
            self.selected = None
            return None

    def OnModelBeginDrag(self, event):
        """Allow drag-and-drop for leaf nodes."""
        obj = self.m_tree.__fer__(event.GetItem())
        if obj is None:
            return
        if obj.draggable():
            event.Allow()
            self.dragObject = obj

    def OnModelEndDrag(self, event):
        '''Handle drop operation'''
        if not self.dragObject:
            return
        obj = self.m_tree.__fer__(event.GetItem())
        if obj is None or self.dragObject in obj.path:
            return
        self.dragObject.drop(obj)

    def OnUpdateEditPaste(self, event):
        """Handle update paste event"""
        event.Enable(self.can_paste)

    def DoRenderAddElement(self, obj):
        """Inserts element in tree"""
        # model tree
        treeOrder = [
            model.Workspace, model.Project, model.py.Package, model.cc.Inheritance,
            model.py.Inheritance,
            model.cc.Friendship, model.cc.RelationFrom, model.cc.RelationTo,
            model.ClassDiagram, model.cc.Type, model.Folder, model.Library,
            model.cc.Namespace, model.py.ImportsFolder, model.py.Import,
            model.cc.Class, model.py.Class, model.cc.Enum, model.cc.MemberData,
            model.py.MemberData, model.cc.InitMethod, model.cc.ExitMethod,
            model.cc.IsClassMethod, model.cc.Constructor, model.py.InitMethod,
            model.cc.MemberMethod, model.py.MemberMethod, model.cc.Argument,
            model.py.Argument, model.py.ArgsArgument, model.py.KwArgsArgument,
            model.py.Decorator,
            model.cc.Destructor, model.cc.Module, model.py.Module, model.cc.Function,
            model.py.Function, model.cc.Data, model.py.Data, model.LibrariesFolder,
            model.cc.TypesFolder, model.cc.pyBoostModule]
        if not obj._visibleInTree or type(obj) not in treeOrder:
            return
        ti = treeOrder.index(type(obj))
        #check parent
        if self.m_tree.HoldsObject(obj.parent):
            p = obj.parent
        else:
            p = self.m_tree.GetRootItem()
        if obj.parent is not None:
            # find some major friend item with the same class
            tribal = obj.parent[type(obj)]
            index = tribal.index(obj)
            pre = None
            while index > 0 and pre is None:
                index = index - 1
                candidate = tribal[index]
                if not self.m_tree.HoldsObject(candidate):
                    continue
                pre = candidate
            if pre is not None:
                self.m_tree.InsertItem(p, pre, obj.tree_label,
                    obj.bitmap_index, obj.bitmap_index, obj)
                if hasattr(obj, 'bitmap_open_index'):
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index, wx.TreeItemIcon_Expanded)
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index, wx.TreeItemIcon_SelectedExpanded)
                if type(obj) is model.cc.Constructor:
                    self.m_tree.SetItemBold(obj, bold=obj.IsPreferred())
                elif type(obj) in [model.py.Module, model.py.Package]:
                    self.m_tree.SetItemBold(obj, bold=obj._entry)
                return
        itemCount = 0
        citem, cookie = self.m_tree.GetFirstChild(p)
        if type(citem) is wx.TreeItemId:
            citem = self.m_tree.__fer__(citem)
        if type(citem) in treeOrder:
            if ti <= treeOrder.index(type(citem)):
                self.m_tree.PrependItem(p, obj.tree_label,
                     obj.bitmap_index, obj.bitmap_index, obj)
                if hasattr(obj, 'bitmap_open_index'):
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index, wx.TreeItemIcon_Expanded)
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index, wx.TreeItemIcon_SelectedExpanded)
                if type(obj) is model.cc.Constructor:
                    self.m_tree.SetItemBold(obj, bold=obj.IsPreferred())
                elif type(obj) in [model.py.Module, model.py.Package]:
                    self.m_tree.SetItemBold(obj, bold=obj._entry)
                return
        while type(citem) is not wx.TreeItemId or citem.IsOk():
            itemCount = itemCount + 1
            citem, cookie = self.m_tree.GetNextChild(p, cookie)
            if type(citem) not in treeOrder:
                continue
            if ti <= treeOrder.index(type(citem)):
                self.m_tree.InsertItemBefore(p, itemCount,
                     obj.tree_label,
                     obj.bitmap_index, obj.bitmap_index, data=obj)
                if hasattr(obj, 'bitmap_open_index'):
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index, wx.TreeItemIcon_Expanded)
                    self.m_tree.SetItemImage(obj,
                        obj.bitmap_open_index,
                        wx.TreeItemIcon_SelectedExpanded)
                if type(obj) is model.cc.Constructor:
                    self.m_tree.SetItemBold(obj, bold=obj.IsPreferred())
                elif type(obj) in [model.py.Module, model.py.Package]:
                    self.m_tree.SetItemBold(obj, bold=obj._entry)
                return
        #Ok, do apppend
        self.m_tree.AppendItem(p, obj.tree_label, obj.bitmap_index,
            obj.bitmap_index, obj)
        if hasattr(obj, 'bitmap_open_index'):
            self.m_tree.SetItemImage(obj,
                obj.bitmap_open_index, wx.TreeItemIcon_Expanded)
            self.m_tree.SetItemImage(obj, obj.bitmap_open_index,
                wx.TreeItemIcon_SelectedExpanded)
        if type(obj) is model.cc.Constructor:
            self.m_tree.SetItemBold(obj, bold=obj.IsPreferred())
        elif type(obj) in [model.py.Module, model.py.Package]:
            self.m_tree.SetItemBold(obj, bold=obj._entry)

    def DoRenderRemoveElement(self, obj):
        """Do remove element in tree"""
        if self.m_tree.HoldsObject(obj):
            self.m_tree.Delete(obj)

    def UpdateElement(self, obj):
        """Update the tree label for a object"""
        if not self.m_tree.HoldsObject(obj):
            return
        self.m_tree.SetItemText(obj, obj.tree_label)
        self.m_tree.SetItemImage(obj,
            obj.bitmap_index, wx.TreeItemIcon_Normal)
        if hasattr(obj, 'bitmap_open_index'):
            self.m_tree.SetItemImage(obj,
                obj.bitmap_open_index, wx.TreeItemIcon_Expanded)
            self.m_tree.SetItemImage(obj,
                obj.bitmap_open_index, wx.TreeItemIcon_SelectedExpanded)
        self.m_tree.SetItemImage(obj,
            obj.bitmap_index, wx.TreeItemIcon_Selected)
        if type(obj) is model.cc.Constructor:
            self.m_tree.SetItemBold(obj, bold=obj.IsPreferred())
        elif type(obj) in [model.py.Module, model.py.Package]:
            self.m_tree.SetItemBold(obj, bold=obj._entry)

    def OnTreeModelTooltip(self, event):
        """Handles tree model tooltips"""
        obj = self.m_tree.__fer__(event.GetItem())
        if obj is None:
            event.SetToolTip('missing description')
        elif len(obj.note) == 0:
            event.SetToolTip('missing description')
        else:
            event.SetToolTip(obj.note)

    def OnUpdateEditCopy(self, event):
        """Handle update edit copy"""
        event.Enable(self.can_copy)

    def OnEditCopy(self, event):
        """Handle edit copy event"""
        clipboard.copy(clip_item_model(self.selected))

    def OnUpdateEditCut(self, event):
        """Handle cut event"""
        # for the moment, this event is disabled
        event.Enable(self.can_cut)

    def OnEditCut(self, event):
        """Handle cut event"""
        clipboard.copy(clip_item_model(self.selected))
        self.OnDelete(event)

    def OnEditPaste(self, event):
        """Handle paste event"""
        data = clipboard.data
        if data.lang == 'c++':
            # The paste event must check about collission
            if data.type is model.cc.Argument:
                self.pasteArgument()
            elif data.type is model.cc.MemberData:
                self.pasteMemberData()
            elif data.type is model.cc.Constructor:
                self.pasteConstructor()
            elif data.type in [model.cc.MemberMethod, model.cc.IsClassMethod]:
                self.pasteMemberMethod()
        elif data.lang == 'python':
            if data.type is model.py.Argument:
                self.pastePyArgument()
            elif data.type is model.py.MemberData:
                self.pastePyMemberData()
            elif data.type is model.py.InitMethod:
                self.pastePyInit()
            elif data.type is model.py.MemberMethod:
                self.pastePyMemberMethod()
            elif data.type is model.py.Class:
                self.pastePyClass()
            elif data.type is model.py.Function:
                self.pastePyFunction()
            elif data.type is model.py.Import:
                self.pastePyImport()
            elif data.type is model.py.ImportsFolder:
                self.pastePyImportsFolder()
            elif data.type is model.py.Inheritance:
                self.pastePyInheritance()
            elif data.type is model.py.Module:
                self.pastePyModule()

    def OnUpdateDelete(self, event):
        """Update delete element"""
        event.Enable(self.can_delete)

    def OnDelete(self, event):
        """delete element"""
        obj = self.selected
        aliasMap = {
            model.cc.Class: "c++ class {}", model.py.Class: "python class {}",
            model.cc.Inheritance: "inheritance {}", model.py.Inheritance: "c++ inheritance from {}",
            model.py.Inheritance: "inheritance {}", model.py.Inheritance: "python inheritance from {}",
            model.py.Package: "python package {}",
            model.cc.Argument: "c++ method argument {}",
            model.py.Argument: "python method argument {}",
            model.py.ArgsArgument: "python method argument list",
            model.py.KwArgsArgument: "python method argument dict",
            model.cc.Constructor: "constructor {}",
            model.py.InitMethod: "__init__ method",
            model.cc.Destructor: "destructor {}", model.Folder: "folder {}",
            model.cc.IsClassMethod: "method {}", model.cc.Friendship: "friend {}",
            model.cc.MemberData: "member {}", model.cc.MemberMethod: "c++ method {}",
            model.py.MemberMethod: "python method {}",
            model.ClassDiagram: "diagram {}", model.Project: "project {}",
            model.cc.RelationFrom: "relation {}", model.cc.RelationTo: "relation {}",
            model.cc.Namespace: "namespace {}", model.cc.Type: "type {}",
            model.cc.Module: 'c++ module "{}"', model.cc.Function: "c++ function {}",
            model.cc.pyBoostModule: 'c++ boost.python "{}"',
            model.py.Function: 'python function {}',
            model.py.Module: 'python module "{}"', model.Library: "library {}",
            model.cc.Data: 'c++ variable {}', model.py.Data: 'python variable {}',
            model.py.Import: 'python import {}', model.py.Decorator: 'python decorator {}',
            model.Workspace: 'workspace {}'}
        tran.TransactionStack.DoBeginTransaction("delete " +
             aliasMap[type(obj)].format(obj._name))
        if type(obj) in [model.cc.RelationFrom, model.cc.RelationTo]:
            #if delete some side of relation, we must delete both sides
            #then, redirecting to hidden parent is what we do
            obj._key.Delete()
        elif isinstance(obj, model.TComponent):
            obj.Delete()
        else:
            tran.TransactionStack.DoDelete(obj)
        tran.TransactionStack.DoCommit()

    def OnUpdateEditOpen(self, event):
        """Handle update open code edit"""
        event.Enable(self.can_edit_open)

    def OnEditOpen(self, event):
        """Do open code editor"""
        obj = self.selected
        if obj is None:
            return
        if hasattr(obj, '_pane') and obj._pane is not None:
            self.frame.docBook.SetSelection(
                self.frame.docBook.GetPageIndex(obj._pane))
            return
        t = type(obj)
        handle_map = {
            self.OpenConstructor: [model.cc.Constructor],
            self.OpenMethod: [model.cc.MemberMethod, model.cc.IsClassMethod,
                model.cc.InitMethod, model.cc.ExitMethod, model.cc.Destructor,
                model.cc.Function],
            self.OpenPythonMethod: [model.py.MemberMethod, model.py.InitMethod,
                model.py.Function],
            self.OpenPythonModule: [model.py.Module],
            self.OpenClassDiagram: [model.ClassDiagram]}
        import traceback
        import sys
        try:
            (x for x in handle_map if t in handle_map[x]).next()(obj)
        except Exception as inst:
            traceback.print_exc(file=sys.stdout)
            print type(inst)     # the exception instance
            print inst.args      # arguments stored in .args
            print inst

    def OnUpdateEditContext(self, event):
        """Handle update edit context"""
        event.Enable(self.can_edit_context)

    @tran.TransactionalMethod('apply contexts to {}')
    def OnEditContext(self, event):
        """Handle edit context event"""
        obj = self.selected
        dialog = ui_dlg.cc.SelectContexts(context.frame, obj)
        if dialog.ShowModal() != wx.ID_OK:
            return False
        obj.SaveState()
        dialog.CopyAttributes(obj)
        obj.project.SetModified(True)
        sname = tran.TransactionStack.instance.GetName()
        sname = sname.format(obj._name)
        tran.TransactionStack.instance.SetName(sname)
        return True

    def OnUpdateEditUserSections(self, event):
        """Update Add constructor method"""
        event.Enable(self.can_edit_user_sections)

    @tran.TransactionalMethod('edit {} user sections')
    @wxx.EditionDialog(ui_dlg.UserSectionsDialog)
    def OnEditUserSections(self, event):
        """Edit user sections in class"""
        return (context.frame, self.selected)

    def OnUpdateRunProject(self, event):
        """Update the project run event"""
        if not hasattr(self.frame, '_runProcess'):
            v = self.selected
            if v and hasattr(v, 'project'):
                v = v.project
                if v and v._language == 'python' and v.main_file:
                    v = v.main_file
                    event.Enable(os.path.exists(v.key_file))
                    return
        event.Enable(False)

    def OnUpdateStopRun(self, event):
        """default event handler"""
        event.Enable(hasattr(self.frame, '_runProcess'))

    def OnStopRun(self, event):
        """Stop running"""
        self.frame.StopRunning()

    def OnRunProject(self, event):
        """Execute the project"""
        path = self.selected.project.main_file.key_file
        book = self.frame.docBook
        n = book.GetPageCount()
        for pane in [book.GetPage(i) for i in range(0, n)]:
            try:
                if pane.object.project is self.selected:
                    pane.Commit()
            except:
                pass
        self.frame.RunPythonScript(path)

    def OnUpdateProjectContexts(self, event):
        """Update project contexs if any"""
        obj = self.selected
        event.Enable(bool(obj and obj.project and obj.project._language == 'c++'))

    @tran.TransactionalMethod('edit contexts')
    def OnProjectContexts(self, event):
        """Handle project contexts"""
        project = self.selected.project
        d = ui_dlg.ContextItems(context.frame, project)
        if d.ShowModal() != wx.ID_OK:
            return False
        project.SaveState()
        d.CopyAttributes(project)
        project.SetModified(True)
        return True

    def OnUpdateExportFiles(self, event):
        """Update export code command"""
        event.Enable(bool(self.selected and self.selected.project))

    def OnExportFiles(self, event):
        """Handle export code event"""
        if type(self.selected) is model.py.Module:
            self.selected.ExportPythonCodeFiles()
        else:
            dialog = ui_dlg.GenerateSourcesDialog(context.frame, self.selected.project)
            dialog.ShowModal()

    def OnUpdateProjectLibraries(self, event):
        """Update libraries"""
        obj = self.selected
        obj = obj and obj.project
        event.Enable(bool(obj and obj._language == 'c++'))

    @tran.TransactionalMethod('select libraries')
    @wxx.CreationDialog(ui_dlg.SelectLibrariesDialog, model.Library)
    def OnProjectLibraries(self, event):
        """Handle select libraries event"""
        return (context.frame, self.selected.project)

    def OnUpdateAddFolder(self, event):
        """Update add folder method"""
        event.Enable(bool(self.selected and self.selected.inner_folder_container))

    @tran.TransactionalMethod('add folder {}')
    @wxx.CreationDialog(app.ui.dlg.FolderDialog, model.Folder)
    def OnAddFolder(self, event):
        """Handle add folder command"""
        return (context.frame, self.selected.inner_folder_container)

    def OnUpdateAddClassDiagram(self, event):
        """Update add class diagram"""
        event.Enable(bool(self.selected and self.selected.inner_diagram_container))

    @tran.TransactionalMethod('add class diagram {}')
    @wxx.CreationDialog(ui_dlg.ClassDiagramDialog, model.ClassDiagram)
    def OnAddClassDiagram(self, event):
        """add class diagram"""
        return (context.frame, self.selected.inner_diagram_container)

    def OnUpdateAddModule(self, event):
        """Update add module"""
        v = self.selected
        if v:
            v = self.selected.inner_module_container
            if v:
                if v.project._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ module {}')
    @wxx.CreationDialog(ui_dlg.ModuleDialog, model.cc.Module)
    def OnAddModule(self, event):
        """Handle add module method"""
        return (context.frame, self.selected.inner_module_container)

    def OnUpdateAddNamespace(self, event):
        """Updade Addnamespace method"""
        event.Enable(bool(self.selected
            and self.selected.inner_namespace_container))

    @tran.TransactionalMethod('add namespace {}')
    @wxx.CreationDialog(ui_dlg.NamespaceDialog, model.cc.Namespace)
    def OnAddNamespace(self, event):
        """Handles add namespace method"""
        return (context.frame, self.selected.inner_namespace_container)

    def OnUpdateAddType(self, event):
        """Update AddType method"""
        event.Enable(bool(self.selected and self.selected.inner_type_container))

    @tran.TransactionalMethod('add type {}')
    @wxx.CreationDialog(ui_dlg.TypeDialog, model.cc.Type)
    def OnAddType(self, event):
        """Handles add type method"""
        return (context.frame, self.selected.inner_type_container)

    def OnUpdateAddEnum(self, event):
        """Update AddType method"""
        event.Enable(bool(self.selected and self.selected.inner_enum_container))

    @tran.TransactionalMethod('add enum {}')
    @wxx.CreationDialog(ui_dlg.EnumDialog, model.cc.Enum)
    def OnAddEnum(self, event):
        """Handles add enum method"""
        return (context.frame, self.selected.inner_enum_container)

    def OnUpdateAddClass(self, event):
        """Updade AddClass method"""
        event.Enable(self.can_add_class)

    @tran.TransactionalMethod('add c++ class {}')
    @wxx.CreationDialog(ui_dlg.ClassDialog, model.cc.Class)
    def OnAddClass(self, event):
        """Handles add class method"""
        cnt = self.selected.inner_class_container
        return (context.frame, cnt)

    def OnUpdateAddInheritance(self, event):
        """Handle update add c++ inheritance"""
        event.Enable(self.can_add_inheritance)

    @tran.TransactionalMethod('add c++ {} inheritance')
    @wxx.CreationDialog(ui_dlg.InheritanceDialog, model.cc.Inheritance)
    def OnAddInheritance(self, event):
        """Handle add inheritance command"""
        return (context.frame, self.selected.inner_inheritance_container)

    def OnUpdateSelectFriends(self, event):
        """Handle update select friends event"""
        v = self.selected
        if v:
            v = v.inner_class
            if v and v.project._language == 'c++':
                event.Enable(True)
                return
        event.Enable(False)

    @tran.TransactionalMethod('select friends')
    @wxx.CreationDialog(ui_dlg.SelectFriendsDialog, model.cc.Friendship)
    def OnSelectFriends(self, event):
        """Handle select friends"""
        return (context.frame, self.selected)

    def OnUpdateAddMember(self, event):
        """Update add member"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                if v.project._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ {} class member')
    @wxx.CreationDialog(ui_dlg.MemberDialog, model.cc.MemberData)
    def OnAddMember(self, event):
        """Handle add member command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddConstructor(self, event):
        """Update Add constructor method"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                v = v.project
                if v._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @tran.TransactionalMethod('add {} constructor')
    @wxx.CreationDialog(ui_dlg.ConstructorDialog, model.cc.Constructor)
    def OnAddConstructor(self, event):
        """Handle add constructor command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddMethod(self, event):
        """Update add method method"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                if v.project._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ method {}')
    @wxx.CreationDialog(ui_dlg.MemberMethodDialog, model.cc.MemberMethod)
    def OnAddMethod(self, event):
        """Handle add method command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddDestructor(self, event):
        """Update Add destructor method"""
        event.Enable(self.can_add_destructor)

    @tran.TransactionalMethod('add {} destructor')
    @wxx.CreationDialog(ui_dlg.DestructorDialog, model.cc.Destructor)
    def OnAddDestructor(self, event):
        """Handle add destructor command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddArgument(self, event):
        """Update add argument method"""
        v = self.selected
        if v:
            v = v.inner_argument_container
            if v and v.project._language == 'c++':
                event.Enable(True)
                return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ method argument {}')
    @wxx.CreationDialog(ui_dlg.ArgumentDialog, model.cc.Argument)
    def OnAddArgument(self, event):
        """Handle add method command"""
        return (context.frame, self.selected.inner_argument_container)

    def OnUpdateAddFunction(self, event):
        """Handle update add function method"""
        v = self.selected
        if v:
            v = v.inner_function_container
            if v and v.project._language == 'c++':
                event.Enable(True)
                return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ function {}')
    @wxx.CreationDialog(ui_dlg.FunctionDialog, model.cc.Function)
    def OnAddFunction(self, event):
        """Handle add function command"""
        return (context.frame, self.selected.inner_function_container)

    def OnUpdateAddVariable(self, event):
        """Update AddVariable method"""
        v = self.selected
        if v:
            v = self.selected.inner_variable_container
            if v and v.project._language == 'c++':
                event.Enable(True)
                return
        event.Enable(False)

    @tran.TransactionalMethod('add c++ variable {}')
    @wxx.CreationDialog(ui_dlg.VariableDialog, model.cc.Data)
    def OnAddVariable(self, event):
        """Handles add variable method"""
        return (context.frame, self.selected.inner_variable_container)

    def OnUpdateAddVirtualMethods(self, event):
        """Update AddVariable method"""
        v = self.selected
        if v:
            v = self.selected.inner_member_container
            if v and v.project._language == 'c++':
                event.Enable(True)
                return
        event.Enable(False)

    @tran.TransactionalMethod('add virtual methods')
    @wxx.CreationDialog(ui_dlg.VirtualMethodsDialog, model.cc.MemberMethod)
    def OnAddVirtualMethods(self, event):
        """Handles add variable method"""
        return (context.frame, self.selected.inner_class)

    def OnUpdateAddIsClassMethod(self, event):
        """Update OnUpdateAddIsClassMethod method"""
        obj = self.selected
        event.Enable(
            bool(obj and obj.inner_class and obj.project._language == 'c++' and
             len(obj.inner_class._deriv) > 0))

    @tran.TransactionalMethod('add is_class methods')
    @wxx.CreationDialog(ui_dlg.IsClassMethods, model.cc.IsClassMethod)
    def OnAddIsClassMethod(self, event):
        """Handle add is_class method"""
        return (context.frame, self.selected.inner_class)

    def OnUpdateAddRelation(self, event):
        """Update add relation method"""
        obj = self.selected
        event.Enable(bool(obj and obj.project and obj.project._language == 'c++'
            and obj.inner_relation_container))

    @tran.TransactionalMethod('add relation')
    @wxx.CreationDialog(ui_dlg.RelationDialog, model.cc.Relation)
    def OnAddRelation(self, event):
        """Handle add relation method"""
        return (context.frame, self.selected.inner_relation_container)

    def OnUpdateAddPathToConsole(self, event):
        """Update save project method"""
        if self.selected:
            proj = self.selected.project
            if proj and proj._language == 'python':
                event.Enable(True)
                return
        event.Enable(False)

    def OnAddPathToConsole(self, event):
        """Update save project method"""
        proj = self.selected.project
        frame = context.frame
        entry = frame.m_pythonEntry
        entry.run("import sys; sys.path.append('{dir}')".format(dir=proj.dir))

    def OnUpdateRuleOfThree(self, event):
        """Update rule of three"""
        #we need to have class
        cls = self.selected and self.selected.inner_class
        if not cls:
            event.Enable(False)
            return
        #ok, rule of three is applicable only if not yet applied
        self_class = lambda x: x.inner_class == cls
        dtor = cls(model.cc.Destructor, filter=self_class, cut=True)
        ctor = cls(model.cc.Constructor, filter=self_class, cut=True)
        cpyo = cls(model.cc.MemberMethod, filter=lambda x: self_class(x) and x._name == 'operator =')
        bdtor = (len(dtor) > 0)
        bctor = False
        for t in ctor:
            args = t[model.cc.Argument]
            if len(args) != 1:
                continue
            ti = args[0]._typei
            if ti._type == cls and ti._const and ti._ref and not ti._ptr and not ti._array:
                bctor = True
                break
        bcpyo = False
        for t in cpyo:
            args = t[model.cc.Argument]
            if len(args) != 1:
                continue
            ti = args[0]._typei
            if ti._type == cls and ti._const and ti._ref and not ti._ptr and not ti._array:
                bcpyo = True
                break
        event.Enable((bctor or bdtor or bcpyo) and not (bctor and bdtor and bcpyo))

    @tran.TransactionalMethod('apply rule of three')
    def OnRuleOfThree(self, event):
        """Apply rule of three"""
        cls = self.selected and self.selected.inner_class
        if not cls:
            return
        #ok, rule of three is applicable only if not yet applied
        cls_member = lambda x: x.inner_class == cls
        dtor = cls(model.cc.Destructor, filter=cls_member, cut=True)
        ctor = cls(model.cc.Constructor, filter=cls_member, cut=True)
        cpyo = cls(model.cc.MemberMethod, filter=lambda x: cls_member(x) and x._name == 'operator =')
        if len(dtor) == 0:
            # Create new destructor
            model.cc.Destructor(parent=cls, serial=cls._serial, note="Destructor created by rule of three")
        bctor = False
        for t in ctor:
            args = t[model.cc.Argument]
            if len(args) != 1:
                continue
            ti = args[0]._typei
            if ti._type == cls and ti._const and ti._ref and not ti._ptr and not ti._array:
                bctor = True
                break
        if not bctor:
            # Create new constructor
            ctor = model.cc.Constructor(parent=cls, name=cls._name, autoargs=False,
                note="Constructor created by rule of three")
            model.cc.Argument(parent=ctor,
                type=model.cc.typeinst(type=cls, ref=True, const=True),
                name='ref{}'.format(cls._name))
        bcpyo = False
        for t in cpyo:
            args = t[model.cc.Argument]
            if len(args) != 1:
                continue
            ti = args[0]._typei
            if ti._type == cls and ti._const and ti._ref and not ti._ptr and not ti._array:
                bcpyo = True
                break
        if not bcpyo:
            #create copy assignment
            # travel through members and copy them
            code = '\t//Autogenerated copy\n'
            # Travel through bases with copy operator (not virtual)
            bases = [x._ancestor for x in cls(model.cc.Inheritance,
                filter=lambda x: cls_member(x) and not x._virtual)]
            for base in bases:
                cpyos = base(model.cc.MemberMethod,
                    filter=lambda x: x.inner_class == base and x._name == 'operator =')
                for cpyo in cpyos:
                    args = cpyo[model.cc.Argument]
                    if len(args) != 1:
                        continue
                    ti = args[0]._typei
                    if ti._type != base or not ti._const or not ti._ref or ti._ptr or ti._array:
                        continue
                    #Ok, this base has copy operator
                    code += '\t{base.scope}{base._name}(ref{cls._name});\n'.format(base=base, cls=cls)
                    break
            # ok now do the same for members
            for member in cls(model.cc.MemberData, filter=lambda x: cls_member(x) and not x._static):
                code += '\t{v} = ref{c}.{v};\n'.format(v=member.prefixed_name, c=cls._name)
            code += '\treturn *this;'
            assig = model.cc.MemberMethod(parent=cls, name='operator =',
                type=model.cc.typeinst(type=cls, ref=True, const=True),
                content=code,
                note="Copy asignment created by rule of three")
            model.cc.Argument(parent=assig, type=model.cc.typeinst(type=cls,
                ref=True, const=True), name='ref{}'.format(cls._name))
        return True

    def OnUpdateAddBoostPython(self, event):
        """Update add boost.python interface"""
        obj = self.selected
        obj = obj and obj.project
        event.Enable(bool(obj and obj._language == 'c++'))

    @tran.TransactionalMethod('Add boost interface')
    @wxx.CreationDialog(ui_dlg.BoostPythonModuleDialog, model.cc.pyBoostModule)
    def OnAddBoostPython(self, event):
        """Do add boost.python interface"""
        return (context.frame, self.selected.project)

    def OnUpdateSetPreferredCtor(self, event):
        """Update set preferred ctor"""
        obj = self.selected
        if obj is None or type(obj) is not model.cc.Constructor:
            event.Enable(False)
        else:
            event.Enable(True)
            ctor = obj.inner_class.GetPreferredConstructor()
            event.Check(ctor is obj)

    def OnSetPreferredCtor(self, event):
        """Handle set preferred ctor command"""
        obj = self.selected
        pref = obj.inner_class.GetPreferredConstructor()
        if pref is not None:
            pref.SetPreferred(False)
            self.UpdateTreeModel(pref)
        if pref is not obj:
            obj.SetPreferred(True)
            self.UpdateTreeModel(obj)

    def OnUpdateAddPyPackage(self, event):
        """Update add package"""
        v = self.selected
        if v:
            v = self.selected.inner_package_container
            if v:
                if v.project._language == 'python':
                    event.Enable(True)
                    return
        event.Enable(False)

    @deco.with_python_export
    @tran.TransactionalMethod('add python pakage {}')
    @wxx.CreationDialog(ui_dlg.PyPackageDialog, model.py.Package)
    def OnAddPyPackage(self, event):
        """Handle add module method"""
        return (context.frame, self.selected.inner_module_container)

    def OnUpdateAddPyModule(self, event):
        """Update add module"""
        event.Enable(self.can_add_py_module)

    @deco.with_python_export
    @tran.TransactionalMethod('add python module {}')
    @wxx.CreationDialog(ui_dlg.PyModuleDialog, model.py.Module)
    def OnAddPyModule(self, event):
        """Handle add module method"""
        return (context.frame, self.selected.inner_module_container)

    def OnUpdateAddPyImport(self, event):
        """Update AddPyImport method"""
        event.Enable(self.can_add_py_import)

    @deco.with_python_export
    @tran.TransactionalMethod('add phython import {}')
    @wxx.CreationDialog(ui_dlg.PyImportDialog, model.py.Import)
    def OnAddPyImport(self, event):
        """Handle add python __init__ method"""
        return (context.frame, self.selected.inner_import_container)

    def OnUpdateAddPyClass(self, event):
        """Updade AddPyClass method"""
        event.Enable(self.can_add_py_class)

    @deco.with_python_export
    @tran.TransactionalMethod('add python class {}')
    @wxx.CreationDialog(ui_dlg.PyClassDialog, model.py.Class)
    def OnAddPyClass(self, event):
        """Handles add pythpn class"""
        cnt = self.selected.inner_class_container
        return (context.frame, cnt)

    def OnUpdateAddPyInheritance(self, event):
        """Handle update add python inheritance"""
        event.Enable(self.can_add_py_inheritance)

    @deco.with_python_export
    @tran.TransactionalMethod('add python {} inheritance')
    @wxx.CreationDialog(ui_dlg.PyInheritanceDialog, model.py.Inheritance)
    def OnAddPyInheritance(self, event):
        """Handle add inheritance command"""
        return (context.frame, self.selected.inner_inheritance_container)

    def OnUpdateAddPyInit(self, event):
        """Update AddPyInit method"""
        v = self.selected
        if v:
            v = self.selected.inner_member_container
            if v and v.project._language == "python":
                cls = v.inner_class
                event.Enable(not cls(model.py.InitMethod,
                    filter=lambda x: x.inner_class == cls, cut=True))
                return
        event.Enable(False)

    @deco.with_python_export
    @tran.TransactionalMethod('add phython __init__')
    def OnAddPyInit(self, event):
        """Handle add python __init__ method"""
        model.py.InitMethod(parent=self.selected.inner_member_container)
        return True

    def OnUpdateAddPyMethod(self, event):
        """Update add method method"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                if v.project._language == 'python':
                    event.Enable(True)
                    return
        event.Enable(False)

    @deco.with_python_export
    @tran.TransactionalMethod('add python method {}')
    @wxx.CreationDialog(ui_dlg.PyMemberMethodDialog, model.py.MemberMethod)
    def OnAddPyMethod(self, event):
        """Handle add method command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddPyArgument(self, event):
        """Update add argument list method"""
        event.Enable(self.can_add_py_arg)

    @deco.with_python_export
    @tran.TransactionalMethod('add python method argument {}')
    @wxx.CreationDialog(ui_dlg.PyArgumentDialog, model.py.Argument)
    def OnAddPyArgument(self, event):
        """Handle add method command"""
        return (context.frame, self.selected.inner_argument_container)

    def OnUpdateAddArgArgs(self, event):
        """Update add argument list method"""
        event.Enable(self.can_add_py_argargs)

    @deco.with_python_export
    @tran.TransactionalMethod('add *args')
    def OnAddArgArgs(self, event):
        """Handle add arg list command"""
        cnt = self.selected.inner_argument_container
        return model.py.ArgsArgument(parent=cnt)

    def OnUpdateAddArgKwArgs(self, event):
        """Update add argument list method"""
        event.Enable(self.can_add_py_kwargs)

    @deco.with_python_export
    @tran.TransactionalMethod('add *kwargs')
    def OnAddArgKwArgs(self, event):
        """Handle add arg list command"""
        cnt = self.selected.inner_argument_container
        return model.py.KwArgsArgument(parent=cnt)

    def OnUpdateAddPyMember(self, event):
        """Update add member"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                if v.project._language == 'python':
                    event.Enable(True)
                    return
        event.Enable(False)

    @deco.with_python_export
    @tran.TransactionalMethod('add python {} class member')
    @wxx.CreationDialog(ui_dlg.PyMemberDialog, model.py.MemberData)
    def OnAddPyMember(self, event):
        """Handle add member command"""
        return (context.frame, self.selected.inner_member_container)

    def OnUpdateAddPyFunction(self, event):
        """Handle update add function method"""
        event.Enable(self.can_add_py_function)

    @deco.with_python_export
    @tran.TransactionalMethod('add python function {}')
    @wxx.CreationDialog(ui_dlg.PyFunctionDialog, model.py.Function)
    def OnAddPyFunction(self, event):
        """Handle add function command"""
        return (context.frame, self.selected.inner_function_container)

    def OnUpdateAddPyVariable(self, event):
        """Update AddVariable method"""
        event.Enable(self.can_add_py_variable)

    @deco.with_python_export
    @tran.TransactionalMethod('add python variable {}')
    @wxx.CreationDialog(ui_dlg.PyVariableDialog, model.py.Data)
    def OnAddPyVariable(self, event):
        """Handles add variable method"""
        return (context.frame, self.selected.inner_variable_container)

    def OnUpdatePySetEntry(self, event):
        """Update set the main file"""
        v = self.selected
        if v and type(v) in [model.py.Module, model.py.Package]:
            event.Enable(True)
            event.Check(v._entry)
            return
        event.Check(False)
        event.Enable(False)

    @tran.TransactionalMethod('set python entry')
    def OnPySetEntry(self, event):
        """Do a selection of entry point"""
        project = self.selected.project
        project.SaveState()
        old = project.main_file
        if old:
            old.SaveState()
            old._entry = False
        if old == self.selected:
            project.main_file = None
        else:
            self.selected.SaveState()
            project.main_file = self.selected
            self.selected._entry = True
        return True

    def OnUpdateEditDecorators(self, event):
        """Update decorators edition"""
        v = self.selected
        event.Enable(bool(
            v and type(v) in [model.py.MemberMethod,
                model.py.Function, model.py.InitMethod]))

    @deco.with_python_export
    @tran.TransactionalMethod('edit {} decorators')
    @wxx.CreationDialog(ui_dlg.EditDecoratorsDialog, model.py.Decorator)
    def OnEditDecorators(self, event):
        """Edit decorators"""
        return (context.frame, self.selected)

    def OnUpdateAddImportsFolder(self, event):
        """Update add imports folder"""
        event.Enable(self.can_add_py_imports_folder)

    @tran.TransactionalMethod('add python imports folder')
    def OnAddImportsFolder(self, event):
        """Add imports folder"""
        kwargs = {}
        kwargs['parent'] = self.selected.inner_import_container
        model.py.ImportsFolder(**kwargs)
        return True

    @tran.TransactionalMethod('paste c++ argument')
    def pasteArgument(self):
        """Handle paste argument"""
        test = True
        data = clipboard.data
        name = data.args['name']
        target = self.selected.inner_argument_container
        if name in [x._name for x in target[model.cc.Argument]]:
            split = min([i for i in range(0, len(name)) if name[i:].isdigit()] + [len(name)])
            pre = name[0:split]
            index = int('0' + name[split:]) + 1
            while test:
                next_name = pre + str(index)
                if next_name in [x._name for x in target[model.cc.Argument]]:
                    index = index + 1
                else:
                    test = False
            name = next_name
        kwargs = copy.copy(data.args)
        kwargs['name'] = name
        kwargs['parent'] = target
        model.cc.Argument(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python argument')
    def pastePyArgument(self):
        """Handle paste argument"""
        test = True
        data = clipboard.data
        name = data.args['name']
        split = min([i for i in range(0, len(name)) if name[i:].isdigit()] + [len(name)])
        pre = name[0:split]
        index = int('0' + name[split:])
        target = self.selected.inner_argument_container
        while test:
            next_name = pre + str(index)
            if next_name in [x._name for x in target[model.py.Argument]]:
                index = index + 1
            else:
                test = False
        kwargs = copy.copy(data.args)
        kwargs['name'] = next_name
        kwargs['parent'] = target
        model.py.Argument(**kwargs)
        return True

    @tran.TransactionalMethod('paste c++ member')
    def pasteMemberData(self):
        """Handle paste member"""
        data = clipboard.data
        name = data.args['name']
        split = min([i for i in range(0, len(name)) if name[i:].isdigit()] + [len(name)])
        pre = name[0:split]
        index = int('0' + name[split:])
        members = self.selected.inner_class(model.cc.MemberData)
        next_name = pre
        while next_name in [x._name for x in members]:
            index = index + 1
            next_name = pre + str(index)
        kwargs = copy.copy(data.args)
        kwargs['name'] = next_name
        kwargs['parent'] = self.selected.inner_member_container
        model.cc.MemberData(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python member')
    def pastePyMemberData(self):
        """Handle paste member"""
        data = clipboard.data
        name = data.args['name']
        split = min([i for i in range(0, len(name)) if name[i:].isdigit()] + [len(name)])
        pre = name[0:split]
        index = int('0' + name[split:])
        members = self.selected.inner_class(model.py.MemberData)
        next_name = pre
        while next_name in [x._name for x in members]:
            index = index + 1
            next_name = pre + str(index)
        kwargs = copy.copy(data.args)
        kwargs['name'] = next_name
        kwargs['parent'] = self.selected.inner_member_container
        model.py.MemberData(**kwargs)
        return True

    @tran.TransactionalMethod('paste c++ constructor')
    def pasteConstructor(self):
        """Handle paste constructor"""
        # pasting a constructor is easy, we dont need to check anything more
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_member_container
        model.cc.Constructor(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python __init__')
    def pastePyInit(self):
        """Handle paste constructor"""
        # pasting a constructor is easy, we dont need to check anything more
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_member_container
        model.py.InitMethod(**kwargs)
        return True

    @tran.TransactionalMethod('paste c++ member method')
    def pasteMemberMethod(self):
        """Handle paste method"""
        # pasting a method is easy, we dont need to check anything more
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_member_container
        model.cc.MemberMethod(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python member method')
    def pastePyMemberMethod(self):
        """Handle paste method"""
        # pasting a method is easy, we dont need to check anything more
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_member_container
        model.py.MemberMethod(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python import')
    def pastePyImport(self):
        """Handle paste import"""
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_import_container
        model.py.Import(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python import folder')
    def pastePyImportsFolder(self):
        """Handle pasting an import folder"""
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_import_container
        model.py.ImportsFolder(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python inheritance')
    def pastePyInheritance(self):
        """Handle pasting an inheritance"""
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_inheritance_container
        model.py.Inheritance(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python class')
    def pastePyClass(self):
        """Handle paste python class"""
        # pasting a python class has two main scenarios:
            # a) pasting inside the same project
            # b) pasting inside other project
        # how to check it?
        # case A:-
        # This cass seems easy: all we need to do is to rename
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['derivatives'] = None
        kwargs['parent'] = self.selected.inner_member_container
        model.py.Class(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python function')
    def pastePyFunction(self):
        """Handle pase python function"""
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_method_container
        model.py.Function(**kwargs)
        return True

    @deco.with_python_export
    @tran.TransactionalMethod('paste python module')
    def pastePyModule(self):
        """Handle paste python module"""
        data = clipboard.data
        kwargs = copy.copy(data.args)
        kwargs['parent'] = self.selected.inner_module_container
        model.py.Module(**kwargs)
        return True
