From d9e796a09c07fdc2abc8a8f6d0a6352159623180 Mon Sep 17 00:00:00 2001
From: Manuel Kaufmann <humitos@gmail.com>
Date: Wed, 18 Jul 2012 11:21:59 -0300
Subject: [PATCH Log] Port to Gtk3 SL #3761
Convert all the gtk2 and sugar-toolkit code to launch this Activity
using Gtk3.
All these steps are documented here:
* http://wiki.sugarlabs.org/go/Features/GTK3/Porting/Log
Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
---
logviewer.py | 140 ++++++++++++++++++++++++++++++++--------------------------
setup.py | 2 +-
2 files changed, 79 insertions(+), 63 deletions(-)
diff --git a/logviewer.py b/logviewer.py
index 71ab5c1..b65370e 100644
a
|
b
|
from gettext import gettext as _ |
22 | 22 | |
23 | 23 | import re |
24 | 24 | |
25 | | import gtk |
26 | | import pango |
27 | | import gobject |
28 | | import gio |
29 | | |
30 | | from sugar.activity import activity |
31 | | from sugar.activity.widgets import ActivityToolbarButton |
32 | | from sugar import env |
33 | | from sugar.graphics import iconentry |
34 | | from sugar.graphics.toolbutton import ToolButton |
35 | | from sugar.graphics.toggletoolbutton import ToggleToolButton |
36 | | from sugar.graphics.palette import Palette |
37 | | from sugar.graphics.alert import NotifyAlert |
| 25 | from gi.repository import Gtk |
| 26 | from gi.repository import Gdk |
| 27 | from gi.repository import Pango |
| 28 | from gi.repository import GObject |
| 29 | from gi.repository import Gio |
| 30 | |
| 31 | from sugar3.activity import activity |
| 32 | from sugar3.activity.widgets import ActivityToolbarButton |
| 33 | from sugar3 import env |
| 34 | from sugar3.graphics import iconentry |
| 35 | from sugar3.graphics.toolbutton import ToolButton |
| 36 | from sugar3.graphics.toggletoolbutton import ToggleToolButton |
| 37 | from sugar3.graphics.palette import Palette |
| 38 | from sugar3.graphics.alert import NotifyAlert |
38 | 39 | from logcollect import LogCollect |
39 | | from sugar.graphics.toolbarbox import ToolbarBox |
40 | | from sugar.activity.widgets import CopyButton, StopButton |
41 | | from sugar.datastore import datastore |
| 40 | from sugar3.graphics.toolbarbox import ToolbarBox |
| 41 | from sugar3.activity.widgets import CopyButton, StopButton |
| 42 | from sugar3.datastore import datastore |
42 | 43 | |
43 | 44 | |
44 | 45 | _AUTOSEARCH_TIMEOUT = 1000 |
… |
… |
def _notify_response_cb(notify, response, activity): |
49 | 50 | activity.remove_alert(notify) |
50 | 51 | |
51 | 52 | |
52 | | class MultiLogView(gtk.HPaned): |
| 53 | class MultiLogView(Gtk.HPaned): |
53 | 54 | |
54 | 55 | def __init__(self, paths, extra_files): |
55 | | gtk.HPaned.__init__(self) |
| 56 | GObject.GObject.__init__(self) |
56 | 57 | |
57 | 58 | self.paths = paths |
58 | 59 | self.extra_files = extra_files |
… |
… |
class MultiLogView(gtk.HPaned): |
73 | 74 | self._find_logs() |
74 | 75 | |
75 | 76 | def _build_treeview(self): |
76 | | self._treeview = gtk.TreeView() |
| 77 | self._treeview = Gtk.TreeView() |
77 | 78 | |
78 | 79 | self._treeview.set_rules_hint(True) |
79 | 80 | self._treeview.connect('cursor-changed', self._cursor_changed_cb) |
80 | 81 | |
81 | | self._treemodel = gtk.TreeStore(gobject.TYPE_STRING) |
| 82 | self._treemodel = Gtk.TreeStore(GObject.TYPE_STRING) |
82 | 83 | |
83 | | sorted = gtk.TreeModelSort(self._treemodel) |
84 | | sorted.set_sort_column_id(0, gtk.SORT_ASCENDING) |
| 84 | # README: https://bugzilla.gnome.org/show_bug.cgi?id=680009 |
| 85 | sorted = self._treemodel.sort_new_with_model() |
| 86 | sorted.set_sort_column_id(0, Gtk.SortType.ASCENDING) |
85 | 87 | sorted.set_sort_func(0, self._sort_logfile) |
86 | 88 | self._treeview.set_model(sorted) |
87 | 89 | |
88 | | renderer = gtk.CellRendererText() |
89 | | col = gtk.TreeViewColumn(_('Log Files'), renderer, text=0) |
| 90 | renderer = Gtk.CellRendererText() |
| 91 | col = Gtk.TreeViewColumn(_('Log Files'), renderer, text=0) |
90 | 92 | self._treeview.append_column(col) |
91 | 93 | |
92 | 94 | self.path_iter = {} |
… |
… |
class MultiLogView(gtk.HPaned): |
96 | 98 | if len(self.extra_files): |
97 | 99 | self.extra_iter = self._treemodel.append(None, [_('Other')]) |
98 | 100 | |
99 | | scroll = gtk.ScrolledWindow() |
100 | | scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
| 101 | scroll = Gtk.ScrolledWindow() |
| 102 | scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) |
101 | 103 | scroll.add(self._treeview) |
102 | | scroll.set_size_request(gtk.gdk.screen_width() * 30 / 100, -1) |
| 104 | scroll.set_size_request(Gdk.Screen.width() * 30 / 100, -1) |
103 | 105 | |
104 | 106 | self.add1(scroll) |
105 | 107 | |
106 | 108 | def _build_textview(self): |
107 | | self._textview = gtk.TextView() |
108 | | self._textview.set_wrap_mode(gtk.WRAP_NONE) |
| 109 | self._textview = Gtk.TextView() |
| 110 | self._textview.set_wrap_mode(Gtk.WrapMode.NONE) |
109 | 111 | |
110 | | pangoFont = pango.FontDescription('Mono') |
| 112 | pangoFont = Pango.FontDescription('Mono') |
111 | 113 | self._textview.modify_font(pangoFont) |
112 | 114 | |
113 | | bgcolor = gtk.gdk.color_parse('#FFFFFF') |
114 | | self._textview.modify_base(gtk.STATE_NORMAL, bgcolor) |
| 115 | bgcolor = Gdk.color_parse('#FFFFFF') |
| 116 | self._textview.modify_base(Gtk.StateType.NORMAL, bgcolor) |
115 | 117 | |
116 | 118 | self._textview.set_editable(False) |
117 | 119 | |
118 | | self._tagtable = gtk.TextTagTable() |
119 | | hilite_tag = gtk.TextTag('search-hilite') |
| 120 | self._tagtable = Gtk.TextTagTable() |
| 121 | hilite_tag = Gtk.TextTag.new('search-hilite') |
120 | 122 | hilite_tag.props.background = '#FFFFB0' |
121 | 123 | self._tagtable.add(hilite_tag) |
122 | | select_tag = gtk.TextTag('search-select') |
| 124 | select_tag = Gtk.TextTag.new('search-select') |
123 | 125 | select_tag.props.background = '#B0B0FF' |
124 | 126 | self._tagtable.add(select_tag) |
125 | 127 | |
126 | | scroll = gtk.ScrolledWindow() |
127 | | scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
| 128 | scroll = Gtk.ScrolledWindow() |
| 129 | scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) |
128 | 130 | scroll.add(self._textview) |
129 | 131 | |
130 | 132 | self.add2(scroll) |
131 | 133 | |
132 | | def _sort_logfile(self, treemodel, itera, iterb): |
| 134 | def _sort_logfile(self, treemodel, itera, iterb, user_data=None): |
133 | 135 | a = treemodel.get_value(itera, 0) |
134 | 136 | b = treemodel.get_value(iterb, 0) |
135 | 137 | if a == None or b == None: |
… |
… |
class MultiLogView(gtk.HPaned): |
162 | 164 | def _configure_watcher(self): |
163 | 165 | # Setting where GIO will be watching |
164 | 166 | for p in self.paths: |
165 | | monitor = gio.File(p).monitor_directory() |
| 167 | monitor = Gio.File.new_for_path(p)\ |
| 168 | .monitor_directory(Gio.FileMonitorFlags.NONE, None) |
166 | 169 | monitor.connect('changed', self._log_file_changed_cb) |
167 | 170 | self._gio_monitors.append(monitor) |
168 | 171 | |
169 | 172 | for f in self.extra_files: |
170 | | monitor = gio.File(f).monitor_file() |
| 173 | monitor = Gio.File.new_for_path(f)\ |
| 174 | .monitor_file(Gio.FileMonitorFlags.NONE, None) |
171 | 175 | monitor.connect('changed', self._log_file_changed_cb) |
172 | 176 | self._gio_monitors.append(monitor) |
173 | 177 | |
174 | 178 | def _log_file_changed_cb(self, monitor, log_file, other_file, event): |
175 | 179 | logfile = log_file.get_basename() |
176 | 180 | |
177 | | if event == gio.FILE_MONITOR_EVENT_CHANGED: |
| 181 | if event == Gio.FileMonitorEvent.CHANGED: |
178 | 182 | if logfile in self.logs: |
179 | 183 | self.logs[logfile].update() |
180 | | elif event == gio.FILE_MONITOR_EVENT_DELETED: |
| 184 | elif event == Gio.FileMonitorEvent.DELETED: |
181 | 185 | if logfile in self.logs: |
182 | 186 | self._remove_log_file(logfile) |
183 | | elif event == gio.FILE_MONITOR_EVENT_CREATED: |
| 187 | elif event == Gio.FileMonitorEvent.CREATED: |
184 | 188 | self._add_log_file(log_file.get_path()) |
185 | 189 | |
186 | 190 | def _cursor_changed_cb(self, treeview): |
187 | 191 | treestore, text_iter = self._treeview.get_selection().get_selected() |
188 | | self._show_log(treestore.get_value(text_iter, 0)) |
| 192 | # FIXME: None is not a possible value |
| 193 | if text_iter: |
| 194 | self._show_log(treestore.get_value(text_iter, 0)) |
189 | 195 | |
190 | 196 | def _show_log(self, logfile): |
191 | 197 | if logfile in self.logs: |
192 | 198 | log = self.logs[logfile] |
193 | 199 | self._textview.set_buffer(log) |
194 | | self._textview.scroll_to_mark(log.get_insert(), 0) |
| 200 | self._textview.scroll_to_mark( |
| 201 | log.get_insert(), 0, use_align=False, xalign=0.5, yalign=0.5) |
195 | 202 | self.active_log = log |
196 | 203 | |
197 | 204 | def _find_logs(self): |
… |
… |
class MultiLogView(gtk.HPaned): |
243 | 250 | if self.active_log == None: |
244 | 251 | self.active_log = log |
245 | 252 | self._show_log(logfile) |
| 253 | # README: I don't understand how it works, sometimes it fails |
| 254 | # http://developer.gnome.org/gtk3/3.5/GtkTreeModelFilter.html#gtk-tree-model-filter-convert-child-iter-to-iter |
246 | 255 | log_iter = \ |
247 | 256 | self._treeview.get_model().convert_child_iter_to_iter(None, |
248 | 257 | log.iter) |
249 | 258 | self._treeview.get_selection().select_iter(log_iter) |
250 | 259 | |
251 | 260 | if written > 0 and self.active_log == log: |
252 | | self._textview.scroll_to_mark(log.get_insert(), 0) |
| 261 | self._textview.scroll_to_mark( |
| 262 | log.get_insert(), 0, use_align=False, xalign=0.5, yalign=0.5) |
253 | 263 | |
254 | 264 | def _remove_log_file(self, logfile): |
255 | 265 | log = self.logs[logfile] |
… |
… |
class MultiLogView(gtk.HPaned): |
312 | 322 | self._textview.scroll_to_iter(end, 0.1) |
313 | 323 | |
314 | 324 | |
315 | | class LogBuffer(gtk.TextBuffer): |
| 325 | class LogBuffer(Gtk.TextBuffer): |
316 | 326 | |
317 | 327 | def __init__(self, tagtable, logfile, iterator): |
318 | | gtk.TextBuffer.__init__(self, tagtable) |
| 328 | # GObject.GObject.__init__(self, tagtable) |
| 329 | GObject.GObject.__init__(self) |
| 330 | |
| 331 | # FIXME: it's not possible to set this value |
| 332 | # self.props.tag_table = tagtable |
319 | 333 | |
320 | 334 | self.logfile = logfile |
321 | 335 | self._pos = 0 |
… |
… |
class LogActivity(activity.Activity): |
367 | 381 | |
368 | 382 | self._build_toolbox() |
369 | 383 | |
| 384 | # Get Sugar's clipboard |
| 385 | self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) |
370 | 386 | self.show() |
371 | 387 | |
372 | 388 | def _build_toolbox(self): |
… |
… |
class LogActivity(activity.Activity): |
389 | 405 | toolbar_box.toolbar.insert(wrap_btn, -1) |
390 | 406 | |
391 | 407 | self.search_entry = iconentry.IconEntry() |
392 | | self.search_entry.set_size_request(gtk.gdk.screen_width() / 3, -1) |
| 408 | self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) |
393 | 409 | self.search_entry.set_icon_from_name( |
394 | 410 | iconentry.ICON_ENTRY_PRIMARY, 'system-search') |
395 | 411 | self.search_entry.add_clear_button() |
396 | 412 | self.search_entry.connect('activate', self._search_entry_activate_cb) |
397 | 413 | self.search_entry.connect('changed', self._search_entry_changed_cb) |
398 | | search_item = gtk.ToolItem() |
| 414 | search_item = Gtk.ToolItem() |
399 | 415 | search_item.add(self.search_entry) |
400 | 416 | toolbar_box.toolbar.insert(search_item, -1) |
401 | 417 | |
… |
… |
class LogActivity(activity.Activity): |
423 | 439 | delete_btn.connect('clicked', self._delete_log_cb) |
424 | 440 | toolbar_box.toolbar.insert(delete_btn, -1) |
425 | 441 | |
426 | | separator = gtk.SeparatorToolItem() |
| 442 | separator = Gtk.SeparatorToolItem() |
427 | 443 | separator.set_expand(True) |
428 | 444 | separator.set_draw(False) |
429 | 445 | toolbar_box.toolbar.insert(separator, -1) |
… |
… |
class LogActivity(activity.Activity): |
435 | 451 | |
436 | 452 | def __copy_clicked_cb(self, button): |
437 | 453 | if self.viewer.active_log: |
438 | | self.viewer.active_log.copy_clipboard(gtk.clipboard_get()) |
| 454 | self.viewer.active_log.copy_clipboard(self.clipboard) |
439 | 455 | |
440 | 456 | def _wrap_cb(self, button): |
441 | 457 | if button.get_active(): |
442 | | self.viewer._textview.set_wrap_mode(gtk.WRAP_WORD_CHAR) |
| 458 | self.viewer._textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) |
443 | 459 | else: |
444 | | self.viewer._textview.set_wrap_mode(gtk.WRAP_NONE) |
| 460 | self.viewer._textview.set_wrap_mode(Gtk.WrapMode.NONE) |
445 | 461 | |
446 | 462 | def _search_entry_activate_cb(self, entry): |
447 | 463 | if self._autosearch_timer: |
448 | | gobject.source_remove(self._autosearch_timer) |
| 464 | GObject.source_remove(self._autosearch_timer) |
449 | 465 | self.viewer.set_search_text(entry.props.text) |
450 | 466 | self._update_search_buttons() |
451 | 467 | |
452 | 468 | def _search_entry_changed_cb(self, entry): |
453 | 469 | if self._autosearch_timer: |
454 | | gobject.source_remove(self._autosearch_timer) |
455 | | self._autosearch_timer = gobject.timeout_add(_AUTOSEARCH_TIMEOUT, |
| 470 | GObject.source_remove(self._autosearch_timer) |
| 471 | self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT, |
456 | 472 | self.__autosearch_timer_cb) |
457 | 473 | |
458 | 474 | def __autosearch_timer_cb(self): |
… |
… |
class CollectorPalette(Palette): |
503 | 519 | |
504 | 520 | self._collector = LogCollect() |
505 | 521 | |
506 | | label = gtk.Label( |
| 522 | label = Gtk.Label(label= |
507 | 523 | _('This captures information about the system\n'\ |
508 | 524 | 'and running processes to a journal entry.\n'\ |
509 | 525 | 'Use this to improve a problem report.')) |
510 | 526 | |
511 | | send_button = gtk.Button(_('Capture information')) |
| 527 | send_button = Gtk.Button(_('Capture information')) |
512 | 528 | send_button.connect('clicked', self._on_send_button_clicked_cb) |
513 | 529 | |
514 | | vbox = gtk.VBox(False, 5) |
515 | | vbox.pack_start(label) |
516 | | vbox.pack_start(send_button) |
| 530 | vbox = Gtk.VBox(False, 5) |
| 531 | vbox.pack_start(label, True, True, 0) |
| 532 | vbox.pack_start(send_button, True, True, 0) |
517 | 533 | vbox.show_all() |
518 | 534 | |
519 | 535 | self.set_content(vbox) |
diff --git a/setup.py b/setup.py
index 876cd3f..95390a3 100755
a
|
b
|
|
16 | 16 | # along with this program; if not, write to the Free Software |
17 | 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | 18 | |
19 | | from sugar.activity import bundlebuilder |
| 19 | from sugar3.activity import bundlebuilder |
20 | 20 | |
21 | 21 | bundlebuilder.start() |
22 | 22 | |