3588 lines · 112.0 KB · Python
RawDownload
 		self.view = QTreeView()		self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)		self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard 		self.context_menu = TreeContextMenu(self.view) 	def DisplayFound(self, ids):		if not len(ids):			return False		parent = QModelIndex()		for dbid in ids:			found = False			n = self.model.rowCount(parent)			for row in xrange(n):				child = self.model.index(row, 0, parent)				if child.internalPointer().dbid == dbid:					found = True					self.view.setCurrentIndex(child)					parent = child					break			if not found:				break		return found 	def Find(self, value, direction, pattern, context):		self.view.setFocus()		self.find_bar.Busy()		self.model.Find(value, direction, pattern, context, self.FindDone) 	def FindDone(self, ids):		found = True		if not self.DisplayFound(ids):			found = False		self.find_bar.Idle()		if not found:			self.find_bar.NotFound()  # Context-sensitive call graph window class CallGraphWindow(TreeWindowBase): 	def __init__(self, glb, parent=None):		super(CallGraphWindow, self).__init__(parent) 		self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 		self.view.setModel(self.model) 		for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):			self.view.setColumnWidth(c, w) 		self.find_bar = FindBar(self, self) 		self.vbox = VBox(self.view, self.find_bar.Widget()) 		self.setWidget(self.vbox.Widget()) 		AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") # Call tree window class CallTreeWindow(TreeWindowBase): 	def __init__(self, glb, parent=None):		super(CallTreeWindow, self).__init__(parent) 		self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 		self.view.setModel(self.model) 		for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)):			self.view.setColumnWidth(c, w) 		self.find_bar = FindBar(self, self) 		self.vbox = VBox(self.view, self.find_bar.Widget()) 		self.setWidget(self.vbox.Widget()) 		AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree") # Child data item  finder class ChildDataItemFinder(): 	def __init__(self, root):		self.root = root		self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (None,) * 5		self.rows = []		self.pos = 0 	def FindSelect(self):		self.rows = []		if self.pattern:			pattern = re.compile(self.value)			for child in self.root.child_items:				for column_data in child.data:					if re.search(pattern, str(column_data)) is not None:						self.rows.append(child.row)						break		else:			for child in self.root.child_items:				for column_data in child.data:					if self.value in str(column_data):						self.rows.append(child.row)						break 	def FindValue(self):		self.pos = 0		if self.last_value != self.value or self.pattern != self.last_pattern:			self.FindSelect()		if not len(self.rows):			return -1		return self.rows[self.pos] 	def FindThread(self):		if self.direction == 0 or self.value != self.last_value or self.pattern != self.last_pattern:			row = self.FindValue()		elif len(self.rows):			if self.direction > 0:				self.pos += 1				if self.pos >= len(self.rows):					self.pos = 0			else:				self.pos -= 1				if self.pos < 0:					self.pos = len(self.rows) - 1			row = self.rows[self.pos]		else:			row = -1		return (True, row) 	def Find(self, value, direction, pattern, context, callback):		self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (value, direction,pattern, self.value, self.pattern)		# Use a thread so the UI is not blocked		thread = Thread(self.FindThread)		thread.done.connect(lambda row, t=thread, c=callback: self.FindDone(t, c, row), Qt.QueuedConnection)		thread.start() 	def FindDone(self, thread, callback, row):		callback(row) # Number of database records to fetch in one go glb_chunk_sz = 10000 # Background process for SQL data fetcher class SQLFetcherProcess(): 	def __init__(self, dbref, sql, buffer, head, tail, fetch_count, fetching_done, process_target, wait_event, fetched_event, prep):		# Need a unique connection name		conn_name = "SQLFetcher" + str(os.getpid())		self.db, dbname = dbref.Open(conn_name)		self.sql = sql		self.buffer = buffer		self.head = head		self.tail = tail		self.fetch_count = fetch_count		self.fetching_done = fetching_done		self.process_target = process_target		self.wait_event = wait_event		self.fetched_event = fetched_event		self.prep = prep		self.query = QSqlQuery(self.db)		self.query_limit = 0 if "$$last_id$$" in sql else 2		self.last_id = -1		self.fetched = 0		self.more = True		self.local_head = self.head.value		self.local_tail = self.tail.value 	def Select(self):		if self.query_limit:			if self.query_limit == 1:				return			self.query_limit -= 1		stmt = self.sql.replace("$$last_id$$", str(self.last_id))		QueryExec(self.query, stmt) 	def Next(self):		if not self.query.next():			self.Select()			if not self.query.next():				return None		self.last_id = self.query.value(0)		return self.prep(self.query) 	def WaitForTarget(self):		while True:			self.wait_event.clear()			target = self.process_target.value			if target > self.fetched or target < 0:				break			self.wait_event.wait()		return target 	def HasSpace(self, sz):		if self.local_tail <= self.local_head:			space = len(self.buffer) - self.local_head			if space > sz:				return True			if space >= glb_nsz:				# Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer				nd = pickle.dumps(0, pickle.HIGHEST_PROTOCOL)				self.buffer[self.local_head : self.local_head + len(nd)] = nd			self.local_head = 0		if self.local_tail - self.local_head > sz:			return True		return False 	def WaitForSpace(self, sz):		if self.HasSpace(sz):			return		while True:			self.wait_event.clear()			self.local_tail = self.tail.value			if self.HasSpace(sz):				return			self.wait_event.wait() 	def AddToBuffer(self, obj):		d = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)		n = len(d)		nd = pickle.dumps(n, pickle.HIGHEST_PROTOCOL)		sz = n + glb_nsz		self.WaitForSpace(sz)		pos = self.local_head		self.buffer[pos : pos + len(nd)] = nd		self.buffer[pos + glb_nsz : pos + sz] = d		self.local_head += sz 	def FetchBatch(self, batch_size):		fetched = 0		while batch_size > fetched:			obj = self.Next()			if obj is None:				self.more = False				break			self.AddToBuffer(obj)			fetched += 1		if fetched:			self.fetched += fetched			with self.fetch_count.get_lock():				self.fetch_count.value += fetched			self.head.value = self.local_head			self.fetched_event.set() 	def Run(self):		while self.more:			target = self.WaitForTarget()			if target < 0:				break			batch_size = min(glb_chunk_sz, target - self.fetched)			self.FetchBatch(batch_size)		self.fetching_done.value = True		self.fetched_event.set() def SQLFetcherFn(*x):	process = SQLFetcherProcess(*x)	process.Run() # SQL data fetcher class SQLFetcher(QObject): 	done = Signal(object) 	def __init__(self, glb, sql, prep, process_data, parent=None):		super(SQLFetcher, self).__init__(parent)		self.process_data = process_data		self.more = True		self.target = 0		self.last_target = 0		self.fetched = 0		self.buffer_size = 16 * 1024 * 1024		self.buffer = Array(c_char, self.buffer_size, lock=False)		self.head = Value(c_longlong)		self.tail = Value(c_longlong)		self.local_tail = 0		self.fetch_count = Value(c_longlong)		self.fetching_done = Value(c_bool)		self.last_count = 0		self.process_target = Value(c_longlong)		self.wait_event = Event()		self.fetched_event = Event()		glb.AddInstanceToShutdownOnExit(self)		self.process = Process(target=SQLFetcherFn, args=(glb.dbref, sql, self.buffer, self.head, self.tail, self.fetch_count, self.fetching_done, self.process_target, self.wait_event, self.fetched_event, prep))		self.process.start()		self.thread = Thread(self.Thread)		self.thread.done.connect(self.ProcessData, Qt.QueuedConnection)		self.thread.start() 	def Shutdown(self):		# Tell the thread and process to exit		self.process_target.value = -1		self.wait_event.set()		self.more = False		self.fetching_done.value = True		self.fetched_event.set() 	def Thread(self):		if not self.more:			return True, 0		while True:			self.fetched_event.clear()			fetch_count = self.fetch_count.value			if fetch_count != self.last_count:				break			if self.fetching_done.value:				self.more = False				return True, 0			self.fetched_event.wait()		count = fetch_count - self.last_count		self.last_count = fetch_count		self.fetched += count		return False, count 	def Fetch(self, nr):		if not self.more:			# -1 inidcates there are no more			return -1		result = self.fetched		extra = result + nr - self.target		if extra > 0:			self.target += extra			# process_target < 0 indicates shutting down			if self.process_target.value >= 0:				self.process_target.value = self.target			self.wait_event.set()		return result 	def RemoveFromBuffer(self):		pos = self.local_tail		if len(self.buffer) - pos < glb_nsz:			pos = 0		n = pickle.loads(self.buffer[pos : pos + glb_nsz])		if n == 0:			pos = 0			n = pickle.loads(self.buffer[0 : glb_nsz])		pos += glb_nsz		obj = pickle.loads(self.buffer[pos : pos + n])		self.local_tail = pos + n		return obj 	def ProcessData(self, count):		for i in xrange(count):			obj = self.RemoveFromBuffer()			self.process_data(obj)		self.tail.value = self.local_tail		self.wait_event.set()		self.done.emit(count) # Fetch more records bar class FetchMoreRecordsBar(): 	def __init__(self, model, parent):		self.model = model 		self.label = QLabel("Number of records (x " + "{:,}".format(glb_chunk_sz) + ") to fetch:")		self.label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) 		self.fetch_count = QSpinBox()		self.fetch_count.setRange(1, 1000000)		self.fetch_count.setValue(10)		self.fetch_count.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) 		self.fetch = QPushButton("Go!")		self.fetch.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)		self.fetch.released.connect(self.FetchMoreRecords) 		self.progress = QProgressBar()		self.progress.setRange(0, 100)		self.progress.hide() 		self.done_label = QLabel("All records fetched")		self.done_label.hide() 		self.spacer = QLabel("") 		self.close_button = QToolButton()		self.close_button.setIcon(parent.style().standardIcon(QStyle.SP_DockWidgetCloseButton))		self.close_button.released.connect(self.Deactivate) 		self.hbox = QHBoxLayout()		self.hbox.setContentsMargins(0, 0, 0, 0) 		self.hbox.addWidget(self.label)		self.hbox.addWidget(self.fetch_count)		self.hbox.addWidget(self.fetch)		self.hbox.addWidget(self.spacer)		self.hbox.addWidget(self.progress)		self.hbox.addWidget(self.done_label)		self.hbox.addWidget(self.close_button) 		self.bar = QWidget()		self.bar.setLayout(self.hbox)		self.bar.show() 		self.in_progress = False		self.model.progress.connect(self.Progress) 		self.done = False 		if not model.HasMoreRecords():			self.Done() 	def Widget(self):		return self.bar 	def Activate(self):		self.bar.show()		self.fetch.setFocus() 	def Deactivate(self):		self.bar.hide() 	def Enable(self, enable):		self.fetch.setEnabled(enable)		self.fetch_count.setEnabled(enable) 	def Busy(self):		self.Enable(False)		self.fetch.hide()		self.spacer.hide()		self.progress.show() 	def Idle(self):		self.in_progress = False		self.Enable(True)		self.progress.hide()		self.fetch.show()		self.spacer.show() 	def Target(self):		return self.fetch_count.value() * glb_chunk_sz 	def Done(self):		self.done = True		self.Idle()		self.label.hide()		self.fetch_count.hide()		self.fetch.hide()		self.spacer.hide()		self.done_label.show() 	def Progress(self, count):		if self.in_progress:			if count:				percent = ((count - self.start) * 100) / self.Target()				if percent >= 100:					self.Idle()				else:					self.progress.setValue(percent)		if not count:			# Count value of zero means no more records			self.Done() 	def FetchMoreRecords(self):		if self.done:			return		self.progress.setValue(0)		self.Busy()		self.in_progress = True		self.start = self.model.FetchMoreRecords(self.Target()) # Brance data model level two item class BranchLevelTwoItem(): 	def __init__(self, row, col, text, parent_item):		self.row = row		self.parent_item = parent_item		self.data = [""] * (col + 1)		self.data[col] = text		self.level = 2 	def getParentItem(self):		return self.parent_item 	def getRow(self):		return self.row 	def childCount(self):		return 0 	def hasChildren(self):		return False 	def getData(self, column):		return self.data[column] # Brance data model level one item class BranchLevelOneItem(): 	def __init__(self, glb, row, data, parent_item):

Lines 1001–1500 of 3588. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t