From 6e4b1cac30d297718218dc268199ed20df074b98 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 9 Apr 2019 09:25:57 +0300 Subject: perf scripts python: export-to-sqlite.py: Fix use of parent_id in calls_view Fix following error using calls_view: Query failed: ambiguous column name: parent_id Unable to execute statement Signed-off-by: Adrian Hunter Cc: Jiri Olsa Fixes: 8ce9a7251d11 ("perf scripts python: export-to-sqlite.py: Export calls parent_id") Link: http://lkml.kernel.org/r/20190409062557.26138-1-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-sqlite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index 3b71902a5a21..bf271fbc3a88 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py @@ -331,7 +331,7 @@ if perf_db_export_calls: 'return_id,' 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 'parent_call_path_id,' - 'parent_id' + 'calls.parent_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') do_query(query, 'CREATE VIEW samples_view AS ' -- cgit From be6e747136a4dc8aad99259e47fd6f7362a43996 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:24 +0300 Subject: perf scripts python: exported-sql-viewer.py: Move view creation As preparation for adding support for copying to clipboard, create view in TreeWindowBase instead of derived classes. Committer testing: Tested using an old .db used to test some older patches: $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db Nothing breaks. Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 74ef92f1d19a..db4655168ab1 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -877,9 +877,10 @@ class TreeWindowBase(QMdiSubWindow): super(TreeWindowBase, self).__init__(parent) self.model = None - self.view = None self.find_bar = None + self.view = QTreeView() + def DisplayFound(self, ids): if not len(ids): return False @@ -921,7 +922,6 @@ class CallGraphWindow(TreeWindowBase): self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) - self.view = QTreeView() self.view.setModel(self.model) for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): @@ -944,7 +944,6 @@ class CallTreeWindow(TreeWindowBase): self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) - self.view = QTreeView() self.view.setModel(self.model) for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): -- cgit From 4b2084537e5f3b58337bce894391fb63bf3b0e28 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:23 +0300 Subject: perf scripts python: exported-sql-viewer.py: Fix error when shrinking / enlarging font Fix the following error if shrink / enlarge font is used with the help window. Traceback (most recent call last): File "tools/perf/scripts/python/exported-sql-viewer.py", line 2791, in ShrinkFont ShrinkFont(win.view) AttributeError: 'HelpWindow' object has no attribute 'view' Committer testing: Before, matches above output: $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db Traceback (most recent call last): File "/home/acme/libexec/perf-core/scripts/python/exported-sql-viewer.py", line 2780, in EnlargeFont EnlargeFont(win.view) AttributeError: 'HelpWindow' object has no attribute 'view' $ After: No more tracebacks, but the fonts don't get enlarged, which is kinda frustrating... Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-2-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index db4655168ab1..fd073e4af8da 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -2755,6 +2755,14 @@ class MainWindow(QMainWindow): help_menu = menu.addMenu("&Help") help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) + def Try(self, fn): + win = self.mdi_area.activeSubWindow() + if win: + try: + fn(win.view) + except: + pass + def Find(self): win = self.mdi_area.activeSubWindow() if win: @@ -2772,12 +2780,10 @@ class MainWindow(QMainWindow): pass def ShrinkFont(self): - win = self.mdi_area.activeSubWindow() - ShrinkFont(win.view) + self.Try(ShrinkFont) def EnlargeFont(self): - win = self.mdi_area.activeSubWindow() - EnlargeFont(win.view) + self.Try(EnlargeFont) def EventMenu(self, events, reports_menu): branches_events = 0 -- cgit From 3ac641f4acd66c109b74f108f8a61f2905702b10 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:25 +0300 Subject: perf scripts python: exported-sql-viewer.py: Add tree level As preparation for adding support for copying to clipboard, keep track of what level each item is in tree items. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-4-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index fd073e4af8da..48953257a1f0 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): self.query_done = False; self.child_count = 0 self.child_items = [] + if parent_item: + self.level = parent_item.level + 1 + else: + self.level = 0 def getChildItem(self, row): return self.child_items[row] -- cgit From 96c43b9a7ab3b70bc35d762f7b76082dfd118a6a Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:26 +0300 Subject: perf scripts python: exported-sql-viewer.py: Add copy to clipboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for copying to clipboard. Two menu options are added to copy the selected rows / columns with normal spacing, or as comma-separated-values. In the case of trees, only entire rows can be copied. Comitter testing: $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db Select the lines, press control+C and on the same terminal, press control+shift+V and voilà: Call Path Object Count Time (ns) Time (%) Branch Count Branch Count (%) ▼ 14503:14503 ▼ _start ld-2.28.so 1 156267 100.0 10602 100.0 unknown unknown 1 2276 1.5 1 0.0 ▼ _dl_start ld-2.28.so 1 137047 87.7 10088 95.2 ▶ unknown unknown 4 4127 3.0 4 0.0 _dl_setup_hash ld-2.28.so 1 0 0.0 1 0.0 ▶ _dl_sysdep_start ld-2.28.so 1 131342 95.8 9981 98.9 ▼ _dl_init ld-2.28.so 1 9142 5.9 326 3.1 ▼ call_init.part.0 ld-2.28.so 3 9133 99.9 319 97.9 ▶ _init libc-2.28.so 1 6877 75.3 110 34.5 ▶ check_stdfiles_vtables libc-2.28.so 1 76 0.8 2 0.6 ▶ init_cacheinfo libc-2.28.so 1 1991 21.8 197 61.8 ▶ _start simple-retpoline 1 7457 4.8 182 1.7 Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-5-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 217 +++++++++++++++++++++++ 1 file changed, 217 insertions(+) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 48953257a1f0..baa2b220238a 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -884,6 +884,8 @@ class TreeWindowBase(QMdiSubWindow): self.find_bar = None self.view = QTreeView() + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) + self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard def DisplayFound(self, ids): if not len(ids): @@ -1652,6 +1654,8 @@ class BranchWindow(QMdiSubWindow): self.view = QTreeView() self.view.setUniformRowHeights(True) + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) + self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard self.view.setModel(self.model) self.ResizeColumnsToContents() @@ -2264,6 +2268,207 @@ class ResizeColumnsToContentsBase(QObject): self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) self.ResizeColumnsToContents() +# Convert value to CSV + +def ToCSValue(val): + if '"' in val: + val = val.replace('"', '""') + if "," in val or '"' in val: + val = '"' + val + '"' + return val + +# Key to sort table model indexes by row / column, assuming fewer than 1000 columns + +glb_max_cols = 1000 + +def RowColumnKey(a): + return a.row() * glb_max_cols + a.column() + +# Copy selected table cells to clipboard + +def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False): + indexes = sorted(view.selectedIndexes(), key=RowColumnKey) + idx_cnt = len(indexes) + if not idx_cnt: + return + if idx_cnt == 1: + with_hdr=False + min_row = indexes[0].row() + max_row = indexes[0].row() + min_col = indexes[0].column() + max_col = indexes[0].column() + for i in indexes: + min_row = min(min_row, i.row()) + max_row = max(max_row, i.row()) + min_col = min(min_col, i.column()) + max_col = max(max_col, i.column()) + if max_col > glb_max_cols: + raise RuntimeError("glb_max_cols is too low") + max_width = [0] * (1 + max_col - min_col) + for i in indexes: + c = i.column() - min_col + max_width[c] = max(max_width[c], len(str(i.data()))) + text = "" + pad = "" + sep = "" + if with_hdr: + model = indexes[0].model() + for col in range(min_col, max_col + 1): + val = model.headerData(col, Qt.Horizontal) + if as_csv: + text += sep + ToCSValue(val) + sep = "," + else: + c = col - min_col + max_width[c] = max(max_width[c], len(val)) + width = max_width[c] + align = model.headerData(col, Qt.Horizontal, Qt.TextAlignmentRole) + if align & Qt.AlignRight: + val = val.rjust(width) + text += pad + sep + val + pad = " " * (width - len(val)) + sep = " " + text += "\n" + pad = "" + sep = "" + last_row = min_row + for i in indexes: + if i.row() > last_row: + last_row = i.row() + text += "\n" + pad = "" + sep = "" + if as_csv: + text += sep + ToCSValue(str(i.data())) + sep = "," + else: + width = max_width[i.column() - min_col] + if i.data(Qt.TextAlignmentRole) & Qt.AlignRight: + val = str(i.data()).rjust(width) + else: + val = str(i.data()) + text += pad + sep + val + pad = " " * (width - len(val)) + sep = " " + QApplication.clipboard().setText(text) + +def CopyTreeCellsToClipboard(view, as_csv=False, with_hdr=False): + indexes = view.selectedIndexes() + if not len(indexes): + return + + selection = view.selectionModel() + + first = None + for i in indexes: + above = view.indexAbove(i) + if not selection.isSelected(above): + first = i + break + + if first is None: + raise RuntimeError("CopyTreeCellsToClipboard internal error") + + model = first.model() + row_cnt = 0 + col_cnt = model.columnCount(first) + max_width = [0] * col_cnt + + indent_sz = 2 + indent_str = " " * indent_sz + + expanded_mark_sz = 2 + if sys.version_info[0] == 3: + expanded_mark = "\u25BC " + not_expanded_mark = "\u25B6 " + else: + expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xBC) + " ", "utf-8") + not_expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xB6) + " ", "utf-8") + leaf_mark = " " + + if not as_csv: + pos = first + while True: + row_cnt += 1 + row = pos.row() + for c in range(col_cnt): + i = pos.sibling(row, c) + if c: + n = len(str(i.data())) + else: + n = len(str(i.data()).strip()) + n += (i.internalPointer().level - 1) * indent_sz + n += expanded_mark_sz + max_width[c] = max(max_width[c], n) + pos = view.indexBelow(pos) + if not selection.isSelected(pos): + break + + text = "" + pad = "" + sep = "" + if with_hdr: + for c in range(col_cnt): + val = model.headerData(c, Qt.Horizontal, Qt.DisplayRole).strip() + if as_csv: + text += sep + ToCSValue(val) + sep = "," + else: + max_width[c] = max(max_width[c], len(val)) + width = max_width[c] + align = model.headerData(c, Qt.Horizontal, Qt.TextAlignmentRole) + if align & Qt.AlignRight: + val = val.rjust(width) + text += pad + sep + val + pad = " " * (width - len(val)) + sep = " " + text += "\n" + pad = "" + sep = "" + + pos = first + while True: + row = pos.row() + for c in range(col_cnt): + i = pos.sibling(row, c) + val = str(i.data()) + if not c: + if model.hasChildren(i): + if view.isExpanded(i): + mark = expanded_mark + else: + mark = not_expanded_mark + else: + mark = leaf_mark + val = indent_str * (i.internalPointer().level - 1) + mark + val.strip() + if as_csv: + text += sep + ToCSValue(val) + sep = "," + else: + width = max_width[c] + if c and i.data(Qt.TextAlignmentRole) & Qt.AlignRight: + val = val.rjust(width) + text += pad + sep + val + pad = " " * (width - len(val)) + sep = " " + pos = view.indexBelow(pos) + if not selection.isSelected(pos): + break + text = text.rstrip() + "\n" + pad = "" + sep = "" + + QApplication.clipboard().setText(text) + +def CopyCellsToClipboard(view, as_csv=False, with_hdr=False): + view.CopyCellsToClipboard(view, as_csv, with_hdr) + +def CopyCellsToClipboardHdr(view): + CopyCellsToClipboard(view, False, True) + +def CopyCellsToClipboardCSV(view): + CopyCellsToClipboard(view, True, True) + # Table window class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): @@ -2282,6 +2487,8 @@ class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): self.view.verticalHeader().setVisible(False) self.view.sortByColumn(-1, Qt.AscendingOrder) self.view.setSortingEnabled(True) + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) + self.view.CopyCellsToClipboard = CopyTableCellsToClipboard self.ResizeColumnsToContents() @@ -2398,6 +2605,8 @@ class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase): self.view.setModel(self.model) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.view.verticalHeader().setVisible(False) + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) + self.view.CopyCellsToClipboard = CopyTableCellsToClipboard self.ResizeColumnsToContents() @@ -2735,6 +2944,8 @@ class MainWindow(QMainWindow): file_menu.addAction(CreateExitAction(glb.app, self)) edit_menu = menu.addMenu("&Edit") + edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy)) + edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self)) edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) @@ -2767,6 +2978,12 @@ class MainWindow(QMainWindow): except: pass + def CopyToClipboard(self): + self.Try(CopyCellsToClipboardHdr) + + def CopyToClipboardCSV(self): + self.Try(CopyCellsToClipboardCSV) + def Find(self): win = self.mdi_area.activeSubWindow() if win: -- cgit From 9bc4e4bfe6169343a8f019cd5d7843a558b78363 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:27 +0300 Subject: perf scripts python: exported-sql-viewer.py: Add context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a context menu (right-click) that provides options for copying to clipboard, including, for trees, the ability to copy only the cell under the mouse pointer. Committer testing: $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db Simply right click and pick "Copy selection", that at this point has just the first line, not expanded, then see what was copied by pressing shift+control+v on a terminal: Call Path,Object,Count,Time (ns),Time (%),Branch Count,Branch Count (%) ▶ simple-retpolin,,,,,, Ditto after expanding, i.e. the selection continues to be just one line: Call Path Object Count Time (ns) Time (%) Branch Count Branch Count (%) ▼ simple-retpolin Now select all the lines with the mouse and control+shift+v again: Call Path Object Count Time (ns) Time (%) Branch Count Branch Count (%) ▼ 14503:14503 ▼ _start ld-2.28.so 1 156267 100.0 10602 100.0 ▶ unknown unknown 1 2276 1.5 1 0.0 ▶ _dl_start ld-2.28.so 1 137047 87.7 10088 95.2 ▶ _dl_init ld-2.28.so 1 9142 5.9 326 3.1 ▼ _start simple-retpoline 1 7457 4.8 182 1.7 ▶ unknown unknown 1 805 10.8 1 0.5 ▶ __libc_start_main libc-2.28.so 1 6347 85.1 179 98.4 Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-6-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index baa2b220238a..affd80ebcae0 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -887,6 +887,8 @@ class TreeWindowBase(QMdiSubWindow): 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 @@ -1660,6 +1662,8 @@ class BranchWindow(QMdiSubWindow): self.ResizeColumnsToContents() + self.context_menu = TreeContextMenu(self.view) + self.find_bar = FindBar(self, self, True) self.finder = ChildDataItemFinder(self.model.root) @@ -2469,6 +2473,39 @@ def CopyCellsToClipboardHdr(view): def CopyCellsToClipboardCSV(view): CopyCellsToClipboard(view, True, True) +# Context menu + +class ContextMenu(object): + + def __init__(self, view): + self.view = view + self.view.setContextMenuPolicy(Qt.CustomContextMenu) + self.view.customContextMenuRequested.connect(self.ShowContextMenu) + + def ShowContextMenu(self, pos): + menu = QMenu(self.view) + self.AddActions(menu) + menu.exec_(self.view.mapToGlobal(pos)) + + def AddCopy(self, menu): + menu.addAction(CreateAction("&Copy selection", "Copy to clipboard", lambda: CopyCellsToClipboardHdr(self.view), self.view)) + menu.addAction(CreateAction("Copy selection as CS&V", "Copy to clipboard as CSV", lambda: CopyCellsToClipboardCSV(self.view), self.view)) + + def AddActions(self, menu): + self.AddCopy(menu) + +class TreeContextMenu(ContextMenu): + + def __init__(self, view): + super(TreeContextMenu, self).__init__(view) + + def AddActions(self, menu): + i = self.view.currentIndex() + text = str(i.data()).strip() + if len(text): + menu.addAction(CreateAction('Copy "' + text + '"', "Copy to clipboard", lambda: QApplication.clipboard().setText(text), self.view)) + self.AddCopy(menu) + # Table window class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): @@ -2492,6 +2529,8 @@ class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): self.ResizeColumnsToContents() + self.context_menu = ContextMenu(self.view) + self.find_bar = FindBar(self, self, True) self.finder = ChildDataItemFinder(self.data_model) @@ -2608,6 +2647,8 @@ class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase): self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) self.view.CopyCellsToClipboard = CopyTableCellsToClipboard + self.context_menu = ContextMenu(self.view) + self.ResizeColumnsToContents() self.find_bar = FindBar(self, self, True) -- cgit From b62d18aba1109506c1926ab7b564c4ac3bd48786 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 3 May 2019 15:08:28 +0300 Subject: perf scripts python: exported-sql-viewer.py: Add 'About' dialog box With support for Python 2 or 3 and PySide 1 or 2 (Qt 4 or 5), it is useful to see what versions are in use. Add an 'About' dialog box that displays Python, PySide, Qt and database server (SQLite or PostgreSQL) version numbers. Committer testing: $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db Then go to 'Help', then 'About', select all the lines with the mouse press 'Control+C', then, on the same terminal press control+shift+V which shows my current environment: Python version: 2.7.16 PySide version: 1 Qt version: 4.8.7 SQLite version: 3.26.0 Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190503120828.25326-7-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index affd80ebcae0..affed7d149be 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -2913,6 +2913,60 @@ class HelpOnlyWindow(QMainWindow): self.setCentralWidget(self.text) +# PostqreSQL server version + +def PostqreSQLServerVersion(db): + query = QSqlQuery(db) + QueryExec(query, "SELECT VERSION()") + if query.next(): + v_str = query.value(0) + v_list = v_str.strip().split(" ") + if v_list[0] == "PostgreSQL" and v_list[2] == "on": + return v_list[1] + return v_str + return "Unknown" + +# SQLite version + +def SQLiteVersion(db): + query = QSqlQuery(db) + QueryExec(query, "SELECT sqlite_version()") + if query.next(): + return query.value(0) + return "Unknown" + +# About dialog + +class AboutDialog(QDialog): + + def __init__(self, glb, parent=None): + super(AboutDialog, self).__init__(parent) + + self.setWindowTitle("About Exported SQL Viewer") + self.setMinimumWidth(300) + + pyside_version = "1" if pyside_version_1 else "2" + + text = "
"
+		text += "Python version:     " + sys.version.split(" ")[0] + "\n"
+		text += "PySide version:     " + pyside_version + "\n"
+		text += "Qt version:         " + qVersion() + "\n"
+		if glb.dbref.is_sqlite3:
+			text += "SQLite version:     " + SQLiteVersion(glb.db) + "\n"
+		else:
+			text += "PostqreSQL version: " + PostqreSQLServerVersion(glb.db) + "\n"
+		text += "
" + + self.text = QTextBrowser() + self.text.setHtml(text) + self.text.setReadOnly(True) + self.text.setOpenExternalLinks(True) + + self.vbox = QVBoxLayout() + self.vbox.addWidget(self.text) + + self.setLayout(self.vbox); + # Font resize def ResizeFont(widget, diff): @@ -3010,6 +3064,7 @@ class MainWindow(QMainWindow): help_menu = menu.addMenu("&Help") help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) + help_menu.addAction(CreateAction("&About Exported SQL Viewer", "About this application", self.About, self)) def Try(self, fn): win = self.mdi_area.activeSubWindow() @@ -3095,6 +3150,10 @@ class MainWindow(QMainWindow): def Help(self): HelpWindow(self.glb, self) + def About(self): + dialog = AboutDialog(self.glb, self) + dialog.exec_() + # XED Disassembler class xed_state_t(Structure): -- cgit From 1a59d1b8e05ea6ab45f7e18897de1ef0e6bc3da6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 27 May 2019 08:55:05 +0200 Subject: treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version this program is distributed in the hope that it will be useful but without any warranty without even the implied warranty of merchantability or fitness for a particular purpose see the gnu general public license for more details you should have received a copy of the gnu general public license along with this program if not write to the free software foundation inc 59 temple place suite 330 boston ma 02111 1307 usa extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 1334 file(s). Signed-off-by: Thomas Gleixner Reviewed-by: Allison Randal Reviewed-by: Richard Fontana Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070033.113240726@linutronix.de Signed-off-by: Greg Kroah-Hartman --- tools/perf/scripts/python/Perf-Trace-Util/Context.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c index 1a0d27757eec..217568bc29ce 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c +++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c @@ -1,22 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Context.c. Python interfaces for perf script. * * Copyright (C) 2010 Tom Zanussi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include -- cgit