aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts/python/exported-sql-viewer.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/scripts/python/exported-sql-viewer.py')
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py340
1 files changed, 333 insertions, 7 deletions
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
index 74ef92f1d19a..affed7d149be 100755
--- a/tools/perf/scripts/python/exported-sql-viewer.py
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -456,6 +456,10 @@ class CallGraphLevelItemBase(object):
456 self.query_done = False; 456 self.query_done = False;
457 self.child_count = 0 457 self.child_count = 0
458 self.child_items = [] 458 self.child_items = []
459 if parent_item:
460 self.level = parent_item.level + 1
461 else:
462 self.level = 0
459 463
460 def getChildItem(self, row): 464 def getChildItem(self, row):
461 return self.child_items[row] 465 return self.child_items[row]
@@ -877,9 +881,14 @@ class TreeWindowBase(QMdiSubWindow):
877 super(TreeWindowBase, self).__init__(parent) 881 super(TreeWindowBase, self).__init__(parent)
878 882
879 self.model = None 883 self.model = None
880 self.view = None
881 self.find_bar = None 884 self.find_bar = None
882 885
886 self.view = QTreeView()
887 self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)
888 self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard
889
890 self.context_menu = TreeContextMenu(self.view)
891
883 def DisplayFound(self, ids): 892 def DisplayFound(self, ids):
884 if not len(ids): 893 if not len(ids):
885 return False 894 return False
@@ -921,7 +930,6 @@ class CallGraphWindow(TreeWindowBase):
921 930
922 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 931 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
923 932
924 self.view = QTreeView()
925 self.view.setModel(self.model) 933 self.view.setModel(self.model)
926 934
927 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): 935 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
@@ -944,7 +952,6 @@ class CallTreeWindow(TreeWindowBase):
944 952
945 self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 953 self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x))
946 954
947 self.view = QTreeView()
948 self.view.setModel(self.model) 955 self.view.setModel(self.model)
949 956
950 for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): 957 for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)):
@@ -1649,10 +1656,14 @@ class BranchWindow(QMdiSubWindow):
1649 1656
1650 self.view = QTreeView() 1657 self.view = QTreeView()
1651 self.view.setUniformRowHeights(True) 1658 self.view.setUniformRowHeights(True)
1659 self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)
1660 self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard
1652 self.view.setModel(self.model) 1661 self.view.setModel(self.model)
1653 1662
1654 self.ResizeColumnsToContents() 1663 self.ResizeColumnsToContents()
1655 1664
1665 self.context_menu = TreeContextMenu(self.view)
1666
1656 self.find_bar = FindBar(self, self, True) 1667 self.find_bar = FindBar(self, self, True)
1657 1668
1658 self.finder = ChildDataItemFinder(self.model.root) 1669 self.finder = ChildDataItemFinder(self.model.root)
@@ -2261,6 +2272,240 @@ class ResizeColumnsToContentsBase(QObject):
2261 self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) 2272 self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths)
2262 self.ResizeColumnsToContents() 2273 self.ResizeColumnsToContents()
2263 2274
2275# Convert value to CSV
2276
2277def ToCSValue(val):
2278 if '"' in val:
2279 val = val.replace('"', '""')
2280 if "," in val or '"' in val:
2281 val = '"' + val + '"'
2282 return val
2283
2284# Key to sort table model indexes by row / column, assuming fewer than 1000 columns
2285
2286glb_max_cols = 1000
2287
2288def RowColumnKey(a):
2289 return a.row() * glb_max_cols + a.column()
2290
2291# Copy selected table cells to clipboard
2292
2293def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False):
2294 indexes = sorted(view.selectedIndexes(), key=RowColumnKey)
2295 idx_cnt = len(indexes)
2296 if not idx_cnt:
2297 return
2298 if idx_cnt == 1:
2299 with_hdr=False
2300 min_row = indexes[0].row()
2301 max_row = indexes[0].row()
2302 min_col = indexes[0].column()
2303 max_col = indexes[0].column()
2304 for i in indexes:
2305 min_row = min(min_row, i.row())
2306 max_row = max(max_row, i.row())
2307 min_col = min(min_col, i.column())
2308 max_col = max(max_col, i.column())
2309 if max_col > glb_max_cols:
2310 raise RuntimeError("glb_max_cols is too low")
2311 max_width = [0] * (1 + max_col - min_col)
2312 for i in indexes:
2313 c = i.column() - min_col
2314 max_width[c] = max(max_width[c], len(str(i.data())))
2315 text = ""
2316 pad = ""
2317 sep = ""
2318 if with_hdr:
2319 model = indexes[0].model()
2320 for col in range(min_col, max_col + 1):
2321 val = model.headerData(col, Qt.Horizontal)
2322 if as_csv:
2323 text += sep + ToCSValue(val)
2324 sep = ","
2325 else:
2326 c = col - min_col
2327 max_width[c] = max(max_width[c], len(val))
2328 width = max_width[c]
2329 align = model.headerData(col, Qt.Horizontal, Qt.TextAlignmentRole)
2330 if align & Qt.AlignRight:
2331 val = val.rjust(width)
2332 text += pad + sep + val
2333 pad = " " * (width - len(val))
2334 sep = " "
2335 text += "\n"
2336 pad = ""
2337 sep = ""
2338 last_row = min_row
2339 for i in indexes:
2340 if i.row() > last_row:
2341 last_row = i.row()
2342 text += "\n"
2343 pad = ""
2344 sep = ""
2345 if as_csv:
2346 text += sep + ToCSValue(str(i.data()))
2347 sep = ","
2348 else:
2349 width = max_width[i.column() - min_col]
2350 if i.data(Qt.TextAlignmentRole) & Qt.AlignRight:
2351 val = str(i.data()).rjust(width)
2352 else:
2353 val = str(i.data())
2354 text += pad + sep + val
2355 pad = " " * (width - len(val))
2356 sep = " "
2357 QApplication.clipboard().setText(text)
2358
2359def CopyTreeCellsToClipboard(view, as_csv=False, with_hdr=False):
2360 indexes = view.selectedIndexes()
2361 if not len(indexes):
2362 return
2363
2364 selection = view.selectionModel()
2365
2366 first = None
2367 for i in indexes:
2368 above = view.indexAbove(i)
2369 if not selection.isSelected(above):
2370 first = i
2371 break
2372
2373 if first is None:
2374 raise RuntimeError("CopyTreeCellsToClipboard internal error")
2375
2376 model = first.model()
2377 row_cnt = 0
2378 col_cnt = model.columnCount(first)
2379 max_width = [0] * col_cnt
2380
2381 indent_sz = 2
2382 indent_str = " " * indent_sz
2383
2384 expanded_mark_sz = 2
2385 if sys.version_info[0] == 3:
2386 expanded_mark = "\u25BC "
2387 not_expanded_mark = "\u25B6 "
2388 else:
2389 expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xBC) + " ", "utf-8")
2390 not_expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xB6) + " ", "utf-8")
2391 leaf_mark = " "
2392
2393 if not as_csv:
2394 pos = first
2395 while True:
2396 row_cnt += 1
2397 row = pos.row()
2398 for c in range(col_cnt):
2399 i = pos.sibling(row, c)
2400 if c:
2401 n = len(str(i.data()))
2402 else:
2403 n = len(str(i.data()).strip())
2404 n += (i.internalPointer().level - 1) * indent_sz
2405 n += expanded_mark_sz
2406 max_width[c] = max(max_width[c], n)
2407 pos = view.indexBelow(pos)
2408 if not selection.isSelected(pos):
2409 break
2410
2411 text = ""
2412 pad = ""
2413 sep = ""
2414 if with_hdr:
2415 for c in range(col_cnt):
2416 val = model.headerData(c, Qt.Horizontal, Qt.DisplayRole).strip()
2417 if as_csv:
2418 text += sep + ToCSValue(val)
2419 sep = ","
2420 else:
2421 max_width[c] = max(max_width[c], len(val))
2422 width = max_width[c]
2423 align = model.headerData(c, Qt.Horizontal, Qt.TextAlignmentRole)
2424 if align & Qt.AlignRight:
2425 val = val.rjust(width)
2426 text += pad + sep + val
2427 pad = " " * (width - len(val))
2428 sep = " "
2429 text += "\n"
2430 pad = ""
2431 sep = ""
2432
2433 pos = first
2434 while True:
2435 row = pos.row()
2436 for c in range(col_cnt):
2437 i = pos.sibling(row, c)
2438 val = str(i.data())
2439 if not c:
2440 if model.hasChildren(i):
2441 if view.isExpanded(i):
2442 mark = expanded_mark
2443 else:
2444 mark = not_expanded_mark
2445 else:
2446 mark = leaf_mark
2447 val = indent_str * (i.internalPointer().level - 1) + mark + val.strip()
2448 if as_csv:
2449 text += sep + ToCSValue(val)
2450 sep = ","
2451 else:
2452 width = max_width[c]
2453 if c and i.data(Qt.TextAlignmentRole) & Qt.AlignRight:
2454 val = val.rjust(width)
2455 text += pad + sep + val
2456 pad = " " * (width - len(val))
2457 sep = " "
2458 pos = view.indexBelow(pos)
2459 if not selection.isSelected(pos):
2460 break
2461 text = text.rstrip() + "\n"
2462 pad = ""
2463 sep = ""
2464
2465 QApplication.clipboard().setText(text)
2466
2467def CopyCellsToClipboard(view, as_csv=False, with_hdr=False):
2468 view.CopyCellsToClipboard(view, as_csv, with_hdr)
2469
2470def CopyCellsToClipboardHdr(view):
2471 CopyCellsToClipboard(view, False, True)
2472
2473def CopyCellsToClipboardCSV(view):
2474 CopyCellsToClipboard(view, True, True)
2475
2476# Context menu
2477
2478class ContextMenu(object):
2479
2480 def __init__(self, view):
2481 self.view = view
2482 self.view.setContextMenuPolicy(Qt.CustomContextMenu)
2483 self.view.customContextMenuRequested.connect(self.ShowContextMenu)
2484
2485 def ShowContextMenu(self, pos):
2486 menu = QMenu(self.view)
2487 self.AddActions(menu)
2488 menu.exec_(self.view.mapToGlobal(pos))
2489
2490 def AddCopy(self, menu):
2491 menu.addAction(CreateAction("&Copy selection", "Copy to clipboard", lambda: CopyCellsToClipboardHdr(self.view), self.view))
2492 menu.addAction(CreateAction("Copy selection as CS&V", "Copy to clipboard as CSV", lambda: CopyCellsToClipboardCSV(self.view), self.view))
2493
2494 def AddActions(self, menu):
2495 self.AddCopy(menu)
2496
2497class TreeContextMenu(ContextMenu):
2498
2499 def __init__(self, view):
2500 super(TreeContextMenu, self).__init__(view)
2501
2502 def AddActions(self, menu):
2503 i = self.view.currentIndex()
2504 text = str(i.data()).strip()
2505 if len(text):
2506 menu.addAction(CreateAction('Copy "' + text + '"', "Copy to clipboard", lambda: QApplication.clipboard().setText(text), self.view))
2507 self.AddCopy(menu)
2508
2264# Table window 2509# Table window
2265 2510
2266class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): 2511class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
@@ -2279,9 +2524,13 @@ class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
2279 self.view.verticalHeader().setVisible(False) 2524 self.view.verticalHeader().setVisible(False)
2280 self.view.sortByColumn(-1, Qt.AscendingOrder) 2525 self.view.sortByColumn(-1, Qt.AscendingOrder)
2281 self.view.setSortingEnabled(True) 2526 self.view.setSortingEnabled(True)
2527 self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)
2528 self.view.CopyCellsToClipboard = CopyTableCellsToClipboard
2282 2529
2283 self.ResizeColumnsToContents() 2530 self.ResizeColumnsToContents()
2284 2531
2532 self.context_menu = ContextMenu(self.view)
2533
2285 self.find_bar = FindBar(self, self, True) 2534 self.find_bar = FindBar(self, self, True)
2286 2535
2287 self.finder = ChildDataItemFinder(self.data_model) 2536 self.finder = ChildDataItemFinder(self.data_model)
@@ -2395,6 +2644,10 @@ class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
2395 self.view.setModel(self.model) 2644 self.view.setModel(self.model)
2396 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) 2645 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
2397 self.view.verticalHeader().setVisible(False) 2646 self.view.verticalHeader().setVisible(False)
2647 self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)
2648 self.view.CopyCellsToClipboard = CopyTableCellsToClipboard
2649
2650 self.context_menu = ContextMenu(self.view)
2398 2651
2399 self.ResizeColumnsToContents() 2652 self.ResizeColumnsToContents()
2400 2653
@@ -2660,6 +2913,60 @@ class HelpOnlyWindow(QMainWindow):
2660 2913
2661 self.setCentralWidget(self.text) 2914 self.setCentralWidget(self.text)
2662 2915
2916# PostqreSQL server version
2917
2918def PostqreSQLServerVersion(db):
2919 query = QSqlQuery(db)
2920 QueryExec(query, "SELECT VERSION()")
2921 if query.next():
2922 v_str = query.value(0)
2923 v_list = v_str.strip().split(" ")
2924 if v_list[0] == "PostgreSQL" and v_list[2] == "on":
2925 return v_list[1]
2926 return v_str
2927 return "Unknown"
2928
2929# SQLite version
2930
2931def SQLiteVersion(db):
2932 query = QSqlQuery(db)
2933 QueryExec(query, "SELECT sqlite_version()")
2934 if query.next():
2935 return query.value(0)
2936 return "Unknown"
2937
2938# About dialog
2939
2940class AboutDialog(QDialog):
2941
2942 def __init__(self, glb, parent=None):
2943 super(AboutDialog, self).__init__(parent)
2944
2945 self.setWindowTitle("About Exported SQL Viewer")
2946 self.setMinimumWidth(300)
2947
2948 pyside_version = "1" if pyside_version_1 else "2"
2949
2950 text = "<pre>"
2951 text += "Python version: " + sys.version.split(" ")[0] + "\n"
2952 text += "PySide version: " + pyside_version + "\n"
2953 text += "Qt version: " + qVersion() + "\n"
2954 if glb.dbref.is_sqlite3:
2955 text += "SQLite version: " + SQLiteVersion(glb.db) + "\n"
2956 else:
2957 text += "PostqreSQL version: " + PostqreSQLServerVersion(glb.db) + "\n"
2958 text += "</pre>"
2959
2960 self.text = QTextBrowser()
2961 self.text.setHtml(text)
2962 self.text.setReadOnly(True)
2963 self.text.setOpenExternalLinks(True)
2964
2965 self.vbox = QVBoxLayout()
2966 self.vbox.addWidget(self.text)
2967
2968 self.setLayout(self.vbox);
2969
2663# Font resize 2970# Font resize
2664 2971
2665def ResizeFont(widget, diff): 2972def ResizeFont(widget, diff):
@@ -2732,6 +3039,8 @@ class MainWindow(QMainWindow):
2732 file_menu.addAction(CreateExitAction(glb.app, self)) 3039 file_menu.addAction(CreateExitAction(glb.app, self))
2733 3040
2734 edit_menu = menu.addMenu("&Edit") 3041 edit_menu = menu.addMenu("&Edit")
3042 edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy))
3043 edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self))
2735 edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) 3044 edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find))
2736 edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) 3045 edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)]))
2737 edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) 3046 edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")]))
@@ -2755,6 +3064,21 @@ class MainWindow(QMainWindow):
2755 3064
2756 help_menu = menu.addMenu("&Help") 3065 help_menu = menu.addMenu("&Help")
2757 help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) 3066 help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents))
3067 help_menu.addAction(CreateAction("&About Exported SQL Viewer", "About this application", self.About, self))
3068
3069 def Try(self, fn):
3070 win = self.mdi_area.activeSubWindow()
3071 if win:
3072 try:
3073 fn(win.view)
3074 except:
3075 pass
3076
3077 def CopyToClipboard(self):
3078 self.Try(CopyCellsToClipboardHdr)
3079
3080 def CopyToClipboardCSV(self):
3081 self.Try(CopyCellsToClipboardCSV)
2758 3082
2759 def Find(self): 3083 def Find(self):
2760 win = self.mdi_area.activeSubWindow() 3084 win = self.mdi_area.activeSubWindow()
@@ -2773,12 +3097,10 @@ class MainWindow(QMainWindow):
2773 pass 3097 pass
2774 3098
2775 def ShrinkFont(self): 3099 def ShrinkFont(self):
2776 win = self.mdi_area.activeSubWindow() 3100 self.Try(ShrinkFont)
2777 ShrinkFont(win.view)
2778 3101
2779 def EnlargeFont(self): 3102 def EnlargeFont(self):
2780 win = self.mdi_area.activeSubWindow() 3103 self.Try(EnlargeFont)
2781 EnlargeFont(win.view)
2782 3104
2783 def EventMenu(self, events, reports_menu): 3105 def EventMenu(self, events, reports_menu):
2784 branches_events = 0 3106 branches_events = 0
@@ -2828,6 +3150,10 @@ class MainWindow(QMainWindow):
2828 def Help(self): 3150 def Help(self):
2829 HelpWindow(self.glb, self) 3151 HelpWindow(self.glb, self)
2830 3152
3153 def About(self):
3154 dialog = AboutDialog(self.glb, self)
3155 dialog.exec_()
3156
2831# XED Disassembler 3157# XED Disassembler
2832 3158
2833class xed_state_t(Structure): 3159class xed_state_t(Structure):