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
« 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.
16import builtins 1ab
17import wx 1ab
19from wx import Colour 1ab
20from ..widgets import RIDEDialog, VirtualList, VerticalSizer, ImageList, ImageProvider, ButtonWithHandler 1ab
21from ..widgets.list import ListModel 1ab
23_ = wx.GetTranslation # To keep linter/code analyser happy 1ab
24builtins.__dict__['_'] = wx.GetTranslation 1ab
27class UsagesDialog(RIDEDialog): 1ab
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)
49 def add_usage(self, usage): 1ab
50 self.usages.add_usage(usage)
52 def begin_searching(self): 1ab
53 from ..ui.searchdots import DottedSearch
54 self._dots = DottedSearch(self, self._update_searching)
55 self._dots.start()
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()
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()
66 def _usage_selected(self, idx): 1ab
67 for listener in self._selection_listeners:
68 listener(self.usages.usage(idx).item.parent, self._name)
70 def add_selection_listener(self, listener): 1ab
71 self._selection_listeners.append(listener)
73 def _add_view_components(self): 1ab
74 """ Just ignore it """
75 pass
78class UsagesDialogWithUserKwNavigation(UsagesDialog): 1ab
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)
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)
100def resource_import_usage_dialog(name, highlight, controller): 1ab
101 return UsagesDialogWithUserKwNavigation(name, highlight, controller, usages=ResourceImportListModel([]))
104class _UsagesListModel(ListModel): 1ab
106 def __init__(self, usages): 1ab
107 self._usages = usages
108 self._create_image_list()
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
119 @property 1ab
120 def images(self): 1ab
121 return self._images
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)
132 def add_usage(self, usage): 1ab
133 self._usages.append(usage)
135 def usage(self, idx): 1ab
136 return self._usages[idx]
138 @property 1ab
139 def total_usages(self): 1ab
140 return sum(u.count for u in self._usages)
142 @property 1ab
143 def count(self): 1ab
144 return len(self._usages)
147class UsagesListModel(_UsagesListModel): 1ab
149 def __init__(self, usages): 1ab
150 _UsagesListModel.__init__(self, usages)
151 self.headers = [_('Location'), _('Usage'), _('Source')]
153 def item_text(self, row, col): 1ab
154 u = self.usage(row)
155 return [u.location, u.usage, u.source][col]
158class ResourceImportListModel(_UsagesListModel): 1ab
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))
167 def item_text(self, row, col): 1ab
168 u = self.usage(row)
169 return [u.name, u.location][col]
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
176 @property 1ab
177 def total_usages(self): 1ab
178 return len(self._usages)
181class RecursiveResourceImportListModel(_UsagesListModel): 1ab
183 def __init__(self, usages): 1ab
184 _UsagesListModel.__init__(self, usages)
185 self.headers = [_('Imported name'), _('Imported Location'), _('Importing Name'), _('Importing Location')]
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]