Coverage for src/robotide/ui/pluginmanager.py: 22%

127 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-06 10:40 +0100

1# Copyright 2008-2015 Nokia Networks 

2# Copyright 2016- Robot Framework Foundation 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); 

5# you may not use this file except in compliance with the License. 

6# You may obtain a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, 

12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

13# See the License for the specific language governing permissions and 

14# limitations under the License. 

15 

16import builtins 1ab

17import wx 1ab

18from wx import Colour 1ab

19from wx.adv import HyperlinkCtrl 1ab

20from wx.lib.scrolledpanel import ScrolledPanel 1ab

21 

22from ..context import LOG 1ab

23from ..publish import RideLogException 1ab

24from ..widgets import Label, RIDEDialog, ButtonWithHandler 1ab

25 

26_ = wx.GetTranslation # To keep linter/code analyser happy 1ab

27builtins.__dict__['_'] = wx.GetTranslation 1ab

28 

29 

30class PluginManager(object): 1ab

31 

32 def __init__(self, notebook): 1ab

33 self._notebook = notebook 

34 self._panel = None 

35 

36 def show(self, plugins): 1ab

37 if not self._panel: 

38 self._panel = _PluginPanel(self._notebook.GetParent(), plugins, self._show_panel) 

39 self._show_panel() 

40 

41 def _show_panel(self): 1ab

42 self._panel.Show() 

43 

44 

45class _PluginPanel(RIDEDialog): 1ab

46 

47 def __init__(self, notebook, plugins, activation_callback): 1ab

48 RIDEDialog.__init__(self, parent=notebook, title=_("Manage Plugins"), size=(800, 600)) 

49 self.SetBackgroundColour(Colour(self.color_background)) 

50 self.SetForegroundColour(Colour(self.color_foreground)) 

51 sizer = wx.BoxSizer(wx.VERTICAL) 

52 sizer.Add(self._create_header(), 0, flag=wx.EXPAND | wx.LEFT | 

53 wx.RIGHT | wx.TOP, border=16) 

54 sizer.Add(self._create_info_text(), 0, 

55 flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=16) 

56 sizer.Add(self._create_line(), 0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT) 

57 sizer.Add(self._create_body(plugins, activation_callback), 1, 

58 flag=wx.EXPAND | wx.ALL, border=16) 

59 self.SetSizer(sizer) 

60 self.CenterOnParent() 

61 

62 def _create_header(self): 1ab

63 header = Label(self, wx.ID_ANY, _("Installed Plugins\n")) 

64 self.font = self.GetFont() 

65 self.font.SetPointSize(self.font_size) 

66 if self.font_face is None: 

67 self.font_face = self.font.GetFaceName() 

68 else: 

69 self.font.SetFaceName(self.font_face) 

70 self.SetFont(self.font) 

71 header.SetFont(wx.Font(wx.FontInfo(14 if self.font_size<=11 else self.font_size + 3).Bold())) 

72 return header 

73 

74 def _create_line(self): 1ab

75 return wx.StaticLine(self) 

76 

77 def _create_body(self, plugins, activation_callback): 1ab

78 panel = ScrolledPanel(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL | wx.SIZE_AUTO) 

79 panel.SetupScrolling() 

80 sizer = wx.FlexGridSizer(0, 2, hgap=8, vgap=8) 

81 sizer.AddGrowableCol(1, 1) 

82 sizer.Add(self._create_label(panel, _('Enabled')), 0, wx.BOTTOM, border=8) 

83 sizer.Add(self._create_label(panel, _('Plugin')), 0, wx.BOTTOM | wx.EXPAND, border=8) 

84 for plugin in sorted(plugins, key=lambda p: p.name): 

85 sizer.Add(_PluginEnablationCheckBox(panel, plugin, activation_callback), 

86 flag=wx.ALIGN_LEFT) 

87 sizer.Add(_PluginRow(panel, plugin, self.color_background), 0, wx.EXPAND) 

88 panel.SetSizer(sizer) 

