Save As - show a save-as alert on stop
When an activity is to stop, and the save-as setting is enabled, and the journal entry has not been named, show an alert asking for a name, with keyboard focus in the name entry with the name selected. Return key commits the save with the name as shown. Escape key cancels the alert and the stop. While the alert is shown, the activity stop button(s) will be insensitive. As a side-effect, when an entry is resumed, switching to the journal will show a clone entry with the same name. When the activity is stopped, the clone entry will be removed or renamed. Forced power down and reboot will show the clone entry. https://wiki.sugarlabs.org/go/Features/Save-As Signed-off-by: James Cameron <quozl@laptop.org>
This commit is contained in:
parent
3a574ae778
commit
ba6993d705
@ -85,7 +85,7 @@ from telepathy.constants import CONNECTION_HANDLE_TYPE_ROOM
|
|||||||
|
|
||||||
from sugar3 import util
|
from sugar3 import util
|
||||||
from sugar3 import power
|
from sugar3 import power
|
||||||
from sugar3.profile import get_nick_name, get_color
|
from sugar3.profile import get_nick_name, get_color, get_save_as
|
||||||
from sugar3.presence import presenceservice
|
from sugar3.presence import presenceservice
|
||||||
from sugar3.activity.activityservice import ActivityService
|
from sugar3.activity.activityservice import ActivityService
|
||||||
from sugar3.graphics import style
|
from sugar3.graphics import style
|
||||||
@ -379,6 +379,8 @@ class Activity(Window, Gtk.Container):
|
|||||||
self._max_participants = None
|
self._max_participants = None
|
||||||
self._invites_queue = []
|
self._invites_queue = []
|
||||||
self._jobject = None
|
self._jobject = None
|
||||||
|
self._jobject_old = None
|
||||||
|
self._is_resumed = False
|
||||||
self._read_file_called = False
|
self._read_file_called = False
|
||||||
|
|
||||||
self._session = _get_session()
|
self._session = _get_session()
|
||||||
@ -397,6 +399,7 @@ class Activity(Window, Gtk.Container):
|
|||||||
share_scope = SCOPE_PRIVATE
|
share_scope = SCOPE_PRIVATE
|
||||||
|
|
||||||
if handle.object_id:
|
if handle.object_id:
|
||||||
|
self._is_resumed = True
|
||||||
self._jobject = datastore.get(handle.object_id)
|
self._jobject = datastore.get(handle.object_id)
|
||||||
|
|
||||||
if 'share-scope' in self._jobject.metadata:
|
if 'share-scope' in self._jobject.metadata:
|
||||||
@ -413,13 +416,15 @@ class Activity(Window, Gtk.Container):
|
|||||||
self._jobject.metadata['spent-times'] += ', 0'
|
self._jobject.metadata['spent-times'] += ', 0'
|
||||||
else:
|
else:
|
||||||
self._jobject.metadata['spent-times'] = '0'
|
self._jobject.metadata['spent-times'] = '0'
|
||||||
|
else:
|
||||||
|
self._is_resumed = False
|
||||||
|
self._jobject = self._initialize_journal_object()
|
||||||
|
self.set_title(self._jobject.metadata['title'])
|
||||||
|
|
||||||
self.shared_activity = None
|
self.shared_activity = None
|
||||||
self._join_id = None
|
self._join_id = None
|
||||||
|
|
||||||
if handle.object_id is None:
|
self._original_title = self._jobject.metadata['title']
|
||||||
logging.debug('Creating a jobject.')
|
|
||||||
self._jobject = self._initialize_journal_object()
|
|
||||||
|
|
||||||
if handle.invited:
|
if handle.invited:
|
||||||
wait_loop = GObject.MainLoop()
|
wait_loop = GObject.MainLoop()
|
||||||
@ -451,6 +456,13 @@ class Activity(Window, Gtk.Container):
|
|||||||
self._busy_count = 0
|
self._busy_count = 0
|
||||||
self._stop_buttons = []
|
self._stop_buttons = []
|
||||||
|
|
||||||
|
if self._is_resumed and get_save_as():
|
||||||
|
# preserve original and use a copy for editing
|
||||||
|
self._jobject_old = self._jobject
|
||||||
|
self._jobject = datastore.copy(self._jobject, '/')
|
||||||
|
|
||||||
|
self._original_title = self._jobject.metadata['title']
|
||||||
|
|
||||||
def add_stop_button(self, button):
|
def add_stop_button(self, button):
|
||||||
self._stop_buttons.append(button)
|
self._stop_buttons.append(button)
|
||||||
|
|
||||||
@ -1091,6 +1103,92 @@ class Activity(Window, Gtk.Container):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _show_stop_dialog(self):
|
||||||
|
for button in self._stop_buttons:
|
||||||
|
button.set_sensitive(False)
|
||||||
|
alert = Alert()
|
||||||
|
alert.props.title = _('Stop')
|
||||||
|
alert.props.msg = _('Stop: name your journal entry')
|
||||||
|
|
||||||
|
title = self._jobject.metadata['title']
|
||||||
|
alert.entry = alert.add_entry()
|
||||||
|
alert.entry.set_text(title)
|
||||||
|
|
||||||
|
label, tip = self._get_save_label_tip(title)
|
||||||
|
button = alert.add_button(Gtk.ResponseType.OK, label,
|
||||||
|
Icon(icon_name='dialog-ok'))
|
||||||
|
button.add_accelerator('clicked', self.sugar_accel_group,
|
||||||
|
Gdk.KEY_Return, 0, 0)
|
||||||
|
button.set_tooltip_text(tip)
|
||||||
|
alert.ok = button
|
||||||
|
|
||||||
|
label, tip = self._get_erase_label_tip()
|
||||||
|
button = alert.add_button(Gtk.ResponseType.ACCEPT, label,
|
||||||
|
Icon(icon_name='list-remove'))
|
||||||
|
button.set_tooltip_text(tip)
|
||||||
|
|
||||||
|
button = alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'),
|
||||||
|
Icon(icon_name='dialog-cancel'))
|
||||||
|
button.add_accelerator('clicked', self.sugar_accel_group,
|
||||||
|
Gdk.KEY_Escape, 0, 0)
|
||||||
|
button.set_tooltip_text(_('Cancel stop and continue the activity'))
|
||||||
|
|
||||||
|
alert.connect('realize', self.__stop_dialog_realize_cb)
|
||||||
|
alert.connect('response', self.__stop_dialog_response_cb)
|
||||||
|
alert.entry.connect('changed', self.__stop_dialog_changed_cb, alert)
|
||||||
|
self.add_alert(alert)
|
||||||
|
alert.show()
|
||||||
|
|
||||||
|
def __stop_dialog_realize_cb(self, alert):
|
||||||
|
alert.entry.grab_focus()
|
||||||
|
|
||||||
|
def __stop_dialog_response_cb(self, alert, response_id):
|
||||||
|
if response_id == Gtk.ResponseType.OK:
|
||||||
|
title = alert.entry.get_text()
|
||||||
|
if self._is_resumed and \
|
||||||
|
title == self._original_title:
|
||||||
|
datastore.delete(self._jobject_old.get_object_id())
|
||||||
|
self._jobject.metadata['title'] = title
|
||||||
|
self._do_close(False)
|
||||||
|
|
||||||
|
if response_id == Gtk.ResponseType.ACCEPT:
|
||||||
|
datastore.delete(self._jobject.get_object_id())
|
||||||
|
self._do_close(True)
|
||||||
|
|
||||||
|
if response_id == Gtk.ResponseType.CANCEL:
|
||||||
|
for button in self._stop_buttons:
|
||||||
|
button.set_sensitive(True)
|
||||||
|
|
||||||
|
self.remove_alert(alert)
|
||||||
|
|
||||||
|
def __stop_dialog_changed_cb(self, entry, alert):
|
||||||
|
label, tip = self._get_save_label_tip(entry.get_text())
|
||||||
|
|
||||||
|
alert.ok.set_label(label)
|
||||||
|
alert.ok.set_tooltip_text(tip)
|
||||||
|
|
||||||
|
def _get_save_label_tip(self, title):
|
||||||
|
label = _('Save new')
|
||||||
|
tip = _('Save a new journal entry')
|
||||||
|
if self._is_resumed and \
|
||||||
|
title == self._original_title:
|
||||||
|
label = _('Save')
|
||||||
|
tip = _('Save into the old journal entry')
|
||||||
|
|
||||||
|
return label, tip
|
||||||
|
|
||||||
|
def _get_erase_label_tip(self):
|
||||||
|
if self._is_resumed:
|
||||||
|
label = _('Erase changes')
|
||||||
|
tip = _('Erase what you have done, '
|
||||||
|
'and leave your old journal entry unchanged')
|
||||||
|
else:
|
||||||
|
label = _('Erase')
|
||||||
|
tip = _('Erase what you have done, '
|
||||||
|
'and avoid making a journal entry')
|
||||||
|
|
||||||
|
return label, tip
|
||||||
|
|
||||||
def _prepare_close(self, skip_save=False):
|
def _prepare_close(self, skip_save=False):
|
||||||
if not skip_save:
|
if not skip_save:
|
||||||
try:
|
try:
|
||||||
@ -1119,6 +1217,16 @@ class Activity(Window, Gtk.Container):
|
|||||||
self._session.unregister(self)
|
self._session.unregister(self)
|
||||||
power.get_power_manager().shutdown()
|
power.get_power_manager().shutdown()
|
||||||
|
|
||||||
|
def _do_close(self, skip_save):
|
||||||
|
self.busy()
|
||||||
|
self.emit('_closing')
|
||||||
|
if not self._closing:
|
||||||
|
if not self._prepare_close(skip_save):
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self._updating_jobject:
|
||||||
|
self._complete_close()
|
||||||
|
|
||||||
def close(self, skip_save=False):
|
def close(self, skip_save=False):
|
||||||
'''
|
'''
|
||||||
Request that the activity be stopped and saved to the Journal
|
Request that the activity be stopped and saved to the Journal
|
||||||
@ -1133,15 +1241,13 @@ class Activity(Window, Gtk.Container):
|
|||||||
if not self.can_close():
|
if not self.can_close():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
|
if get_save_as():
|
||||||
self.emit('_closing')
|
if self._jobject.metadata['title'] != self._original_title:
|
||||||
|
self._do_close(skip_save)
|
||||||
if not self._closing:
|
else:
|
||||||
if not self._prepare_close(skip_save):
|
self._show_stop_dialog()
|
||||||
return
|
else:
|
||||||
|
self._do_close(skip_save)
|
||||||
if not self._updating_jobject:
|
|
||||||
self._complete_close()
|
|
||||||
|
|
||||||
def __realize_cb(self, window):
|
def __realize_cb(self, window):
|
||||||
display_name = Gdk.Display.get_default().get_name()
|
display_name = Gdk.Display.get_default().get_name()
|
||||||
|
Loading…
Reference in New Issue
Block a user