Implement 'deleting' drawings
Enable the delete button that's been hidden away so far. When clicked, we suffix the cached json file with '.deleted'. This also causes a popup with an undo button to appear (taken from Nautilus). When clicked, that button will restore the drawing again. This is really all just renaming anyway, because nothing ever gets deleted here. An extra filter is needed to skip Tuhi drawings that have been deleted in the GUI - we don't want to add the drawings we just deleted again just because Tuhi still keeps them in cache.pull/145/head
parent
ff35e5bfc5
commit
a857b14b8a
|
@ -26,10 +26,11 @@
|
|||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_remove">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">icon_remove</property>
|
||||
<signal name="clicked" handler="_on_button_removed_clicked" swapped="no"/>
|
||||
<signal name="clicked" handler="_on_delete_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -88,19 +88,105 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<object class="GtkOverlay">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkFlowBox" id="flowbox_drawings">
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkFlowBox" id="flowbox_drawings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="index">-1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="overlay">
|
||||
<object class="GtkRevealer" id="overlay_undo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="transition_type">none</property>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">4</property>
|
||||
<property name="margin_start">12</property>
|
||||
<property name="margin_end">4</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="notification_delete_undo">
|
||||
<property name="label" translatable="yes">Undo delete drawing</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="margin_right">6</property>
|
||||
<property name="margin_end">6</property>
|
||||
<signal name="clicked" handler="_on_undo_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="notification_delete_close">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="_on_undo_close_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">window-close-symbolic</property>
|
||||
<property name="icon_size">2</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="image-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="app-notification"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -124,7 +210,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
@ -90,12 +90,37 @@ class Config(GObject.Object):
|
|||
if path.exists():
|
||||
return
|
||||
|
||||
# Tuhi may still cache files we've 'deleted' locally. These need to
|
||||
# be ignored because they're still technically deleted.
|
||||
deleted = Path(ROOT_PATH, f'{timestamp}.json.deleted')
|
||||
if deleted.exists():
|
||||
return
|
||||
|
||||
with open(path, 'w') as fd:
|
||||
fd.write(json_string)
|
||||
|
||||
self._drawings.append(json.loads(json_string))
|
||||
self.notify('drawings')
|
||||
|
||||
def delete_drawing(self, timestamp):
|
||||
# We don't delete json files immediately, we just rename them
|
||||
# so we can resurrect them in the future if need be.
|
||||
path = Path(ROOT_PATH, f'{timestamp}.json')
|
||||
target = Path(ROOT_PATH, f'{timestamp}.json.deleted')
|
||||
path.rename(target)
|
||||
|
||||
self._drawings = [d for d in self._drawings if d['timestamp'] != timestamp]
|
||||
self.notify('drawings')
|
||||
|
||||
def undelete_drawing(self, timestamp):
|
||||
path = Path(ROOT_PATH, f'{timestamp}.json')
|
||||
target = Path(ROOT_PATH, f'{timestamp}.json.deleted')
|
||||
target.rename(path)
|
||||
|
||||
with open(path) as fd:
|
||||
self._drawings.append(json.load(fd))
|
||||
self.notify('drawings')
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
if cls._config_obj is None:
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#
|
||||
from gi.repository import GObject, Gtk
|
||||
|
||||
from .config import Config
|
||||
|
||||
import datetime
|
||||
import time
|
||||
import gi
|
||||
|
@ -87,3 +89,7 @@ class Drawing(Gtk.Box):
|
|||
# FIXME: error handling
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
@Gtk.Template.Callback('_on_delete_button_clicked')
|
||||
def _on_delete_button_clicked(self, button):
|
||||
Config.load().delete_drawing(self.timestamp)
|
||||
|
|
|
@ -54,6 +54,9 @@ class DrawingPerspective(Gtk.Stack):
|
|||
flowbox_drawings = Gtk.Template.Child()
|
||||
spinner_sync = Gtk.Template.Child()
|
||||
label_last_sync = Gtk.Template.Child()
|
||||
overlay_undo = Gtk.Template.Child()
|
||||
notification_delete_undo = Gtk.Template.Child()
|
||||
notification_delete_close = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -102,6 +105,19 @@ class DrawingPerspective(Gtk.Stack):
|
|||
|
||||
self.flowbox_drawings.insert(drawing, index)
|
||||
|
||||
# Remove deleted ones
|
||||
deleted = [d for d in self.known_drawings if d not in config.drawings]
|
||||
for d in deleted:
|
||||
child = self.flowbox_drawings.get_child_at_index(0)
|
||||
while child is not None:
|
||||
if child.get_child().timestamp == d['timestamp']:
|
||||
self.flowbox_drawings.remove(child)
|
||||
self.known_drawings.remove(d)
|
||||
self.notification_delete_undo.deleted_drawing = d['timestamp']
|
||||
self.overlay_undo.set_reveal_child(True)
|
||||
break
|
||||
child = self.flowbox_drawings.get_child_at_index(0)
|
||||
|
||||
@GObject.Property
|
||||
def device(self):
|
||||
return self._device
|
||||
|
@ -180,3 +196,12 @@ class DrawingPerspective(Gtk.Stack):
|
|||
logger.debug(f'{device.name} - listening stopped, restarting')
|
||||
# We never want to stop listening
|
||||
device.start_listening()
|
||||
|
||||
@Gtk.Template.Callback('_on_undo_close_clicked')
|
||||
def _on_undo_close_clicked(self, button):
|
||||
self.overlay_undo.set_reveal_child(False)
|
||||
|
||||
@Gtk.Template.Callback('_on_undo_clicked')
|
||||
def _on_undo_clicked(self, button):
|
||||
Config.load().undelete_drawing(button.deleted_drawing)
|
||||
self.overlay_undo.set_reveal_child(False)
|
||||
|
|
Loading…
Reference in New Issue