Merge Stable Changesto Master #9
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
|
@ -0,0 +1,129 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.40.0 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.24"/>
|
||||||
|
<object class="GtkListStore" id="du_store">
|
||||||
|
<columns>
|
||||||
|
<!-- column-name Size -->
|
||||||
|
<column type="gchararray"/>
|
||||||
|
<!-- column-name Dir -->
|
||||||
|
<column type="gchararray"/>
|
||||||
|
</columns>
|
||||||
|
</object>
|
||||||
|
<object class="GtkDialog" id="du_dialog">
|
||||||
|
<property name="width-request">420</property>
|
||||||
|
<property name="height-request">450</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="window-position">center</property>
|
||||||
|
<property name="destroy-with-parent">True</property>
|
||||||
|
<property name="type-hint">dialog</property>
|
||||||
|
<property name="skip-taskbar-hint">True</property>
|
||||||
|
<property name="skip-pager-hint">True</property>
|
||||||
|
<property name="decorated">False</property>
|
||||||
|
<property name="deletable">False</property>
|
||||||
|
<property name="gravity">center</property>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">2</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkButtonBox">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="layout-style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton">
|
||||||
|
<property name="label">gtk-close</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">True</property>
|
||||||
|
<property name="use-stock">True</property>
|
||||||
|
<signal name="released" handler="_hide_du_menu" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="current_dir_lbl">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-start">5</property>
|
||||||
|
<property name="margin-end">5</property>
|
||||||
|
<property name="margin-top">5</property>
|
||||||
|
<property name="margin-bottom">5</property>
|
||||||
|
<property name="label" translatable="yes">Current Directory:</property>
|
||||||
|
<property name="justify">center</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="shadow-type">in</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTreeView">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="model">du_store</property>
|
||||||
|
<property name="headers-clickable">False</property>
|
||||||
|
<child internal-child="selection">
|
||||||
|
<object class="GtkTreeSelection"/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTreeViewColumn">
|
||||||
|
<property name="title" translatable="yes">Disk Usage</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCellRendererText"/>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="text">0</attribute>
|
||||||
|
</attributes>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCellRendererText"/>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="text">1</attribute>
|
||||||
|
</attributes>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"manifest": {
|
||||||
|
"name": "Disk Usage",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {
|
||||||
|
"ui_target": "context_menu_plugins",
|
||||||
|
"pass_fm_events": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Python imports
|
||||||
|
import os, threading, subprocess, time, inspect
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from plugins.plugin_base import PluginBase
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Threads WILL NOT die with parent's destruction.
|
||||||
|
def threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
# NOTE: Threads WILL die with parent's destruction.
|
||||||
|
def daemon_threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginBase):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.name = "Disk Usage" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
|
||||||
|
# where self.name should not be needed for message comms
|
||||||
|
|
||||||
|
self.path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
self._GLADE_FILE = f"{self.path}/du_usage.glade"
|
||||||
|
self._du_dialog = None
|
||||||
|
self._du_store = None
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._builder = Gtk.Builder()
|
||||||
|
self._builder.add_from_file(self._GLADE_FILE)
|
||||||
|
|
||||||
|
classes = [self]
|
||||||
|
handlers = {}
|
||||||
|
for c in classes:
|
||||||
|
methods = None
|
||||||
|
try:
|
||||||
|
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||||
|
handlers.update(methods)
|
||||||
|
except Exception as e:
|
||||||
|
print(repr(e))
|
||||||
|
|
||||||
|
self._builder.connect_signals(handlers)
|
||||||
|
|
||||||
|
self._du_dialog = self._builder.get_object("du_dialog")
|
||||||
|
self._du_store = self._builder.get_object("du_store")
|
||||||
|
self._current_dir_lbl = self._builder.get_object("current_dir_lbl")
|
||||||
|
|
||||||
|
self._event_system.subscribe("show_du_menu", self._show_du_menu)
|
||||||
|
|
||||||
|
def generate_reference_ui_element(self):
|
||||||
|
item = Gtk.ImageMenuItem(self.name)
|
||||||
|
item.set_image( Gtk.Image(stock=Gtk.STOCK_HARDDISK) )
|
||||||
|
item.connect("activate", self._show_du_menu)
|
||||||
|
item.set_always_show_image(True)
|
||||||
|
return item
|
||||||
|
|
||||||
|
def _get_state(self, widget=None, eve=None):
|
||||||
|
self._event_system.emit("get_current_state")
|
||||||
|
|
||||||
|
def _set_current_dir_lbl(self, widget=None, eve=None):
|
||||||
|
self._current_dir_lbl.set_label(f"Current Directory:\n{self._fm_state.tab.get_current_directory()}")
|
||||||
|
|
||||||
|
def _show_du_menu(self, widget=None, eve=None):
|
||||||
|
self._fm_state = None
|
||||||
|
self._get_state()
|
||||||
|
self._set_current_dir_lbl()
|
||||||
|
self.load_du_data()
|
||||||
|
self._du_dialog.run()
|
||||||
|
|
||||||
|
def load_du_data(self):
|
||||||
|
self._du_store.clear()
|
||||||
|
|
||||||
|
path = self._fm_state.tab.get_current_directory()
|
||||||
|
# NOTE: -h = human readable, -d = depth asigned to 1
|
||||||
|
command = ["du", "-h", "-d", "1", path]
|
||||||
|
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||||
|
raw_data = proc.communicate()[0]
|
||||||
|
data = raw_data.decode("utf-8").strip() # NOTE: Will return data AFTER completion (if any)
|
||||||
|
parts = data.split("\n")
|
||||||
|
|
||||||
|
# NOTE: Last entry is curret dir. Move to top of list and pop off...
|
||||||
|
size, file = parts[-1].split("\t")
|
||||||
|
self._du_store.append([size, file.split("/")[-1]])
|
||||||
|
parts.pop()
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
size, file = part.split("\t")
|
||||||
|
self._du_store.append([size, file.split("/")[-1]])
|
||||||
|
|
||||||
|
def _hide_du_menu(self, widget=None, eve=None):
|
||||||
|
self._du_dialog.hide()
|
|
@ -29,9 +29,11 @@ def run():
|
||||||
# Add long and short arguments
|
# Add long and short arguments
|
||||||
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
|
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
|
||||||
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
|
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
|
||||||
|
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
|
||||||
|
|
||||||
parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.")
|
parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.")
|
||||||
parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.")
|
parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.")
|
||||||
|
|
||||||
# Read arguments (If any...)
|
# Read arguments (If any...)
|
||||||
args, unknownargs = parser.parse_known_args()
|
args, unknownargs = parser.parse_known_args()
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi
|
||||||
cm = ContextMenu()
|
cm = ContextMenu()
|
||||||
cm.build_context_menu()
|
cm.build_context_menu()
|
||||||
|
|
||||||
|
if args.no_plugins == "false":
|
||||||
self.plugins.launch_plugins()
|
self.plugins.launch_plugins()
|
||||||
|
|
||||||
for arg in unknownargs + [args.new_tab,]:
|
for arg in unknownargs + [args.new_tab,]:
|
||||||
|
|
|
@ -3,6 +3,11 @@ import os, subprocess, hashlib
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
|
|
||||||
# Gtk imports
|
# Gtk imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gio
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from .xdg.DesktopEntry import DesktopEntry
|
from .xdg.DesktopEntry import DesktopEntry
|
||||||
|
@ -36,8 +41,13 @@ class DesktopIconMixin:
|
||||||
elif os.path.exists(icon):
|
elif os.path.exists(icon):
|
||||||
return self.create_scaled_image(icon, self.sys_icon_wh)
|
return self.create_scaled_image(icon, self.sys_icon_wh)
|
||||||
else:
|
else:
|
||||||
alt_icon_path = ""
|
gio_icon = Gio.Icon.new_for_string(icon)
|
||||||
|
gicon = Gtk.Image.new_from_gicon(gio_icon, 32)
|
||||||
|
pixbuf = gicon.get_pixbuf()
|
||||||
|
if pixbuf:
|
||||||
|
return pixbuf
|
||||||
|
|
||||||
|
alt_icon_path = ""
|
||||||
for dir in self.ICON_DIRS:
|
for dir in self.ICON_DIRS:
|
||||||
alt_icon_path = self.traverse_icons_folder(dir, icon)
|
alt_icon_path = self.traverse_icons_folder(dir, icon)
|
||||||
if alt_icon_path != "":
|
if alt_icon_path != "":
|
||||||
|
|
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 2.0 KiB |