217 lines
7.2 KiB
Python
217 lines
7.2 KiB
Python
# Python imports
|
|
import os, threading, subprocess
|
|
|
|
# Lib imports
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "3.0")
|
|
gi.require_version('Gdk', '3.0')
|
|
from gi.repository import Gtk, Gdk, GLib, Gio, GdkPixbuf
|
|
|
|
# Application imports
|
|
|
|
|
|
def threaded(fn):
|
|
def wrapper(*args, **kwargs):
|
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
class WidgetMixin:
|
|
|
|
def load_store(self, view, store, save_state=False):
|
|
store.clear()
|
|
dir = view.get_current_directory()
|
|
files = view.get_files()
|
|
|
|
icon = GdkPixbuf.Pixbuf.new_from_file(view.DEFAULT_ICON)
|
|
for i, file in enumerate(files):
|
|
store.append([icon, file[0]])
|
|
self.create_icon(i, view, store, dir, file[0])
|
|
|
|
# NOTE: Not likely called often from here but it could be useful
|
|
if save_state:
|
|
self.window_controller.save_state()
|
|
|
|
@threaded
|
|
def create_icon(self, i, view, store, dir, file):
|
|
icon = view.create_icon(dir, file)
|
|
fpath = f"{dir}/{file}"
|
|
GLib.idle_add(self.update_store, (i, store, icon, view, fpath,))
|
|
|
|
# NOTE: Might need to keep an eye on this throwing invalid iters when too
|
|
# many updates are happening to a folder. Example: /tmp
|
|
def update_store(self, item):
|
|
i, store, icon, view, fpath = item
|
|
itr = None
|
|
|
|
try:
|
|
itr = store.get_iter(i)
|
|
except Exception as e:
|
|
print(":Invalid Itr detected: (Potential race condition...)")
|
|
print(f"Index Requested: {i}")
|
|
print(f"Store Size: {len(store)}")
|
|
return
|
|
|
|
if not icon:
|
|
icon = self.get_system_thumbnail(fpath, view.SYS_ICON_WH[0])
|
|
if not icon:
|
|
if fpath.endswith(".gif"):
|
|
icon = GdkPixbuf.PixbufAnimation.get_static_image(fpath)
|
|
else:
|
|
icon = GdkPixbuf.Pixbuf.new_from_file(view.DEFAULT_ICON)
|
|
|
|
store.set_value(itr, 0, icon)
|
|
|
|
|
|
def get_system_thumbnail(self, filename, size):
|
|
try:
|
|
if os.path.exists(filename):
|
|
gioFile = Gio.File.new_for_path(filename)
|
|
info = gioFile.query_info('standard::icon' , 0, Gio.Cancellable())
|
|
icon = info.get_icon().get_names()[0]
|
|
iconTheme = Gtk.IconTheme.get_default()
|
|
iconData = iconTheme.lookup_icon(icon , size , 0)
|
|
if iconData:
|
|
iconPath = iconData.get_filename()
|
|
return GdkPixbuf.Pixbuf.new_from_file(iconPath)
|
|
else:
|
|
return None
|
|
else:
|
|
return None
|
|
except Exception as e:
|
|
print("System icon generation issue:")
|
|
return None
|
|
|
|
|
|
|
|
|
|
def create_tab_widget(self, view):
|
|
tab = Gtk.ButtonBox()
|
|
label = Gtk.Label()
|
|
tid = Gtk.Label()
|
|
close = Gtk.Button()
|
|
icon = Gtk.Image(stock=Gtk.STOCK_CLOSE)
|
|
|
|
label.set_label(f"{view.get_end_of_path()}")
|
|
label.set_width_chars(len(view.get_end_of_path()))
|
|
label.set_xalign(0.0)
|
|
tid.set_label(f"{view.id}")
|
|
|
|
close.add(icon)
|
|
tab.add(label)
|
|
tab.add(close)
|
|
tab.add(tid)
|
|
|
|
close.connect("released", self.close_tab)
|
|
tab.show_all()
|
|
tid.hide()
|
|
return tab
|
|
|
|
def create_grid_iconview_widget(self, view, wid):
|
|
scroll = Gtk.ScrolledWindow()
|
|
grid = Gtk.IconView()
|
|
store = Gtk.ListStore(GdkPixbuf.Pixbuf, str)
|
|
|
|
grid.set_model(store)
|
|
grid.set_pixbuf_column(0)
|
|
grid.set_text_column(1)
|
|
|
|
grid.set_item_orientation(1)
|
|
grid.set_selection_mode(3)
|
|
grid.set_item_width(96)
|
|
grid.set_item_padding(8)
|
|
grid.set_margin(12)
|
|
grid.set_row_spacing(18)
|
|
grid.set_columns(-1)
|
|
grid.set_spacing(12)
|
|
grid.set_column_spacing(18)
|
|
|
|
grid.connect("button_release_event", self.grid_icon_single_click)
|
|
grid.connect("item-activated", self.grid_icon_double_click)
|
|
grid.connect("selection-changed", self.grid_set_selected_items)
|
|
grid.connect("drag-data-get", self.grid_on_drag_set)
|
|
grid.connect("drag-data-received", self.grid_on_drag_data_received)
|
|
grid.connect("drag-motion", self.grid_on_drag_motion)
|
|
|
|
URI_TARGET_TYPE = 80
|
|
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
|
targets = [ uri_target ]
|
|
action = Gdk.DragAction.COPY
|
|
grid.enable_model_drag_dest(targets, action)
|
|
grid.enable_model_drag_source(0, targets, action)
|
|
|
|
grid.show_all()
|
|
scroll.add(grid)
|
|
grid.set_name(f"{wid}|{view.id}")
|
|
scroll.set_name(f"{wid}|{view.id}")
|
|
self.builder.expose_object(f"{wid}|{view.id}|iconview", grid)
|
|
self.builder.expose_object(f"{wid}|{view.id}", scroll)
|
|
return scroll, store
|
|
|
|
def create_grid_treeview_widget(self, view, wid):
|
|
scroll = Gtk.ScrolledWindow()
|
|
grid = Gtk.TreeView()
|
|
store = Gtk.ListStore(GdkPixbuf.Pixbuf, str)
|
|
# store = Gtk.TreeStore(GdkPixbuf.Pixbuf, str)
|
|
column = Gtk.TreeViewColumn("Icons")
|
|
icon = Gtk.CellRendererPixbuf()
|
|
name = Gtk.CellRendererText()
|
|
selec = grid.get_selection()
|
|
|
|
grid.set_model(store)
|
|
selec.set_mode(3)
|
|
column.pack_start(icon, False)
|
|
column.pack_start(name, True)
|
|
column.add_attribute(icon, "pixbuf", 0)
|
|
column.add_attribute(name, "text", 1)
|
|
column.set_expand(False)
|
|
column.set_sizing(2)
|
|
column.set_min_width(120)
|
|
column.set_max_width(74)
|
|
|
|
grid.append_column(column)
|
|
grid.set_search_column(1)
|
|
grid.set_rubber_banding(True)
|
|
grid.set_headers_visible(False)
|
|
grid.set_enable_tree_lines(False)
|
|
|
|
grid.connect("button_release_event", self.grid_icon_single_click)
|
|
grid.connect("row-activated", self.grid_icon_double_click)
|
|
grid.connect("drag-data-get", self.grid_on_drag_set)
|
|
grid.connect("drag-data-received", self.grid_on_drag_data_received)
|
|
grid.connect("drag-motion", self.grid_on_drag_motion)
|
|
|
|
URI_TARGET_TYPE = 80
|
|
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
|
targets = [ uri_target ]
|
|
action = Gdk.DragAction.COPY
|
|
grid.enable_model_drag_dest(targets, action)
|
|
grid.enable_model_drag_source(0, targets, action)
|
|
|
|
|
|
grid.show_all()
|
|
scroll.add(grid)
|
|
grid.set_name(f"{wid}|{view.id}")
|
|
scroll.set_name(f"{wid}|{view.id}")
|
|
grid.columns_autosize()
|
|
self.builder.expose_object(f"{wid}|{view.id}", scroll)
|
|
return scroll, store
|
|
|
|
|
|
def get_store_and_label_from_notebook(self, notebook, _name):
|
|
icon_view = None
|
|
tab_label = None
|
|
store = None
|
|
|
|
for obj in notebook.get_children():
|
|
icon_view = obj.get_children()[0]
|
|
name = icon_view.get_name()
|
|
if name == _name:
|
|
store = icon_view.get_model()
|
|
tab_label = notebook.get_tab_label(obj).get_children()[0]
|
|
|
|
return store, tab_label
|