generated from itdominator/Python-With-Gtk-Template
164 lines
6.5 KiB
Python
164 lines
6.5 KiB
Python
# Python imports
|
||
|
||
# Lib imports
|
||
import gi
|
||
gi.require_version('Gtk', '3.0')
|
||
gi.require_version('Gdk', '3.0')
|
||
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
|
||
|
||
|
||
|
||
class DragArea(Gtk.Fixed):
|
||
def __init__(self):
|
||
super(DragArea, self).__init__()
|
||
|
||
self._children_content = []
|
||
|
||
self._setup_styling()
|
||
self._setup_signals()
|
||
self._set_up_dnd()
|
||
self._subscribe_to_events()
|
||
self._load_widgets()
|
||
|
||
|
||
def _setup_styling(self):
|
||
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):
|
||
...
|
||
|
||
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:
|
||
self._load_dnd_text(data, _x, _y)
|
||
return
|
||
|
||
if info == 80:
|
||
self._load_dnd_files(data, _x, _y)
|
||
return
|
||
|
||
def _load_dnd_text(self, data, _x, _y):
|
||
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()
|
||
|
||
def _load_dnd_files(self, data, _x, _y):
|
||
uris = data.get_uris()
|
||
|
||
if len(uris) == 0:
|
||
uris = data.get_text().split("\n")
|
||
|
||
for uri in uris:
|
||
event_system.emit("set_widget_type", "FileWidget")
|
||
dynamic_widget = self.add_or_select_widget(x = _x, y = _y)
|
||
dynamic_widget.get_body().set_file_path(uri)
|
||
dynamic_widget.save()
|
||
_y += 85
|
||
|
||
|
||
def _move_callback(self, widget = None, x = None, y = None):
|
||
self.move(widget.get_parent(), x, y)
|
||
|
||
def wrap_widget_in_trap(self, widget):
|
||
eve_trap_box = Gtk.EventBox()
|
||
eve_trap_box.connect("button-release-event", self._release_event)
|
||
eve_trap_box.add(widget)
|
||
eve_trap_box.show()
|
||
|
||
return eve_trap_box
|
||
|
||
def _release_event(self, widget = None, eve = None):
|
||
return True
|
||
|
||
def _handle_add(self, widget, x, y):
|
||
widget_wrapped = self.wrap_widget_in_trap(widget)
|
||
|
||
self._children_content.append(widget)
|
||
self.put(widget_wrapped, x, y)
|
||
|
||
def add_fixed_base_widgets(self, name = None, date = None, update_header_callback = None):
|
||
entry = Gtk.Entry(text = name)
|
||
wrapped_entry = self.wrap_widget_in_trap( entry )
|
||
date_label = Gtk.Label(label = date)
|
||
wrapped_date = self.wrap_widget_in_trap( date_label )
|
||
|
||
ctx = entry.get_style_context()
|
||
ctx.add_class("drag-area-title")
|
||
|
||
entry.connect("changed", update_header_callback)
|
||
entry.set_width_chars(25)
|
||
entry.set_max_length(25)
|
||
|
||
self.put(wrapped_entry, 30, 30)
|
||
self.put(wrapped_date, 30, 65)
|
||
|
||
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
|
||
y = dynamic_widget.get_header()._current_y
|
||
self._handle_add(dynamic_widget, x, y)
|