Florian Walbroel commited on 2021-09-02 15:50:45
Showing 2 changed files, with 120 additions and 9 deletions.
| ... | ... |
@@ -55,6 +55,10 @@ |
| 55 | 55 |
<child> |
| 56 | 56 |
<placeholder/> |
| 57 | 57 |
</child> |
| 58 |
+ <child> |
|
| 59 |
+ <object class="GtkOverlay"> |
|
| 60 |
+ <property name="visible">True</property> |
|
| 61 |
+ <property name="can_focus">False</property> |
|
| 58 | 62 |
<child> |
| 59 | 63 |
<object class="GtkBox" id="TopVBox"> |
| 60 | 64 |
<property name="visible">True</property> |
| ... | ... |
@@ -334,6 +338,67 @@ |
| 334 | 338 |
</packing> |
| 335 | 339 |
</child> |
| 336 | 340 |
</object> |
| 341 |
+ <packing> |
|
| 342 |
+ <property name="index">-1</property> |
|
| 343 |
+ </packing> |
|
| 344 |
+ </child> |
|
| 345 |
+ <child type="overlay"> |
|
| 346 |
+ <object class="GtkRevealer" id="NotificationRevealer"> |
|
| 347 |
+ <property name="visible">True</property> |
|
| 348 |
+ <property name="can_focus">False</property> |
|
| 349 |
+ <property name="halign">center</property> |
|
| 350 |
+ <property name="valign">start</property> |
|
| 351 |
+ <property name="transition_type">slide-up</property> |
|
| 352 |
+ <child> |
|
| 353 |
+ <object class="GtkBox"> |
|
| 354 |
+ <property name="visible">True</property> |
|
| 355 |
+ <property name="can_focus">False</property> |
|
| 356 |
+ <property name="halign">center</property> |
|
| 357 |
+ <property name="valign">start</property> |
|
| 358 |
+ <property name="spacing">6</property> |
|
| 359 |
+ <child> |
|
| 360 |
+ <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> |
|
| 365 |
+ <property name="justify">center</property> |
|
| 366 |
+ </object> |
|
| 367 |
+ <packing> |
|
| 368 |
+ <property name="expand">False</property> |
|
| 369 |
+ <property name="fill">True</property> |
|
| 370 |
+ <property name="position">1</property> |
|
| 371 |
+ </packing> |
|
| 372 |
+ </child> |
|
| 373 |
+ <child> |
|
| 374 |
+ <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> |
|
| 397 |
+ </object> |
|
| 398 |
+ </child> |
|
| 399 |
+ </object> |
|
| 400 |
+ </child> |
|
| 401 |
+ </object> |
|
| 337 | 402 |
</child> |
| 338 | 403 |
</object> |
| 339 | 404 |
</interface> |
| ... | ... |
@@ -19,7 +19,7 @@ import gi |
| 19 | 19 |
gi.require_version('Gdk', '3.0')
|
| 20 | 20 |
gi.require_version('Gtk', '3.0')
|
| 21 | 21 |
# pylint: disable=C0413 |
| 22 |
-from gi.repository import Gdk, Gtk, GLib |
|
| 22 |
+from gi.repository import Gdk, Gtk, GLib, GObject |
|
| 23 | 23 |
|
| 24 | 24 |
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit) |
| 25 | 25 |
|
| ... | ... |
@@ -192,12 +192,16 @@ class UptGui: |
| 192 | 192 |
self.wid_processes_tree = self.builder.get_object('ProcessesTree')
|
| 193 | 193 |
self.wid_processes_view = self.builder.get_object('ProcessesView')
|
| 194 | 194 |
self.wid_tree_toggle = self.builder.get_object('TreeToggle')
|
| 195 |
+ self.notifier = self.builder.get_object("NotificationRevealer")
|
|
| 196 |
+ self.notifier_msg = self.builder.get_object("NotificationMessage")
|
|
| 197 |
+ self.notifier_timeout = None |
|
| 195 | 198 |
handlers = {
|
| 196 | 199 |
'onDestroy': self.onDestroy, |
| 197 | 200 |
'onDetailsRowActivated': self.onDetailsRowActivated, |
| 198 | 201 |
'onProcessesCursorChanged': self.onProcessesCursorChanged, |
| 199 | 202 |
'onProcessesRowActivated': self.onProcessesRowActivated, |
| 200 |
- 'onTreeToggled': self.onTreeToggled |
|
| 203 |
+ 'onTreeToggled': self.onTreeToggled, |
|
| 204 |
+ 'onNotificationClose': self.onNotificationClose, |
|
| 201 | 205 |
} |
| 202 | 206 |
self.builder.connect_signals(handlers) |
| 203 | 207 |
# open trace file |
| ... | ... |
@@ -281,8 +285,7 @@ class UptGui: |
| 281 | 285 |
self.DETAIL_VALUE)) |
| 282 | 286 |
child_iter = self.wid_details_tree.iter_next(child_iter) |
| 283 | 287 |
string = cmdline2str(strings) |
| 284 |
- self.clipboard.set_text(string, -1) |
|
| 285 |
- self.clipboard.store() |
|
| 288 |
+ self.storeInClipboardAndNotify(string) |
|
| 286 | 289 |
# get proc_id of selected row, nothing else to do if none |
| 287 | 290 |
proc_id = self.wid_details_tree.get_value(detail_iter, |
| 288 | 291 |
self.DETAIL_PROC_ID) |
| ... | ... |
@@ -340,8 +343,7 @@ class UptGui: |
| 340 | 343 |
if proc.cmdline: |
| 341 | 344 |
string += ' ' + cmdline2str(proc.cmdline) |
| 342 | 345 |
string += ' )' |
| 343 |
- self.clipboard.set_text(string, -1) |
|
| 344 |
- self.clipboard.store() |
|
| 346 |
+ self.storeInClipboardAndNotify(string) |
|
| 345 | 347 |
|
| 346 | 348 |
def onTreeToggled(self, _widget): |
| 347 | 349 |
""" |
| ... | ... |
@@ -352,6 +354,51 @@ class UptGui: |
| 352 | 354 |
# re-populate processes view |
| 353 | 355 |
self.populateProcesses() |
| 354 | 356 |
|
| 357 |
+ def onNotificationClose(self, _widget): |
|
| 358 |
+ """ |
|
| 359 |
+ Notification close button pressed: close the notification |
|
| 360 |
+ """ |
|
| 361 |
+ self.closeNotification() |
|
| 362 |
+ |
|
| 363 |
+ def closeNotification(self): |
|
| 364 |
+ """ |
|
| 365 |
+ Closes the notification and kills the timeout if set |
|
| 366 |
+ """ |
|
| 367 |
+ self.notifier.set_reveal_child(False) |
|
| 368 |
+ if self.notifier_timeout is not None: |
|
| 369 |
+ GObject.source_remove(self.notifier_timeout) |
|
| 370 |
+ self.notifier_timeout = None |
|
| 371 |
+ |
|
| 372 |
+ def showNotification(self, message: str, timeout_ms: int = None): |
|
| 373 |
+ """ |
|
| 374 |
+ Shows a notification with the given message text, if timeout (in ms) |
|
| 375 |
+ is provided also sets a timeout to close the notification |
|
| 376 |
+ """ |
|
| 377 |
+ self.closeNotification() |
|
| 378 |
+ |
|
| 379 |
+ self.notifier_msg.set_text(message) |
|
| 380 |
+ self.notifier.set_reveal_child(True) |
|
| 381 |
+ |
|
| 382 |
+ if timeout_ms is not None: |
|
| 383 |
+ self.notifier_timeout = GObject.timeout_add( |
|
| 384 |
+ timeout_ms, self.closeNotification) |
|
| 385 |
+ |
|
| 386 |
+ def storeInClipboard(self, string: str): |
|
| 387 |
+ """ |
|
| 388 |
+ Stores a string in the clipboard |
|
| 389 |
+ """ |
|
| 390 |
+ self.clipboard.set_text(string, -1) |
|
| 391 |
+ self.clipboard.store() |
|
| 392 |
+ |
|
| 393 |
+ def storeInClipboardAndNotify(self, string: str): |
|
| 394 |
+ """ |
|
| 395 |
+ Stores a string in the clipboard and shows a "copied to clipboard" |
|
| 396 |
+ notification |
|
| 397 |
+ """ |
|
| 398 |
+ self.storeInClipboard(string) |
|
| 399 |
+ msg = string if len(string) <= 100 else string[:97] + "..." |
|
| 400 |
+ self.showNotification(f"'{msg:s}'\nCopied to clipboard", 1000)
|
|
| 401 |
+ |
|
| 355 | 402 |
def openTrace(self, proto_filename: str): |
| 356 | 403 |
""" |
| 357 | 404 |
Open a trace file. |
| ... | ... |
@@ -512,9 +559,8 @@ class UptGui: |
| 512 | 559 |
for i, child_proc in enumerate(child_procs): |
| 513 | 560 |
child_iter = add(f'child {i:d}',
|
| 514 | 561 |
cmdline2str(child_proc.cmdline), list_iter) |
| 515 |
- self.wid_details_tree.set_value(child_iter, |
|
| 516 |
- self.DETAIL_PROC_ID, |
|
| 517 |
- child_proc.proc_id) |
|
| 562 |
+ self.wid_details_tree.set_value( |
|
| 563 |
+ child_iter, self.DETAIL_PROC_ID, child_proc.proc_id) |
|
| 518 | 564 |
self.wid_details_view.expand_row( |
| 519 | 565 |
self.wid_details_tree.get_path(list_iter), True) |
| 520 | 566 |
|
| 521 | 567 |