diff --git a/src/core/widgets/drag_area_widget.py b/src/core/widgets/drag_area_widget.py index af52805..1dd41a6 100644 --- a/src/core/widgets/drag_area_widget.py +++ b/src/core/widgets/drag_area_widget.py @@ -8,6 +8,7 @@ gi.require_version('GtkSource', '4') from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GtkSource +from gi.repository import Gio # Application imports from .template.dynamic_widget_template import DynamicWidget @@ -22,6 +23,7 @@ class DragArea(Gtk.Fixed): self._setup_styling() self._setup_signals() + self._set_up_dnd() self._subscribe_to_events() self._load_widgets() @@ -30,6 +32,7 @@ class DragArea(Gtk.Fixed): self.set_size_request(1800, 1800) def _setup_signals(self): + self.connect("drag-data-received", self._on_drag_data_received) ... def _subscribe_to_events(self): @@ -38,6 +41,70 @@ class DragArea(Gtk.Fixed): def _load_widgets(self): ... + def _set_up_dnd(self): + # https://python-gtk-3-tutorial.readthedocs.io/en/latest/drag_and_drop.html + # https://www.openshot.org/blog/2008/09/12/drag-drop-with-gtk-and-python/ + + # Gtk.DestDefaults.MOTION - This checks if the drag matches this widget's list of possible targets and actions, then calls the drag_status() as appropriate. + # Gtk.DestDefaults.HIGHLIGHT - This draws a highlight on this widget as long as a drag is over this widget + # Gtk.DestDefaults.DROP - When a drop occurs, if the drag matches this widget's list of possible targets and actions call drag_get_data() on behalf of the widget. Whether or not the drop is successful, call drag_finish(). If the action was a move and the drag was successful, then TRUE will be passed for the delete parameter to drag_finish(). + # Gtk.DestDefaults.ALL - If set, specifies that all default actions should be taken + flags = Gtk.DestDefaults.ALL + + # The target is a list of tuples containing target information that is human-understandable descriptions of the data type. + # If TargetFlags set to 0, it means there are no constraints. + # Gtk.TargetFlags.SAME_APP (1) - The target will only be selected for drags within a single application. + # Gtk.TargetFlags.SAME_WIDGET (2) - The target will only be selected for drags within a single widget. + # Gtk.TargetFlags.OTHER_APP (4) - The target will not be selected for drags within a single application + # Gtk.TargetFlags.OTHER_WIDGET (8) - The target will not be selected for drags withing a single widget. + + # A random id for the target types. Note: Can be used in code to determin action flow + PLAIN_TEXT_TARGET_TYPE = 70 + URI_TARGET_TYPE = 80 + text_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(0), PLAIN_TEXT_TARGET_TYPE) + uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE) + targets = [ uri_target, text_target ] + + # The actions argument is a bitmask of or a combination of one or more of the following values − + # Gdk.DragAction.COPY - data provided by the source will be copied to the destination widget. + # Gdk.DragAction.MOVE - data provided by the source will be moved to the destination widget. + # Gdk.DragAction.LINK - the destination widget will create a link to the provided data, rather than copy its contents. + # Gdk.DragAction.PRIVATE - the destination widget is free to do anything with the copy of the data provided. + # Gdk.DragAction.ASK - allows the destination widget to ask the user which action should be performed. + action = Gdk.DragAction.COPY + + # Set the app to allow drops from any type of file. Supposedly works but doesn't for me. + # self.drawArea.drag_dest_set(7, [], 2) + self.drag_dest_set(flags, targets, action) + + def _on_drag_data_received(self, widget, drag_context, _x, _y, data, info, time): + if info == 70: + event_system.emit("set_widget_type", "TextAreaWidget") + dynamic_widget = self.add_or_select_widget(x = _x, y = _y) + body = dynamic_widget.get_body() + + body.buffer.set_text(data.get_text()) + dynamic_widget.save() + + return + + if info == 80: + uris = data.get_uris() + + if len(uris) == 0: + uris = data.get_text().split("\n") + + for uri in uris: + gfile = None + try: + gfile = Gio.File.new_for_uri(uri) + except Exception as e: + gfile = Gio.File.new_for_path(uri) + + # event_system.emit('create_view', (None, None, gfile,)) + + return + def _move_callback(self, widget = None, x = None, y = None): self.move(widget.get_parent(), x, y) @@ -74,11 +141,18 @@ class DragArea(Gtk.Fixed): self.put(wrapped_entry, 30, 30) self.put(wrapped_date, 30, 65) - def add_or_select_widget(self, widget = None, eve = None): - dynamic_widget = DynamicWidget(self._move_callback, None, eve.x, eve.y) - self._handle_add(dynamic_widget, eve.x, eve.y) + def add_or_select_widget(self, widget = None, eve = None, x = None, y = None): + if eve: + x = eve.x + y = eve.y + + dynamic_widget = DynamicWidget(self._move_callback, None, x, y) + + self._handle_add(dynamic_widget, x, y) dynamic_widget.save() + return dynamic_widget + def load_path_to_widget(self, path): dynamic_widget = DynamicWidget(self._move_callback, path) x = dynamic_widget.get_header()._current_x diff --git a/src/core/widgets/page_widget.py b/src/core/widgets/page_widget.py index a3c0ada..f72a0e0 100644 --- a/src/core/widgets/page_widget.py +++ b/src/core/widgets/page_widget.py @@ -52,7 +52,6 @@ class Page(Gtk.ScrolledWindow): def _load_widgets(self): self._drag_area = DragArea() eve_box = Gtk.EventBox() - eve_box.connect("button-release-event", self._release_event) eve_box.add(self._drag_area) diff --git a/src/core/widgets/pages/pages_widget.py b/src/core/widgets/pages/pages_widget.py index eff7da1..d0e82bf 100644 --- a/src/core/widgets/pages/pages_widget.py +++ b/src/core/widgets/pages/pages_widget.py @@ -36,6 +36,7 @@ class Pages(Gtk.Notebook): def _setup_signals(self): label = self._tab_widget.get_children()[0] self.connect("switch-page", self._switch_page_update) + self.connect("map", self._map_update) label.connect("button-release-event", self._change_section_name) def _load_widgets(self): @@ -85,6 +86,15 @@ class Pages(Gtk.Notebook): path = page.get_manifest_pth().replace("MANIFEST", "") settings.set_active_page(path) + def _map_update(self, widget = None): + path = self.get_section_pth() + settings.set_active_section(path) + + page = self.get_nth_page( self.get_current_page() ) + path = page.get_manifest_pth() + settings.set_active_page(path) + + def _change_section_name(self, widget = None, eve = None): if eve.button == 3: # NOTE: If right click label = widget.get_children()[0] # NOTE: Pull from event box diff --git a/src/core/widgets/widget_selector/widgets/text_area.py b/src/core/widgets/widget_selector/widgets/text_area.py index b0732ae..2d40d8a 100644 --- a/src/core/widgets/widget_selector/widgets/text_area.py +++ b/src/core/widgets/widget_selector/widgets/text_area.py @@ -1,4 +1,5 @@ # Python imports +import hashlib # Lib imports import gi @@ -16,6 +17,7 @@ class TextAreaWidget(WidgetSaveLoadController, GtkSource.View): super(TextAreaWidget, self).__init__() self.buffer = self.get_buffer() + self._buffer_hash = None self._setup_styling() self._setup_signals() @@ -39,7 +41,15 @@ class TextAreaWidget(WidgetSaveLoadController, GtkSource.View): ... def _key_released(self, widget = None, eve = None): - self.get_parent().save_needed = True + if eve.type == 9: + _hash = self.get_hash( self.get_buffer_text() ) + if _hash == self._buffer_hash: + return + + if (eve.keyval >= 32 or eve.keyval <= 126) or (eve.keyval in [65288, 65289, 65293]): + self.get_parent().save_needed = True + self._buffer_hash = _hash + def get_buffer_text(self): start, end = self.buffer.get_start_iter(), self.buffer.get_end_iter() @@ -58,7 +68,14 @@ class TextAreaWidget(WidgetSaveLoadController, GtkSource.View): self.load_saveable_data() def load_saveable_data(self): - self.buffer.set_text(self.save_collection["data"]) + text = self.save_collection["data"] + self._buffer_hash = self.get_hash(text) + + self.buffer.set_text(text) + + def get_hash(self, text): + sha = hashlib.sha1(text.encode("utf-8")) + return sha.hexdigest() def new(self): widget = TextAreaWidget() diff --git a/src/utils/widget_save_load_controller.py b/src/utils/widget_save_load_controller.py index 823d933..023526b 100644 --- a/src/utils/widget_save_load_controller.py +++ b/src/utils/widget_save_load_controller.py @@ -1,8 +1,6 @@ # Python imports # Lib imports -import gi -from gi.repository import GLib # Application imports