89 return panel 

90 

91 def _create_info_text(self): 1ab

92 info = wx.StaticText(self, wx.ID_ANY, _("Info. Enabling and disabling plugins might" 

93 " require RIDE restart for menus to work.")) 

94 info.SetFont(wx.Font(wx.FontInfo(12).Family(wx.FONTFAMILY_SWISS).Bold(False))) 

95 return info 

96 

97 def _create_label(self, parent, text): 1ab

98 bold_font = self.GetFont() 

99 if self.font_face: 

100 bold_font.SetFaceName(self.font_face) 

101 bold_font.SetWeight(wx.FONTWEIGHT_BOLD) 

102 bold_font.SetPointSize(self.font_size) 

103 label = Label(parent, wx.ID_ANY, text) 

104 label.SetFont(bold_font) 

105 return label 

106 

107 

108class _PluginEnablationCheckBox(wx.CheckBox): 1ab

109 

110 def __init__(self, parent, plugin, activation_callback): 1ab

111 wx.CheckBox.__init__(self, parent) 

112 self.SetValue(plugin.enabled) 

113 self.Bind(wx.EVT_CHECKBOX, self.on_check_box) 

114 if plugin.error: 

115 self.Enable(False) 

116 self._plugin = plugin 

117 self._callback = activation_callback 

118 

119 def on_check_box(self, event): 1ab

120 if event.IsChecked(): 

121 self._execute(self._plugin.enable) 

122 else: 

123 self._execute(self._plugin.disable) 

124 self._callback() 

125 

126 def _execute(self, method): 1ab

127 try: 

128 method() 

129 except Exception as err: 

130 self.SetValue(False) 

131 self.Enable(False) 

132 msg = 'Failed to %s plugin %s:\n%s\n\nYou should restart RIDE now!' % (method.__name__, 

133 self._plugin.name, 

134 err) 

135 self._plugin.error = err 

136 self._plugin.doc = msg 

137 LOG.error(msg) 

138 RideLogException(message=msg, exception=err, level='ERROR').publish() 

139 

140 

141class _PluginRow(wx.Panel): 1ab

142 

143 def __init__(self, parent, plugin, backgound_color): 1ab

144 wx.Panel.__init__(self, parent) 

145 sz_head = wx.FlexGridSizer(0, 3, hgap=4, vgap=4) 

146 l_name = self._get_name(plugin) 

147 sz_head.Add(l_name) 

148 b_spacing = Label(self, label=' ') 

149 sz_head.Add(b_spacing) 

150 if hasattr(plugin, 'on_config_panel'): 

151 try: 

152 sz_head.Add(ButtonWithHandler(self, _('Settings'), bitmap='wrench.png', 

153 color_secondary_background=backgound_color, 

154 handler=lambda e: plugin.on_config_panel()), 

155 flag=wx.ALIGN_LEFT) 

156 except AttributeError: 

157 pass 

158 sizer = wx.BoxSizer(wx.VERTICAL) 

159 sizer.Add(sz_head) 

160 for name, value in plugin.metadata.items(): 

161 sizer.Add(self._get_metadata(name, value)) 

162 sizer.Add(self._get_description(plugin), 0, wx.EXPAND) 

163 self.SetSizer(sizer) 

164 

165 def _get_name(self, plugin): 1ab

166 return Label(self, label=plugin.name) 

167 

168 def _get_metadata(self, name, value): 1ab

169 sizer = wx.BoxSizer(wx.HORIZONTAL) 

170 sizer.Add(Label(self, label='%s: ' % name)) 

171 if value.split('://')[0] in ['http', 'https']: 

172 sizer.Add(HyperlinkCtrl(self, -1, label=value, url=value)) 

173 else: 

174 sizer.Add(Label(self, label=value)) 

175 return sizer 

176 

177 def _get_description(self, plugin): 1ab

178 desc = Label(self, label=plugin.doc) 

179 if plugin.error: 

180 desc.SetForegroundColour("firebrick") 

181 return desc