Stefan Schuermans commited on 2026-03-03 19:57:52
Showing 2 changed files, with 246 additions and 301 deletions.
| ... | ... |
@@ -1,7 +1,6 @@ |
| 1 | 1 |
<?xml version="1.0" encoding="UTF-8"?> |
| 2 |
-<!-- Generated with glade 3.22.1 --> |
|
| 3 | 2 |
<interface> |
| 4 |
- <requires lib="gtk+" version="3.20"/> |
|
| 3 |
+ <requires lib="gtk" version="4.0"/> |
|
| 5 | 4 |
<object class="GtkTreeStore" id="DetailsTree"> |
| 6 | 5 |
<columns> |
| 7 | 6 |
<!-- column-name proc_id --> |
| ... | ... |
@@ -48,80 +47,36 @@ |
| 48 | 47 |
<column type="gchararray"/> |
| 49 | 48 |
</columns> |
| 50 | 49 |
</object> |
| 51 |
- <object class="GtkWindow" id="Application"> |
|
| 52 |
- <property name="visible">True</property> |
|
| 53 |
- <property name="can_focus">False</property> |
|
| 54 |
- <signal name="destroy" handler="onDestroy" swapped="no"/> |
|
| 55 |
- <child> |
|
| 56 |
- <placeholder/> |
|
| 57 |
- </child> |
|
| 58 |
- <child> |
|
| 59 |
- <object class="GtkOverlay"> |
|
| 60 |
- <property name="visible">True</property> |
|
| 61 |
- <property name="can_focus">False</property> |
|
| 50 |
+ <object class="GtkOverlay" id="MainOverlay"> |
|
| 62 | 51 |
<child> |
| 63 | 52 |
<object class="GtkBox" id="TopVBox"> |
| 64 |
- <property name="visible">True</property> |
|
| 65 |
- <property name="can_focus">False</property> |
|
| 66 | 53 |
<property name="orientation">vertical</property> |
| 67 | 54 |
<child> |
| 68 |
- <object class="GtkButtonBox" id="ButtonBox"> |
|
| 69 |
- <property name="visible">True</property> |
|
| 70 |
- <property name="can_focus">False</property> |
|
| 71 |
- <property name="layout_style">start</property> |
|
| 55 |
+ <object class="GtkBox" id="ButtonBox"> |
|
| 72 | 56 |
<child> |
| 73 | 57 |
<object class="GtkToggleButton" id="TreeToggle"> |
| 74 | 58 |
<property name="label" translatable="yes">Tree</property> |
| 75 |
- <property name="visible">True</property> |
|
| 76 |
- <property name="can_focus">True</property> |
|
| 77 |
- <property name="receives_default">True</property> |
|
| 78 | 59 |
<property name="active">True</property> |
| 79 |
- <signal name="toggled" handler="onTreeToggled" swapped="no"/> |
|
| 80 | 60 |
</object> |
| 81 |
- <packing> |
|
| 82 |
- <property name="expand">True</property> |
|
| 83 |
- <property name="fill">True</property> |
|
| 84 |
- <property name="position">0</property> |
|
| 85 |
- </packing> |
|
| 86 |
- </child> |
|
| 87 |
- <child> |
|
| 88 |
- <placeholder/> |
|
| 89 |
- </child> |
|
| 90 |
- <child> |
|
| 91 |
- <placeholder/> |
|
| 92 | 61 |
</child> |
| 93 | 62 |
</object> |
| 94 |
- <packing> |
|
| 95 |
- <property name="expand">False</property> |
|
| 96 |
- <property name="fill">True</property> |
|
| 97 |
- <property name="position">0</property> |
|
| 98 |
- </packing> |
|
| 99 | 63 |
</child> |
| 100 | 64 |
<child> |
| 101 | 65 |
<object class="GtkBox" id="TopHBox"> |
| 102 |
- <property name="visible">True</property> |
|
| 103 |
- <property name="can_focus">False</property> |
|
| 66 |
+ <property name="hexpand">True</property> |
|
| 67 |
+ <property name="vexpand">True</property> |
|
| 104 | 68 |
<child> |
| 105 |
- <object class="GtkScrolledWindow" id="ProcessesScoll"> |
|
| 106 |
- <property name="width_request">256</property> |
|
| 107 |
- <property name="height_request">256</property> |
|
| 108 |
- <property name="visible">True</property> |
|
| 109 |
- <property name="can_focus">True</property> |
|
| 110 |
- <property name="shadow_type">in</property> |
|
| 69 |
+ <object class="GtkScrolledWindow" id="ProcessesScroll"> |
|
| 70 |
+ <property name="hexpand">True</property> |
|
| 71 |
+ <property name="vexpand">True</property> |
|
| 72 |
+ <property name="min-content-width">256</property> |
|
| 73 |
+ <property name="min-content-height">256</property> |
|
| 111 | 74 |
<child> |
| 112 | 75 |
<object class="GtkTreeView" id="ProcessesView"> |
| 113 |
- <property name="visible">True</property> |
|
| 114 |
- <property name="can_focus">True</property> |
|
| 115 | 76 |
<property name="model">ProcessesTree</property> |
| 116 |
- <property name="rules_hint">True</property> |
|
| 117 |
- <property name="search_column">0</property> |
|
| 118 |
- <property name="fixed_height_mode">True</property> |
|
| 119 |
- <property name="enable_tree_lines">True</property> |
|
| 120 |
- <signal name="cursor-changed" handler="onProcessesCursorChanged" swapped="no"/> |
|
| 121 |
- <signal name="row-activated" handler="onProcessesRowActivated" swapped="no"/> |
|
| 122 |
- <child internal-child="selection"> |
|
| 123 |
- <object class="GtkTreeSelection"/> |
|
| 124 |
- </child> |
|
| 77 |
+ <property name="search-column">0</property> |
|
| 78 |
+ <property name="fixed-height-mode">True</property> |
|
| 79 |
+ <property name="enable-tree-lines">True</property> |
|
| 125 | 80 |
<child> |
| 126 | 81 |
<object class="GtkTreeViewColumn" id="ProcessesCommandCol"> |
| 127 | 82 |
<property name="resizable">True</property> |
| ... | ... |
@@ -129,8 +84,8 @@ |
| 129 | 84 |
<property name="title" translatable="yes">Command</property> |
| 130 | 85 |
<property name="clickable">True</property> |
| 131 | 86 |
<property name="reorderable">True</property> |
| 132 |
- <property name="sort_indicator">True</property> |
|
| 133 |
- <property name="sort_column_id">5</property> |
|
| 87 |
+ <property name="sort-indicator">True</property> |
|
| 88 |
+ <property name="sort-column-id">5</property> |
|
| 134 | 89 |
<child> |
| 135 | 90 |
<object class="GtkCellRendererText" id="ProcessesCommandText"/> |
| 136 | 91 |
<attributes> |
| ... | ... |
@@ -146,8 +101,8 @@ |
| 146 | 101 |
<property name="title" translatable="yes">Begin</property> |
| 147 | 102 |
<property name="clickable">True</property> |
| 148 | 103 |
<property name="reorderable">True</property> |
| 149 |
- <property name="sort_indicator">True</property> |
|
| 150 |
- <property name="sort_column_id">1</property> |
|
| 104 |
+ <property name="sort-indicator">True</property> |
|
| 105 |
+ <property name="sort-column-id">1</property> |
|
| 151 | 106 |
<child> |
| 152 | 107 |
<object class="GtkCellRendererText" id="ProcessesBeginText"/> |
| 153 | 108 |
<attributes> |
| ... | ... |
@@ -163,8 +118,8 @@ |
| 163 | 118 |
<property name="title" translatable="yes">End</property> |
| 164 | 119 |
<property name="clickable">True</property> |
| 165 | 120 |
<property name="reorderable">True</property> |
| 166 |
- <property name="sort_indicator">True</property> |
|
| 167 |
- <property name="sort_column_id">3</property> |
|
| 121 |
+ <property name="sort-indicator">True</property> |
|
| 122 |
+ <property name="sort-column-id">3</property> |
|
| 168 | 123 |
<child> |
| 169 | 124 |
<object class="GtkCellRendererText" id="ProcessesEndText"/> |
| 170 | 125 |
<attributes> |
| ... | ... |
@@ -180,8 +135,8 @@ |
| 180 | 135 |
<property name="title" translatable="yes">CPU Time</property> |
| 181 | 136 |
<property name="clickable">True</property> |
| 182 | 137 |
<property name="reorderable">True</property> |
| 183 |
- <property name="sort_indicator">True</property> |
|
| 184 |
- <property name="sort_column_id">6</property> |
|
| 138 |
+ <property name="sort-indicator">True</property> |
|
| 139 |
+ <property name="sort-column-id">6</property> |
|
| 185 | 140 |
<child> |
| 186 | 141 |
<object class="GtkCellRendererText" id="ProcessesCpuTimeText"/> |
| 187 | 142 |
<attributes> |
| ... | ... |
@@ -197,8 +152,8 @@ |
| 197 | 152 |
<property name="title" translatable="yes">Memory</property> |
| 198 | 153 |
<property name="clickable">True</property> |
| 199 | 154 |
<property name="reorderable">True</property> |
| 200 |
- <property name="sort_indicator">True</property> |
|
| 201 |
- <property name="sort_column_id">8</property> |
|
| 155 |
+ <property name="sort-indicator">True</property> |
|
| 156 |
+ <property name="sort-column-id">8</property> |
|
| 202 | 157 |
<child> |
| 203 | 158 |
<object class="GtkCellRendererText" id="ProcessesMemoryText"/> |
| 204 | 159 |
<attributes> |
| ... | ... |
@@ -214,8 +169,8 @@ |
| 214 | 169 |
<property name="title" translatable="yes">Page Faults</property> |
| 215 | 170 |
<property name="clickable">True</property> |
| 216 | 171 |
<property name="reorderable">True</property> |
| 217 |
- <property name="sort_indicator">True</property> |
|
| 218 |
- <property name="sort_column_id">10</property> |
|
| 172 |
+ <property name="sort-indicator">True</property> |
|
| 173 |
+ <property name="sort-column-id">10</property> |
|
| 219 | 174 |
<child> |
| 220 | 175 |
<object class="GtkCellRendererText" id="ProcessesPageFaultsText"/> |
| 221 | 176 |
<attributes> |
| ... | ... |
@@ -231,8 +186,8 @@ |
| 231 | 186 |
<property name="title" translatable="yes">File System Operations</property> |
| 232 | 187 |
<property name="clickable">True</property> |
| 233 | 188 |
<property name="reorderable">True</property> |
| 234 |
- <property name="sort_indicator">True</property> |
|
| 235 |
- <property name="sort_column_id">12</property> |
|
| 189 |
+ <property name="sort-indicator">True</property> |
|
| 190 |
+ <property name="sort-column-id">12</property> |
|
| 236 | 191 |
<child> |
| 237 | 192 |
<object class="GtkCellRendererText" id="ProcessesFileSysOpsText"/> |
| 238 | 193 |
<attributes> |
| ... | ... |
@@ -248,8 +203,8 @@ |
| 248 | 203 |
<property name="title" translatable="yes">Context Switches</property> |
| 249 | 204 |
<property name="clickable">True</property> |
| 250 | 205 |
<property name="reorderable">True</property> |
| 251 |
- <property name="sort_indicator">True</property> |
|
| 252 |
- <property name="sort_column_id">14</property> |
|
| 206 |
+ <property name="sort-indicator">True</property> |
|
| 207 |
+ <property name="sort-column-id">14</property> |
|
| 253 | 208 |
<child> |
| 254 | 209 |
<object class="GtkCellRendererText" id="ProcessesCtxSwText"/> |
| 255 | 210 |
<attributes> |
| ... | ... |
@@ -261,32 +216,19 @@ |
| 261 | 216 |
</object> |
| 262 | 217 |
</child> |
| 263 | 218 |
</object> |
| 264 |
- <packing> |
|
| 265 |
- <property name="expand">True</property> |
|
| 266 |
- <property name="fill">True</property> |
|
| 267 |
- <property name="position">0</property> |
|
| 268 |
- </packing> |
|
| 269 | 219 |
</child> |
| 270 | 220 |
<child> |
| 271 | 221 |
<object class="GtkScrolledWindow" id="DetailsScroll"> |
| 272 |
- <property name="width_request">256</property> |
|
| 273 |
- <property name="height_request">256</property> |
|
| 274 |
- <property name="visible">True</property> |
|
| 275 |
- <property name="can_focus">True</property> |
|
| 276 |
- <property name="shadow_type">in</property> |
|
| 222 |
+ <property name="hexpand">True</property> |
|
| 223 |
+ <property name="vexpand">True</property> |
|
| 224 |
+ <property name="min-content-width">256</property> |
|
| 225 |
+ <property name="min-content-height">256</property> |
|
| 277 | 226 |
<child> |
| 278 | 227 |
<object class="GtkTreeView" id="DetailsView"> |
| 279 |
- <property name="visible">True</property> |
|
| 280 |
- <property name="can_focus">True</property> |
|
| 281 | 228 |
<property name="model">DetailsTree</property> |
| 282 |
- <property name="rules_hint">True</property> |
|
| 283 |
- <property name="search_column">0</property> |
|
| 284 |
- <property name="fixed_height_mode">True</property> |
|
| 285 |
- <property name="enable_tree_lines">True</property> |
|
| 286 |
- <signal name="row-activated" handler="onDetailsRowActivated" swapped="no"/> |
|
| 287 |
- <child internal-child="selection"> |
|
| 288 |
- <object class="GtkTreeSelection"/> |
|
| 289 |
- </child> |
|
| 229 |
+ <property name="search-column">0</property> |
|
| 230 |
+ <property name="fixed-height-mode">True</property> |
|
| 231 |
+ <property name="enable-tree-lines">True</property> |
|
| 290 | 232 |
<child> |
| 291 | 233 |
<object class="GtkTreeViewColumn" id="DetailsKeyCol"> |
| 292 | 234 |
<property name="resizable">True</property> |
| ... | ... |
@@ -294,8 +236,8 @@ |
| 294 | 236 |
<property name="title" translatable="yes">Key</property> |
| 295 | 237 |
<property name="clickable">True</property> |
| 296 | 238 |
<property name="reorderable">True</property> |
| 297 |
- <property name="sort_indicator">True</property> |
|
| 298 |
- <property name="sort_column_id">1</property> |
|
| 239 |
+ <property name="sort-indicator">True</property> |
|
| 240 |
+ <property name="sort-column-id">1</property> |
|
| 299 | 241 |
<child> |
| 300 | 242 |
<object class="GtkCellRendererText" id="DetailsKeyText"/> |
| 301 | 243 |
<attributes> |
| ... | ... |
@@ -311,8 +253,8 @@ |
| 311 | 253 |
<property name="title" translatable="yes">Value</property> |
| 312 | 254 |
<property name="clickable">True</property> |
| 313 | 255 |
<property name="reorderable">True</property> |
| 314 |
- <property name="sort_indicator">True</property> |
|
| 315 |
- <property name="sort_column_id">2</property> |
|
| 256 |
+ <property name="sort-indicator">True</property> |
|
| 257 |
+ <property name="sort-column-id">2</property> |
|
| 316 | 258 |
<child> |
| 317 | 259 |
<object class="GtkCellRendererText" id="DetailsValueText"/> |
| 318 | 260 |
<attributes> |
| ... | ... |
@@ -324,76 +266,34 @@ |
| 324 | 266 |
</object> |
| 325 | 267 |
</child> |
| 326 | 268 |
</object> |
| 327 |
- <packing> |
|
| 328 |
- <property name="expand">True</property> |
|
| 329 |
- <property name="fill">True</property> |
|
| 330 |
- <property name="position">1</property> |
|
| 331 |
- </packing> |
|
| 332 | 269 |
</child> |
| 333 | 270 |
</object> |
| 334 |
- <packing> |
|
| 335 |
- <property name="expand">True</property> |
|
| 336 |
- <property name="fill">True</property> |
|
| 337 |
- <property name="position">1</property> |
|
| 338 |
- </packing> |
|
| 339 | 271 |
</child> |
| 340 | 272 |
</object> |
| 341 |
- <packing> |
|
| 342 |
- <property name="index">-1</property> |
|
| 343 |
- </packing> |
|
| 344 | 273 |
</child> |
| 345 | 274 |
<child type="overlay"> |
| 346 | 275 |
<object class="GtkRevealer" id="NotificationRevealer"> |
| 347 |
- <property name="visible">True</property> |
|
| 348 |
- <property name="can_focus">False</property> |
|
| 349 | 276 |
<property name="halign">center</property> |
| 350 | 277 |
<property name="valign">start</property> |
| 351 |
- <property name="transition_type">slide-up</property> |
|
| 278 |
+ <property name="transition-type">slide-up</property> |
|
| 352 | 279 |
<child> |
| 353 | 280 |
<object class="GtkBox"> |
| 354 |
- <property name="visible">True</property> |
|
| 355 |
- <property name="can_focus">False</property> |
|
| 356 | 281 |
<property name="halign">center</property> |
| 357 | 282 |
<property name="valign">start</property> |
| 358 | 283 |
<property name="spacing">6</property> |
| 284 |
+ <style> |
|
| 285 |
+ <class name="app-notification"/> |
|
| 286 |
+ </style> |
|
| 359 | 287 |
<child> |
| 360 | 288 |
<object class="GtkLabel" id="NotificationMessage"> |
| 361 |
- <property name="visible">True</property> |
|
| 362 |
- <property name="can_focus">False</property> |
|
| 363 |
- <property name="label" translatable="yes">Sample notification message to be |
|
| 364 |
-shown to the user</property> |
|
| 289 |
+ <property name="label" translatable="yes">notification</property> |
|
| 365 | 290 |
<property name="justify">center</property> |
| 366 | 291 |
</object> |
| 367 |
- <packing> |
|
| 368 |
- <property name="expand">False</property> |
|
| 369 |
- <property name="fill">True</property> |
|
| 370 |
- <property name="position">1</property> |
|
| 371 |
- </packing> |
|
| 372 | 292 |
</child> |
| 373 | 293 |
<child> |
| 374 | 294 |
<object class="GtkButton" id="NotificationClose"> |
| 375 |
- <property name="visible">True</property> |
|
| 376 |
- <property name="can_focus">True</property> |
|
| 377 |
- <property name="receives_default">True</property> |
|
| 378 |
- <property name="relief">none</property> |
|
| 379 |
- <signal name="clicked" handler="onNotificationClose" swapped="no"/> |
|
| 380 |
- <child> |
|
| 381 |
- <object class="GtkImage"> |
|
| 382 |
- <property name="visible">True</property> |
|
| 383 |
- <property name="can_focus">False</property> |
|
| 384 |
- <property name="icon_name">window-close-symbolic</property> |
|
| 385 |
- </object> |
|
| 386 |
- </child> |
|
| 387 |
- </object> |
|
| 388 |
- <packing> |
|
| 389 |
- <property name="expand">False</property> |
|
| 390 |
- <property name="fill">True</property> |
|
| 391 |
- <property name="position">2</property> |
|
| 392 |
- </packing> |
|
| 393 |
- </child> |
|
| 394 |
- <style> |
|
| 395 |
- <class name="app-notification"/> |
|
| 396 |
- </style> |
|
| 295 |
+ <property name="has-frame">False</property> |
|
| 296 |
+ <property name="icon-name">window-close-symbolic</property> |
|
| 397 | 297 |
</object> |
| 398 | 298 |
</child> |
| 399 | 299 |
</object> |
| ... | ... |
@@ -14,17 +14,15 @@ import time |
| 14 | 14 |
import uproctrace.gui_glade |
| 15 | 15 |
import uproctrace.processes |
| 16 | 16 |
|
| 17 |
-# pylint: disable=C0411 |
|
| 18 | 17 |
import gi |
| 19 |
-gi.require_version('Gdk', '3.0')
|
|
| 20 |
-gi.require_version('Gtk', '3.0')
|
|
| 21 |
-# pylint: disable=C0413 |
|
| 22 |
-from gi.repository import Gdk, Gtk, GLib, GObject |
|
| 23 | 18 |
|
| 24 |
-GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit) |
|
| 19 |
+gi.require_version("Gtk", "4.0")
|
|
| 20 |
+# pylint: disable=wrong-import-position |
|
| 21 |
+# pylint: disable=too-many-positional-arguments |
|
| 22 |
+from gi.repository import Gdk, Gtk, GLib |
|
| 25 | 23 |
|
| 26 | 24 |
# regular expression for an environment variable assignment |
| 27 |
-RE_ENV_VAR = re.compile(r'^(?P<name>[A-Za-z_][A-Za-z0-9_]*)=(?P<value>.*)$') |
|
| 25 |
+RE_ENV_VAR = re.compile(r"^(?P<name>[A-Za-z_][A-Za-z0-9_]*)=(?P<value>.*)$") |
|
| 28 | 26 |
|
| 29 | 27 |
|
| 30 | 28 |
def add_none(val_a: int, val_b: int) -> int: |
| ... | ... |
@@ -41,8 +39,8 @@ def cmdline2str(cmdline: list) -> str: |
| 41 | 39 |
Convert command line to string. |
| 42 | 40 |
""" |
| 43 | 41 |
if cmdline is None: |
| 44 |
- return '???' |
|
| 45 |
- return ' '.join([cmdline_str_escape(s) for s in cmdline]) |
|
| 42 |
+ return "???" |
|
| 43 |
+ return " ".join([cmdline_str_escape(s) for s in cmdline]) |
|
| 46 | 44 |
|
| 47 | 45 |
|
| 48 | 46 |
def cmdline_str_escape(string: str) -> str: |
| ... | ... |
@@ -56,9 +54,9 @@ def cmdline_str_escape(string: str) -> str: |
| 56 | 54 |
return shlex.quote(string) |
| 57 | 55 |
# variable assignment -> escape only value part |
| 58 | 56 |
# (also works if it only looks like a variable assignment) |
| 59 |
- name = match.group('name')
|
|
| 60 |
- value = shlex.quote(match.group('value'))
|
|
| 61 |
- return f'{name:s}={value:s}'
|
|
| 57 |
+ name = match.group("name")
|
|
| 58 |
+ value = shlex.quote(match.group("value"))
|
|
| 59 |
+ return f"{name:s}={value:s}"
|
|
| 62 | 60 |
|
| 63 | 61 |
|
| 64 | 62 |
def duration2str(duration: float) -> str: |
| ... | ... |
@@ -66,7 +64,7 @@ def duration2str(duration: float) -> str: |
| 66 | 64 |
Convert duration to string. |
| 67 | 65 |
""" |
| 68 | 66 |
if duration is None: |
| 69 |
- return '???' |
|
| 67 |
+ return "???" |
|
| 70 | 68 |
# split into day, hours, minutes, seconds |
| 71 | 69 |
dur_s = int(duration) |
| 72 | 70 |
dur_m = dur_s // 60 |
| ... | ... |
@@ -82,21 +80,21 @@ def duration2str(duration: float) -> str: |
| 82 | 80 |
dur_ms = dur_us // 1000 |
| 83 | 81 |
dur_us = dur_us % 1000 |
| 84 | 82 |
# assemble text |
| 85 |
- txt = '' |
|
| 83 |
+ txt = "" |
|
| 86 | 84 |
if dur_d > 0: |
| 87 |
- txt += f'{dur_d:d} d '
|
|
| 85 |
+ txt += f"{dur_d:d} d "
|
|
| 88 | 86 |
if dur_h > 0 or txt: |
| 89 |
- txt += f'{dur_h:d} h '
|
|
| 87 |
+ txt += f"{dur_h:d} h "
|
|
| 90 | 88 |
if dur_m > 0 or txt: |
| 91 |
- txt += f'{dur_m:d} m '
|
|
| 89 |
+ txt += f"{dur_m:d} m "
|
|
| 92 | 90 |
if dur_s > 0 or txt: |
| 93 |
- txt += f'{dur_s:d} s '
|
|
| 91 |
+ txt += f"{dur_s:d} s "
|
|
| 94 | 92 |
if dur_ms > 0 or txt: |
| 95 |
- txt += f'{dur_ms:d} ms '
|
|
| 93 |
+ txt += f"{dur_ms:d} ms "
|
|
| 96 | 94 |
if dur_us > 0 or txt: |
| 97 |
- txt += f'{dur_us:d} us '
|
|
| 98 |
- txt += f'{dur_ns:d} ns '
|
|
| 99 |
- txt += f'({duration:f} s)'
|
|
| 95 |
+ txt += f"{dur_us:d} us "
|
|
| 96 |
+ txt += f"{dur_ns:d} ns "
|
|
| 97 |
+ txt += f"({duration:f} s)"
|
|
| 100 | 98 |
return txt |
| 101 | 99 |
|
| 102 | 100 |
|
| ... | ... |
@@ -105,8 +103,8 @@ def int2str(val: int) -> str: |
| 105 | 103 |
Convert integer to string, support None. |
| 106 | 104 |
""" |
| 107 | 105 |
if val is None: |
| 108 |
- return '???' |
|
| 109 |
- return f'{val:d}'
|
|
| 106 |
+ return "???" |
|
| 107 |
+ return f"{val:d}"
|
|
| 110 | 108 |
|
| 111 | 109 |
|
| 112 | 110 |
def kb2str(size_kb: int) -> str: |
| ... | ... |
@@ -114,20 +112,20 @@ def kb2str(size_kb: int) -> str: |
| 114 | 112 |
Convert size in KiB to string. |
| 115 | 113 |
""" |
| 116 | 114 |
if size_kb is None: |
| 117 |
- return '???' |
|
| 115 |
+ return "???" |
|
| 118 | 116 |
# split into GiB, MiB, KiB |
| 119 | 117 |
mib = size_kb // 1024 |
| 120 | 118 |
kib = size_kb % 1024 |
| 121 | 119 |
gib = mib // 1024 |
| 122 | 120 |
mib = mib % 1024 |
| 123 | 121 |
# assemble text |
| 124 |
- txt = '' |
|
| 122 |
+ txt = "" |
|
| 125 | 123 |
if gib > 0: |
| 126 |
- txt += f'{gib:d} GiB '
|
|
| 124 |
+ txt += f"{gib:d} GiB "
|
|
| 127 | 125 |
if mib > 0 or txt: |
| 128 |
- txt += f'{mib:d} MiB '
|
|
| 129 |
- txt += f'{kib:d} KiB '
|
|
| 130 |
- txt += f'({size_kb:d} KiB)'
|
|
| 126 |
+ txt += f"{mib:d} MiB "
|
|
| 127 |
+ txt += f"{kib:d} KiB "
|
|
| 128 |
+ txt += f"({size_kb:d} KiB)"
|
|
| 131 | 129 |
return txt |
| 132 | 130 |
|
| 133 | 131 |
|
| ... | ... |
@@ -136,7 +134,7 @@ def str2str(str_or_none: str) -> str: |
| 136 | 134 |
Convert string (or None) to string. |
| 137 | 135 |
""" |
| 138 | 136 |
if str_or_none is None: |
| 139 |
- return '???' |
|
| 137 |
+ return "???" |
|
| 140 | 138 |
return str_or_none |
| 141 | 139 |
|
| 142 | 140 |
|
| ... | ... |
@@ -145,19 +143,19 @@ def timestamp2str(timestamp: float) -> str: |
| 145 | 143 |
Convert a timestamp to a human-reable time string." |
| 146 | 144 |
""" |
| 147 | 145 |
if timestamp is None: |
| 148 |
- return '???' |
|
| 146 |
+ return "???" |
|
| 149 | 147 |
sec = int(timestamp) |
| 150 | 148 |
nsec = int((timestamp - sec) * 1e9) |
| 151 |
- time_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(sec))
|
|
| 152 |
- return time_str + f'.{nsec:09d}'
|
|
| 149 |
+ time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(sec))
|
|
| 150 |
+ return time_str + f".{nsec:09d}"
|
|
| 153 | 151 |
|
| 154 | 152 |
|
| 155 |
-class UptGui: |
|
| 153 |
+class UptGui(Gtk.Application): |
|
| 156 | 154 |
""" |
| 157 | 155 |
Graphical user interface of UProcTrace. |
| 158 | 156 |
""" |
| 159 | 157 |
|
| 160 |
- # pylint: disable=R0902 |
|
| 158 |
+ # pylint: disable=too-many-instance-attributes |
|
| 161 | 159 |
|
| 162 | 160 |
DETAIL_PROC_ID = 0 |
| 163 | 161 |
DETAIL_KEY = 1 |
| ... | ... |
@@ -183,65 +181,120 @@ class UptGui: |
| 183 | 181 |
""" |
| 184 | 182 |
Construct the GUI. |
| 185 | 183 |
""" |
| 184 |
+ super().__init__() |
|
| 185 |
+ self.proto_filename = proto_filename |
|
| 186 |
+ self.builder = None |
|
| 187 |
+ self.clipboard = None |
|
| 188 |
+ self.show_processes_as_tree = None |
|
| 189 |
+ self.wid_details_tree = None |
|
| 190 |
+ self.wid_details_view = None |
|
| 191 |
+ self.wid_processes_tree = None |
|
| 192 |
+ self.wid_processes_view = None |
|
| 193 |
+ self.wid_tree_toggle = None |
|
| 194 |
+ self.notifier = None |
|
| 195 |
+ self.notifier_msg = None |
|
| 196 |
+ self.notifier_timeout = None |
|
| 197 |
+ self.window = None |
|
| 198 |
+ self.processes = None |
|
| 199 |
+ self.connect("activate", self._on_activate)
|
|
| 200 |
+ |
|
| 201 |
+ def _on_activate(self, _app): |
|
| 202 |
+ """ |
|
| 203 |
+ Application activated: build UI and show window. |
|
| 204 |
+ """ |
|
| 186 | 205 |
self.builder = Gtk.Builder() |
| 187 | 206 |
self.builder.add_from_string(uproctrace.gui_glade.DATA) |
| 188 |
- self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) |
|
| 207 |
+ self.clipboard = Gdk.Display.get_default().get_clipboard() |
|
| 189 | 208 |
self.show_processes_as_tree = True |
| 190 |
- self.wid_details_tree = self.builder.get_object('DetailsTree')
|
|
| 191 |
- self.wid_details_view = self.builder.get_object('DetailsView')
|
|
| 192 |
- self.wid_processes_tree = self.builder.get_object('ProcessesTree')
|
|
| 193 |
- self.wid_processes_view = self.builder.get_object('ProcessesView')
|
|
| 194 |
- self.wid_tree_toggle = self.builder.get_object('TreeToggle')
|
|
| 209 |
+ self.wid_details_tree = self.builder.get_object("DetailsTree")
|
|
| 210 |
+ self.wid_details_view = self.builder.get_object("DetailsView")
|
|
| 211 |
+ self.wid_processes_tree = self.builder.get_object("ProcessesTree")
|
|
| 212 |
+ self.wid_processes_view = self.builder.get_object("ProcessesView")
|
|
| 213 |
+ self.wid_tree_toggle = self.builder.get_object("TreeToggle")
|
|
| 195 | 214 |
self.notifier = self.builder.get_object("NotificationRevealer")
|
| 196 | 215 |
self.notifier_msg = self.builder.get_object("NotificationMessage")
|
| 197 | 216 |
self.notifier_timeout = None |
| 198 |
- handlers = {
|
|
| 199 |
- 'onDestroy': self.onDestroy, |
|
| 200 |
- 'onDetailsRowActivated': self.onDetailsRowActivated, |
|
| 201 |
- 'onNotificationClose': self.onNotificationClose, |
|
| 202 |
- 'onProcessesCursorChanged': self.onProcessesCursorChanged, |
|
| 203 |
- 'onProcessesRowActivated': self.onProcessesRowActivated, |
|
| 204 |
- 'onTreeToggled': self.onTreeToggled, |
|
| 205 |
- } |
|
| 206 |
- self.builder.connect_signals(handlers) |
|
| 217 |
+ # connect signals manually (GTK4 has no builder.connect_signals) |
|
| 218 |
+ self.wid_details_view.connect("row-activated", self.onDetailsRowActivated)
|
|
| 219 |
+ self.wid_processes_view.connect("cursor-changed", self.onProcessesCursorChanged)
|
|
| 220 |
+ self.wid_processes_view.connect("row-activated", self.onProcessesRowActivated)
|
|
| 221 |
+ self.wid_tree_toggle.connect("toggled", self.onTreeToggled)
|
|
| 222 |
+ close_btn = self.builder.get_object("NotificationClose")
|
|
| 223 |
+ close_btn.connect("clicked", self.onNotificationClose)
|
|
| 224 |
+ # create application window |
|
| 225 |
+ self.window = Gtk.ApplicationWindow(application=self) |
|
| 226 |
+ overlay = self.builder.get_object("MainOverlay")
|
|
| 227 |
+ self.window.set_child(overlay) |
|
| 228 |
+ # handle SIGINT |
|
| 229 |
+ GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.quit) |
|
| 207 | 230 |
# open trace file |
| 208 |
- self.openTrace(proto_filename) |
|
| 231 |
+ self.openTrace(self.proto_filename) |
|
| 232 |
+ # show window |
|
| 233 |
+ self.window.present() |
|
| 209 | 234 |
|
| 210 |
- def fillProcessesEntry(self, proc_iter, |
|
| 211 |
- proc: uproctrace.processes.Process): |
|
| 235 |
+ def fillProcessesEntry(self, proc_iter, proc: uproctrace.processes.Process): |
|
| 212 | 236 |
""" |
| 213 | 237 |
Fill attributes of processes tree entry. |
| 214 | 238 |
proc_iter: process tree entry |
| 215 | 239 |
proc: process object |
| 216 | 240 |
""" |
| 217 |
- self.wid_processes_tree.set_value(proc_iter, self.PROC_PROC_ID, |
|
| 218 |
- proc.proc_id) |
|
| 219 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_BEGIN_TIMESTAMP, |
|
| 241 |
+ self.wid_processes_tree.set_value(proc_iter, self.PROC_PROC_ID, proc.proc_id) |
|
| 242 |
+ self.fillProcessesEntryAttr( |
|
| 243 |
+ proc_iter, |
|
| 244 |
+ self.PROC_BEGIN_TIMESTAMP, |
|
| 220 | 245 |
self.PROC_BEGIN_TIMESTAMP_TEXT, |
| 221 |
- timestamp2str, proc.begin_timestamp) |
|
| 222 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_END_TIMESTAMP, |
|
| 246 |
+ timestamp2str, |
|
| 247 |
+ proc.begin_timestamp, |
|
| 248 |
+ ) |
|
| 249 |
+ self.fillProcessesEntryAttr( |
|
| 250 |
+ proc_iter, |
|
| 251 |
+ self.PROC_END_TIMESTAMP, |
|
| 223 | 252 |
self.PROC_END_TIMESTAMP_TEXT, |
| 224 |
- timestamp2str, proc.end_timestamp) |
|
| 225 |
- self.wid_processes_tree.set_value(proc_iter, self.PROC_CMDLINE, |
|
| 226 |
- cmdline2str(proc.cmdline)) |
|
| 227 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_CPU_TIME, |
|
| 228 |
- self.PROC_CPU_TIME_TEXT, duration2str, |
|
| 229 |
- proc.cpu_time) |
|
| 230 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_MAX_RSS_KB, |
|
| 231 |
- self.PROC_MAX_RSS_KB_TEXT, kb2str, |
|
| 232 |
- proc.max_rss_kb) |
|
| 233 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_PAGE_FAULTS, |
|
| 234 |
- self.PROC_PAGE_FAULTS_TEXT, int2str, |
|
| 235 |
- add_none(proc.min_flt, proc.maj_flt)) |
|
| 236 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_FILE_SYS_OPS, |
|
| 237 |
- self.PROC_FILE_SYS_OPS_TEXT, int2str, |
|
| 238 |
- add_none(proc.in_block, proc.ou_block)) |
|
| 239 |
- self.fillProcessesEntryAttr(proc_iter, self.PROC_CTX_SW, |
|
| 240 |
- self.PROC_CTX_SW_TEXT, int2str, |
|
| 241 |
- add_none(proc.n_v_csw, proc.n_iv_csw)) |
|
| 242 |
- |
|
| 243 |
- def fillProcessesEntryAttr(self, proc_iter, col: int, text_col: int, |
|
| 244 |
- val2str_func, val): |
|
| 253 |
+ timestamp2str, |
|
| 254 |
+ proc.end_timestamp, |
|
| 255 |
+ ) |
|
| 256 |
+ self.wid_processes_tree.set_value( |
|
| 257 |
+ proc_iter, self.PROC_CMDLINE, cmdline2str(proc.cmdline) |
|
| 258 |
+ ) |
|
| 259 |
+ self.fillProcessesEntryAttr( |
|
| 260 |
+ proc_iter, |
|
| 261 |
+ self.PROC_CPU_TIME, |
|
| 262 |
+ self.PROC_CPU_TIME_TEXT, |
|
| 263 |
+ duration2str, |
|
| 264 |
+ proc.cpu_time, |
|
| 265 |
+ ) |
|
| 266 |
+ self.fillProcessesEntryAttr( |
|
| 267 |
+ proc_iter, |
|
| 268 |
+ self.PROC_MAX_RSS_KB, |
|
| 269 |
+ self.PROC_MAX_RSS_KB_TEXT, |
|
| 270 |
+ kb2str, |
|
| 271 |
+ proc.max_rss_kb, |
|
| 272 |
+ ) |
|
| 273 |
+ self.fillProcessesEntryAttr( |
|
| 274 |
+ proc_iter, |
|
| 275 |
+ self.PROC_PAGE_FAULTS, |
|
| 276 |
+ self.PROC_PAGE_FAULTS_TEXT, |
|
| 277 |
+ int2str, |
|
| 278 |
+ add_none(proc.min_flt, proc.maj_flt), |
|
| 279 |
+ ) |
|
| 280 |
+ self.fillProcessesEntryAttr( |
|
| 281 |
+ proc_iter, |
|
| 282 |
+ self.PROC_FILE_SYS_OPS, |
|
| 283 |
+ self.PROC_FILE_SYS_OPS_TEXT, |
|
| 284 |
+ int2str, |
|
| 285 |
+ add_none(proc.in_block, proc.ou_block), |
|
| 286 |
+ ) |
|
| 287 |
+ self.fillProcessesEntryAttr( |
|
| 288 |
+ proc_iter, |
|
| 289 |
+ self.PROC_CTX_SW, |
|
| 290 |
+ self.PROC_CTX_SW_TEXT, |
|
| 291 |
+ int2str, |
|
| 292 |
+ add_none(proc.n_v_csw, proc.n_iv_csw), |
|
| 293 |
+ ) |
|
| 294 |
+ |
|
| 295 |
+ def fillProcessesEntryAttr( |
|
| 296 |
+ self, proc_iter, col: int, text_col: int, val2str_func, val |
|
| 297 |
+ ): |
|
| 245 | 298 |
""" |
| 246 | 299 |
Fill attribute of processes tree entry. |
| 247 | 300 |
proc_iter: process tree entry |
| ... | ... |
@@ -252,14 +305,7 @@ class UptGui: |
| 252 | 305 |
""" |
| 253 | 306 |
# pylint: disable=R0913 |
| 254 | 307 |
self.wid_processes_tree.set_value(proc_iter, col, val) |
| 255 |
- self.wid_processes_tree.set_value(proc_iter, text_col, |
|
| 256 |
- val2str_func(val)) |
|
| 257 |
- |
|
| 258 |
- def onDestroy(self, _widget): |
|
| 259 |
- """ |
|
| 260 |
- Window will be destroyed. |
|
| 261 |
- """ |
|
| 262 |
- Gtk.main_quit() |
|
| 308 |
+ self.wid_processes_tree.set_value(proc_iter, text_col, val2str_func(val)) |
|
| 263 | 309 |
|
| 264 | 310 |
def onDetailsRowActivated(self, _widget, _row, _col): |
| 265 | 311 |
""" |
| ... | ... |
@@ -273,22 +319,20 @@ class UptGui: |
| 273 | 319 |
if detail_iter is None: |
| 274 | 320 |
return |
| 275 | 321 |
# copy string of selected item or subtree to clipboard |
| 276 |
- string = self.wid_details_tree.get_value(detail_iter, |
|
| 277 |
- self.DETAIL_VALUE) |
|
| 322 |
+ string = self.wid_details_tree.get_value(detail_iter, self.DETAIL_VALUE) |
|
| 278 | 323 |
child_iter = self.wid_details_tree.iter_children(detail_iter) |
| 279 | 324 |
if child_iter is not None: |
| 280 | 325 |
# selected row has children, assemble command line from children |
| 281 | 326 |
strings = [] |
| 282 | 327 |
while child_iter is not None: |
| 283 | 328 |
strings.append( |
| 284 |
- self.wid_details_tree.get_value(child_iter, |
|
| 285 |
- self.DETAIL_VALUE)) |
|
| 329 |
+ self.wid_details_tree.get_value(child_iter, self.DETAIL_VALUE) |
|
| 330 |
+ ) |
|
| 286 | 331 |
child_iter = self.wid_details_tree.iter_next(child_iter) |
| 287 | 332 |
string = cmdline2str(strings) |
| 288 | 333 |
self.storeInClipboardAndNotify(string) |
| 289 | 334 |
# get proc_id of selected row, nothing else to do if none |
| 290 |
- proc_id = self.wid_details_tree.get_value(detail_iter, |
|
| 291 |
- self.DETAIL_PROC_ID) |
|
| 335 |
+ proc_id = self.wid_details_tree.get_value(detail_iter, self.DETAIL_PROC_ID) |
|
| 292 | 336 |
if proc_id < 0: |
| 293 | 337 |
return |
| 294 | 338 |
# select process |
| ... | ... |
@@ -309,8 +353,7 @@ class UptGui: |
| 309 | 353 |
if proc_iter is None: |
| 310 | 354 |
self.showDetails(None) |
| 311 | 355 |
return |
| 312 |
- proc_id = self.wid_processes_tree.get_value(proc_iter, |
|
| 313 |
- self.PROC_PROC_ID) |
|
| 356 |
+ proc_id = self.wid_processes_tree.get_value(proc_iter, self.PROC_PROC_ID) |
|
| 314 | 357 |
# show details of selected process |
| 315 | 358 |
self.showDetails(proc_id) |
| 316 | 359 |
|
| ... | ... |
@@ -326,8 +369,7 @@ class UptGui: |
| 326 | 369 |
if processes_iter is None: |
| 327 | 370 |
return |
| 328 | 371 |
# get process |
| 329 |
- proc_id = self.wid_processes_tree.get_value(processes_iter, |
|
| 330 |
- self.PROC_PROC_ID) |
|
| 372 |
+ proc_id = self.wid_processes_tree.get_value(processes_iter, self.PROC_PROC_ID) |
|
| 331 | 373 |
if proc_id is None or proc_id < 0: |
| 332 | 374 |
return |
| 333 | 375 |
proc = self.processes.getProcess(proc_id) |
| ... | ... |
@@ -335,14 +377,14 @@ class UptGui: |
| 335 | 377 |
return |
| 336 | 378 |
# copy shell command line to repeat process call to clipboard |
| 337 | 379 |
# ( cd <workdir>; env -i <environment> <cmdline> ) |
| 338 |
- string = '('
|
|
| 380 |
+ string = "("
|
|
| 339 | 381 |
if proc.cwd: |
| 340 |
- string += ' cd ' + cmdline_str_escape(proc.cwd) + ';' |
|
| 382 |
+ string += " cd " + cmdline_str_escape(proc.cwd) + ";" |
|
| 341 | 383 |
if proc.environ: |
| 342 |
- string += ' env -i ' + cmdline2str(sorted(proc.environ)) |
|
| 384 |
+ string += " env -i " + cmdline2str(sorted(proc.environ)) |
|
| 343 | 385 |
if proc.cmdline: |
| 344 |
- string += ' ' + cmdline2str(proc.cmdline) |
|
| 345 |
- string += ' )' |
|
| 386 |
+ string += " " + cmdline2str(proc.cmdline) |
|
| 387 |
+ string += " )" |
|
| 346 | 388 |
self.storeInClipboardAndNotify(string) |
| 347 | 389 |
|
| 348 | 390 |
def onTreeToggled(self, _widget): |
| ... | ... |
@@ -366,7 +408,7 @@ class UptGui: |
| 366 | 408 |
""" |
| 367 | 409 |
self.notifier.set_reveal_child(False) |
| 368 | 410 |
if self.notifier_timeout is not None: |
| 369 |
- GObject.source_remove(self.notifier_timeout) |
|
| 411 |
+ GLib.source_remove(self.notifier_timeout) |
|
| 370 | 412 |
self.notifier_timeout = None |
| 371 | 413 |
|
| 372 | 414 |
def showNotification(self, message: str, timeout_ms: int = None): |
| ... | ... |
@@ -380,15 +422,13 @@ class UptGui: |
| 380 | 422 |
self.notifier.set_reveal_child(True) |
| 381 | 423 |
|
| 382 | 424 |
if timeout_ms is not None: |
| 383 |
- self.notifier_timeout = GObject.timeout_add( |
|
| 384 |
- timeout_ms, self.closeNotification) |
|
| 425 |
+ self.notifier_timeout = GLib.timeout_add(timeout_ms, self.closeNotification) |
|
| 385 | 426 |
|
| 386 | 427 |
def storeInClipboard(self, string: str): |
| 387 | 428 |
""" |
| 388 | 429 |
Stores a string in the clipboard |
| 389 | 430 |
""" |
| 390 |
- self.clipboard.set_text(string, -1) |
|
| 391 |
- self.clipboard.store() |
|
| 431 |
+ self.clipboard.set(string) |
|
| 392 | 432 |
|
| 393 | 433 |
def storeInClipboardAndNotify(self, string: str): |
| 394 | 434 |
""" |
| ... | ... |
@@ -404,7 +444,7 @@ class UptGui: |
| 404 | 444 |
Open a trace file. |
| 405 | 445 |
""" |
| 406 | 446 |
# load new data |
| 407 |
- with open(proto_filename, 'rb') as proto_file: |
|
| 447 |
+ with open(proto_filename, "rb") as proto_file: |
|
| 408 | 448 |
self.processes = uproctrace.processes.Processes(proto_file) |
| 409 | 449 |
# populate processes view |
| 410 | 450 |
self.populateProcesses() |
| ... | ... |
@@ -425,7 +465,8 @@ class UptGui: |
| 425 | 465 |
proc = procs[0] |
| 426 | 466 |
del procs[0] |
| 427 | 467 |
proc_iter = self.wid_processes_tree.append( |
| 428 |
- parent_iter if self.show_processes_as_tree else None) |
|
| 468 |
+ parent_iter if self.show_processes_as_tree else None |
|
| 469 |
+ ) |
|
| 429 | 470 |
self.fillProcessesEntry(proc_iter, proc) |
| 430 | 471 |
to_be_output.append((proc.children, proc_iter)) |
| 431 | 472 |
# show all processes |
| ... | ... |
@@ -454,7 +496,7 @@ class UptGui: |
| 454 | 496 |
if proc_store.get_value(proc_iter, self.PROC_PROC_ID) != proc_id: |
| 455 | 497 |
return |
| 456 | 498 |
proc_sel.select_iter(proc_iter) |
| 457 |
- self.wid_processes_view.scroll_to_cell(proc_path) |
|
| 499 |
+ self.wid_processes_view.scroll_to_cell(proc_path, None, False, 0, 0) |
|
| 458 | 500 |
|
| 459 | 501 |
self.wid_processes_tree.foreach(update, None) |
| 460 | 502 |
|
| ... | ... |
@@ -480,11 +523,9 @@ class UptGui: |
| 480 | 523 |
Return iterator to added detail. |
| 481 | 524 |
""" |
| 482 | 525 |
detail_iter = self.wid_details_tree.append(parent_iter) |
| 483 |
- self.wid_details_tree.set_value(detail_iter, self.DETAIL_PROC_ID, |
|
| 484 |
- -1) |
|
| 526 |
+ self.wid_details_tree.set_value(detail_iter, self.DETAIL_PROC_ID, -1) |
|
| 485 | 527 |
self.wid_details_tree.set_value(detail_iter, self.DETAIL_KEY, key) |
| 486 |
- self.wid_details_tree.set_value(detail_iter, self.DETAIL_VALUE, |
|
| 487 |
- value) |
|
| 528 |
+ self.wid_details_tree.set_value(detail_iter, self.DETAIL_VALUE, value) |
|
| 488 | 529 |
return detail_iter |
| 489 | 530 |
|
| 490 | 531 |
def add_list(key: str, values: list, parent_iter=None): |
| ... | ... |
@@ -494,10 +535,10 @@ class UptGui: |
| 494 | 535 |
Return iterator to added top-level of detail subtree. |
| 495 | 536 |
""" |
| 496 | 537 |
if values is None: |
| 497 |
- return add(key, '???', parent_iter) |
|
| 498 |
- list_iter = add(key, f'{len(values):d} entries', parent_iter)
|
|
| 538 |
+ return add(key, "???", parent_iter) |
|
| 539 |
+ list_iter = add(key, f"{len(values):d} entries", parent_iter)
|
|
| 499 | 540 |
for i, value in enumerate(values): |
| 500 |
- add(f'{key} {i:d}', value, list_iter)
|
|
| 541 |
+ add(f"{key} {i:d}", value, list_iter)
|
|
| 501 | 542 |
return list_iter |
| 502 | 543 |
|
| 503 | 544 |
def add_list_sorted(key: str, values: list, parent_iter=None): |
| ... | ... |
@@ -519,50 +560,61 @@ class UptGui: |
| 519 | 560 |
for sub_key, val in zip(sub_keys, values): |
| 520 | 561 |
add(sub_key, int2str(val), sum_iter) |
| 521 | 562 |
self.wid_details_view.expand_row( |
| 522 |
- self.wid_details_tree.get_path(sum_iter), True) |
|
| 563 |
+ self.wid_details_tree.get_path(sum_iter), True |
|
| 564 |
+ ) |
|
| 523 | 565 |
return sum_iter |
| 524 | 566 |
|
| 525 |
- add('begin time', timestamp2str(proc.begin_timestamp))
|
|
| 526 |
- cmdline_iter = add_list('command line', proc.cmdline)
|
|
| 567 |
+ add("begin time", timestamp2str(proc.begin_timestamp))
|
|
| 568 |
+ cmdline_iter = add_list("command line", proc.cmdline)
|
|
| 527 | 569 |
self.wid_details_view.expand_row( |
| 528 |
- self.wid_details_tree.get_path(cmdline_iter), True) |
|
| 529 |
- add_sum('context switches', ['involuntary', 'voluntary'],
|
|
| 530 |
- [proc.n_iv_csw, proc.n_v_csw]) |
|
| 531 |
- add('CPU time', duration2str(proc.cpu_time))
|
|
| 532 |
- add('end time', timestamp2str(proc.end_timestamp))
|
|
| 533 |
- add_list_sorted('environment', proc.environ)
|
|
| 534 |
- add('executable', str2str(proc.exe))
|
|
| 535 |
- add_sum('file system operations', ['input', 'output'],
|
|
| 536 |
- [proc.in_block, proc.ou_block]) |
|
| 537 |
- add('max. resident memory', kb2str(proc.max_rss_kb))
|
|
| 538 |
- add_sum('page faults', ['major', 'minor'],
|
|
| 539 |
- [proc.maj_flt, proc.min_flt]) |
|
| 540 |
- add('pid', int2str(proc.pid))
|
|
| 541 |
- add('ppid', int2str(proc.ppid))
|
|
| 542 |
- add('system CPU time', duration2str(proc.sys_time))
|
|
| 543 |
- add('user CPU time', duration2str(proc.user_time))
|
|
| 544 |
- add('working directory', str2str(proc.cwd))
|
|
| 570 |
+ self.wid_details_tree.get_path(cmdline_iter), True |
|
| 571 |
+ ) |
|
| 572 |
+ add_sum( |
|
| 573 |
+ "context switches", |
|
| 574 |
+ ["involuntary", "voluntary"], |
|
| 575 |
+ [proc.n_iv_csw, proc.n_v_csw], |
|
| 576 |
+ ) |
|
| 577 |
+ add("CPU time", duration2str(proc.cpu_time))
|
|
| 578 |
+ add("end time", timestamp2str(proc.end_timestamp))
|
|
| 579 |
+ add_list_sorted("environment", proc.environ)
|
|
| 580 |
+ add("executable", str2str(proc.exe))
|
|
| 581 |
+ add_sum( |
|
| 582 |
+ "file system operations", |
|
| 583 |
+ ["input", "output"], |
|
| 584 |
+ [proc.in_block, proc.ou_block], |
|
| 585 |
+ ) |
|
| 586 |
+ add("max. resident memory", kb2str(proc.max_rss_kb))
|
|
| 587 |
+ add_sum("page faults", ["major", "minor"], [proc.maj_flt, proc.min_flt])
|
|
| 588 |
+ add("pid", int2str(proc.pid))
|
|
| 589 |
+ add("ppid", int2str(proc.ppid))
|
|
| 590 |
+ add("system CPU time", duration2str(proc.sys_time))
|
|
| 591 |
+ add("user CPU time", duration2str(proc.user_time))
|
|
| 592 |
+ add("working directory", str2str(proc.cwd))
|
|
| 545 | 593 |
# add parent |
| 546 | 594 |
parent_proc = proc.parent |
| 547 | 595 |
if parent_proc is None: |
| 548 |
- add('parent', '???')
|
|
| 596 |
+ add("parent", "???")
|
|
| 549 | 597 |
else: |
| 550 |
- parent_iter = add('parent', cmdline2str(parent_proc.cmdline))
|
|
| 551 |
- self.wid_details_tree.set_value(parent_iter, self.DETAIL_PROC_ID, |
|
| 552 |
- parent_proc.proc_id) |
|
| 598 |
+ parent_iter = add("parent", cmdline2str(parent_proc.cmdline))
|
|
| 599 |
+ self.wid_details_tree.set_value( |
|
| 600 |
+ parent_iter, self.DETAIL_PROC_ID, parent_proc.proc_id |
|
| 601 |
+ ) |
|
| 553 | 602 |
# add children |
| 554 | 603 |
child_procs = proc.children |
| 555 | 604 |
if child_procs is None: |
| 556 |
- add('children', '???')
|
|
| 605 |
+ add("children", "???")
|
|
| 557 | 606 |
else: |
| 558 |
- list_iter = add('children', f'{len(child_procs):d} entries')
|
|
| 607 |
+ list_iter = add("children", f"{len(child_procs):d} entries")
|
|
| 559 | 608 |
for i, child_proc in enumerate(child_procs): |
| 560 |
- child_iter = add(f'child {i:d}',
|
|
| 561 |
- cmdline2str(child_proc.cmdline), list_iter) |
|
| 609 |
+ child_iter = add( |
|
| 610 |
+ f"child {i:d}", cmdline2str(child_proc.cmdline), list_iter
|
|
| 611 |
+ ) |
|
| 562 | 612 |
self.wid_details_tree.set_value( |
| 563 |
- child_iter, self.DETAIL_PROC_ID, child_proc.proc_id) |
|
| 613 |
+ child_iter, self.DETAIL_PROC_ID, child_proc.proc_id |
|
| 614 |
+ ) |
|
| 564 | 615 |
self.wid_details_view.expand_row( |
| 565 |
- self.wid_details_tree.get_path(list_iter), True) |
|
| 616 |
+ self.wid_details_tree.get_path(list_iter), True |
|
| 617 |
+ ) |
|
| 566 | 618 |
|
| 567 | 619 |
|
| 568 | 620 |
def run(proto_filename): |
| ... | ... |
@@ -570,9 +622,4 @@ def run(proto_filename): |
| 570 | 622 |
Run the graphical user interface for the specified trace file. |
| 571 | 623 |
""" |
| 572 | 624 |
app = UptGui(proto_filename) |
| 573 |
- try: |
|
| 574 |
- Gtk.main() |
|
| 575 |
- except KeyboardInterrupt: |
|
| 576 |
- pass |
|
| 577 |
- finally: |
|
| 578 |
- del app |
|
| 625 |
+ app.run(None) |
|
| 579 | 626 |