diff options
Diffstat (limited to 'tools/perf/scripts/python/exported-sql-viewer.py')
| -rwxr-xr-x | tools/perf/scripts/python/exported-sql-viewer.py | 340 |
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 | |||
| 2277 | def 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 | |||
| 2286 | glb_max_cols = 1000 | ||
| 2287 | |||
| 2288 | def RowColumnKey(a): | ||
| 2289 | return a.row() * glb_max_cols + a.column() | ||
| 2290 | |||
| 2291 | # Copy selected table cells to clipboard | ||
| 2292 | |||
| 2293 | def 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 | |||
| 2359 | def 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 | |||
| 2467 | def CopyCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
| 2468 | view.CopyCellsToClipboard(view, as_csv, with_hdr) | ||
| 2469 | |||
| 2470 | def CopyCellsToClipboardHdr(view): | ||
| 2471 | CopyCellsToClipboard(view, False, True) | ||
| 2472 | |||
| 2473 | def CopyCellsToClipboardCSV(view): | ||
| 2474 | CopyCellsToClipboard(view, True, True) | ||
| 2475 | |||
| 2476 | # Context menu | ||
| 2477 | |||
| 2478 | class 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 | |||
| 2497 | class 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 | ||
| 2266 | class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | 2511 | class 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 | |||
| 2918 | def 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 | |||
| 2931 | def 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 | |||
| 2940 | class 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 | ||
| 2665 | def ResizeFont(widget, diff): | 2972 | def 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 | ||
| 2833 | class xed_state_t(Structure): | 3159 | class xed_state_t(Structure): |
