Skip to content

Commit 245eff9

Browse files
committed
Replace deprecated GTK API calls and update WidgetInvoker click callbacks
- In sugar3/graphics/alert.py, update the label wrapping call by replacing the deprecated set_line_wrap() with set_wrap(). - In sugar3/graphics/palettewindow.py, change the connection for the 'clicked' signal in WidgetInvoker so that it now uses __clicked_cb (for non‐event driven activations) instead of __click_event_cb. This ensures the intended callback is invoked for user interactions
1 parent 06aa51f commit 245eff9

File tree

5 files changed

+88
-98
lines changed

5 files changed

+88
-98
lines changed

src/sugar3/activity/activity.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ class MySpecialToolbar(Gtk.Toolbar):
185185
import dbus
186186
import dbus.service
187187
from dbus import PROPERTIES_IFACE
188-
189188
from sugar3 import util
190189
from sugar3 import power
191190
from sugar3.profile import get_color, get_save_as
@@ -981,13 +980,15 @@ def set_last_value(values_list, new_value):
981980
# Cannot call datastore.write async for creates:
982981
# https://dev.laptop.org/ticket/3071
983982
if self._jobject.object_id is None:
984-
datastore.write(self._jobject, transfer_ownership=True)
983+
datastore.write(self._jobject)
985984
else:
986985
self._updating_jobject = True
987-
datastore.write(self._jobject,
988-
transfer_ownership=True,
989-
reply_handler=self.__save_cb,
990-
error_handler=self.__save_error_cb)
986+
try:
987+
datastore.write(self._jobject)
988+
except Exception as exc:
989+
self.__save_error_cb(exc)
990+
else:
991+
self.__save_cb()
991992

