eg/Classes/PluginItem.py
# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2020 EventGhost Project <http://www.eventghost.net/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.
import base64
import pickle
import wx
# Local imports
import eg
from ActionItem import ActionItem
from TreeItem import TreeItem
class PluginItem(ActionItem):
xmlTag = "Plugin"
icon = eg.Icons.PLUGIN_ICON
isRenameable = False
info = None
@eg.AssertInActionThread
def __init__(self, parent, node):
TreeItem.__init__(self, parent, node)
if node.text:
try:
args = pickle.loads(base64.b64decode(node.text))
except AttributeError:
args = ()
else:
args = ()
evalName = node.attrib.get('identifier', None)
self.pluginName = node.attrib.get('file', None)
guid = node.attrib.get('guid', self.pluginName)
self.info = info = eg.pluginManager.OpenPlugin(
guid,
evalName,
args,
self,
)
self.name = eg.text.General.pluginLabel % info.label
if info.icon != self.icon:
self.icon = eg.Icons.PluginSubIcon(info.icon)
#self.icon = info.icon
self.url = info.url
self.executable = info.instance
def AskCut(self):
return self.AskDelete()
def AskDelete(self):
actionItemCls = self.document.ActionItem
def SearchFunc(obj):
if obj.__class__ == actionItemCls:
if obj.executable and obj.executable.plugin == self.executable:
return True
return None
if self.root.Traverse(SearchFunc) is not None:
eg.MessageBox(
eg.text.General.deletePlugin,
eg.APP_NAME,
wx.NO_DEFAULT | wx.OK | wx.ICON_EXCLAMATION
)
return False
if not TreeItem.AskDelete(self):
return False
return True
@eg.AssertInActionThread
def Delete(self):
info = self.info
def DoIt():
info.Close()
info.instance.OnDelete()
info.RemovePluginInstance()
eg.actionThread.Call(DoIt)
ActionItem.Delete(self)
self.executable = None
self.info = None
@eg.AssertInActionThread
def Execute(self):
if not self.isEnabled:
return None, None
if eg.config.logActions:
self.Print(self.name)
if self.shouldSelectOnExecute:
wx.CallAfter(self.Select)
eg.indent += 1
self.info.Start()
eg.indent -= 1
eg.result = self.executable
return None, None
# The Find function calls this from MainThread, so we can't restrict this
# to the ActionThread
#@eg.AssertInActionThread
def GetArguments(self):
return self.info.args
def GetBasePath(self):
"""
Returns the filesystem path, where additional files (like pictures)
should be found.
Overrides ActionItem.GetBasePath()
"""
return self.info.path
def GetData(self):
attr, text = TreeItem.GetData(self)
del attr[0]
attr.append(('Identifier', self.executable.info.evalName))
guid = self.executable.info.guid
if guid:
attr.append(('Guid', guid))
attr.append(('File', self.pluginName))
text = base64.b64encode(pickle.dumps(self.info.args, 2))
return attr, text
def GetLabel(self):
return self.name
def GetTypeName(self):
return self.executable.info.name
def NeedsStartupConfiguration(self):
"""
Returns True if the item wants to be configured after creation.
Overrides ActionItem.NeedsStartupConfiguration()
"""
# if the Configure method of the executable is overriden, we assume
# the item wants to be configured after creation
return (
self.executable.Configure.im_func !=
eg.PluginBase.Configure.im_func
)
def RefreshAllVisibleActions(self):
"""
Calls Refresh() for all currently visible actions of this plugin.
"""
actionItemCls = self.document.ActionItem
plugin = self.info.instance
def Traverse(item):
if item.__class__ == actionItemCls:
if item.executable.plugin == plugin:
pass
#eg.Notify("NodeChanged", item)
else:
if item.childs and item in item.document.expandedNodes:
for child in item.childs:
Traverse(child)
Traverse(self.root)
@eg.LogIt
def RestoreState(self):
if self.isEnabled:
eg.actionThread.Call(self.info.Start)
@eg.LogIt
@eg.AssertInActionThread
def SetArguments(self, args):
info = self.info
if not info.lastException and args == self.info.args:
return
self.info.args = args
label = info.instance.GetLabel(*args)
if label != info.label:
info.label = label
self.name = eg.text.General.pluginLabel % label
#eg.Notify("NodeChanged", self)
self.RefreshAllVisibleActions()
if self.isEnabled:
eg.actionThread.Call(self.info.Stop)
eg.actionThread.Call(self.info.Start)
def SetAttributes(self, tree, itemId):
if (
self.info is None or
self.info.lastException or
self.info.initFailed
):
tree.SetItemTextColour(itemId, eg.colour.pluginError)
@eg.AssertInActionThread
def SetEnable(self, flag=True):
ActionItem.SetEnable(self, flag)
if flag:
self.info.Start()
else:
self.info.Stop()