| Home | Trees | Indices | Help |
|---|
|
|
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Fraunhofer nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32
33 from python_qt_binding import loadUi
34 from python_qt_binding.QtCore import QObject, Signal, Qt
35 from python_qt_binding.QtGui import QStandardItemModel, QStandardItem
36 import os
37 import threading
38 import rospy
39
40 from node_manager_fkie.common import package_name
41 from node_manager_fkie.html_delegate import HTMLDelegate
42 from node_manager_fkie.launch_config import LaunchConfig
43
44 try:
45 from python_qt_binding.QtGui import QCheckBox, QFrame, QLabel, QTreeWidget, QTreeWidgetItem, QPushButton, QGroupBox, QDockWidget
46 from python_qt_binding.QtGui import QHBoxLayout, QVBoxLayout, QSpacerItem, QSplitter, QSizePolicy, QAbstractItemView, QItemSelectionModel
47 except:
48 from python_qt_binding.QtWidgets import QCheckBox, QFrame, QLabel, QTreeWidget, QTreeWidgetItem, QPushButton, QGroupBox, QDockWidget
49 from python_qt_binding.QtWidgets import QHBoxLayout, QVBoxLayout, QSpacerItem, QSplitter, QSizePolicy, QAbstractItemView
50 from python_qt_binding.QtCore import QItemSelectionModel
51
52
53 GRAPH_CACHE = {}
54 CHACHE_MUTEX = threading.RLock()
55
56
58 '''
59 A frame to find text in the Editor.
60 '''
61 load_signal = Signal(str, bool)
62 ''' @ivar: filename of file to load, True if insert after the current open tab'''
63 goto_signal = Signal(str, int)
64 ''' @ivar: filename, line to go'''
65 DATA_FILE = Qt.UserRole + 1
66 DATA_LINE = Qt.UserRole + 2
67 DATA_INC_FILE = Qt.UserRole + 3
68 DATA_LEVEL = Qt.UserRole + 4
69
71 QDockWidget.__init__(self, "LaunchGraph", parent)
72 graph_ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'GraphDockWidget.ui')
73 loadUi(graph_ui_file, self)
74 self.setObjectName('LaunchGraph')
75 self.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
76 self._tabwidget = tabwidget
77 self._current_path = None
78 self._root_path = None
79 self._current_deep = 0
80 self.graphTreeView.setSelectionBehavior(QAbstractItemView.SelectRows)
81 model = QStandardItemModel()
82 self.graphTreeView.setModel(model)
83 self.graphTreeView.setUniformRowHeights(True)
84 self.graphTreeView.header().hide()
85 self.htmlDelegate = HTMLDelegate()
86 self.graphTreeView.setItemDelegateForColumn(0, self.htmlDelegate)
87 self.graphTreeView.activated.connect(self.on_activated)
88 self.graphTreeView.clicked.connect(self.on_clicked)
89 self._created_tree = False
90 self._refill_tree([], [], False)
91
93 with CHACHE_MUTEX:
94 GRAPH_CACHE.clear()
95 self._created_tree = False
96 self.graphTreeView.model().clear()
97 crp = self._current_path
98 self._current_path = None
99 self.set_file(crp, self._root_path)
100
102 self._root_path = root_path
103 if self._current_path != current_path:
104 self._current_path = current_path
105 # TODO: run analyzer/path parser in a new thread
106 self.setWindowTitle("Include Graph - loading...")
107 self._fill_graph_thread = GraphThread(current_path, root_path)
108 self._fill_graph_thread.graph.connect(self._refill_tree)
109 self._fill_graph_thread.start()
110
112 selected = self.graphTreeView.selectionModel().selectedIndexes()
113 for index in selected:
114 item = self.graphTreeView.model().itemFromIndex(index.parent())
115 self.load_signal.emit(item.data(self.DATA_INC_FILE), self._current_deep < item.data(self.DATA_LEVEL))
116
118 item = self.graphTreeView.model().itemFromIndex(index)
119 self.load_signal.emit(item.data(self.DATA_INC_FILE), self._current_deep < item.data(self.DATA_LEVEL))
120
122 item = self.graphTreeView.model().itemFromIndex(index)
123 self.goto_signal.emit(item.data(self.DATA_FILE), item.data(self.DATA_LINE))
124
126 self.setVisible(True)
127 self.raise_()
128 self.activateWindow()
129 self.graphTreeView.setFocus()
130
132 deep = 0
133 file_dsrc = self._root_path
134 try:
135 file_dsrc = os.path.basename(self._root_path)
136 except Exception:
137 pass
138 self.setWindowTitle("Include Graph - %s" % file_dsrc)
139 if not self._created_tree and create_tree:
140 with CHACHE_MUTEX:
141 if self._root_path in GRAPH_CACHE:
142 pkg, _ = package_name(os.path.dirname(self._root_path))
143 itemstr = '%s [%s]' % (os.path.basename(self._root_path), pkg)
144 inc_item = QStandardItem('%s' % itemstr)
145 inc_item.setData(self._root_path, self.DATA_FILE)
146 inc_item.setData(-1, self.DATA_LINE)
147 inc_item.setData(self._root_path, self.DATA_INC_FILE)
148 inc_item.setData(deep, self.DATA_LEVEL)
149 self._append_items(inc_item, deep + 1)
150 self.graphTreeView.model().appendRow(inc_item)
151 # self.graphTreeView.expand(self.graphTreeView.model().indexFromItem(inc_item))
152 self._created_tree = True
153 items = self.graphTreeView.model().match(self.graphTreeView.model().index(0, 0), self.DATA_INC_FILE, self._current_path, 10, Qt.MatchRecursive)
154 first = True
155 self.graphTreeView.selectionModel().clearSelection()
156 for item in items:
157 if first:
158 self._current_deep = item.data(self.DATA_LEVEL)
159 self.graphTreeView.selectionModel().select(item, QItemSelectionModel.SelectCurrent)
160 first = False
161 else:
162 self.graphTreeView.selectionModel().select(item, QItemSelectionModel.Select)
163 self.graphTreeView.expandAll()
164
166 path = item.data(self.DATA_INC_FILE)
167 if not path:
168 path = item.data(self.DATA_FILE)
169 if path in GRAPH_CACHE:
170 for inc_lnr, inc_path in GRAPH_CACHE[path]:
171 pkg, _ = package_name(os.path.dirname(inc_path))
172 itemstr = '%s [%s]' % (os.path.basename(inc_path), pkg)
173 inc_item = QStandardItem('%d: %s' % (inc_lnr + 1, itemstr))
174 inc_item.setData(path, self.DATA_FILE)
175 inc_item.setData(inc_lnr + 1, self.DATA_LINE)
176 inc_item.setData(inc_path, self.DATA_INC_FILE)
177 inc_item.setData(deep, self.DATA_LEVEL)
178 self._append_items(inc_item, deep + 1)
179 item.appendRow(inc_item)
180
181
183 '''
184 A thread to parse file for includes
185 '''
186 graph = Signal(list, list)
187 '''
188 @ivar: graph is a signal, which emit two list for files include the current path and a list with included files.
189 Each entry is a tuple of the line number and path.
190 '''
191
193 '''
194 :param root_path: the open root file
195 :type root_path: str
196 :param current_path: current shown file
197 :type current_path: str
198 '''
199 QObject.__init__(self)
200 threading.Thread.__init__(self)
201 self.setDaemon(True)
202 self.current_path = current_path
203 self.root_path = root_path
204
206 '''
207 '''
208 try:
209 includes = self._get_includes(self.current_path)
210 included_from = []
211 incs = self._get_includes(self.root_path)
212 included_from = self._find_inc_file(self.current_path, incs, self.root_path)
213 self.graph.emit(included_from, includes)
214 except Exception:
215 import traceback
216 formatted_lines = traceback.format_exc(1).splitlines()
217 print "Error while parse launch file for includes:\n\t%s" % traceback.format_exc()
218 try:
219 rospy.logwarn("Error while parse launch file for includes:\n\t%s", formatted_lines[-1])
220 except Exception:
221 pass
222
224 result = []
225 with CHACHE_MUTEX:
226 if path:
227 if path in GRAPH_CACHE:
228 result = GRAPH_CACHE[path]
229 else:
230 result = LaunchConfig.included_files(path, recursive=False, unique=False)
231 GRAPH_CACHE[path] = result
232 return result
233
243
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Fri May 3 02:27:58 2019 | http://epydoc.sourceforge.net |