Coverage for src/robotide/usages/usagesdialog.py: 37%

114 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

18 

19from wx import Colour 1ab

20from ..widgets import RIDEDialog, VirtualList, VerticalSizer, ImageList, ImageProvider, ButtonWithHandler 1ab

21from ..widgets.list import ListModel 1ab

22 

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

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

25 

26 

27class UsagesDialog(RIDEDialog): 1ab

28 

29 def __init__(self, name, usages=None, prefix=None): 1ab

30 self._dots = None 

31 self._name = name 

32 self._selection_listeners = [] 

33 title = "'%s'" % name 

34 RIDEDialog.__init__(self, title=title, size=(650, 400)) 

35 # set Left to Right direction (while we don't have localization) 

36 self.SetLayoutDirection(wx.Layout_LeftToRight) 

37 self.SetSizer(VerticalSizer()) 

38 self.SetBackgroundColour(Colour(self.color_background)) 

39 self.SetForegroundColour(Colour(self.color_foreground)) 

40 self._add_view_components() 

41 self.usages = usages or UsagesListModel([]) 

42 # print(f"DEBUG: usagesdialog.py UsagesDialog INIT: usages={self.usages} NAME={name} prefix={prefix}") 

43 self.usage_list = VirtualList(self, self.usages.headers, self.usages) 

44 self.usage_list.SetBackgroundColour(Colour(self.color_secondary_background)) 

45 self.usage_list.SetForegroundColour(Colour(self.color_secondary_foreground)) 

46 self.usage_list.add_selection_listener(self._usage_selected) 

47 self.Sizer.add_expanding(self.usage_list) 

48 

49 def add_usage(self, usage): 1ab

50 self.usages.add_usage(usage) 

51 

52 def begin_searching(self): 1ab

53 from ..ui.searchdots import DottedSearch 

54 self._dots = DottedSearch(self, self._update_searching) 

55 self._dots.start() 

56 

57 def _update_searching(self, dots): 1ab

58 self.SetTitle(_("'%s' - %d matches found - Searching%s") % (self._name, self.usages.total_usages, dots)) 

59 self.usage_list.refresh_items() 

60 

61 def end_searching(self): 1ab

62 self._dots.stop() 

63 self.SetTitle(_("'%s' - %d matches") % (self._name, self.usages.total_usages)) 

64 self.usage_list.refresh_items() 

65 

66 def _usage_selected(self, idx): 1ab

67 for listener in self._selection_listeners: 

68 listener(self.usages.usage(idx).item.parent, self._name) 

69 

70 def add_selection_listener(self, listener): 1ab

71 self._selection_listeners.append(listener) 

72 

73 def _add_view_components(self): 1ab

74 """ Just ignore it """ 

75 pass 

76 

77 

78class UsagesDialogWithUserKwNavigation(UsagesDialog): 1ab

79 

80 def __init__(self, name, highlight, controller, usages=None, prefix=None): 1ab

81 """ 

82 import os 

83 if not prefix: 

84 prefix = os.path.basename(controller.source).split('.')[0] 

85 """ 

86 # print(f"DEBUG: usagesdialog.py UsagesDialogWithUserKwNavigation ENTER name={name}," 

87 # f" controller_name={controller.name} usages={usages}" 

88 # f" source={controller.source} prefix={prefix}") 

89 self.on_go_to_definition = lambda evt: highlight(controller, name) 

90 UsagesDialog.__init__(self, name, usages=usages, prefix=prefix) 

91 

92 def _add_view_components(self): 1ab

93 button = ButtonWithHandler(self, _('Go to definition'), mk_handler='Go to definition', 

94 handler=self.on_go_to_definition) 

95 button.SetBackgroundColour(Colour(self.color_secondary_background)) 

96 button.SetForegroundColour(Colour(self.color_secondary_foreground)) 

97 self.Sizer.Add(button, 0, wx.ALL, 3) 

98 

99 

100def resource_import_usage_dialog(name, highlight, controller): 1ab

101 return UsagesDialogWithUserKwNavigation(name, highlight, controller, usages=ResourceImportListModel([])) 

102 

103 

104class _UsagesListModel(ListModel): 1ab

105 

106 def __init__(self, usages): 1ab

107 self._usages = usages 

108 self._create_image_list() 

109 

110 def _create_image_list(self): 1ab

111 images = ImageList(16, 16) 

112 provider = ImageProvider() 

113 images.add_image(provider.TESTCASEIMG) 

114 images.add_image(provider.KEYWORDIMG) 

115 images.add_image(provider.DATAFILEIMG) 

116 images.add_image(provider.DATADIRIMG) 

117 self._images = images 

118 

119 @property 1ab

120 def images(self): 1ab

121 return self._images 

122 

123 def image(self, item): 1ab

124 # DEBUG: better mechanism for item type recognition 

125 parent_type = self._usages[item].parent.__class__.__name__ 

126 return {'TestCaseController': 0, 

127 'UserKeywordController': 1, 

128 'TestCaseFileController': 2, 

129 'ResourceFileController': 2, 

130 'TestDataDirectoryController': 3}.get(parent_type, -1) 

131 

132 def add_usage(self, usage): 1ab

133 self._usages.append(usage) 

134 

135 def usage(self, idx): 1ab

136 return self._usages[idx] 

137 

138 @property 1ab

139 def total_usages(self): 1ab

140 return sum(u.count for u in self._usages) 

141 

142 @property 1ab

143 def count(self): 1ab

144 return len(self._usages) 

145 

146 

147class UsagesListModel(_UsagesListModel): 1ab

148 

149 def __init__(self, usages): 1ab

150 _UsagesListModel.__init__(self, usages) 

151 self.headers = [_('Location'), _('Usage'), _('Source')] 

152 

153 def item_text(self, row, col): 1ab

154 u = self.usage(row) 

155 return [u.location, u.usage, u.source][col] 

156 

157 

158class ResourceImportListModel(_UsagesListModel): 1ab

159 

160 def __init__(self, usages): 1ab

161 _UsagesListModel.__init__(self, usages) 

162 self.headers = ['Name', 'Location'] 

163 # wxPyDeprecationWarning: Using deprecated class. Use ItemAttr instead 

164 self._cannot_rename_item_attr = wx.ItemAttr() # wx.ListItemAttr() 

165 self._cannot_rename_item_attr.SetBackgroundColour(wx.Colour(255, 64, 64)) 

166 

167 def item_text(self, row, col): 1ab

168 u = self.usage(row) 

169 return [u.name, u.location][col] 

170 

171 def item_attributes(self, idx): 1ab

172 if self._usages[idx].can_be_renamed: 

173 return None 

174 return self._cannot_rename_item_attr 

175 

176 @property 1ab

177 def total_usages(self): 1ab

178 return len(self._usages) 

179 

180 

181class RecursiveResourceImportListModel(_UsagesListModel): 1ab

182 

183 def __init__(self, usages): 1ab

184 _UsagesListModel.__init__(self, usages) 

185 self.headers = [_('Imported name'), _('Imported Location'), _('Importing Name'), _('Importing Location')] 

186 

187 def item_text(self, row, col): 1ab

188 u = self.usage(row) 

189 return [u.res_name, u.res_src, u.name, u.location][col]