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

import os
import wx
import wxx
import tran
import app
import model
#import dlg
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


# 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_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 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.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),
        #tree navigation facilities
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_LEFT, BaseView._leftKeyId)
        ])
        self.SetAcceleratorTable(aTable)

    def NodeOnAddClass(self, event):
        """Attempt to translate method"""
        s = self.selected
        if not s:
            return
        #determine languaje
        project = s.project
        if project is None:
            return
        if not s.inner_class_container:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            self.OnAddClass(event)
        else:
            self.OnAddPyClass(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 not self.selected:
            return
        #determine languaje
        project = self.selected.project
        if project is None:
            return
        if project._language == 'c++':
            # Ok, choose to member/data
            if self.selected.outer_class:
                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"""
        v = self.selected
        if v:
            v = v.inner_class_container
            if v:
                v = v.project
                if v._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @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"""
        v = self.selected
        if v:
            v = v.inner_inheritance_container
            if v:
                if v.project._language == 'c++':
                    event.Enable(True)
                    return
        event.Enable(False)

    @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"""
        v = self.selected
        if v:
            v = v.inner_member_container
            if v:
                if v.project._language == 'c++':
                    cls = v.inner_class
                    event.Enable(not cls(model.cc.Destructor,
                        filter=lambda x: x.inner_class == cls, cut=True))
                    return
        event.Enable(False)

    @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"""
        v = self.selected
        if v:
            v = v.inner_class_container
            if v:
                v = v.project
                if v._language == 'python':
                    event.Enable(True)
                    return
        event.Enable(False)

    @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