992993
def copy(self):
993994
'''
@@ -1417,6 +1418,10 @@ def _set_cursor(self, cursor):
14171418
# In GTK4, setting a cursor on a window is not supported.
14181419
# This method is now a no-op.
14191420
pass
1421+
1422+
def reveal(self):
1423+
"""Bring the activity window to the front."""
1424+
self.present()
14201425

14211426

14221427
class _ClientHandler(dbus.service.Object):
@@ -1495,6 +1500,8 @@ def GetAll(self, interface_name):
14951500
return r
14961501
else:
14971502
logging.debug('InvalidArgument')
1503+
1504+
14981505

14991506

15001507
_session = None

src/sugar3/activity/widgets.py

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -47,40 +47,44 @@ def _create_activity_icon(metadata):
4747
from sugar3.activity.activity import get_bundle_path
4848
bundle = get_bundle_instance(get_bundle_path())
4949
icon = Icon(file=bundle.get_icon(), xo_color=color)
50-
5150
return icon
5251

5352

5453
class ActivityButton(ToolButton):
5554

5655
def __init__(self, activity, **kwargs):
5756
ToolButton.__init__(self, **kwargs)
58-
5957
icon = _create_activity_icon(activity.metadata)
6058
self.set_child(icon)
6159
icon.set_visible(True)
62-
6360
self.props.hide_tooltip_on_click = False
6461
self.palette_invoker.props.toggle_palette = True
65-
self.props.tooltip_text = activity.metadata['title']
62+
# Use safe get for title
63+
self.props.tooltip_text = activity.metadata.get('title', '')
6664
activity.metadata.connect('updated', self.__jobject_updated_cb)
6765

6866
def __jobject_updated_cb(self, jobject):
69-
self.props.tooltip_text = jobject['title']
67+
# Use get('title', '') to avoid KeyError
68+
self.props.tooltip_text = jobject.get('title', '')
69+
70+
7071

7172

7273
class ActivityToolbarButton(ToolbarButton):
7374

7475
def __init__(self, activity, **kwargs):
7576
toolbar = ActivityToolbar(activity, orientation_left=True)
7677
toolbar.connect('enter-key-press', lambda widget: self.emit('clicked'))
77-
78+
# Initialize with the toolbar as page.
7879
ToolbarButton.__init__(self, page=toolbar, **kwargs)
79-
8080
icon = _create_activity_icon(activity.metadata)
8181
self.set_child(icon)
8282
icon.set_visible(True)
8383

84+
def do_snapshot(self, snapshot):
85+
# Override do_snapshot to bypass ToolbarBox’s super() call that fails when self isn’t a ToolbarBox.
86+
return None
87+
8488

8589
class StopButton(ToolButton):
8690

@@ -93,7 +97,7 @@ def __init__(self, activity, **kwargs):
9397

9498
def __stop_button_clicked_cb(self, button, activity):
9599
activity.close()
96-
100+
97101
def get_toplevel(self):
98102
return self.get_ancestor(Gtk.Window)
99103

@@ -190,9 +194,9 @@ def __init__(self, activity, **kwargs):
190194
geometry = monitor.get_geometry()
191195
self.entry.set_size_request(int(geometry.width / 3), -1)
192196

197+
# Safe retrieval of title
193198
self.entry.set_text(activity.metadata.get('title', ''))
194199
self.entry.connect('notify::has-focus', self.__focus_changed_cb, activity)
195-
# self.entry.connect('focus-out-event', self.__focus_out_event_cb, activity)
196200
self.entry.connect('activate', self.__activate_cb, activity)
197201
self.entry.set_visible(True)
198202
# Use a GestureClick on the entry
@@ -213,11 +217,6 @@ def __focus_changed_cb(self, widget, param_spec, activity):
213217
widget.select_region(0, 0)
214218
self.save_title(activity)
215219

216-
def __focus_out_event_cb(self, widget, event, activity):
217-
widget.select_region(0, 0)
218-
self.save_title(activity)
219-
return False
220-
221220
def __activate_cb(self, entry, activity):
222221
self.save_title(activity)
223222
entry.select_region(0, 0)
@@ -227,36 +226,22 @@ def __activate_cb(self, entry, activity):
227226
return False
228227

229228
def __jobject_updated_cb(self, jobject):
229+
# Use get() to avoid KeyError while updating title
230+
new_title = jobject.get('title', '')
230231
if self.entry.has_focus():
231232
return
232-
if self.entry.get_text() == jobject['title']:
233+
if self.entry.get_text() == new_title:
233234
return
234-
self.entry.set_text(jobject['title'])
235-
236-
def __closing_cb(self, activity):
237-
self.save_title(activity)
238-
return False
239-
240-
def __button_press_event_cb(self, widget, event):
241-
if widget.is_focus():
242-
return False
243-
else:
244-
widget.grab_focus()
245-
widget.select_region(0, -1)
246-
return True
235+
self.entry.set_text(new_title)
247236

248237
def save_title(self, activity):
249238
title = self.entry.get_text()
250-
# Use get('title', '') so that we have a default if "title" is missing.
251239
if title == activity.metadata.get('title', ''):
252240
return
253-
254241
activity.metadata['title'] = title
255242
activity.metadata['title_set_by_user'] = '1'
256243
activity.save()
257-
258244
activity.set_title(title)
259-
260245
shared_activity = activity.get_shared_activity()
261246
if shared_activity is not None:
262247
shared_activity.props.name = title
@@ -277,8 +262,7 @@ def __init__(self, activity, **kwargs):
277262
display = Gdk.Display.get_default()
278263
monitor = display.get_monitors().get_item(0)
279264
geometry = monitor.get_geometry()
280-
sw.set_size_request(int(geometry.width / 2),
281-
2 * style.GRID_CELL_SIZE)
265+
sw.set_size_request(int(geometry.width / 2), 2 * style.GRID_CELL_SIZE)
282266
sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
283267
self._text_view = Gtk.TextView()
284268
self._text_view.set_cursor_visible(True)
@@ -289,8 +273,6 @@ def __init__(self, activity, **kwargs):
289273
if 'description' in activity.metadata:
290274
text_buffer.set_text(activity.metadata['description'])
291275
self._text_view.set_buffer(text_buffer)
292-
# Replace "focus-out-event" with "notify::has-focus" for GTK4
293-
# self._text_view.connect('focus-out-event', self.__description_changed_cb, activity)
294276
self._text_view.connect('notify::has-focus', self.__focus_changed_cb, activity)
295277
sw.set_child(self._text_view)
296278
description_box.append_item(sw, vertical_padding=0)
@@ -303,44 +285,30 @@ def __focus_changed_cb(self, widget, pspec, activity):
303285
if not widget.has_focus():
304286
self.__description_changed_cb(widget, None, activity)
305287

288+
def __jobject_updated_cb(self, jobject):
289+
if self._text_view.has_focus():
290+
return
291+
descr = jobject.get('description', '')
292+
if self._get_text_from_buffer() == descr:
293+
return
294+
buf = self._text_view.get_buffer()
295+
buf.set_text(descr)
296+
306297
def __description_changed_cb(self, widget, event, activity):
307298
description = self._get_text_from_buffer()
308-
if 'description' in activity.metadata and \
309-
description == activity.metadata['description']:
299+
if 'description' in activity.metadata and description == activity.metadata['description']:
310300
return
311301
activity.metadata['description'] = description
312302
activity.save()
313303
return False
314304

315-
def set_expanded(self, expanded):
316-
box = self.toolbar_box
317-
if not box:
318-
return
319-
320-
if not expanded:
321-
self.palette_invoker.notify_popdown()
322-
return
323-
324-
if box.expanded_button is not None:
325-
box.expanded_button.queue_draw()
326-
if box.expanded_button != self:
327-
box.expanded_button.set_expanded(False)
328-
box.expanded_button = self
329-
330-
def get_toolbar_box(self):
331-
parent = self.get_parent()
332-
if not hasattr(parent, 'owner'):
333-
return None
334-
return parent.owner
335-
336-
toolbar_box = property(get_toolbar_box)
337-
338305
def _get_text_from_buffer(self):
339306
buf = self._text_view.get_buffer()
340307
start_iter = buf.get_start_iter()
341308
end_iter = buf.get_end_iter()
342309
return buf.get_text(start_iter, end_iter, False)
343310

311+
344312
def __jobject_updated_cb(self, jobject):
345313
if self._text_view.has_focus():
346314
return
@@ -370,30 +338,35 @@ class ActivityToolbar(Gtk.Box):
370338

371339
def __init__(self, activity, orientation_left=False):
372340
Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
373-
374341
self._activity = activity
375342

343+
# Helper: remove child from existing parent before appending.
344+
def safe_append(box, widget):
345+
if widget.get_parent() is not None:
346+
widget.get_parent().remove(widget)
347+
box.append(widget)
348+
376349
if activity.metadata:
377350
title_button = TitleEntry(activity)
378-
title_button.connect('enter-key-press',
379-
lambda widget: self.emit('enter-key-press'))
351+
title_button.connect('enter-key-press', lambda widget: self.emit('enter-key-press'))
380352
title_button.set_visible(True)
381-
self.append(title_button)
353+
safe_append(self, title_button)
382354

383355
if not orientation_left:
384356
separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
385357
separator.set_visible(True)
386358
separator.set_expand(True)
387-
self.append(separator)
359+
safe_append(self, separator)
388360

389361
if activity.metadata:
390362
description_item = DescriptionItem(activity)
391363
description_item.set_visible(True)
392-
self.append(description_item)
364+
safe_append(self, description_item)
393365

394366
self.share = ShareButton(activity)
395367
self.share.set_visible(True)
396-
self.append(self.share)
368+
safe_append(self, self.share)
369+
397370

398371

399372
class EditToolbar(Gtk.Box):

src/sugar3/datastore/datastore.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
from gi.repository import GObject
3030
from gi.repository import Gio
3131
import dbus
32+
_bus = dbus.SessionBus()
33+
import uuid
3234

3335
from sugar3 import env
3436
from sugar3 import mime
@@ -93,8 +95,8 @@ def __init__(self, properties=None):
9395
pass
9496
self._properties = properties
9597

96-
default_keys = ['activity', 'activity_id',
97-
'mime_type', 'title_set_by_user']
98+
default_keys = ['activity', 'activity_id', 'mime_type', 'title',
99+
'title_set_by_user', 'spent-times']
98100
for key in default_keys:
99101
if key not in self._properties:
100102
self._properties[key] = ''
@@ -149,16 +151,18 @@ class DSObject(object):
149151
def __init__(self, object_id, metadata=None, file_path=None):
150152
self._update_signal_match = None
151153
self._object_id = None
152-
153154
self.set_object_id(object_id)
154-
155-
self._metadata = metadata
155+
from sugar3.datastore.datastore import DSMetadata
156+
self._metadata = metadata if metadata is not None else DSMetadata()
156157
self._file_path = file_path
157158
self._destroyed = False
158159
self._owns_file = False
159-
160+
160161
def get_object_id(self):
161162
return self._object_id
163+
164+
def get_properties(self):
165+
return self.metadata
162166

163167
def set_object_id(self, object_id):
164168
if self._update_signal_match is not None:
@@ -224,6 +228,12 @@ def __del__(self):
224228

225229
def copy(self):
226230
return DSObject(None, self._metadata.copy(), self._file_path)
231+
232+
def get_preview(self):
233+
return self.metadata.get('preview', '')
234+
235+
def get_icon(self):
236+
return self.metadata.get('icon', '')
227237

228238

229239
class RawObject(object):
@@ -364,19 +374,15 @@ def write(jobject):
364374
if jobject.object_id is None:
365375
try:
366376
jobject.object_id = _create_ds_entry(jobject.get_properties(),
367-
jobject.get_file_path(),
368-
jobject.get_preview(),
369-
jobject.get_icon())
377+
jobject.get_file_path())
370378
except (TypeError, dbus.exceptions.DBusException) as e:
371379
logging.warning('Error writing to datastore: %s', e)
372380
# Create a temporary object ID if DataStore is not available
373381
jobject.object_id = 'temp_' + str(uuid.uuid4())
374382
else:
375383
_update_ds_entry(jobject.object_id,
376-
jobject.get_properties(),
377-
jobject.get_file_path(),
378-
jobject.get_preview(),
379-
jobject.get_icon())
384+
jobject.get_properties(),
385+
jobject.get_file_path())
380386

381387

382388
def delete(object_id):

src/sugar3/graphics/alert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def do_set_property(self, pspec, value):
161161
if self._msg != value:
162162
self._msg = value
163163
self._msg_label.set_markup(self._msg)
164-
self._msg_label.set_line_wrap(True)
164+
self._msg_label.set_wrap(True)
165165
elif pspec.name == 'icon':
166166
if self._icon != value:
167167
self._icon = value

0 commit comments

Comments
 (0)