diff options
Diffstat (limited to 'tools/perf/scripts/python/exported-sql-viewer.py')
-rwxr-xr-x | tools/perf/scripts/python/exported-sql-viewer.py | 217 |
1 files changed, 217 insertions, 0 deletions
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): | |||
884 | self.find_bar = None | 884 | self.find_bar = None |
885 | 885 | ||
886 | self.view = QTreeView() | 886 | self.view = QTreeView() |
887 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
888 | self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard | ||
887 | 889 | ||
888 | def DisplayFound(self, ids): | 890 | def DisplayFound(self, ids): |
889 | if not len(ids): | 891 | if not len(ids): |
@@ -1652,6 +1654,8 @@ class BranchWindow(QMdiSubWindow): | |||
1652 | 1654 | ||
1653 | self.view = QTreeView() | 1655 | self.view = QTreeView() |
1654 | self.view.setUniformRowHeights(True) | 1656 | self.view.setUniformRowHeights(True) |
1657 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
1658 | self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard | ||
1655 | self.view.setModel(self.model) | 1659 | self.view.setModel(self.model) |
1656 | 1660 | ||
1657 | self.ResizeColumnsToContents() | 1661 | self.ResizeColumnsToContents() |
@@ -2264,6 +2268,207 @@ class ResizeColumnsToContentsBase(QObject): | |||
2264 | self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) | 2268 | self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) |
2265 | self.ResizeColumnsToContents() | 2269 | self.ResizeColumnsToContents() |
2266 | 2270 | ||
2271 | # Convert value to CSV | ||
2272 | |||
2273 | def ToCSValue(val): | ||
2274 | if '"' in val: | ||
2275 | val = val.replace('"', '""') | ||
2276 | if "," in val or '"' in val: | ||
2277 | val = '"' + val + '"' | ||
2278 | return val | ||
2279 | |||
2280 | # Key to sort table model indexes by row / column, assuming fewer than 1000 columns | ||
2281 | |||
2282 | glb_max_cols = 1000 | ||
2283 | |||
2284 | def RowColumnKey(a): | ||
2285 | return a.row() * glb_max_cols + a.column() | ||
2286 | |||
2287 | # Copy selected table cells to clipboard | ||
2288 | |||
2289 | def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
2290 | indexes = sorted(view.selectedIndexes(), key=RowColumnKey) | ||
2291 | idx_cnt = len(indexes) | ||
2292 | if not idx_cnt: | ||
2293 | return | ||
2294 | if idx_cnt == 1: | ||
2295 | with_hdr=False | ||
2296 | min_row = indexes[0].row() | ||
2297 | max_row = indexes[0].row() | ||
2298 | min_col = indexes[0].column() | ||
2299 | max_col = indexes[0].column() | ||
2300 | for i in indexes: | ||
2301 | min_row = min(min_row, i.row()) | ||
2302 | max_row = max(max_row, i.row()) | ||
2303 | min_col = min(min_col, i.column()) | ||
2304 | max_col = max(max_col, i.column()) | ||
2305 | if max_col > glb_max_cols: | ||
2306 | raise RuntimeError("glb_max_cols is too low") | ||
2307 | max_width = [0] * (1 + max_col - min_col) | ||
2308 | for i in indexes: | ||
2309 | c = i.column() - min_col | ||
2310 | max_width[c] = max(max_width[c], len(str(i.data()))) | ||
2311 | text = "" | ||
2312 | pad = "" | ||
2313 | sep = "" | ||
2314 | if with_hdr: | ||
2315 | model = indexes[0].model() | ||
2316 | for col in range(min_col, max_col + 1): | ||
2317 | val = model.headerData(col, Qt.Horizontal) | ||
2318 | if as_csv: | ||
2319 | text += sep + ToCSValue(val) | ||
2320 | sep = "," | ||
2321 | else: | ||
2322 | c = col - min_col | ||
2323 | max_width[c] = max(max_width[c], len(val)) | ||
2324 | width = max_width[c] | ||
2325 | align = model.headerData(col, Qt.Horizontal, Qt.TextAlignmentRole) | ||
2326 | if align & Qt.AlignRight: | ||
2327 | val = val.rjust(width) | ||
2328 | text += pad + sep + val | ||
2329 | pad = " " * (width - len(val)) | ||
2330 | sep = " " | ||
2331 | text += "\n" | ||
2332 | pad = "" | ||
2333 | sep = "" | ||
2334 | last_row = min_row | ||
2335 | for i in indexes: | ||
2336 | if i.row() > last_row: | ||
2337 | last_row = i.row() | ||
2338 | text += "\n" | ||
2339 | pad = "" | ||
2340 | sep = "" | ||
2341 | if as_csv: | ||
2342 | text += sep + ToCSValue(str(i.data())) | ||
2343 | sep = "," | ||
2344 | else: | ||
2345 | width = max_width[i.column() - min_col] | ||
2346 | if i.data(Qt.TextAlignmentRole) & Qt.AlignRight: | ||
2347 | val = str(i.data()).rjust(width) | ||
2348 | else: | ||
2349 | val = str(i.data()) | ||
2350 | text += pad + sep + val | ||
2351 | pad = " " * (width - len(val)) | ||
2352 | sep = " " | ||
2353 | QApplication.clipboard().setText(text) | ||
2354 | |||
2355 | def CopyTreeCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
2356 | indexes = view.selectedIndexes() | ||
2357 | if not len(indexes): | ||
2358 | return | ||
2359 | |||
2360 | selection = view.selectionModel() | ||
2361 | |||
2362 | first = None | ||
2363 | for i in indexes: | ||
2364 | above = view.indexAbove(i) | ||
2365 | if not selection.isSelected(above): | ||
2366 | first = i | ||
2367 | break | ||
2368 | |||
2369 | if first is None: | ||
2370 | raise RuntimeError("CopyTreeCellsToClipboard internal error") | ||
2371 | |||
2372 | model = first.model() | ||
2373 | row_cnt = 0 | ||
2374 | col_cnt = model.columnCount(first) | ||
2375 | max_width = [0] * col_cnt | ||
2376 | |||
2377 | indent_sz = 2 | ||
2378 | indent_str = " " * indent_sz | ||
2379 | |||
2380 | expanded_mark_sz = 2 | ||
2381 | if sys.version_info[0] == 3: | ||
2382 | expanded_mark = "\u25BC " | ||
2383 | not_expanded_mark = "\u25B6 " | ||
2384 | else: | ||
2385 | expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xBC) + " ", "utf-8") | ||
2386 | not_expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xB6) + " ", "utf-8") | ||
2387 | leaf_mark = " " | ||
2388 | |||
2389 | if not as_csv: | ||
2390 | pos = first | ||
2391 | while True: | ||
2392 | row_cnt += 1 | ||
2393 | row = pos.row() | ||
2394 | for c in range(col_cnt): | ||
2395 | i = pos.sibling(row, c) | ||
2396 | if c: | ||
2397 | n = len(str(i.data())) | ||
2398 | else: | ||
2399 | n = len(str(i.data()).strip()) | ||
2400 | n += (i.internalPointer().level - 1) * indent_sz | ||
2401 | n += expanded_mark_sz | ||
2402 | max_width[c] = max(max_width[c], n) | ||
2403 | pos = view.indexBelow(pos) | ||
2404 | if not selection.isSelected(pos): | ||
2405 | break | ||
2406 | |||
2407 | text = "" | ||
2408 | pad = "" | ||
2409 | sep = "" | ||
2410 | if with_hdr: | ||
2411 | for c in range(col_cnt): | ||
2412 | val = model.headerData(c, Qt.Horizontal, Qt.DisplayRole).strip() | ||
2413 | if as_csv: | ||
2414 | text += sep + ToCSValue(val) | ||
2415 | sep = "," | ||
2416 | else: | ||
2417 | max_width[c] = max(max_width[c], len(val)) | ||
2418 | width = max_width[c] | ||
2419 | align = model.headerData(c, Qt.Horizontal, Qt.TextAlignmentRole) | ||
2420 | if align & Qt.AlignRight: | ||
2421 | val = val.rjust(width) | ||
2422 | text += pad + sep + val | ||
2423 | pad = " " * (width - len(val)) | ||
2424 | sep = " " | ||
2425 | text += "\n" | ||
2426 | pad = "" | ||
2427 | sep = "" | ||
2428 | |||
2429 | pos = first | ||
2430 | while True: | ||
2431 | row = pos.row() | ||
2432 | for c in range(col_cnt): | ||
2433 | i = pos.sibling(row, c) | ||
2434 | val = str(i.data()) | ||
2435 | if not c: | ||
2436 | if model.hasChildren(i): | ||
2437 | if view.isExpanded(i): | ||
2438 | mark = expanded_mark | ||
2439 | else: | ||
2440 | mark = not_expanded_mark | ||
2441 | else: | ||
2442 | mark = leaf_mark | ||
2443 | val = indent_str * (i.internalPointer().level - 1) + mark + val.strip() | ||
2444 | if as_csv: | ||
2445 | text += sep + ToCSValue(val) | ||
2446 | sep = "," | ||
2447 | else: | ||
2448 | width = max_width[c] | ||
2449 | if c and i.data(Qt.TextAlignmentRole) & Qt.AlignRight: | ||
2450 | val = val.rjust(width) | ||
2451 | text += pad + sep + val | ||
2452 | pad = " " * (width - len(val)) | ||
2453 | sep = " " | ||
2454 | pos = view.indexBelow(pos) | ||
2455 | if not selection.isSelected(pos): | ||
2456 | break | ||
2457 | text = text.rstrip() + "\n" | ||
2458 | pad = "" | ||
2459 | sep = "" | ||
2460 | |||
2461 | QApplication.clipboard().setText(text) | ||
2462 | |||
2463 | def CopyCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
2464 | view.CopyCellsToClipboard(view, as_csv, with_hdr) | ||
2465 | |||
2466 | def CopyCellsToClipboardHdr(view): | ||
2467 | CopyCellsToClipboard(view, False, True) | ||
2468 | |||
2469 | def CopyCellsToClipboardCSV(view): | ||
2470 | CopyCellsToClipboard(view, True, True) | ||
2471 | |||
2267 | # Table window | 2472 | # Table window |
2268 | 2473 | ||
2269 | class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | 2474 | class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): |
@@ -2282,6 +2487,8 @@ class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | |||
2282 | self.view.verticalHeader().setVisible(False) | 2487 | self.view.verticalHeader().setVisible(False) |
2283 | self.view.sortByColumn(-1, Qt.AscendingOrder) | 2488 | self.view.sortByColumn(-1, Qt.AscendingOrder) |
2284 | self.view.setSortingEnabled(True) | 2489 | self.view.setSortingEnabled(True) |
2490 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
2491 | self.view.CopyCellsToClipboard = CopyTableCellsToClipboard | ||
2285 | 2492 | ||
2286 | self.ResizeColumnsToContents() | 2493 | self.ResizeColumnsToContents() |
2287 | 2494 | ||
@@ -2398,6 +2605,8 @@ class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | |||
2398 | self.view.setModel(self.model) | 2605 | self.view.setModel(self.model) |
2399 | self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) | 2606 | self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) |
2400 | self.view.verticalHeader().setVisible(False) | 2607 | self.view.verticalHeader().setVisible(False) |
2608 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
2609 | self.view.CopyCellsToClipboard = CopyTableCellsToClipboard | ||
2401 | 2610 | ||
2402 | self.ResizeColumnsToContents() | 2611 | self.ResizeColumnsToContents() |
2403 | 2612 | ||
@@ -2735,6 +2944,8 @@ class MainWindow(QMainWindow): | |||
2735 | file_menu.addAction(CreateExitAction(glb.app, self)) | 2944 | file_menu.addAction(CreateExitAction(glb.app, self)) |
2736 | 2945 | ||
2737 | edit_menu = menu.addMenu("&Edit") | 2946 | edit_menu = menu.addMenu("&Edit") |
2947 | edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy)) | ||
2948 | edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self)) | ||
2738 | edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) | 2949 | edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) |
2739 | edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) | 2950 | edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) |
2740 | edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) | 2951 | edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) |
@@ -2767,6 +2978,12 @@ class MainWindow(QMainWindow): | |||
2767 | except: | 2978 | except: |
2768 | pass | 2979 | pass |
2769 | 2980 | ||
2981 | def CopyToClipboard(self): | ||
2982 | self.Try(CopyCellsToClipboardHdr) | ||
2983 | |||
2984 | def CopyToClipboardCSV(self): | ||
2985 | self.Try(CopyCellsToClipboardCSV) | ||
2986 | |||
2770 | def Find(self): | 2987 | def Find(self): |
2771 | win = self.mdi_area.activeSubWindow() | 2988 | win = self.mdi_area.activeSubWindow() |
2772 | if win: | 2989 | if win: |