diff --git a/README.md b/README.md
index dd95b27..5073190 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,18 @@ SolarFM is a Gtk+ Python file manager.
# Notes
Still Work in progress! Use at own risk!
+Additionally, if not building a .deb then just move the contents of user_config to their respective folders.
+Copy the share/solarfm folder to your user .config/ directory too.
+
Install Setup
```
sudo apt-get install python3.8 wget python3-setproctitle python3-gi ffmpegthumbnailer steamcmd
```
+# Known Issues
+Doing Ctrl+D when in Terminator (maybe other terminals too) somehow propagates the signal to SolarFM too.
+A selected file in the active quad-pane will move to trash since it is the defaul keybinding for that action.
+
# TODO
Add simpleish preview plugin for various file types.
diff --git a/bin/REMOVE.txt b/bin/REMOVE.txt
deleted file mode 100644
index f95d44d..0000000
--- a/bin/REMOVE.txt
+++ /dev/null
@@ -1 +0,0 @@
-Remove me...
diff --git a/bin/solarfm-0-0-1-x64.deb b/bin/solarfm-0-0-1-x64.deb
deleted file mode 100644
index f09cae7..0000000
Binary files a/bin/solarfm-0-0-1-x64.deb and /dev/null differ
diff --git a/plugins/searcher/mixins/grep_search_mixin.py b/plugins/searcher/mixins/grep_search_mixin.py
index 9e4da85..f485e3c 100644
--- a/plugins/searcher/mixins/grep_search_mixin.py
+++ b/plugins/searcher/mixins/grep_search_mixin.py
@@ -1,12 +1,11 @@
# Python imports
-import ctypes
+import time
import threading
import subprocess
import signal
import json
import shlex
from datetime import datetime
-libgcc_s = ctypes.CDLL('libgcc_s.so.1')
# Lib imports
import gi
diff --git a/plugins/searcher/utils/search.py b/plugins/searcher/utils/search.py
index a61eb12..b87ae6a 100755
--- a/plugins/searcher/utils/search.py
+++ b/plugins/searcher/utils/search.py
@@ -67,21 +67,26 @@ def grep_search(target=None, query=None):
collection = {}
for line in proc_data:
- file, line_no, data = line.split(":", 2)
- b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8')
- b64_data = base64.urlsafe_b64encode(data.encode('utf-8')).decode('utf-8')
+ try:
+ parts = line.split(":", 2)
+ if not len(parts) == 3:
+ continue
- if b64_file in collection.keys():
- collection[f"{b64_file}"][f"{line_no}"] = b64_data
- else:
- collection[f"{b64_file}"] = {}
- collection[f"{b64_file}"] = { f"{line_no}": b64_data}
+ file, line_no, data = parts
+ b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8')
+ b64_data = base64.urlsafe_b64encode(data.encode('utf-8')).decode('utf-8')
- try:
- data = f"GREP|{ts}|{json.dumps(collection, separators=(',', ':'), indent=4)}"
- send_ipc_message(data)
- except Exception as e:
- ...
+ if b64_file in collection.keys():
+ collection[f"{b64_file}"][f"{line_no}"] = b64_data
+ else:
+ collection[f"{b64_file}"] = {}
+ collection[f"{b64_file}"] = { f"{line_no}": b64_data}
+
+
+ data = f"GREP|{ts}|{json.dumps(collection, separators=(',', ':'), indent=4)}"
+ send_ipc_message(data)
+ except Exception as e:
+ traceback.print_exc()
collection = {}
diff --git a/src/debs/chownAll.sh b/src/debs/chown_all.sh
similarity index 100%
rename from src/debs/chownAll.sh
rename to src/debs/chown_all.sh
diff --git a/src/debs/solarfm-0-0-1-x64/DEBIAN/postrm b/src/debs/solarfm-0-0-1-x64/DEBIAN/postrm
index eb94f1c..2646766 100755
--- a/src/debs/solarfm-0-0-1-x64/DEBIAN/postrm
+++ b/src/debs/solarfm-0-0-1-x64/DEBIAN/postrm
@@ -1,11 +1,12 @@
#!/bin/bash
-#postrm (script executed after uninstalling the package)
-#set -e
+# Note: postrm (script executed after uninstalling the package)
+# set -e
+
if [ -f /bin/solarfm ]; then
rm /bin/solarfm
fi
-if [ -d /opt/SolarFM ]; then
- rm -rf /opt/SolarFM
+if [ -f /opt/solarfm.zip ]; then
+ rm /opt/solarfm.zip
fi
diff --git a/src/debs/solarfm-0-0-1-x64/bin/solarfm b/src/debs/solarfm-0-0-1-x64/bin/solarfm
old mode 100644
new mode 100755
index 53fc165..01ad8f9
Binary files a/src/debs/solarfm-0-0-1-x64/bin/solarfm and b/src/debs/solarfm-0-0-1-x64/bin/solarfm differ
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__builtins__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__builtins__.py
deleted file mode 100644
index 02c8d57..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__builtins__.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Python imports
-import builtins
-
-# Lib imports
-
-# Application imports
-from ipc_server import IPCServer
-
-
-
-
-class EventSystem(IPCServer):
- """ Inheret IPCServerMixin. Create an pub/sub systems. """
-
- def __init__(self):
- super(EventSystem, self).__init__()
-
- # NOTE: The format used is list of [type, target, (data,)] Where:
- # type is useful context for control flow,
- # target is the method to call,
- # data is the method parameters to give
- # Where data may be any kind of data
- self._gui_events = []
- self._module_events = []
-
-
-
- # Makeshift fake "events" type system FIFO
- def _pop_gui_event(self):
- if len(self._gui_events) > 0:
- return self._gui_events.pop(0)
- return None
-
- def _pop_module_event(self):
- if len(self._module_events) > 0:
- return self._module_events.pop(0)
- return None
-
-
- def push_gui_event(self, event):
- if len(event) == 3:
- self._gui_events.append(event)
- return None
-
- raise Exception("Invald event format! Please do: [type, target, (data,)]")
-
- def push_module_event(self, event):
- if len(event) == 3:
- self._module_events.append(event)
- return None
-
- raise Exception("Invald event format! Please do: [type, target, (data,)]")
-
- def read_gui_event(self):
- return self._gui_events[0]
-
- def read_module_event(self):
- return self._module_events[0]
-
- def consume_gui_event(self):
- return self._pop_gui_event()
-
- def consume_module_event(self):
- return self._pop_module_event()
-
-
-
-# NOTE: Just reminding myself we can add to builtins two different ways...
-# __builtins__.update({"event_system": Builtins()})
-builtins.app_name = "SolarFM"
-builtins.event_system = EventSystem()
-builtins.event_sleep_time = 0.2
-builtins.debug = False
-builtins.trace_debug = False
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__init__.py
deleted file mode 100644
index 5416f23..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Base module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__main__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__main__.py
deleted file mode 100644
index 22b79dd..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/__main__.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python3
-
-
-# Python imports
-import argparse, faulthandler, traceback
-from setproctitle import setproctitle
-
-import tracemalloc
-tracemalloc.start()
-
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk
-
-# Application imports
-from app import Application
-
-
-if __name__ == "__main__":
- """ Set process title, get arguments, and create GTK main thread. """
-
- try:
- # import web_pdb
- # web_pdb.set_trace()
-
- setproctitle('SolarFM')
- faulthandler.enable() # For better debug info
- parser = argparse.ArgumentParser()
- # Add long and short arguments
- 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.")
-
- # Read arguments (If any...)
- args, unknownargs = parser.parse_known_args()
-
- Application(args, unknownargs)
- Gtk.main()
- except Exception as e:
- traceback.print_exc()
- quit()
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/app.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/app.py
deleted file mode 100644
index 3e092c9..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/app.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Python imports
-import os, inspect, time
-
-# Lib imports
-
-# Application imports
-from utils.settings import Settings
-from context.controller import Controller
-from __builtins__ import EventSystem
-
-
-
-
-class Application(EventSystem):
- """ Create Settings and Controller classes. Bind signal to Builder. Inherit from Builtins to bind global methods and classes. """
-
- def __init__(self, args, unknownargs):
- if not trace_debug:
- event_system.create_ipc_server()
- time.sleep(0.1)
-
- if not event_system.is_ipc_alive:
- if unknownargs:
- for arg in unknownargs:
- if os.path.isdir(arg):
- message = f"FILE|{arg}"
- event_system.send_ipc_message(message)
-
- if args.new_tab and os.path.isdir(args.new_tab):
- message = f"FILE|{args.new_tab}"
- event_system.send_ipc_message(message)
-
- raise Exception("IPC Server Exists: Will send path(s) to it and close...")
-
-
- settings = Settings()
- settings.create_window()
-
- controller = Controller(args, unknownargs, settings)
- if not controller:
- raise Exception("Controller exited and doesn't exist...")
-
- # Gets the methods from the classes and sets to handler.
- # Then, builder connects to any signals it needs.
- classes = [controller]
- 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))
-
- settings.builder.connect_signals(handlers)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/__init__.py
deleted file mode 100644
index 90cfadc..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
- Gtk Bound Signal Module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller.py
deleted file mode 100644
index fc7fa7c..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Python imports
-import os, gc, threading, time
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk, GLib
-
-# Application imports
-from .mixins.exception_hook_mixin import ExceptionHookMixin
-from .mixins.ui_mixin import UIMixin
-from .signals.ipc_signals_mixin import IPCSignalsMixin
-from .signals.keyboard_signals_mixin import KeyboardSignalsMixin
-from .controller_data import Controller_Data
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
- return wrapper
-
-
-
-
-class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMixin, Controller_Data):
- """ Controller coordinates the mixins and is somewhat the root hub of it all. """
- def __init__(self, args, unknownargs, _settings):
- self.setup_controller_data(_settings)
- self.window.show()
-
- self.generate_windows(self.state)
- self.plugins.launch_plugins()
-
- if debug:
- self.window.set_interactive_debugging(True)
-
- if not trace_debug:
- self.gui_event_observer()
-
- if unknownargs:
- for arg in unknownargs:
- if os.path.isdir(arg):
- message = f"FILE|{arg}"
- event_system.send_ipc_message(message)
-
- if args.new_tab and os.path.isdir(args.new_tab):
- message = f"FILE|{args.new_tab}"
- event_system.send_ipc_message(message)
-
-
- def tear_down(self, widget=None, eve=None):
- event_system.send_ipc_message("close server")
- self.fm_controller.save_state()
- time.sleep(event_sleep_time)
- Gtk.main_quit()
-
-
- @threaded
- def gui_event_observer(self):
- while True:
- time.sleep(event_sleep_time)
- event = event_system.consume_gui_event()
- if event:
- try:
- type, target, data = event
- if type:
- method = getattr(self.__class__, "handle_gui_event_and_set_message")
- GLib.idle_add(method, *(self, type, target, data))
- else:
- method = getattr(self.__class__, target)
- GLib.idle_add(method, *(self, *data,))
- except Exception as e:
- print(repr(e))
-
- def handle_gui_event_and_set_message(self, type, target, parameters):
- method = getattr(self.__class__, f"{target}")
- data = method(*(self, *parameters))
- self.plugins.send_message_to_plugin(type, data)
-
- def open_terminal(self, widget=None, eve=None):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- dir = tab.get_current_directory()
- tab.execute(f"{tab.terminal_app}", dir)
-
- def save_load_session(self, action="save_session"):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- save_load_dialog = self.builder.get_object("save_load_dialog")
-
- if action == "save_session":
- self.fm_controller.save_state()
- return
- elif action == "save_session_as":
- save_load_dialog.set_action(Gtk.FileChooserAction.SAVE)
- elif action == "load_session":
- save_load_dialog.set_action(Gtk.FileChooserAction.OPEN)
- else:
- raise Exception(f"Unknown action given: {action}")
-
- save_load_dialog.set_current_folder(tab.get_current_directory())
- save_load_dialog.set_current_name("session.json")
- response = save_load_dialog.run()
- if response == Gtk.ResponseType.OK:
- if action == "save_session_as":
- path = f"{save_load_dialog.get_current_folder()}/{save_load_dialog.get_current_name()}"
- self.fm_controller.save_state(path)
- elif action == "load_session":
- path = f"{save_load_dialog.get_file().get_path()}"
- session_json = self.fm_controller.load_state(path)
- self.load_session(session_json)
- if (response == Gtk.ResponseType.CANCEL) or (response == Gtk.ResponseType.DELETE_EVENT):
- pass
-
- save_load_dialog.hide()
-
- def load_session(self, session_json):
- if debug:
- print(f"Session Data: {session_json}")
-
- self.ctrl_down = False
- self.shift_down = False
- self.alt_down = False
- for notebook in self.notebooks:
- self.clear_children(notebook)
-
- self.fm_controller.unload_tabs_and_windows()
- self.generate_windows(session_json)
- gc.collect()
-
-
- def do_action_from_menu_controls(self, widget, event_button):
- action = widget.get_name()
- self.hide_context_menu()
- self.hide_new_file_menu()
- self.hide_edit_file_menu()
-
- if action == "open":
- self.open_files()
- if action == "open_with":
- self.show_appchooser_menu()
- if action == "execute":
- self.execute_files()
- if action == "execute_in_terminal":
- self.execute_files(in_terminal=True)
- if action == "rename":
- self.rename_files()
- if action == "cut":
- self.to_copy_files.clear()
- self.cut_files()
- if action == "copy":
- self.to_cut_files.clear()
- self.copy_files()
- if action == "paste":
- self.paste_files()
- if action == "archive":
- self.show_archiver_dialogue()
- if action == "delete":
- self.delete_files()
- if action == "trash":
- self.trash_files()
- if action == "go_to_trash":
- self.path_entry.set_text(self.trash_files_path)
- if action == "restore_from_trash":
- self.restore_trash_files()
- if action == "empty_trash":
- self.empty_trash()
- if action == "create":
- self.show_new_file_menu()
- if action in ["save_session", "save_session_as", "load_session"]:
- self.save_load_session(action)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller_data.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller_data.py
deleted file mode 100644
index 28a09e8..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/controller_data.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# Python imports
-import sys, os, signal
-
-# Lib imports
-from gi.repository import GLib
-
-# Application imports
-from trasher.xdgtrash import XDGTrash
-from shellfm.windows.controller import WindowController
-from plugins.plugins import Plugins
-
-
-
-
-class Controller_Data:
- """ Controller_Data contains most of the state of the app at ay given time. It also has some support methods. """
-
- def setup_controller_data(self, _settings):
- self.trashman = XDGTrash()
- self.fm_controller = WindowController()
- self.plugins = Plugins(_settings)
- self.state = self.fm_controller.load_state()
- self.trashman.regenerate()
-
- self.settings = _settings
- self.builder = self.settings.get_builder()
- self.logger = self.settings.get_logger()
-
- self.window = self.settings.get_main_window()
- self.window1 = self.builder.get_object("window_1")
- self.window2 = self.builder.get_object("window_2")
- self.window3 = self.builder.get_object("window_3")
- self.window4 = self.builder.get_object("window_4")
- self.message_popup_widget = self.builder.get_object("message_popup_widget")
- self.message_text_view = self.builder.get_object("message_text_view")
- self.message_buffer = self.builder.get_object("message_buffer")
- self.arc_command_buffer = self.builder.get_object("arc_command_buffer")
-
- self.exists_file_rename_bttn = self.builder.get_object("exists_file_rename_bttn")
- self.warning_alert = self.builder.get_object("warning_alert")
- self.edit_file_menu = self.builder.get_object("edit_file_menu")
- self.file_exists_dialog = self.builder.get_object("file_exists_dialog")
- self.exists_file_label = self.builder.get_object("exists_file_label")
- self.exists_file_field = self.builder.get_object("exists_file_field")
- self.path_menu = self.builder.get_object("path_menu")
- self.path_entry = self.builder.get_object("path_entry")
-
- self.bottom_size_label = self.builder.get_object("bottom_size_label")
- self.bottom_file_count_label = self.builder.get_object("bottom_file_count_label")
- self.bottom_path_label = self.builder.get_object("bottom_path_label")
-
- self.trash_files_path = GLib.get_user_data_dir() + "/Trash/files"
- self.trash_info_path = GLib.get_user_data_dir() + "/Trash/info"
-
- # In compress commands:
- # %n: First selected filename/dir to archive
- # %N: All selected filenames/dirs to archive, or (with %O) a single filename
- # %o: Resulting single archive file
- # %O: Resulting archive per source file/directory (use changes %N meaning)
- #
- # In extract commands:
- # %x: Archive file to extract
- # %g: Unique extraction target filename with optional subfolder
- # %G: Unique extraction target filename, never with subfolder
- #
- # In list commands:
- # %x: Archive to list
- #
- # Plus standard bash variables are accepted.
- self.arc_commands = [ '$(which 7za || echo 7zr) a %o %N',
- 'zip -r %o %N',
- 'rar a -r %o %N',
- 'tar -cvf %o %N',
- 'tar -cvjf %o %N',
- 'tar -cvzf %o %N',
- 'tar -cvJf %o %N',
- 'gzip -c %N > %O',
- 'xz -cz %N > %O'
- ]
-
- self.notebooks = [self.window1, self.window2, self.window3, self.window4]
- self.selected_files = []
- self.to_copy_files = []
- self.to_cut_files = []
- self.soft_update_lock = {}
-
- self.single_click_open = False
- self.is_pane1_hidden = False
- self.is_pane2_hidden = False
- self.is_pane3_hidden = False
- self.is_pane4_hidden = False
-
- self.override_drop_dest = None
- self.is_searching = False
- self.search_icon_grid = None
- self.search_tab = None
-
- self.skip_edit = False
- self.cancel_edit = False
- self.ctrl_down = False
- self.shift_down = False
- self.alt_down = False
-
- self.success_color = self.settings.get_success_color()
- self.warning_color = self.settings.get_warning_color()
- self.error_color = self.settings.get_error_color()
-
- sys.excepthook = self.custom_except_hook
- self.window.connect("delete-event", self.tear_down)
- GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down)
-
- def get_current_state(self):
- '''
- Returns the state info most useful for any given context and action intent.
-
- Parameters:
- a (obj): self
-
- Returns:
- wid, tid, tab, icon_grid, store
- '''
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- icon_grid = self.builder.get_object(f"{wid}|{tid}|icon_grid")
- store = icon_grid.get_model()
- return wid, tid, tab, icon_grid, store
-
-
- def clear_console(self):
- ''' Clears the terminal screen. '''
- os.system('cls' if os.name == 'nt' else 'clear')
-
- def call_method(self, _method_name, data = None):
- '''
- Calls a method from scope of class.
-
- Parameters:
- a (obj): self
- b (str): method name to be called
- c (*): Data (if any) to be passed to the method.
- Note: It must be structured according to the given methods requirements.
-
- Returns:
- Return data is that which the calling method gives.
- '''
- method_name = str(_method_name)
- method = getattr(self, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
- return method(data) if data else method()
-
- def has_method(self, obj, name):
- ''' Checks if a given method exists. '''
- return callable(getattr(obj, name, None))
-
- def clear_children(self, widget):
- ''' Clear children of a gtk widget. '''
- for child in widget.get_children():
- widget.remove(child)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/__init__.py
deleted file mode 100644
index ded9abc..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Mixins module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/exception_hook_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/exception_hook_mixin.py
deleted file mode 100644
index 08d29cb..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/exception_hook_mixin.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Python imports
-import traceback, threading, time
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk, GLib
-
-# Application imports
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
- return wrapper
-
-
-class ExceptionHookMixin:
- """ ExceptionHookMixin custom exception hook to reroute to a Gtk text area. """
-
- def custom_except_hook(self, exec_type, value, _traceback):
- trace = ''.join(traceback.format_tb(_traceback))
- data = f"Exec Type: {exec_type} <--> Value: {value}\n\n{trace}\n\n\n\n"
- start_itr = self.message_buffer.get_start_iter()
- self.message_buffer.place_cursor(start_itr)
- self.display_message(self.error, data)
-
- def display_message(self, type, text, seconds=None):
- self.message_buffer.insert_at_cursor(text)
- self.message_popup_widget.popup()
- if seconds:
- self.hide_message_timeout(seconds)
-
- @threaded
- def hide_message_timeout(self, seconds=3):
- time.sleep(seconds)
- GLib.idle_add(self.message_popup_widget.popdown)
-
- def save_debug_alerts(self, widget=None, eve=None):
- start_itr, end_itr = self.message_buffer.get_bounds()
- save_location_prompt = Gtk.FileChooserDialog("Choose Save Folder", self.window, \
- action = Gtk.FileChooserAction.SAVE, \
- buttons = (Gtk.STOCK_CANCEL, \
- Gtk.ResponseType.CANCEL, \
- Gtk.STOCK_SAVE, \
- Gtk.ResponseType.OK))
-
- text = self.message_buffer.get_text(start_itr, end_itr, False)
- resp = save_location_prompt.run()
- if (resp == Gtk.ResponseType.CANCEL) or (resp == Gtk.ResponseType.DELETE_EVENT):
- pass
- elif resp == Gtk.ResponseType.OK:
- target = save_location_prompt.get_filename();
- with open(target, "w") as f:
- f.write(text)
-
- save_location_prompt.destroy()
-
-
- def set_arc_buffer_text(self, widget=None, eve=None):
- sid = widget.get_active_id()
- self.arc_command_buffer.set_text(self.arc_commands[int(sid)])
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/show_hide_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/show_hide_mixin.py
deleted file mode 100644
index 2e7a4fd..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/show_hide_mixin.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Python imports
-
-# Gtk imports
-import gi
-gi.require_version('Gtk', '3.0')
-gi.require_version('Gdk', '3.0')
-from gi.repository import Gtk, Gdk
-
-# Application imports
-
-
-class ShowHideMixin:
- def show_messages_popup(self, type, text, seconds=None):
- self.message_popup_widget.popup()
-
- def stop_file_searching(self, widget=None, eve=None):
- self.is_searching = False
-
- def show_exists_page(self, widget=None, eve=None):
- response = self.file_exists_dialog.run()
- self.file_exists_dialog.hide()
-
- if response == Gtk.ResponseType.OK:
- return "rename"
- if response == Gtk.ResponseType.ACCEPT:
- return "rename_auto"
- if response == Gtk.ResponseType.CLOSE:
- return "rename_auto_all"
- if response == Gtk.ResponseType.YES:
- return "overwrite"
- if response == Gtk.ResponseType.APPLY:
- return "overwrite_all"
- if response == Gtk.ResponseType.NO:
- return "skip"
- if response == Gtk.ResponseType.REJECT:
- return "skip_all"
-
- def hide_exists_page_rename(self, widget=None, eve=None):
- self.file_exists_dialog.response(Gtk.ResponseType.OK)
-
- def hide_exists_page_auto_rename(self, widget=None, eve=None):
- self.file_exists_dialog.response(Gtk.ResponseType.ACCEPT)
-
- def hide_exists_page_auto_rename_all(self, widget=None, eve=None):
- self.file_exists_dialog.response(Gtk.ResponseType.CLOSE)
-
-
- def show_about_page(self, widget=None, eve=None):
- about_page = self.builder.get_object("about_page")
- response = about_page.run()
- if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]:
- self.hide_about_page()
-
- def hide_about_page(self, widget=None, eve=None):
- self.builder.get_object("about_page").hide()
-
-
- def show_archiver_dialogue(self, widget=None, eve=None):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- archiver_dialogue = self.builder.get_object("archiver_dialogue")
- archiver_dialogue.set_action(Gtk.FileChooserAction.SAVE)
- archiver_dialogue.set_current_folder(tab.get_current_directory())
- archiver_dialogue.set_current_name("arc.7z")
-
- response = archiver_dialogue.run()
- if response == Gtk.ResponseType.OK:
- self.archive_files(archiver_dialogue)
- if (response == Gtk.ResponseType.CANCEL) or (response == Gtk.ResponseType.DELETE_EVENT):
- pass
-
- archiver_dialogue.hide()
-
- def hide_archiver_dialogue(self, widget=None, eve=None):
- self.builder.get_object("archiver_dialogue").hide()
-
-
- def show_appchooser_menu(self, widget=None, eve=None):
- appchooser_menu = self.builder.get_object("appchooser_menu")
- appchooser_widget = self.builder.get_object("appchooser_widget")
- response = appchooser_menu.run()
-
- if response == Gtk.ResponseType.OK:
- self.open_with_files(appchooser_widget)
- self.hide_appchooser_menu()
-
- if response == Gtk.ResponseType.CANCEL:
- self.hide_appchooser_menu()
-
-
- def hide_appchooser_menu(self, widget=None, eve=None):
- self.builder.get_object("appchooser_menu").hide()
-
- def run_appchooser_launch(self, widget=None, eve=None):
- dialog = widget.get_parent().get_parent()
- dialog.response(Gtk.ResponseType.OK)
-
-
- def show_plugins_popup(self, widget=None, eve=None):
- self.builder.get_object("plugin_list").popup()
-
- def hide_plugins_popup(self, widget=None, eve=None):
- self.builder.get_object("plugin_list").hide()
-
- def show_context_menu(self, widget=None, eve=None):
- self.builder.get_object("context_menu").run()
-
- def hide_context_menu(self, widget=None, eve=None):
- self.builder.get_object("context_menu").hide()
-
-
- def show_new_file_menu(self, widget=None, eve=None):
- self.builder.get_object("context_menu_fname").set_text("")
-
- new_file_menu = self.builder.get_object("new_file_menu")
- response = new_file_menu.run()
- if response == Gtk.ResponseType.APPLY:
- self.create_files()
- if response == Gtk.ResponseType.CANCEL:
- self.hide_new_file_menu()
-
- def hide_new_file_menu(self, widget=None, eve=None):
- self.builder.get_object("new_file_menu").hide()
-
- def show_edit_file_menu(self, widget=None, eve=None):
- if widget:
- widget.grab_focus()
-
- response = self.edit_file_menu.run()
- if response == Gtk.ResponseType.CLOSE:
- self.skip_edit = True
- if response == Gtk.ResponseType.CANCEL:
- self.cancel_edit = True
-
- def hide_edit_file_menu(self, widget=None, eve=None):
- self.builder.get_object("edit_file_menu").hide()
-
- def hide_edit_file_menu_enter_key(self, widget=None, eve=None):
- keyname = Gdk.keyval_name(eve.keyval).lower()
- if keyname in ["return", "enter"]:
- self.builder.get_object("edit_file_menu").hide()
-
- def hide_edit_file_menu_skip(self, widget=None, eve=None):
- self.edit_file_menu.response(Gtk.ResponseType.CLOSE)
-
- def hide_edit_file_menu_cancel(self, widget=None, eve=None):
- self.edit_file_menu.response(Gtk.ResponseType.CANCEL)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/__init__.py
deleted file mode 100644
index 991f9a2..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-UI module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/pane_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/pane_mixin.py
deleted file mode 100644
index 3d2c888..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/pane_mixin.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Python imports
-
-# Lib imports
-
-# Application imports
-
-
-
-
-# TODO: Should rewrite to try and support more windows more naturally
-class PaneMixin:
- """docstring for PaneMixin"""
-
- def toggle_pane(self, child):
- if child.is_visible():
- child.hide()
- else:
- child.show()
-
- def run_flag_toggle(self, pane_index):
- tggl_button = self.builder.get_object(f"tggl_notebook_{pane_index}")
- if pane_index == 1:
- self.is_pane1_hidden = not self.is_pane1_hidden
- tggl_button.set_active(not self.is_pane1_hidden)
- return self.is_pane1_hidden
- elif pane_index == 2:
- self.is_pane2_hidden = not self.is_pane2_hidden
- tggl_button.set_active(not self.is_pane2_hidden)
- return self.is_pane2_hidden
- elif pane_index == 3:
- self.is_pane3_hidden = not self.is_pane3_hidden
- tggl_button.set_active(not self.is_pane3_hidden)
- return self.is_pane3_hidden
- elif pane_index == 4:
- self.is_pane4_hidden = not self.is_pane4_hidden
- tggl_button.set_active(not self.is_pane4_hidden)
- return self.is_pane4_hidden
-
- def toggle_notebook_pane(self, widget, eve=None):
- name = widget.get_name()
- pane_index = int(name[-1])
- master_pane = self.builder.get_object("pane_master")
- pane = self.builder.get_object("pane_top") if pane_index in [1, 2] else self.builder.get_object("pane_bottom")
-
- state = self.run_flag_toggle(pane_index)
- if self.is_pane1_hidden and self.is_pane2_hidden and self.is_pane3_hidden and self.is_pane4_hidden:
- state = self.run_flag_toggle(pane_index)
- self._save_state(state, pane_index)
- return
-
- child = pane.get_child1() if pane_index in [1, 3] else pane.get_child2()
-
- self.toggle_pane(child)
- self._save_state(state, pane_index)
-
- def _save_state(self, state, pane_index):
- window = self.fm_controller.get_window_by_index(pane_index - 1)
- window.set_is_hidden(state)
- self.fm_controller.save_state()
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/tab_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/tab_mixin.py
deleted file mode 100644
index 9ce3953..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/tab_mixin.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Python imports
-import os
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk
-
-# Application imports
-from .widget_mixin import WidgetMixin
-
-
-
-
-class TabMixin(WidgetMixin):
- """docstring for TabMixin"""
-
- def create_tab(self, wid, path=None):
- notebook = self.builder.get_object(f"window_{wid}")
- path_entry = self.builder.get_object(f"path_entry")
- tab = self.fm_controller.add_tab_for_window_by_nickname(f"window_{wid}")
- tab.logger = self.logger
-
- tab.set_wid(wid)
- if path: tab.set_path(path)
-
- tab_widget = self.create_tab_widget(tab)
- scroll, store = self.create_icon_grid_widget(tab, wid)
- # TODO: Fix global logic to make the below work too
- # scroll, store = self.create_icon_tree_widget(tab, wid)
- index = notebook.append_page(scroll, tab_widget)
-
- self.fm_controller.set__wid_and_tid(wid, tab.get_id())
- path_entry.set_text(tab.get_current_directory())
- notebook.show_all()
- notebook.set_current_page(index)
-
- ctx = notebook.get_style_context()
- ctx.add_class("notebook-unselected-focus")
- notebook.set_tab_reorderable(scroll, True)
- self.load_store(tab, store)
- self.set_window_title()
- self.set_file_watcher(tab)
-
-
-
-
- def close_tab(self, button, eve=None):
- notebook = button.get_parent().get_parent()
- wid = int(notebook.get_name()[-1])
- tid = self.get_id_from_tab_box(button.get_parent())
- scroll = self.builder.get_object(f"{wid}|{tid}")
- page = notebook.page_num(scroll)
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- watcher = tab.get_dir_watcher()
-
- watcher.cancel()
- self.get_fm_window(wid).delete_tab_by_id(tid)
- notebook.remove_page(page)
- self.fm_controller.save_state()
- self.set_window_title()
-
- def on_tab_reorder(self, child, page_num, new_index):
- wid, tid = page_num.get_name().split("|")
- window = self.get_fm_window(wid)
- tab = None
-
- for i, tab in enumerate(window.get_all_tabs()):
- if tab.get_id() == tid:
- _tab = window.get_tab_by_id(tid)
- watcher = _tab.get_dir_watcher()
- watcher.cancel()
- window.get_all_tabs().insert(new_index, window.get_all_tabs().pop(i))
-
- tab = window.get_tab_by_id(tid)
- self.set_file_watcher(tab)
- self.fm_controller.save_state()
-
- def on_tab_switch_update(self, notebook, content=None, index=None):
- self.selected_files.clear()
- wid, tid = content.get_children()[0].get_name().split("|")
- self.fm_controller.set__wid_and_tid(wid, tid)
- self.set_path_text(wid, tid)
- self.set_window_title()
-
- def get_id_from_tab_box(self, tab_box):
- return tab_box.get_children()[2].get_text()
-
- def get_tab_label(self, notebook, icon_grid):
- return notebook.get_tab_label(icon_grid.get_parent()).get_children()[0]
-
- def get_tab_close(self, notebook, icon_grid):
- return notebook.get_tab_label(icon_grid.get_parent()).get_children()[1]
-
- def get_tab_icon_grid_from_notebook(self, notebook):
- return notebook.get_children()[1].get_children()[0]
-
- def refresh_tab(data=None):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- tab.load_directory()
- self.load_store(tab, store)
-
- def update_tab(self, tab_label, tab, store, wid, tid):
- self.load_store(tab, store)
- self.set_path_text(wid, tid)
-
- char_width = len(tab.get_end_of_path())
- tab_label.set_width_chars(char_width)
- tab_label.set_label(tab.get_end_of_path())
- self.set_window_title()
- self.set_file_watcher(tab)
- self.fm_controller.save_state()
-
- def do_action_from_bar_controls(self, widget, eve=None):
- action = widget.get_name()
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- notebook = self.builder.get_object(f"window_{wid}")
- store, tab_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
-
- if action == "create_tab":
- dir = tab.get_current_directory()
- self.create_tab(wid, dir)
- self.fm_controller.save_state()
- return
- if action == "go_up":
- tab.pop_from_path()
- if action == "go_home":
- tab.set_to_home()
- if action == "refresh_tab":
- tab.load_directory()
- if action == "path_entry":
- focused_obj = self.window.get_focus()
- dir = f"{tab.get_current_directory()}/"
- path = widget.get_text()
-
- if isinstance(focused_obj, Gtk.Entry):
- path_menu_buttons = self.builder.get_object("path_menu_buttons")
- query = widget.get_text().replace(dir, "")
- files = tab.get_files() + tab.get_hidden()
-
- self.clear_children(path_menu_buttons)
- show_path_menu = False
- for file, hash in files:
- if os.path.isdir(f"{dir}{file}"):
- if query.lower() in file.lower():
- button = Gtk.Button(label=file)
- button.show()
- button.connect("clicked", self.set_path_entry)
- path_menu_buttons.add(button)
- show_path_menu = True
-
- if not show_path_menu:
- self.path_menu.popdown()
- else:
- self.path_menu.popup()
- widget.grab_focus_without_selecting()
- widget.set_position(-1)
-
- if path.endswith(".") or path == dir:
- return
-
- if not tab.set_path(path):
- return
-
- self.update_tab(tab_label, tab, store, wid, tid)
-
- try:
- widget.grab_focus_without_selecting()
- widget.set_position(-1)
- except Exception as e:
- pass
-
- def set_path_entry(self, button=None, eve=None):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- path = f"{tab.get_current_directory()}/{button.get_label()}"
- path_entry = self.builder.get_object("path_entry")
- path_entry.set_text(path)
- path_entry.grab_focus_without_selecting()
- path_entry.set_position(-1)
- self.path_menu.popdown()
-
- def keyboard_close_tab(self):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- notebook = self.builder.get_object(f"window_{wid}")
- scroll = self.builder.get_object(f"{wid}|{tid}")
- page = notebook.page_num(scroll)
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- watcher = tab.get_dir_watcher()
- watcher.cancel()
-
- self.get_fm_window(wid).delete_tab_by_id(tid)
- notebook.remove_page(page)
- self.fm_controller.save_state()
- self.set_window_title()
-
- def show_hide_hidden_files(self):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- tab.set_hiding_hidden(not tab.is_hiding_hidden())
- tab.load_directory()
- self.builder.get_object("refresh_tab").released()
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_file_action_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_file_action_mixin.py
deleted file mode 100644
index 1a84305..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_file_action_mixin.py
+++ /dev/null
@@ -1,457 +0,0 @@
-# Python imports
-import os, time, threading
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk, GObject, GLib, Gio
-
-# Application imports
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
- return wrapper
-
-
-class WidgetFileActionMixin:
- """docstring for WidgetFileActionMixin"""
-
- def sizeof_fmt(self, num, suffix="B"):
- for unit in ["", "K", "M", "G", "T", "Pi", "Ei", "Zi"]:
- if abs(num) < 1024.0:
- return f"{num:3.1f} {unit}{suffix}"
- num /= 1024.0
- return f"{num:.1f} Yi{suffix}"
-
- def get_dir_size(self, sdir):
- """Get the size of a directory. Based on code found online."""
- size = os.path.getsize(sdir)
-
- for item in os.listdir(sdir):
- item = os.path.join(sdir, item)
-
- if os.path.isfile(item):
- size = size + os.path.getsize(item)
- elif os.path.isdir(item):
- size = size + self.get_dir_size(item)
-
- return size
-
-
- def set_file_watcher(self, tab):
- if tab.get_dir_watcher():
- watcher = tab.get_dir_watcher()
- watcher.cancel()
- if debug:
- print(f"Watcher Is Cancelled: {watcher.is_cancelled()}")
-
- cur_dir = tab.get_current_directory()
-
- dir_watcher = Gio.File.new_for_path(cur_dir) \
- .monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, Gio.Cancellable())
-
- wid = tab.get_wid()
- tid = tab.get_id()
- dir_watcher.connect("changed", self.dir_watch_updates, (f"{wid}|{tid}",))
- tab.set_dir_watcher(dir_watcher)
-
- # NOTE: Too lazy to impliment a proper update handler and so just regen store and update tab.
- # Use a lock system to prevent too many update calls for certain instances but user can manually refresh if they have urgency
- def dir_watch_updates(self, file_monitor, file, other_file=None, eve_type=None, data=None):
- if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED,
- Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
- Gio.FileMonitorEvent.MOVED_OUT]:
- if debug:
- print(eve_type)
-
- if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]:
- self.update_on_soft_lock_end(data[0])
- elif data[0] in self.soft_update_lock.keys():
- self.soft_update_lock[data[0]]["last_update_time"] = time.time()
- else:
- self.soft_lock_countdown(data[0])
-
- @threaded
- def soft_lock_countdown(self, tab_widget):
- self.soft_update_lock[tab_widget] = { "last_update_time": time.time()}
-
- lock = True
- while lock:
- time.sleep(0.6)
- last_update_time = self.soft_update_lock[tab_widget]["last_update_time"]
- current_time = time.time()
- if (current_time - last_update_time) > 0.6:
- lock = False
-
-
- self.soft_update_lock.pop(tab_widget, None)
- GLib.idle_add(self.update_on_soft_lock_end, *(tab_widget,))
-
-
- def update_on_soft_lock_end(self, tab_widget):
- wid, tid = tab_widget.split("|")
- notebook = self.builder.get_object(f"window_{wid}")
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- icon_grid = self.builder.get_object(f"{wid}|{tid}|icon_grid")
- store = icon_grid.get_model()
- _store, tab_widget_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
-
- tab.load_directory()
- self.load_store(tab, store)
-
- tab_widget_label.set_label(tab.get_end_of_path())
-
- _wid, _tid, _tab, _icon_grid, _store = self.get_current_state()
-
- if [wid, tid] in [_wid, _tid]:
- self.set_bottom_labels(tab)
-
-
- def popup_search_files(self, wid, keyname):
- entry = self.builder.get_object(f"win{wid}_search_field")
- self.builder.get_object(f"win{wid}_search").popup()
- entry.set_text(keyname)
- entry.grab_focus_without_selecting()
- entry.set_position(-1)
-
- def do_file_search(self, widget, eve=None):
- query = widget.get_text()
- self.search_icon_grid.unselect_all()
- for i, file in enumerate(self.search_tab.get_files()):
- if query and query in file[0].lower():
- path = Gtk.TreePath().new_from_indices([i])
- self.search_icon_grid.select_path(path)
-
- items = self.search_icon_grid.get_selected_items()
- if len(items) == 1:
- self.search_icon_grid.scroll_to_path(items[0], True, 0.5, 0.5)
-
-
- def open_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
-
- for file in uris:
- tab.open_file_locally(file)
-
- def open_with_files(self, appchooser_widget):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- app_info = appchooser_widget.get_app_info()
- uris = self.format_to_uris(store, wid, tid, self.selected_files)
-
- tab.app_chooser_exec(app_info, uris)
-
- def execute_files(self, in_terminal=False):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- paths = self.format_to_uris(store, wid, tid, self.selected_files, True)
- current_dir = tab.get_current_directory()
- command = None
-
- for path in paths:
- command = f"exec '{path}'" if not in_terminal else f"{tab.terminal_app} -e '{path}'"
- tab.execute(command, start_dir=tab.get_current_directory(), use_os_system=False)
-
- def archive_files(self, archiver_dialogue):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- paths = self.format_to_uris(store, wid, tid, self.selected_files, True)
-
- save_target = archiver_dialogue.get_filename();
- sItr, eItr = self.arc_command_buffer.get_bounds()
- pre_command = self.arc_command_buffer.get_text(sItr, eItr, False)
- pre_command = pre_command.replace("%o", save_target)
- pre_command = pre_command.replace("%N", ' '.join(paths))
- command = f"{tab.terminal_app} -e '{pre_command}'"
-
- tab.execute(command, start_dir=None, use_os_system=True)
-
- def rename_files(self):
- rename_label = self.builder.get_object("file_to_rename_label")
- rename_input = self.builder.get_object("new_rename_fname")
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
-
- for uri in uris:
- entry = uri.split("/")[-1]
- rename_label.set_label(entry)
- rename_input.set_text(entry)
-
- self.show_edit_file_menu(rename_input)
- if self.skip_edit:
- self.skip_edit = False
- continue
- if self.cancel_edit:
- self.cancel_edit = False
- break
-
- rname_to = rename_input.get_text().strip()
- target = f"{tab.get_current_directory()}/{rname_to}"
- self.handle_files([uri], "rename", target)
-
-
- self.skip_edit = False
- self.cancel_edit = False
- self.hide_edit_file_menu()
- self.selected_files.clear()
-
- def cut_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
- self.to_cut_files = uris
-
- def copy_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
- self.to_copy_files = uris
-
- def paste_files(self):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- target = f"{tab.get_current_directory()}"
-
- if self.to_copy_files:
- self.handle_files(self.to_copy_files, "copy", target)
- elif self.to_cut_files:
- self.handle_files(self.to_cut_files, "move", target)
-
- def delete_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
- response = None
-
- self.warning_alert.format_secondary_text(f"Do you really want to delete the {len(uris)} file(s)?")
- for uri in uris:
- file = Gio.File.new_for_path(uri)
-
- if not response:
- response = self.warning_alert.run()
- self.warning_alert.hide()
- if response == Gtk.ResponseType.YES:
- type = file.query_file_type(flags=Gio.FileQueryInfoFlags.NONE)
-
- if type == Gio.FileType.DIRECTORY:
- tab.delete_file( file.get_path() )
- else:
- file.delete(cancellable=None)
- else:
- break
-
-
- def trash_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
- for uri in uris:
- self.trashman.trash(uri, False)
-
- def restore_trash_files(self):
- wid, tid, tab, icon_grid, store = self.get_current_state()
- uris = self.format_to_uris(store, wid, tid, self.selected_files, True)
- for uri in uris:
- self.trashman.restore(filename=uri.split("/")[-1], verbose=False)
-
- def empty_trash(self):
- self.trashman.empty(verbose=False)
-
-
- def create_files(self):
- fname_field = self.builder.get_object("context_menu_fname")
- file_name = fname_field.get_text().strip()
- type = self.builder.get_object("context_menu_type_toggle").get_state()
-
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- target = f"{tab.get_current_directory()}"
-
- if file_name:
- path = f"{target}/{file_name}"
-
- if type == True: # Create File
- self.handle_files([path], "create_file")
- else: # Create Folder
- self.handle_files([path], "create_dir")
-
- self.hide_new_file_menu()
-
- def move_files(self, files, target):
- self.handle_files(files, "move", target)
-
- # NOTE: Gtk recommends using fail flow than pre check which is more
- # race condition proof. They're right; but, they can't even delete
- # directories properly. So... f**k them. I'll do it my way.
- def handle_files(self, paths, action, _target_path=None):
- target = None
- _file = None
- response = None
- overwrite_all = False
- rename_auto_all = False
-
- for path in paths:
- try:
- if "file://" in path:
- path = path.split("file://")[1]
-
- file = Gio.File.new_for_path(path)
- if _target_path:
- if os.path.isdir(_target_path):
- info = file.query_info("standard::display-name", 0, cancellable=None)
- _target = f"{_target_path}/{info.get_display_name()}"
- _file = Gio.File.new_for_path(_target)
- else:
- _file = Gio.File.new_for_path(_target_path)
- else:
- _file = Gio.File.new_for_path(path)
-
-
- if _file.query_exists():
- if not overwrite_all and not rename_auto_all:
- self.setup_exists_data(file, _file)
- response = self.show_exists_page()
-
- if response == "overwrite_all":
- overwrite_all = True
- if response == "rename_auto_all":
- rename_auto_all = True
-
- if response == "rename":
- base_path = _file.get_parent().get_path()
- new_name = self.exists_file_field.get_text().strip()
- rfPath = f"{base_path}/{new_name}"
- _file = Gio.File.new_for_path(rfPath)
-
- if response == "rename_auto" or rename_auto_all:
- _file = self.rename_proc(_file)
-
- if response == "overwrite" or overwrite_all:
- type = _file.query_file_type(flags=Gio.FileQueryInfoFlags.NONE)
-
- if type == Gio.FileType.DIRECTORY:
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- tab.delete_file( _file.get_path() )
- else:
- _file.delete(cancellable=None)
-
- if response == "skip":
- continue
- if response == "skip_all":
- break
-
- if _target_path:
- target = _file
- else:
- file = _file
-
-
- if action == "create_file":
- file.create(flags=Gio.FileCreateFlags.NONE, cancellable=None)
- continue
- if action == "create_dir":
- file.make_directory(cancellable=None)
- continue
-
-
- type = file.query_file_type(flags=Gio.FileQueryInfoFlags.NONE)
- if type == Gio.FileType.DIRECTORY:
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- fPath = file.get_path()
- tPath = target.get_path()
- state = True
-
- if action == "copy":
- tab.copy_file(fPath, tPath)
- if action == "move" or action == "rename":
- tab.move_file(fPath, tPath)
- else:
- if action == "copy":
- file.copy(target, flags=Gio.FileCopyFlags.BACKUP, cancellable=None)
- if action == "move" or action == "rename":
- file.move(target, flags=Gio.FileCopyFlags.BACKUP, cancellable=None)
-
- except GObject.GError as e:
- raise OSError(e)
-
- self.exists_file_rename_bttn.set_sensitive(False)
-
-
- def setup_exists_data(self, from_file, to_file):
- from_info = from_file.query_info("standard::*,time::modified", 0, cancellable=None)
- to_info = to_file.query_info("standard::*,time::modified", 0, cancellable=None)
- exists_file_diff_from = self.builder.get_object("exists_file_diff_from")
- exists_file_diff_to = self.builder.get_object("exists_file_diff_to")
- exists_file_from = self.builder.get_object("exists_file_from")
- exists_file_to = self.builder.get_object("exists_file_to")
- from_date = from_info.get_modification_date_time()
- to_date = to_info.get_modification_date_time()
- from_size = from_info.get_size()
- to_size = to_info.get_size()
-
- exists_file_from.set_label(from_file.get_parent().get_path())
- exists_file_to.set_label(to_file.get_parent().get_path())
- self.exists_file_label.set_label(to_file.get_basename())
- self.exists_file_field.set_text(to_file.get_basename())
-
- # Returns: -1, 0 or 1 if dt1 is less than, equal to or greater than dt2.
- age = GLib.DateTime.compare(from_date, to_date)
- age_text = "( same time )"
- if age == -1:
- age_text = "older"
- if age == 1:
- age_text = "newer"
-
- size_text = "( same size )"
- if from_size < to_size:
- size_text = "smaller"
- if from_size > to_size:
- size_text = "larger"
-
- from_label_text = f"{age_text} & {size_text}"
- if age_text != "( same time )" or size_text != "( same size )":
- from_label_text = f"{from_date.format('%F %R')} {self.sizeof_fmt(from_size)} ( {from_size} bytes ) ( {age_text} & {size_text} )"
- to_label_text = f"{to_date.format('%F %R')} {self.sizeof_fmt(to_size)} ( {to_size} bytes )"
-
- exists_file_diff_from.set_text(from_label_text)
- exists_file_diff_to.set_text(to_label_text)
-
-
- def rename_proc(self, gio_file):
- full_path = gio_file.get_path()
- base_path = gio_file.get_parent().get_path()
- file_name = os.path.splitext(gio_file.get_basename())[0]
- extension = os.path.splitext(full_path)[-1]
- target = Gio.File.new_for_path(full_path)
- start = "-copy"
-
- if debug:
- print(f"Path: {full_path}")
- print(f"Base Path: {base_path}")
- print(f'Name: {file_name}')
- print(f"Extension: {extension}")
-
- i = 2
- while target.query_exists():
- try:
- value = file_name[(file_name.find(start)+len(start)):]
- int(value)
- file_name = file_name.split(start)[0]
- except Exception as e:
- pass
-
- target = Gio.File.new_for_path(f"{base_path}/{file_name}-copy{i}{extension}")
- i += 1
-
- return target
-
-
- def exists_rename_field_changed(self, widget):
- nfile_name = widget.get_text().strip()
- ofile_name = self.exists_file_label.get_label()
-
- if nfile_name:
- if nfile_name == ofile_name:
- self.exists_file_rename_bttn.set_sensitive(False)
- else:
- self.exists_file_rename_bttn.set_sensitive(True)
- else:
- self.exists_file_rename_bttn.set_sensitive(False)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_mixin.py
deleted file mode 100644
index 6f496f4..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/widget_mixin.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# Python imports
-import os, threading, subprocess, time
-
-# 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:
- """docstring for WidgetMixin"""
-
- def load_store(self, tab, store, save_state=False):
- store.clear()
- dir = tab.get_current_directory()
- files = tab.get_files()
-
- for i, file in enumerate(files):
- store.append([None, file[0]])
- self.create_icon(i, tab, store, dir, file[0])
-
- # NOTE: Not likely called often from here but it could be useful
- if save_state:
- self.fm_controller.save_state()
-
- @threaded
- def create_icon(self, i, tab, store, dir, file):
- icon = tab.create_icon(dir, file)
- fpath = f"{dir}/{file}"
- GLib.idle_add(self.update_store, (i, store, icon, tab, 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, tab, fpath = item
- itr = None
-
- try:
- itr = store.get_iter(i)
- except Exception as e:
- try:
- time.sleep(0.2)
- 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, tab.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(tab.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, tab):
- tab_widget = Gtk.ButtonBox()
- label = Gtk.Label()
- tid = Gtk.Label()
- close = Gtk.Button()
- icon = Gtk.Image(stock=Gtk.STOCK_CLOSE)
-
- label.set_label(f"{tab.get_end_of_path()}")
- label.set_width_chars(len(tab.get_end_of_path()))
- label.set_xalign(0.0)
- tid.set_label(f"{tab.get_id()}")
-
- close.add(icon)
- tab_widget.add(label)
- tab_widget.add(close)
- tab_widget.add(tid)
-
- close.connect("released", self.close_tab)
- tab_widget.show_all()
- tid.hide()
- return tab_widget
-
- def create_icon_grid_widget(self, tab, wid):
- scroll = Gtk.ScrolledWindow()
- grid = Gtk.IconView()
- store = Gtk.ListStore(GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, 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}|{tab.get_id()}")
- scroll.set_name(f"{wid}|{tab.get_id()}")
- self.builder.expose_object(f"{wid}|{tab.get_id()}|icon_grid", grid)
- self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll)
- return scroll, store
-
- def create_icon_tree_widget(self, tab, wid):
- scroll = Gtk.ScrolledWindow()
- grid = Gtk.TreeView()
- store = Gtk.TreeStore(GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, 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}|{tab.get_id()}")
- scroll.set_name(f"{wid}|{tab.get_id()}")
- grid.columns_autosize()
- self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll)
- return scroll, store
-
-
- def get_store_and_label_from_notebook(self, notebook, _name):
- icon_grid = None
- tab_label = None
- store = None
-
- for obj in notebook.get_children():
- icon_grid = obj.get_children()[0]
- name = icon_grid.get_name()
- if name == _name:
- store = icon_grid.get_model()
- tab_label = notebook.get_tab_label(obj).get_children()[0]
-
- return store, tab_label
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/window_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/window_mixin.py
deleted file mode 100644
index b1e3878..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui/window_mixin.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# Python imports
-import copy
-from os.path import isdir, isfile
-
-
-# Lib imports
-import gi
-gi.require_version('Gdk', '3.0')
-from gi.repository import Gdk, Gio
-
-# Application imports
-from .tab_mixin import TabMixin
-
-
-class WindowMixin(TabMixin):
- """docstring for WindowMixin"""
-
- def generate_windows(self, session_json = None):
- if session_json:
- for j, value in enumerate(session_json):
- i = j + 1
- notebook_tggl_button = self.builder.get_object(f"tggl_notebook_{i}")
- is_hidden = True if value[0]["window"]["isHidden"] == "True" else False
- tabs = value[0]["window"]["tabs"]
- self.fm_controller.create_window()
- notebook_tggl_button.set_active(True)
-
- for tab in tabs:
- self.create_new_tab_notebook(None, i, tab)
-
- if is_hidden:
- self.toggle_notebook_pane(notebook_tggl_button)
-
- try:
- if not self.is_pane4_hidden:
- icon_grid = self.window4.get_children()[1].get_children()[0]
- elif not self.is_pane3_hidden:
- icon_grid = self.window3.get_children()[1].get_children()[0]
- elif not self.is_pane2_hidden:
- icon_grid = self.window2.get_children()[1].get_children()[0]
- elif not self.is_pane1_hidden:
- icon_grid = self.window1.get_children()[1].get_children()[0]
-
- icon_grid.event(Gdk.Event().new(type=Gdk.EventType.BUTTON_RELEASE))
- icon_grid.event(Gdk.Event().new(type=Gdk.EventType.BUTTON_RELEASE))
- except Exception as e:
- print("\n: The saved session might be missing window data! :\nLocation: ~/.config/solarfm/session.json\nFix: Back it up and delete it to reset.\n")
- print(repr(e))
- else:
- for j in range(0, 4):
- i = j + 1
- self.fm_controller.create_window()
- self.create_new_tab_notebook(None, i, None)
-
-
- def get_fm_window(self, wid):
- return self.fm_controller.get_window_by_nickname(f"window_{wid}")
-
- def format_to_uris(self, store, wid, tid, treePaths, use_just_path=False):
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- dir = tab.get_current_directory()
- uris = []
-
- for path in treePaths:
- itr = store.get_iter(path)
- file = store.get(itr, 1)[0]
- fpath = ""
-
- if not use_just_path:
- fpath = f"file://{dir}/{file}"
- else:
- fpath = f"{dir}/{file}"
-
- uris.append(fpath)
-
- return uris
-
-
- def set_bottom_labels(self, tab):
- _wid, _tid, _tab, icon_grid, store = self.get_current_state()
- selected_files = icon_grid.get_selected_items()
- current_directory = tab.get_current_directory()
- path_file = Gio.File.new_for_path(current_directory)
- mount_file = path_file.query_filesystem_info(attributes="filesystem::*", cancellable=None)
- formatted_mount_free = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) )
- formatted_mount_size = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) )
-
- if self.trash_files_path == current_directory:
- self.builder.get_object("restore_from_trash").show()
- self.builder.get_object("empty_trash").show()
- else:
- self.builder.get_object("restore_from_trash").hide()
- self.builder.get_object("empty_trash").hide()
-
- # If something selected
- self.bottom_size_label.set_label(f"{formatted_mount_free} free / {formatted_mount_size}")
- self.bottom_path_label.set_label(tab.get_current_directory())
- if selected_files:
- uris = self.format_to_uris(store, _wid, _tid, selected_files, True)
- combined_size = 0
- for uri in uris:
- try:
- file_info = Gio.File.new_for_path(uri).query_info(attributes="standard::size",
- flags=Gio.FileQueryInfoFlags.NONE,
- cancellable=None)
- file_size = file_info.get_size()
- combined_size += file_size
- except Exception as e:
- if debug:
- print(repr(e))
-
-
- formatted_size = self.sizeof_fmt(combined_size)
- if tab.is_hiding_hidden():
- self.bottom_path_label.set_label(f" {len(uris)} / {tab.get_files_count()} ({formatted_size})")
- else:
- self.bottom_path_label.set_label(f" {len(uris)} / {tab.get_not_hidden_count()} ({formatted_size})")
-
- return
-
- # If nothing selected
- if tab.get_hidden():
- if tab.get_hidden_count() > 0:
- self.bottom_file_count_label.set_label(f"{tab.get_not_hidden_count()} visible ({tab.get_hidden_count()} hidden)")
- else:
- self.bottom_file_count_label.set_label(f"{tab.get_files_count()} items")
- else:
- self.bottom_file_count_label.set_label(f"{tab.get_files_count()} items")
-
-
-
- def set_window_title(self):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- notebook = self.builder.get_object(f"window_{wid}")
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- dir = tab.get_current_directory()
-
- for _notebook in self.notebooks:
- ctx = _notebook.get_style_context()
- ctx.remove_class("notebook-selected-focus")
- ctx.add_class("notebook-unselected-focus")
-
- ctx = notebook.get_style_context()
- ctx.remove_class("notebook-unselected-focus")
- ctx.add_class("notebook-selected-focus")
-
- self.window.set_title(f"SolarFM ~ {dir}")
- self.set_bottom_labels(tab)
-
- def set_path_text(self, wid, tid):
- path_entry = self.builder.get_object("path_entry")
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
- path_entry.set_text(tab.get_current_directory())
-
- def grid_set_selected_items(self, icons_grid):
- self.selected_files = icons_grid.get_selected_items()
-
- def grid_cursor_toggled(self, icons_grid):
- print("wat...")
-
- def grid_icon_single_click(self, icons_grid, eve):
- try:
- self.path_menu.popdown()
- wid, tid = icons_grid.get_name().split("|")
- self.fm_controller.set__wid_and_tid(wid, tid)
- self.set_path_text(wid, tid)
- self.set_window_title()
-
-
- if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 1: # l-click
- if self.single_click_open: # FIXME: need to find a way to pass the model index
- self.grid_icon_double_click(icons_grid)
- elif eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 3: # r-click
- self.show_context_menu()
-
- except Exception as e:
- print(repr(e))
- self.display_message(self.error_color, f"{repr(e)}")
-
- def grid_icon_double_click(self, icons_grid, item, data=None):
- try:
- if self.ctrl_down and self.shift_down:
- self.unset_keys_and_data()
- self.execute_files(in_terminal=True)
- return
- elif self.ctrl_down:
- self.unset_keys_and_data()
- self.execute_files()
- return
-
-
- wid, tid, tab, _icons_grid, store = self.get_current_state()
- notebook = self.builder.get_object(f"window_{wid}")
- tab_label = self.get_tab_label(notebook, icons_grid)
-
- fileName = store[item][1]
- dir = tab.get_current_directory()
- file = f"{dir}/{fileName}"
-
- if isdir(file):
- tab.set_path(file)
- self.update_tab(tab_label, tab, store, wid, tid)
- else:
- self.open_files()
- except Exception as e:
- self.display_message(self.error_color, f"{repr(e)}")
-
-
-
- def grid_on_drag_set(self, icons_grid, drag_context, data, info, time):
- action = icons_grid.get_name()
- wid, tid = action.split("|")
- store = icons_grid.get_model()
- treePaths = icons_grid.get_selected_items()
- # NOTE: Need URIs as URI format for DnD to work. Will strip 'file://'
- # further down call chain when doing internal fm stuff.
- uris = self.format_to_uris(store, wid, tid, treePaths)
- uris_text = '\n'.join(uris)
-
- data.set_uris(uris)
- data.set_text(uris_text, -1)
-
- def grid_on_drag_motion(self, icons_grid, drag_context, x, y, data):
- current = '|'.join(self.fm_controller.get_active_wid_and_tid())
- target = icons_grid.get_name()
- wid, tid = target.split("|")
- store = icons_grid.get_model()
- treePath = icons_grid.get_drag_dest_item().path
-
- if treePath:
- uri = self.format_to_uris(store, wid, tid, treePath)[0].replace("file://", "")
- self.override_drop_dest = uri if isdir(uri) else None
-
- if target not in current:
- self.fm_controller.set__wid_and_tid(wid, tid)
-
-
- def grid_on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
- if info == 80:
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- notebook = self.builder.get_object(f"window_{wid}")
- store, tab_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
- tab = self.get_fm_window(wid).get_tab_by_id(tid)
-
- uris = data.get_uris()
- dest = f"{tab.get_current_directory()}" if not self.override_drop_dest else self.override_drop_dest
- if len(uris) == 0:
- uris = data.get_text().split("\n")
-
- from_uri = '/'.join(uris[0].replace("file://", "").split("/")[:-1])
- if from_uri != dest:
- self.move_files(uris, dest)
-
-
- def create_new_tab_notebook(self, widget=None, wid=None, path=None):
- self.create_tab(wid, path)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui_mixin.py
deleted file mode 100644
index d127b28..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/mixins/ui_mixin.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Python imports
-
-# Gtk imports
-
-# Application imports
-from .show_hide_mixin import ShowHideMixin
-from .ui.widget_file_action_mixin import WidgetFileActionMixin
-from .ui.pane_mixin import PaneMixin
-from .ui.window_mixin import WindowMixin
-from .show_hide_mixin import ShowHideMixin
-
-
-class UIMixin(WidgetFileActionMixin, PaneMixin, WindowMixin, ShowHideMixin):
- pass
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/__init__.py
deleted file mode 100644
index c2a7368..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Signals module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/ipc_signals_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/ipc_signals_mixin.py
deleted file mode 100644
index 64b86dc..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/ipc_signals_mixin.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Python imports
-
-# Lib imports
-
-# Application imports
-
-
-class IPCSignalsMixin:
- """ IPCSignalsMixin handle messages from another starting solarfm process. """
-
- def print_to_console(self, message=None):
- print(self)
- print(message)
-
- def handle_file_from_ipc(self, path):
- wid, tid = self.fm_controller.get_active_wid_and_tid()
- notebook = self.builder.get_object(f"window_{wid}")
- if notebook.is_visible():
- self.create_tab(wid, path)
- return
-
- if not self.is_pane4_hidden:
- self.create_tab(4, path)
- elif not self.is_pane3_hidden:
- self.create_tab(3, path)
- elif not self.is_pane2_hidden:
- self.create_tab(2, path)
- elif not self.is_pane1_hidden:
- self.create_tab(1, path)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/keyboard_signals_mixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/keyboard_signals_mixin.py
deleted file mode 100644
index 16ed902..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/context/signals/keyboard_signals_mixin.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Python imports
-import re
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-gi.require_version('Gdk', '3.0')
-from gi.repository import Gtk, Gdk
-
-# Application imports
-
-
-valid_keyvalue_pat = re.compile(r"[a-z0-9A-Z-_\[\]\(\)\| ]")
-
-
-class KeyboardSignalsMixin:
- """ KeyboardSignalsMixin keyboard hooks controller. """
-
- def unset_keys_and_data(self, widget=None, eve=None):
- self.ctrl_down = False
- self.shift_down = False
- self.alt_down = False
- self.is_searching = False
-
- def global_key_press_controller(self, eve, user_data):
- keyname = Gdk.keyval_name(user_data.keyval).lower()
- if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
- if "control" in keyname:
- self.ctrl_down = True
- if "shift" in keyname:
- self.shift_down = True
- if "alt" in keyname:
- self.alt_down = True
-
- # NOTE: Yes, this should actually be mapped to some key controller setting
- # file or something. Sue me.
- def global_key_release_controller(self, eve, user_data):
- keyname = Gdk.keyval_name(user_data.keyval).lower()
- if debug:
- print(f"global_key_release_controller > key > {keyname}")
-
- if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
- if "control" in keyname:
- self.ctrl_down = False
- if "shift" in keyname:
- self.shift_down = False
- if "alt" in keyname:
- self.alt_down = False
-
- if self.ctrl_down and self.shift_down and keyname == "t":
- self.unset_keys_and_data()
- self.trash_files()
-
- if self.ctrl_down:
- if keyname in ["1", "kp_1", "2", "kp_2", "3", "kp_3", "4", "kp_4"]:
- self.builder.get_object(f"tggl_notebook_{keyname.strip('kp_')}").released()
- if keyname == "q":
- self.tear_down()
- if keyname == "slash" or keyname == "home":
- self.builder.get_object("go_home").released()
- if keyname == "r" or keyname == "f5":
- self.builder.get_object("refresh_tab").released()
- if keyname == "up" or keyname == "u":
- self.builder.get_object("go_up").released()
- if keyname == "l":
- self.unset_keys_and_data()
- self.builder.get_object("path_entry").grab_focus()
- if keyname == "t":
- self.builder.get_object("create_tab").released()
- if keyname == "o":
- self.unset_keys_and_data()
- self.open_files()
- if keyname == "w":
- self.keyboard_close_tab()
- if keyname == "h":
- self.show_hide_hidden_files()
- if keyname == "e":
- self.unset_keys_and_data()
- self.rename_files()
- if keyname == "c":
- self.copy_files()
- self.to_cut_files.clear()
- if keyname == "x":
- self.to_copy_files.clear()
- self.cut_files()
- if keyname == "v":
- self.paste_files()
- if keyname == "n":
- self.unset_keys_and_data()
- self.show_new_file_menu()
-
- if keyname == "delete":
- self.unset_keys_and_data()
- self.delete_files()
- if keyname == "f2":
- self.unset_keys_and_data()
- self.rename_files()
- if keyname == "f4":
- self.unset_keys_and_data()
- self.open_terminal()
- if keyname in ["alt_l", "alt_r"]:
- top_main_menubar = self.builder.get_object("top_main_menubar")
- top_main_menubar.hide() if top_main_menubar.is_visible() else top_main_menubar.show()
-
- if re.fullmatch(valid_keyvalue_pat, keyname):
- if not self.is_searching and not self.ctrl_down \
- and not self.shift_down and not self.alt_down:
- focused_obj = self.window.get_focus()
- if isinstance(focused_obj, Gtk.IconView):
- self.is_searching = True
- wid, tid, self.search_tab, self.search_icon_grid, store = self.get_current_state()
- self.unset_keys_and_data()
- self.popup_search_files(wid, keyname)
- return
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/ipc_server.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/ipc_server.py
deleted file mode 100644
index 0972d86..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/ipc_server.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Python imports
-import os, threading, time
-from multiprocessing.connection import Listener, Client
-
-# Lib imports
-
-# Application imports
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
- return wrapper
-
-
-
-
-class IPCServer:
- """ Create a listener so that other SolarFM instances send requests back to existing instance. """
- def __init__(self, conn_type="socket"):
- self.is_ipc_alive = False
- self._conn_type = conn_type
- self.ipc_authkey = b'solarfm-ipc'
- self.ipc_timeout = 15.0
-
- if conn_type == "socket":
- self.ipc_address = '/tmp/solarfm-ipc.sock'
- else:
- self.ipc_address = '127.0.0.1'
- self.ipc_port = 4848
-
-
- @threaded
- def create_ipc_server(self):
- if self._conn_type == "socket":
- if os.path.exists(self.ipc_address):
- return
-
- listener = Listener(address=self.ipc_address, family="AF_UNIX", authkey=self.ipc_authkey)
- else:
- listener = Listener((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
-
-
- self.is_ipc_alive = True
- while True:
- conn = listener.accept()
- start_time = time.time()
-
- print(f"New Connection: {listener.last_accepted}")
- while True:
- msg = conn.recv()
- if debug:
- print(msg)
-
- if "FILE|" in msg:
- file = msg.split("FILE|")[1].strip()
- if file:
- event_system.push_gui_event([None, "handle_file_from_ipc", (file,)])
-
- conn.close()
- break
-
-
- if msg == 'close connection':
- conn.close()
- break
- if msg == 'close server':
- conn.close()
- break
-
- # NOTE: Not perfect but insures we don't lock up the connection for too long.
- end_time = time.time()
- if (end - start) > self.ipc_timeout:
- conn.close()
-
- listener.close()
-
-
- def send_ipc_message(self, message="Empty Data..."):
- try:
- if self._conn_type == "socket":
- conn = Client(address=self.ipc_address, family="AF_UNIX", authkey=self.ipc_authkey)
- else:
- conn = Client((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
-
-
- conn.send(message)
- conn.send('close connection')
- except Exception as e:
- print(repr(e))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/__init__.py
deleted file mode 100644
index 5624b32..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
- Gtk Bound Plugins Module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/plugins.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/plugins.py
deleted file mode 100644
index 49230f5..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/plugins/plugins.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Python imports
-import os, sys, importlib, traceback
-from os.path import join, isdir
-
-# Lib imports
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk, Gio
-
-# Application imports
-
-
-class Plugin:
- name = None
- module = None
- reference = None
-
-
-class Plugins:
- """Plugins controller"""
-
- def __init__(self, settings):
- self._settings = settings
- self._builder = self._settings.get_builder()
- self._plugins_path = self._settings.get_plugins_path()
- self._plugins_dir_watcher = None
- self._plugin_collection = []
-
-
- def launch_plugins(self):
- self._set_plugins_watcher()
- self.load_plugins()
-
- def _set_plugins_watcher(self):
- self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \
- .monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, Gio.Cancellable())
- self._plugins_dir_watcher.connect("changed", self._on_plugins_changed, ())
-
- def _on_plugins_changed(self, file_monitor, file, other_file=None, eve_type=None, data=None):
- if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED,
- Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
- Gio.FileMonitorEvent.MOVED_OUT]:
- self.reload_plugins(file)
-
- # @threaded
- def load_plugins(self, file=None):
- print(f"Loading plugins...")
- parent_path = os.getcwd()
-
- for file in os.listdir(self._plugins_path):
- try:
- path = join(self._plugins_path, file)
- if isdir(path):
- os.chdir(path)
-
- sys.path.insert(0, path)
- spec = importlib.util.spec_from_file_location(file, join(path, "__main__.py"))
- app = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(app)
-
- plugin_reference = app.Plugin(self._builder, event_system)
- plugin = Plugin()
- plugin.name = plugin_reference.get_plugin_name()
- plugin.module = path
- plugin.reference = plugin_reference
-
- self._plugin_collection.append(plugin)
- except Exception as e:
- print("Malformed plugin! Not loading!")
- traceback.print_exc()
-
- os.chdir(parent_path)
-
-
- def reload_plugins(self, file=None):
- print(f"Reloading plugins... stub.")
-
- def send_message_to_plugin(self, type, data):
- print("Trying to send message to plugin...")
- for plugin in self._plugin_collection:
- if type in plugin.name:
- print('Found plugin; posting message...')
- plugin.reference.set_message(data)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/__init__.py
deleted file mode 100644
index 8a30fad..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Root of ShellFM
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/__init__.py
deleted file mode 100644
index 2463c54..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Window module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/controller.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/controller.py
deleted file mode 100644
index 60c3379..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/controller.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# Python imports
-import threading, json
-from os import path
-
-# Lib imports
-
-# Application imports
-from .window import Window
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
- return wrapper
-
-
-class WindowController:
- def __init__(self):
- USER_HOME = path.expanduser('~')
- CONFIG_PATH = USER_HOME + "/.config/solarfm"
- self._session_file = CONFIG_PATH + "/session.json"
-
- self._event_sleep_time = 1
- self._active_window_id = ""
- self._active_tab_id = ""
- self._windows = []
-
-
- def set__wid_and_tid(self, wid, tid):
- self._active_window_id = str(wid)
- self._active_tab_id = str(tid)
-
- def get_active_wid_and_tid(self):
- return self._active_window_id, self._active_tab_id
-
- def create_window(self):
- window = Window()
- window.set_nickname(f"window_{str(len(self._windows) + 1)}")
- self._windows.append(window)
- return window
-
-
- def add_tab_for_window(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- return window.create_tab()
-
- def add_tab_for_window_by_name(self, name):
- for window in self._windows:
- if window.get_name() == name:
- return window.create_tab()
-
- def add_tab_for_window_by_nickname(self, nickname):
- for window in self._windows:
- if window.get_nickname() == nickname:
- return window.create_tab()
-
- def pop_window(self):
- self._windows.pop()
-
- def delete_window_by_id(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- self._windows.remove(window)
- break
-
- def delete_window_by_name(self, name):
- for window in self._windows:
- if window.get_name() == name:
- self._windows.remove(window)
- break
-
- def delete_window_by_nickname(self, nickname):
- for window in self._windows:
- if window.get_nickname() == nickname:
- self._windows.remove(window)
- break
-
- def get_window_by_id(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- return window
-
- raise(f"No Window by ID {win_id} found!")
-
- def get_window_by_name(self, name):
- for window in self._windows:
- if window.get_name() == name:
- return window
-
- raise(f"No Window by Name {name} found!")
-
- def get_window_by_nickname(self, nickname):
- for window in self._windows:
- if window.get_nickname() == nickname:
- return window
-
- raise(f"No Window by Nickname {nickname} found!")
-
- def get_window_by_index(self, index):
- return self._windows[index]
-
- def get_all_windows(self):
- return self._windows
-
-
- def set_window_nickname(self, win_id = None, nickname = ""):
- for window in self._windows:
- if window.get_id() == win_id:
- window.set_nickname(nickname)
-
- def list_windows(self):
- print("\n[ ---- Windows ---- ]\n")
- for window in self._windows:
- print(f"\nID: {window.get_id()}")
- print(f"Name: {window.get_name()}")
- print(f"Nickname: {window.get_nickname()}")
- print(f"Is Hidden: {window.is_hidden()}")
- print(f"Tab Count: {window.get_tabs_count()}")
- print("\n-------------------------\n")
-
-
-
- def list_files_from_tabs_of_window(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- window.list_files_from_tabs()
- break
-
- def get_tabs_count(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- return window.get_tabs_count()
-
- def get_tabs_from_window(self, win_id):
- for window in self._windows:
- if window.get_id() == win_id:
- return window.get_all_tabs()
-
-
-
-
- def unload_tabs_and_windows(self):
- for window in self._windows:
- window.get_all_tabs().clear()
-
- self._windows.clear()
-
- def save_state(self, session_file = None):
- if not session_file:
- session_file = self._session_file
-
- if len(self._windows) > 0:
- windows = []
- for window in self._windows:
- tabs = []
- for tab in window.get_all_tabs():
- tabs.append(tab.get_current_directory())
-
- windows.append(
- [
- {
- 'window':{
- "ID": window.get_id(),
- "Name": window.get_name(),
- "Nickname": window.get_nickname(),
- "isHidden": f"{window.is_hidden()}",
- 'tabs': tabs
- }
- }
- ]
- )
-
- with open(session_file, 'w') as outfile:
- json.dump(windows, outfile, separators=(',', ':'), indent=4)
- else:
- raise Exception("Window data corrupted! Can not save session!")
-
- def load_state(self, session_file = None):
- if not session_file:
- session_file = self._session_file
-
- if path.isfile(session_file):
- with open(session_file) as infile:
- return json.load(infile)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/__init__.py
deleted file mode 100644
index c4d8aba..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Tabs module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/__init__.py
deleted file mode 100644
index 14bb42f..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Icons module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/icon.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/icon.py
deleted file mode 100644
index 6afa0e5..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/icon.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Python Imports
-import os, subprocess, threading, hashlib
-from os.path import isfile
-
-# Gtk imports
-import gi
-gi.require_version('GdkPixbuf', '2.0')
-from gi.repository import GdkPixbuf
-
-# Application imports
-from .mixins.desktopiconmixin import DesktopIconMixin
-from .mixins.videoiconmixin import VideoIconMixin
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs).start()
- return wrapper
-
-
-class Icon(DesktopIconMixin, VideoIconMixin):
- def create_icon(self, dir, file):
- full_path = f"{dir}/{file}"
- return self.get_icon_image(dir, file, full_path)
-
- def get_icon_image(self, dir, file, full_path):
- try:
- thumbnl = None
-
- if file.lower().endswith(self.fvideos): # Video icon
- thumbnl = self.create_thumbnail(dir, file)
- elif file.lower().endswith(self.fimages): # Image Icon
- thumbnl = self.create_scaled_image(full_path, self.VIDEO_ICON_WH)
- elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing
- thumbnl = self.parse_desktop_files(full_path)
-
- return thumbnl
- except Exception as e:
- return None
-
- def create_thumbnail(self, dir, file):
- full_path = f"{dir}/{file}"
- try:
- file_hash = hashlib.sha256(str.encode(full_path)).hexdigest()
- hash_img_pth = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
- if isfile(hash_img_pth) == False:
- self.generate_video_thumbnail(full_path, hash_img_pth)
-
- thumbnl = self.create_scaled_image(hash_img_pth, self.VIDEO_ICON_WH)
- if thumbnl == None: # If no icon whatsoever, return internal default
- thumbnl = GdkPixbuf.Pixbuf.new_from_file(f"{self.DEFAULT_ICONS}/video.png")
-
- return thumbnl
- except Exception as e:
- print("Thumbnail generation issue:")
- print( repr(e) )
- return GdkPixbuf.Pixbuf.new_from_file(f"{self.DEFAULT_ICONS}/video.png")
-
-
- def create_scaled_image(self, path, wxh):
- try:
- if path.lower().endswith(".gif"):
- return GdkPixbuf.PixbufAnimation.new_from_file(path) \
- .get_static_image() \
- .scale_simple(wxh[0], wxh[1], GdkPixbuf.InterpType.BILINEAR)
- else:
- return GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], True)
- except Exception as e:
- print("Image Scaling Issue:")
- print( repr(e) )
- return None
-
- def create_from_file(self, path):
- try:
- return GdkPixbuf.Pixbuf.new_from_file(path)
- except Exception as e:
- print("Image from file Issue:")
- print( repr(e) )
- return None
-
- def return_generic_icon(self):
- return GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICON)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/__init__.py
deleted file mode 100644
index d5bc819..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Icons mixins module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py
deleted file mode 100644
index 9f5ed2e..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Python Imports
-import os, subprocess, hashlib
-from os.path import isfile
-
-# Gtk imports
-
-# Application imports
-from .xdg.DesktopEntry import DesktopEntry
-
-
-class DesktopIconMixin:
- def parse_desktop_files(self, full_path):
- try:
- xdgObj = DesktopEntry(full_path)
- icon = xdgObj.getIcon()
- alt_icon_path = ""
-
- if "steam" in icon:
- name = xdgObj.getName()
- file_hash = hashlib.sha256(str.encode(name)).hexdigest()
- hash_img_pth = self.STEAM_ICONS_PTH + "/" + file_hash + ".jpg"
-
- if isfile(hash_img_pth) == True:
- # Use video sizes since headers are bigger
- return self.create_scaled_image(hash_img_pth, self.VIDEO_ICON_WH)
-
- exec_str = xdgObj.getExec()
- parts = exec_str.split("steam://rungameid/")
- id = parts[len(parts) - 1]
- imageLink = self.STEAM_BASE_URL + id + "/header.jpg"
- proc = subprocess.Popen(["wget", "-O", hash_img_pth, imageLink])
- proc.wait()
-
- # Use video thumbnail sizes since headers are bigger
- return self.create_scaled_image(hash_img_pth, self.VIDEO_ICON_WH)
- elif os.path.exists(icon):
- return self.create_scaled_image(icon, self.SYS_ICON_WH)
- else:
- alt_icon_path = ""
-
- for dir in self.ICON_DIRS:
- alt_icon_path = self.traverse_icons_folder(dir, icon)
- if alt_icon_path != "":
- break
-
- return self.create_scaled_image(alt_icon_path, self.SYS_ICON_WH)
- except Exception as e:
- print(".desktop icon generation issue:")
- print( repr(e) )
- return None
-
- def traverse_icons_folder(self, path, icon):
- alt_icon_path = ""
-
- for (dirpath, dirnames, filenames) in os.walk(path):
- for file in filenames:
- appNM = "application-x-" + icon
- if icon in file or appNM in file:
- alt_icon_path = dirpath + "/" + file
- break
-
- return alt_icon_path
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/videoiconmixin.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/videoiconmixin.py
deleted file mode 100644
index fc35e9d..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/videoiconmixin.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Python Imports
-import subprocess
-
-# Gtk imports
-
-# Application imports
-
-
-class VideoIconMixin:
- def generate_video_thumbnail(self, full_path, hash_img_pth):
- try:
- proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", "65%", "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_pth])
- proc.wait()
- except Exception as e:
- self.logger.debug(repr(e))
- self.ffprobe_generate_video_thumbnail(full_path, hash_img_pth)
-
-
- def ffprobe_generate_video_thumbnail(self, full_path, hash_img_pth):
- proc = None
- try:
- # Stream duration
- command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", full_path]
- data = subprocess.run(command, stdout=subprocess.PIPE)
- duration = data.stdout.decode('utf-8')
-
- # Format (container) duration
- if "N/A" in duration:
- command = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", full_path]
- data = subprocess.run(command , stdout=subprocess.PIPE)
- duration = data.stdout.decode('utf-8')
-
- # Stream duration type: image2
- if "N/A" in duration:
- command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-f", "image2", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", full_path]
- data = subprocess.run(command, stdout=subprocess.PIPE)
- duration = data.stdout.decode('utf-8')
-
- # Format (container) duration type: image2
- if "N/A" in duration:
- command = ["ffprobe", "-v", "error", "-f", "image2", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", full_path]
- data = subprocess.run(command , stdout=subprocess.PIPE)
- duration = data.stdout.decode('utf-8')
-
- # Get frame roughly 35% through video
- grabTime = str( int( float( duration.split(".")[0] ) * 0.35) )
- command = ["ffmpeg", "-ss", grabTime, "-an", "-i", full_path, "-s", "320x180", "-vframes", "1", hash_img_pth]
- proc = subprocess.Popen(command, stdout=subprocess.PIPE)
- proc.wait()
- except Exception as e:
- print("Video thumbnail generation issue in thread:")
- print( repr(e) )
- self.logger.debug(repr(e))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/BaseDirectory.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/BaseDirectory.py
deleted file mode 100644
index a7c31b1..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/BaseDirectory.py
+++ /dev/null
@@ -1,160 +0,0 @@
-"""
-This module is based on a rox module (LGPL):
-
-http://cvs.sourceforge.net/viewcvs.py/rox/ROX-Lib2/python/rox/basedir.py?rev=1.9&view=log
-
-The freedesktop.org Base Directory specification provides a way for
-applications to locate shared data and configuration:
-
- http://standards.freedesktop.org/basedir-spec/
-
-(based on version 0.6)
-
-This module can be used to load and save from and to these directories.
-
-Typical usage:
-
- from rox import basedir
-
- for dir in basedir.load_config_paths('mydomain.org', 'MyProg', 'Options'):
- print "Load settings from", dir
-
- dir = basedir.save_config_path('mydomain.org', 'MyProg')
- print >>file(os.path.join(dir, 'Options'), 'w'), "foo=2"
-
-Note: see the rox.Options module for a higher-level API for managing options.
-"""
-
-import os, stat
-
-_home = os.path.expanduser('~')
-xdg_data_home = os.environ.get('XDG_DATA_HOME') or \
- os.path.join(_home, '.local', 'share')
-
-xdg_data_dirs = [xdg_data_home] + \
- (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share').split(':')
-
-xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or \
- os.path.join(_home, '.config')
-
-xdg_config_dirs = [xdg_config_home] + \
- (os.environ.get('XDG_CONFIG_DIRS') or '/etc/xdg').split(':')
-
-xdg_cache_home = os.environ.get('XDG_CACHE_HOME') or \
- os.path.join(_home, '.cache')
-
-xdg_data_dirs = [x for x in xdg_data_dirs if x]
-xdg_config_dirs = [x for x in xdg_config_dirs if x]
-
-def save_config_path(*resource):
- """Ensure ``$XDG_CONFIG_HOME//`` exists, and return its path.
- 'resource' should normally be the name of your application. Use this
- when saving configuration settings.
- """
- resource = os.path.join(*resource)
- assert not resource.startswith('/')
- path = os.path.join(xdg_config_home, resource)
- if not os.path.isdir(path):
- os.makedirs(path, 0o700)
- return path
-
-def save_data_path(*resource):
- """Ensure ``$XDG_DATA_HOME//`` exists, and return its path.
- 'resource' should normally be the name of your application or a shared
- resource. Use this when saving or updating application data.
- """
- resource = os.path.join(*resource)
- assert not resource.startswith('/')
- path = os.path.join(xdg_data_home, resource)
- if not os.path.isdir(path):
- os.makedirs(path)
- return path
-
-def save_cache_path(*resource):
- """Ensure ``$XDG_CACHE_HOME//`` exists, and return its path.
- 'resource' should normally be the name of your application or a shared
- resource."""
- resource = os.path.join(*resource)
- assert not resource.startswith('/')
- path = os.path.join(xdg_cache_home, resource)
- if not os.path.isdir(path):
- os.makedirs(path)
- return path
-
-def load_config_paths(*resource):
- """Returns an iterator which gives each directory named 'resource' in the
- configuration search path. Information provided by earlier directories should
- take precedence over later ones, and the user-specific config dir comes
- first."""
- resource = os.path.join(*resource)
- for config_dir in xdg_config_dirs:
- path = os.path.join(config_dir, resource)
- if os.path.exists(path): yield path
-
-def load_first_config(*resource):
- """Returns the first result from load_config_paths, or None if there is nothing
- to load."""
- for x in load_config_paths(*resource):
- return x
- return None
-
-def load_data_paths(*resource):
- """Returns an iterator which gives each directory named 'resource' in the
- application data search path. Information provided by earlier directories
- should take precedence over later ones."""
- resource = os.path.join(*resource)
- for data_dir in xdg_data_dirs:
- path = os.path.join(data_dir, resource)
- if os.path.exists(path): yield path
-
-def get_runtime_dir(strict=True):
- """Returns the value of $XDG_RUNTIME_DIR, a directory path.
-
- This directory is intended for 'user-specific non-essential runtime files
- and other file objects (such as sockets, named pipes, ...)', and
- 'communication and synchronization purposes'.
-
- As of late 2012, only quite new systems set $XDG_RUNTIME_DIR. If it is not
- set, with ``strict=True`` (the default), a KeyError is raised. With
- ``strict=False``, PyXDG will create a fallback under /tmp for the current
- user. This fallback does *not* provide the same guarantees as the
- specification requires for the runtime directory.
-
- The strict default is deliberately conservative, so that application
- developers can make a conscious decision to allow the fallback.
- """
- try:
- return os.environ['XDG_RUNTIME_DIR']
- except KeyError:
- if strict:
- raise
-
- import getpass
- fallback = '/tmp/pyxdg-runtime-dir-fallback-' + getpass.getuser()
- create = False
-
- try:
- # This must be a real directory, not a symlink, so attackers can't
- # point it elsewhere. So we use lstat to check it.
- st = os.lstat(fallback)
- except OSError as e:
- import errno
- if e.errno == errno.ENOENT:
- create = True
- else:
- raise
- else:
- # The fallback must be a directory
- if not stat.S_ISDIR(st.st_mode):
- os.unlink(fallback)
- create = True
- # Must be owned by the user and not accessible by anyone else
- elif (st.st_uid != os.getuid()) \
- or (st.st_mode & (stat.S_IRWXG | stat.S_IRWXO)):
- os.rmdir(fallback)
- create = True
-
- if create:
- os.mkdir(fallback, 0o700)
-
- return fallback
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Config.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Config.py
deleted file mode 100644
index 3f5d654..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Config.py
+++ /dev/null
@@ -1,39 +0,0 @@
-"""
-Functions to configure Basic Settings
-"""
-
-language = "C"
-windowmanager = None
-icon_theme = "hicolor"
-icon_size = 48
-cache_time = 5
-root_mode = False
-
-def setWindowManager(wm):
- global windowmanager
- windowmanager = wm
-
-def setIconTheme(theme):
- global icon_theme
- icon_theme = theme
- import xdg.IconTheme
- xdg.IconTheme.themes = []
-
-def setIconSize(size):
- global icon_size
- icon_size = size
-
-def setCacheTime(time):
- global cache_time
- cache_time = time
-
-def setLocale(lang):
- import locale
- lang = locale.normalize(lang)
- locale.setlocale(locale.LC_ALL, lang)
- import xdg.Locale
- xdg.Locale.update(lang)
-
-def setRootMode(boolean):
- global root_mode
- root_mode = boolean
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/DesktopEntry.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/DesktopEntry.py
deleted file mode 100644
index 803993e..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/DesktopEntry.py
+++ /dev/null
@@ -1,435 +0,0 @@
-"""
-Complete implementation of the XDG Desktop Entry Specification
-http://standards.freedesktop.org/desktop-entry-spec/
-
-Not supported:
-- Encoding: Legacy Mixed
-- Does not check exec parameters
-- Does not check URL's
-- Does not completly validate deprecated/kde items
-- Does not completly check categories
-"""
-
-from .IniFile import IniFile
-from . import Locale
-
-from .IniFile import is_ascii
-
-from .Exceptions import ParsingError
-from .util import which
-import os.path
-import re
-import warnings
-
-class DesktopEntry(IniFile):
- "Class to parse and validate Desktop Entries"
-
- defaultGroup = 'Desktop Entry'
-
- def __init__(self, filename=None):
- """Create a new DesktopEntry.
-
- If filename exists, it will be parsed as a desktop entry file. If not,
- or if filename is None, a blank DesktopEntry is created.
- """
- self.content = dict()
- if filename and os.path.exists(filename):
- self.parse(filename)
- elif filename:
- self.new(filename)
-
- def __str__(self):
- return self.getName()
-
- def parse(self, file):
- """Parse a desktop entry file.
-
- This can raise :class:`~xdg.Exceptions.ParsingError`,
- :class:`~xdg.Exceptions.DuplicateGroupError` or
- :class:`~xdg.Exceptions.DuplicateKeyError`.
- """
- IniFile.parse(self, file, ["Desktop Entry", "KDE Desktop Entry"])
-
- def findTryExec(self):
- """Looks in the PATH for the executable given in the TryExec field.
-
- Returns the full path to the executable if it is found, None if not.
- Raises :class:`~xdg.Exceptions.NoKeyError` if TryExec is not present.
- """
- tryexec = self.get('TryExec', strict=True)
- return which(tryexec)
-
- # start standard keys
- def getType(self):
- return self.get('Type')
- def getVersion(self):
- """deprecated, use getVersionString instead """
- return self.get('Version', type="numeric")
- def getVersionString(self):
- return self.get('Version')
- def getName(self):
- return self.get('Name', locale=True)
- def getGenericName(self):
- return self.get('GenericName', locale=True)
- def getNoDisplay(self):
- return self.get('NoDisplay', type="boolean")
- def getComment(self):
- return self.get('Comment', locale=True)
- def getIcon(self):
- return self.get('Icon', locale=True)
- def getHidden(self):
- return self.get('Hidden', type="boolean")
- def getOnlyShowIn(self):
- return self.get('OnlyShowIn', list=True)
- def getNotShowIn(self):
- return self.get('NotShowIn', list=True)
- def getTryExec(self):
- return self.get('TryExec')
- def getExec(self):
- return self.get('Exec')
- def getPath(self):
- return self.get('Path')
- def getTerminal(self):
- return self.get('Terminal', type="boolean")
- def getMimeType(self):
- """deprecated, use getMimeTypes instead """
- return self.get('MimeType', list=True, type="regex")
- def getMimeTypes(self):
- return self.get('MimeType', list=True)
- def getCategories(self):
- return self.get('Categories', list=True)
- def getStartupNotify(self):
- return self.get('StartupNotify', type="boolean")
- def getStartupWMClass(self):
- return self.get('StartupWMClass')
- def getURL(self):
- return self.get('URL')
- # end standard keys
-
- # start kde keys
- def getServiceTypes(self):
- return self.get('ServiceTypes', list=True)
- def getDocPath(self):
- return self.get('DocPath')
- def getKeywords(self):
- return self.get('Keywords', list=True, locale=True)
- def getInitialPreference(self):
- return self.get('InitialPreference')
- def getDev(self):
- return self.get('Dev')
- def getFSType(self):
- return self.get('FSType')
- def getMountPoint(self):
- return self.get('MountPoint')
- def getReadonly(self):
- return self.get('ReadOnly', type="boolean")
- def getUnmountIcon(self):
- return self.get('UnmountIcon', locale=True)
- # end kde keys
-
- # start deprecated keys
- def getMiniIcon(self):
- return self.get('MiniIcon', locale=True)
- def getTerminalOptions(self):
- return self.get('TerminalOptions')
- def getDefaultApp(self):
- return self.get('DefaultApp')
- def getProtocols(self):
- return self.get('Protocols', list=True)
- def getExtensions(self):
- return self.get('Extensions', list=True)
- def getBinaryPattern(self):
- return self.get('BinaryPattern')
- def getMapNotify(self):
- return self.get('MapNotify')
- def getEncoding(self):
- return self.get('Encoding')
- def getSwallowTitle(self):
- return self.get('SwallowTitle', locale=True)
- def getSwallowExec(self):
- return self.get('SwallowExec')
- def getSortOrder(self):
- return self.get('SortOrder', list=True)
- def getFilePattern(self):
- return self.get('FilePattern', type="regex")
- def getActions(self):
- return self.get('Actions', list=True)
- # end deprecated keys
-
- # desktop entry edit stuff
- def new(self, filename):
- """Make this instance into a new, blank desktop entry.
-
- If filename has a .desktop extension, Type is set to Application. If it
- has a .directory extension, Type is Directory. Other extensions will
- cause :class:`~xdg.Exceptions.ParsingError` to be raised.
- """
- if os.path.splitext(filename)[1] == ".desktop":
- type = "Application"
- elif os.path.splitext(filename)[1] == ".directory":
- type = "Directory"
- else:
- raise ParsingError("Unknown extension", filename)
-
- self.content = dict()
- self.addGroup(self.defaultGroup)
- self.set("Type", type)
- self.filename = filename
- # end desktop entry edit stuff
-
- # validation stuff
- def checkExtras(self):
- # header
- if self.defaultGroup == "KDE Desktop Entry":
- self.warnings.append('[KDE Desktop Entry]-Header is deprecated')
-
- # file extension
- if self.fileExtension == ".kdelnk":
- self.warnings.append("File extension .kdelnk is deprecated")
- elif self.fileExtension != ".desktop" and self.fileExtension != ".directory":
- self.warnings.append('Unknown File extension')
-
- # Type
- try:
- self.type = self.content[self.defaultGroup]["Type"]
- except KeyError:
- self.errors.append("Key 'Type' is missing")
-
- # Name
- try:
- self.name = self.content[self.defaultGroup]["Name"]
- except KeyError:
- self.errors.append("Key 'Name' is missing")
-
- def checkGroup(self, group):
- # check if group header is valid
- if not (group == self.defaultGroup \
- or re.match("^Desktop Action [a-zA-Z0-9-]+$", group) \
- or (re.match("^X-", group) and is_ascii(group))):
- self.errors.append("Invalid Group name: %s" % group)
- else:
- #OnlyShowIn and NotShowIn
- if ("OnlyShowIn" in self.content[group]) and ("NotShowIn" in self.content[group]):
- self.errors.append("Group may either have OnlyShowIn or NotShowIn, but not both")
-
- def checkKey(self, key, value, group):
- # standard keys
- if key == "Type":
- if value == "ServiceType" or value == "Service" or value == "FSDevice":
- self.warnings.append("Type=%s is a KDE extension" % key)
- elif value == "MimeType":
- self.warnings.append("Type=MimeType is deprecated")
- elif not (value == "Application" or value == "Link" or value == "Directory"):
- self.errors.append("Value of key 'Type' must be Application, Link or Directory, but is '%s'" % value)
-
- if self.fileExtension == ".directory" and not value == "Directory":
- self.warnings.append("File extension is .directory, but Type is '%s'" % value)
- elif self.fileExtension == ".desktop" and value == "Directory":
- self.warnings.append("Files with Type=Directory should have the extension .directory")
-
- if value == "Application":
- if "Exec" not in self.content[group]:
- self.warnings.append("Type=Application needs 'Exec' key")
- if value == "Link":
- if "URL" not in self.content[group]:
- self.warnings.append("Type=Link needs 'URL' key")
-
- elif key == "Version":
- self.checkValue(key, value)
-
- elif re.match("^Name"+xdg.Locale.regex+"$", key):
- pass # locale string
-
- elif re.match("^GenericName"+xdg.Locale.regex+"$", key):
- pass # locale string
-
- elif key == "NoDisplay":
- self.checkValue(key, value, type="boolean")
-
- elif re.match("^Comment"+xdg.Locale.regex+"$", key):
- pass # locale string
-
- elif re.match("^Icon"+xdg.Locale.regex+"$", key):
- self.checkValue(key, value)
-
- elif key == "Hidden":
- self.checkValue(key, value, type="boolean")
-
- elif key == "OnlyShowIn":
- self.checkValue(key, value, list=True)
- self.checkOnlyShowIn(value)
-
- elif key == "NotShowIn":
- self.checkValue(key, value, list=True)
- self.checkOnlyShowIn(value)
-
- elif key == "TryExec":
- self.checkValue(key, value)
- self.checkType(key, "Application")
-
- elif key == "Exec":
- self.checkValue(key, value)
- self.checkType(key, "Application")
-
- elif key == "Path":
- self.checkValue(key, value)
- self.checkType(key, "Application")
-
- elif key == "Terminal":
- self.checkValue(key, value, type="boolean")
- self.checkType(key, "Application")
-
- elif key == "Actions":
- self.checkValue(key, value, list=True)
- self.checkType(key, "Application")
-
- elif key == "MimeType":
- self.checkValue(key, value, list=True)
- self.checkType(key, "Application")
-
- elif key == "Categories":
- self.checkValue(key, value)
- self.checkType(key, "Application")
- self.checkCategories(value)
-
- elif re.match("^Keywords"+xdg.Locale.regex+"$", key):
- self.checkValue(key, value, type="localestring", list=True)
- self.checkType(key, "Application")
-
- elif key == "StartupNotify":
- self.checkValue(key, value, type="boolean")
- self.checkType(key, "Application")
-
- elif key == "StartupWMClass":
- self.checkType(key, "Application")
-
- elif key == "URL":
- self.checkValue(key, value)
- self.checkType(key, "URL")
-
- # kde extensions
- elif key == "ServiceTypes":
- self.checkValue(key, value, list=True)
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "DocPath":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "InitialPreference":
- self.checkValue(key, value, type="numeric")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "Dev":
- self.checkValue(key, value)
- self.checkType(key, "FSDevice")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "FSType":
- self.checkValue(key, value)
- self.checkType(key, "FSDevice")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "MountPoint":
- self.checkValue(key, value)
- self.checkType(key, "FSDevice")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif key == "ReadOnly":
- self.checkValue(key, value, type="boolean")
- self.checkType(key, "FSDevice")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- elif re.match("^UnmountIcon"+xdg.Locale.regex+"$", key):
- self.checkValue(key, value)
- self.checkType(key, "FSDevice")
- self.warnings.append("Key '%s' is a KDE extension" % key)
-
- # deprecated keys
- elif key == "Encoding":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif re.match("^MiniIcon"+xdg.Locale.regex+"$", key):
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "TerminalOptions":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "DefaultApp":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "Protocols":
- self.checkValue(key, value, list=True)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "Extensions":
- self.checkValue(key, value, list=True)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "BinaryPattern":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "MapNotify":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif re.match("^SwallowTitle"+xdg.Locale.regex+"$", key):
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "SwallowExec":
- self.checkValue(key, value)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "FilePattern":
- self.checkValue(key, value, type="regex", list=True)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- elif key == "SortOrder":
- self.checkValue(key, value, list=True)
- self.warnings.append("Key '%s' is deprecated" % key)
-
- # "X-" extensions
- elif re.match("^X-[a-zA-Z0-9-]+", key):
- pass
-
- else:
- self.errors.append("Invalid key: %s" % key)
-
- def checkType(self, key, type):
- if not self.getType() == type:
- self.errors.append("Key '%s' only allowed in Type=%s" % (key, type))
-
- def checkOnlyShowIn(self, value):
- values = self.getList(value)
- valid = ["GNOME", "KDE", "LXDE", "MATE", "Razor", "ROX", "TDE", "Unity",
- "XFCE", "Old"]
- for item in values:
- if item not in valid and item[0:2] != "X-":
- self.errors.append("'%s' is not a registered OnlyShowIn value" % item);
-
- def checkCategories(self, value):
- values = self.getList(value)
-
- main = ["AudioVideo", "Audio", "Video", "Development", "Education", "Game", "Graphics", "Network", "Office", "Science", "Settings", "System", "Utility"]
- if not any(item in main for item in values):
- self.errors.append("Missing main category")
-
- additional = ['Building', 'Debugger', 'IDE', 'GUIDesigner', 'Profiling', 'RevisionControl', 'Translation', 'Calendar', 'ContactManagement', 'Database', 'Dictionary', 'Chart', 'Email', 'Finance', 'FlowChart', 'PDA', 'ProjectManagement', 'Presentation', 'Spreadsheet', 'WordProcessor', '2DGraphics', 'VectorGraphics', 'RasterGraphics', '3DGraphics', 'Scanning', 'OCR', 'Photography', 'Publishing', 'Viewer', 'TextTools', 'DesktopSettings', 'HardwareSettings', 'Printing', 'PackageManager', 'Dialup', 'InstantMessaging', 'Chat', 'IRCClient', 'Feed', 'FileTransfer', 'HamRadio', 'News', 'P2P', 'RemoteAccess', 'Telephony', 'TelephonyTools', 'VideoConference', 'WebBrowser', 'WebDevelopment', 'Midi', 'Mixer', 'Sequencer', 'Tuner', 'TV', 'AudioVideoEditing', 'Player', 'Recorder', 'DiscBurning', 'ActionGame', 'AdventureGame', 'ArcadeGame', 'BoardGame', 'BlocksGame', 'CardGame', 'KidsGame', 'LogicGame', 'RolePlaying', 'Shooter', 'Simulation', 'SportsGame', 'StrategyGame', 'Art', 'Construction', 'Music', 'Languages', 'ArtificialIntelligence', 'Astronomy', 'Biology', 'Chemistry', 'ComputerScience', 'DataVisualization', 'Economy', 'Electricity', 'Geography', 'Geology', 'Geoscience', 'History', 'Humanities', 'ImageProcessing', 'Literature', 'Maps', 'Math', 'NumericalAnalysis', 'MedicalSoftware', 'Physics', 'Robotics', 'Spirituality', 'Sports', 'ParallelComputing', 'Amusement', 'Archiving', 'Compression', 'Electronics', 'Emulator', 'Engineering', 'FileTools', 'FileManager', 'TerminalEmulator', 'Filesystem', 'Monitor', 'Security', 'Accessibility', 'Calculator', 'Clock', 'TextEditor', 'Documentation', 'Adult', 'Core', 'KDE', 'GNOME', 'XFCE', 'GTK', 'Qt', 'Motif', 'Java', 'ConsoleOnly']
- allcategories = additional + main
-
- for item in values:
- if item not in allcategories and not item.startswith("X-"):
- self.errors.append("'%s' is not a registered Category" % item);
-
- def checkCategorie(self, value):
- """Deprecated alias for checkCategories - only exists for backwards
- compatibility.
- """
- warnings.warn("checkCategorie is deprecated, use checkCategories",
- DeprecationWarning)
- return self.checkCategories(value)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Exceptions.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Exceptions.py
deleted file mode 100644
index 7096b61..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Exceptions.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-Exception Classes for the xdg package
-"""
-
-debug = False
-
-class Error(Exception):
- """Base class for exceptions defined here."""
- def __init__(self, msg):
- self.msg = msg
- Exception.__init__(self, msg)
- def __str__(self):
- return self.msg
-
-class ValidationError(Error):
- """Raised when a file fails to validate.
-
- The filename is the .file attribute.
- """
- def __init__(self, msg, file):
- self.msg = msg
- self.file = file
- Error.__init__(self, "ValidationError in file '%s': %s " % (file, msg))
-
-class ParsingError(Error):
- """Raised when a file cannot be parsed.
-
- The filename is the .file attribute.
- """
- def __init__(self, msg, file):
- self.msg = msg
- self.file = file
- Error.__init__(self, "ParsingError in file '%s', %s" % (file, msg))
-
-class NoKeyError(Error):
- """Raised when trying to access a nonexistant key in an INI-style file.
-
- Attributes are .key, .group and .file.
- """
- def __init__(self, key, group, file):
- Error.__init__(self, "No key '%s' in group %s of file %s" % (key, group, file))
- self.key = key
- self.group = group
- self.file = file
-
-class DuplicateKeyError(Error):
- """Raised when the same key occurs twice in an INI-style file.
-
- Attributes are .key, .group and .file.
- """
- def __init__(self, key, group, file):
- Error.__init__(self, "Duplicate key '%s' in group %s of file %s" % (key, group, file))
- self.key = key
- self.group = group
- self.file = file
-
-class NoGroupError(Error):
- """Raised when trying to access a nonexistant group in an INI-style file.
-
- Attributes are .group and .file.
- """
- def __init__(self, group, file):
- Error.__init__(self, "No group: %s in file %s" % (group, file))
- self.group = group
- self.file = file
-
-class DuplicateGroupError(Error):
- """Raised when the same key occurs twice in an INI-style file.
-
- Attributes are .group and .file.
- """
- def __init__(self, group, file):
- Error.__init__(self, "Duplicate group: %s in file %s" % (group, file))
- self.group = group
- self.file = file
-
-class NoThemeError(Error):
- """Raised when trying to access a nonexistant icon theme.
-
- The name of the theme is the .theme attribute.
- """
- def __init__(self, theme):
- Error.__init__(self, "No such icon-theme: %s" % theme)
- self.theme = theme
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py
deleted file mode 100644
index 2ff3c05..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py
+++ /dev/null
@@ -1,445 +0,0 @@
-"""
-Complete implementation of the XDG Icon Spec
-http://standards.freedesktop.org/icon-theme-spec/
-"""
-
-import os, time
-import re
-
-from . import IniFile, Config
-from .IniFile import is_ascii
-from .BaseDirectory import xdg_data_dirs
-from .Exceptions import NoThemeError, debug
-
-
-class IconTheme(IniFile):
- "Class to parse and validate IconThemes"
- def __init__(self):
- IniFile.__init__(self)
-
- def __repr__(self):
- return self.name
-
- def parse(self, file):
- IniFile.parse(self, file, ["Icon Theme", "KDE Icon Theme"])
- self.dir = os.path.dirname(file)
- (nil, self.name) = os.path.split(self.dir)
-
- def getDir(self):
- return self.dir
-
- # Standard Keys
- def getName(self):
- return self.get('Name', locale=True)
- def getComment(self):
- return self.get('Comment', locale=True)
- def getInherits(self):
- return self.get('Inherits', list=True)
- def getDirectories(self):
- return self.get('Directories', list=True)
- def getScaledDirectories(self):
- return self.get('ScaledDirectories', list=True)
- def getHidden(self):
- return self.get('Hidden', type="boolean")
- def getExample(self):
- return self.get('Example')
-
- # Per Directory Keys
- def getSize(self, directory):
- return self.get('Size', type="integer", group=directory)
- def getContext(self, directory):
- return self.get('Context', group=directory)
- def getType(self, directory):
- value = self.get('Type', group=directory)
- if value:
- return value
- else:
- return "Threshold"
- def getMaxSize(self, directory):
- value = self.get('MaxSize', type="integer", group=directory)
- if value or value == 0:
- return value
- else:
- return self.getSize(directory)
- def getMinSize(self, directory):
- value = self.get('MinSize', type="integer", group=directory)
- if value or value == 0:
- return value
- else:
- return self.getSize(directory)
- def getThreshold(self, directory):
- value = self.get('Threshold', type="integer", group=directory)
- if value or value == 0:
- return value
- else:
- return 2
-
- def getScale(self, directory):
- value = self.get('Scale', type="integer", group=directory)
- return value or 1
-
- # validation stuff
- def checkExtras(self):
- # header
- if self.defaultGroup == "KDE Icon Theme":
- self.warnings.append('[KDE Icon Theme]-Header is deprecated')
-
- # file extension
- if self.fileExtension == ".theme":
- pass
- elif self.fileExtension == ".desktop":
- self.warnings.append('.desktop fileExtension is deprecated')
- else:
- self.warnings.append('Unknown File extension')
-
- # Check required keys
- # Name
- try:
- self.name = self.content[self.defaultGroup]["Name"]
- except KeyError:
- self.errors.append("Key 'Name' is missing")
-
- # Comment
- try:
- self.comment = self.content[self.defaultGroup]["Comment"]
- except KeyError:
- self.errors.append("Key 'Comment' is missing")
-
- # Directories
- try:
- self.directories = self.content[self.defaultGroup]["Directories"]
- except KeyError:
- self.errors.append("Key 'Directories' is missing")
-
- def checkGroup(self, group):
- # check if group header is valid
- if group == self.defaultGroup:
- try:
- self.name = self.content[group]["Name"]
- except KeyError:
- self.errors.append("Key 'Name' in Group '%s' is missing" % group)
- try:
- self.name = self.content[group]["Comment"]
- except KeyError:
- self.errors.append("Key 'Comment' in Group '%s' is missing" % group)
- elif group in self.getDirectories():
- try:
- self.type = self.content[group]["Type"]
- except KeyError:
- self.type = "Threshold"
- try:
- self.name = self.content[group]["Size"]
- except KeyError:
- self.errors.append("Key 'Size' in Group '%s' is missing" % group)
- elif not (re.match(r"^\[X-", group) and is_ascii(group)):
- self.errors.append("Invalid Group name: %s" % group)
-
- def checkKey(self, key, value, group):
- # standard keys
- if group == self.defaultGroup:
- if re.match("^Name"+xdg.Locale.regex+"$", key):
- pass
- elif re.match("^Comment"+xdg.Locale.regex+"$", key):
- pass
- elif key == "Inherits":
- self.checkValue(key, value, list=True)
- elif key == "Directories":
- self.checkValue(key, value, list=True)
- elif key == "ScaledDirectories":
- self.checkValue(key, value, list=True)
- elif key == "Hidden":
- self.checkValue(key, value, type="boolean")
- elif key == "Example":
- self.checkValue(key, value)
- elif re.match("^X-[a-zA-Z0-9-]+", key):
- pass
- else:
- self.errors.append("Invalid key: %s" % key)
- elif group in self.getDirectories():
- if key == "Size":
- self.checkValue(key, value, type="integer")
- elif key == "Context":
- self.checkValue(key, value)
- elif key == "Type":
- self.checkValue(key, value)
- if value not in ["Fixed", "Scalable", "Threshold"]:
- self.errors.append("Key 'Type' must be one out of 'Fixed','Scalable','Threshold', but is %s" % value)
- elif key == "MaxSize":
- self.checkValue(key, value, type="integer")
- if self.type != "Scalable":
- self.errors.append("Key 'MaxSize' give, but Type is %s" % self.type)
- elif key == "MinSize":
- self.checkValue(key, value, type="integer")
- if self.type != "Scalable":
- self.errors.append("Key 'MinSize' give, but Type is %s" % self.type)
- elif key == "Threshold":
- self.checkValue(key, value, type="integer")
- if self.type != "Threshold":
- self.errors.append("Key 'Threshold' give, but Type is %s" % self.type)
- elif key == "Scale":
- self.checkValue(key, value, type="integer")
- elif re.match("^X-[a-zA-Z0-9-]+", key):
- pass
- else:
- self.errors.append("Invalid key: %s" % key)
-
-
-class IconData(IniFile):
- "Class to parse and validate IconData Files"
- def __init__(self):
- IniFile.__init__(self)
-
- def __repr__(self):
- displayname = self.getDisplayName()
- if displayname:
- return "" % displayname
- else:
- return ""
-
- def parse(self, file):
- IniFile.parse(self, file, ["Icon Data"])
-
- # Standard Keys
- def getDisplayName(self):
- """Retrieve the display name from the icon data, if one is specified."""
- return self.get('DisplayName', locale=True)
- def getEmbeddedTextRectangle(self):
- """Retrieve the embedded text rectangle from the icon data as a list of
- numbers (x0, y0, x1, y1), if it is specified."""
- return self.get('EmbeddedTextRectangle', type="integer", list=True)
- def getAttachPoints(self):
- """Retrieve the anchor points for overlays & emblems from the icon data,
- as a list of co-ordinate pairs, if they are specified."""
- return self.get('AttachPoints', type="point", list=True)
-
- # validation stuff
- def checkExtras(self):
- # file extension
- if self.fileExtension != ".icon":
- self.warnings.append('Unknown File extension')
-
- def checkGroup(self, group):
- # check if group header is valid
- if not (group == self.defaultGroup \
- or (re.match(r"^\[X-", group) and is_ascii(group))):
- self.errors.append("Invalid Group name: %s" % group.encode("ascii", "replace"))
-
- def checkKey(self, key, value, group):
- # standard keys
- if re.match("^DisplayName"+xdg.Locale.regex+"$", key):
- pass
- elif key == "EmbeddedTextRectangle":
- self.checkValue(key, value, type="integer", list=True)
- elif key == "AttachPoints":
- self.checkValue(key, value, type="point", list=True)
- elif re.match("^X-[a-zA-Z0-9-]+", key):
- pass
- else:
- self.errors.append("Invalid key: %s" % key)
-
-
-
-icondirs = []
-for basedir in xdg_data_dirs:
- icondirs.append(os.path.join(basedir, "icons"))
- icondirs.append(os.path.join(basedir, "pixmaps"))
-icondirs.append(os.path.expanduser("~/.icons"))
-
-# just cache variables, they give a 10x speed improvement
-themes = []
-theme_cache = {}
-dir_cache = {}
-icon_cache = {}
-
-def getIconPath(iconname, size = None, theme = None, extensions = ["png", "svg", "xpm"]):
- """Get the path to a specified icon.
-
- size :
- Icon size in pixels. Defaults to ``xdg.Config.icon_size``.
- theme :
- Icon theme name. Defaults to ``xdg.Config.icon_theme``. If the icon isn't
- found in the specified theme, it will be looked up in the basic 'hicolor'
- theme.
- extensions :
- List of preferred file extensions.
-
- Example::
-
- >>> getIconPath("inkscape", 32)
- '/usr/share/icons/hicolor/32x32/apps/inkscape.png'
- """
-
- global themes
-
- if size == None:
- size = xdg.Config.icon_size
- if theme == None:
- theme = xdg.Config.icon_theme
-
- # if we have an absolute path, just return it
- if os.path.isabs(iconname):
- return iconname
-
- # check if it has an extension and strip it
- if os.path.splitext(iconname)[1][1:] in extensions:
- iconname = os.path.splitext(iconname)[0]
-
- # parse theme files
- if (themes == []) or (themes[0].name != theme):
- themes = list(__get_themes(theme))
-
- # more caching (icon looked up in the last 5 seconds?)
- tmp = (iconname, size, theme, tuple(extensions))
- try:
- timestamp, icon = icon_cache[tmp]
- except KeyError:
- pass
- else:
- if (time.time() - timestamp) >= xdg.Config.cache_time:
- del icon_cache[tmp]
- else:
- return icon
-
- for thme in themes:
- icon = LookupIcon(iconname, size, thme, extensions)
- if icon:
- icon_cache[tmp] = (time.time(), icon)
- return icon
-
- # cache stuff again (directories looked up in the last 5 seconds?)
- for directory in icondirs:
- if (directory not in dir_cache \
- or (int(time.time() - dir_cache[directory][1]) >= xdg.Config.cache_time \
- and dir_cache[directory][2] < os.path.getmtime(directory))) \
- and os.path.isdir(directory):
- dir_cache[directory] = (os.listdir(directory), time.time(), os.path.getmtime(directory))
-
- for dir, values in dir_cache.items():
- for extension in extensions:
- try:
- if iconname + "." + extension in values[0]:
- icon = os.path.join(dir, iconname + "." + extension)
- icon_cache[tmp] = [time.time(), icon]
- return icon
- except UnicodeDecodeError as e:
- if debug:
- raise e
- else:
- pass
-
- # we haven't found anything? "hicolor" is our fallback
- if theme != "hicolor":
- icon = getIconPath(iconname, size, "hicolor")
- icon_cache[tmp] = [time.time(), icon]
- return icon
-
-def getIconData(path):
- """Retrieve the data from the .icon file corresponding to the given file. If
- there is no .icon file, it returns None.
-
- Example::
-
- getIconData("/usr/share/icons/Tango/scalable/places/folder.svg")
- """
- if os.path.isfile(path):
- icon_file = os.path.splitext(path)[0] + ".icon"
- if os.path.isfile(icon_file):
- data = IconData()
- data.parse(icon_file)
- return data
-
-def __get_themes(themename):
- """Generator yielding IconTheme objects for a specified theme and any themes
- from which it inherits.
- """
- for dir in icondirs:
- theme_file = os.path.join(dir, themename, "index.theme")
- if os.path.isfile(theme_file):
- break
- theme_file = os.path.join(dir, themename, "index.desktop")
- if os.path.isfile(theme_file):
- break
- else:
- if debug:
- raise NoThemeError(themename)
- return
-
- theme = IconTheme()
- theme.parse(theme_file)
- yield theme
- for subtheme in theme.getInherits():
- for t in __get_themes(subtheme):
- yield t
-
-def LookupIcon(iconname, size, theme, extensions):
- # look for the cache
- if theme.name not in theme_cache:
- theme_cache[theme.name] = []
- theme_cache[theme.name].append(time.time() - (xdg.Config.cache_time + 1)) # [0] last time of lookup
- theme_cache[theme.name].append(0) # [1] mtime
- theme_cache[theme.name].append(dict()) # [2] dir: [subdir, [items]]
-
- # cache stuff (directory lookuped up the in the last 5 seconds?)
- if int(time.time() - theme_cache[theme.name][0]) >= xdg.Config.cache_time:
- theme_cache[theme.name][0] = time.time()
- for subdir in theme.getDirectories():
- for directory in icondirs:
- dir = os.path.join(directory,theme.name,subdir)
- if (dir not in theme_cache[theme.name][2] \
- or theme_cache[theme.name][1] < os.path.getmtime(os.path.join(directory,theme.name))) \
- and subdir != "" \
- and os.path.isdir(dir):
- theme_cache[theme.name][2][dir] = [subdir, os.listdir(dir)]
- theme_cache[theme.name][1] = os.path.getmtime(os.path.join(directory,theme.name))
-
- for dir, values in theme_cache[theme.name][2].items():
- if DirectoryMatchesSize(values[0], size, theme):
- for extension in extensions:
- if iconname + "." + extension in values[1]:
- return os.path.join(dir, iconname + "." + extension)
-
- minimal_size = 2**31
- closest_filename = ""
- for dir, values in theme_cache[theme.name][2].items():
- distance = DirectorySizeDistance(values[0], size, theme)
- if distance < minimal_size:
- for extension in extensions:
- if iconname + "." + extension in values[1]:
- closest_filename = os.path.join(dir, iconname + "." + extension)
- minimal_size = distance
-
- return closest_filename
-
-def DirectoryMatchesSize(subdir, iconsize, theme):
- Type = theme.getType(subdir)
- Size = theme.getSize(subdir)
- Threshold = theme.getThreshold(subdir)
- MinSize = theme.getMinSize(subdir)
- MaxSize = theme.getMaxSize(subdir)
- if Type == "Fixed":
- return Size == iconsize
- elif Type == "Scaleable":
- return MinSize <= iconsize <= MaxSize
- elif Type == "Threshold":
- return Size - Threshold <= iconsize <= Size + Threshold
-
-def DirectorySizeDistance(subdir, iconsize, theme):
- Type = theme.getType(subdir)
- Size = theme.getSize(subdir)
- Threshold = theme.getThreshold(subdir)
- MinSize = theme.getMinSize(subdir)
- MaxSize = theme.getMaxSize(subdir)
- if Type == "Fixed":
- return abs(Size - iconsize)
- elif Type == "Scalable":
- if iconsize < MinSize:
- return MinSize - iconsize
- elif iconsize > MaxSize:
- return MaxSize - iconsize
- return 0
- elif Type == "Threshold":
- if iconsize < Size - Threshold:
- return MinSize - iconsize
- elif iconsize > Size + Threshold:
- return iconsize - MaxSize
- return 0
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IniFile.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IniFile.py
deleted file mode 100644
index 74ab858..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/IniFile.py
+++ /dev/null
@@ -1,419 +0,0 @@
-"""
-Base Class for DesktopEntry, IconTheme and IconData
-"""
-
-import re, os, stat, io
-from .Exceptions import (ParsingError, DuplicateGroupError, NoGroupError,
- NoKeyError, DuplicateKeyError, ValidationError,
- debug)
-# import xdg.Locale
-from . import Locale
-from .util import u
-
-def is_ascii(s):
- """Return True if a string consists entirely of ASCII characters."""
- try:
- s.encode('ascii', 'strict')
- return True
- except UnicodeError:
- return False
-
-class IniFile:
- defaultGroup = ''
- fileExtension = ''
-
- filename = ''
-
- tainted = False
-
- def __init__(self, filename=None):
- self.content = dict()
- if filename:
- self.parse(filename)
-
- def __cmp__(self, other):
- return cmp(self.content, other.content)
-
- def parse(self, filename, headers=None):
- '''Parse an INI file.
-
- headers -- list of headers the parser will try to select as a default header
- '''
- # for performance reasons
- content = self.content
-
- if not os.path.isfile(filename):
- raise ParsingError("File not found", filename)
-
- try:
- # The content should be UTF-8, but legacy files can have other
- # encodings, including mixed encodings in one file. We don't attempt
- # to decode them, but we silence the errors.
- fd = io.open(filename, 'r', encoding='utf-8', errors='replace')
- except IOError as e:
- if debug:
- raise e
- else:
- return
-
- # parse file
- for line in fd:
- line = line.strip()
- # empty line
- if not line:
- continue
- # comment
- elif line[0] == '#':
- continue
- # new group
- elif line[0] == '[':
- currentGroup = line.lstrip("[").rstrip("]")
- if debug and self.hasGroup(currentGroup):
- raise DuplicateGroupError(currentGroup, filename)
- else:
- content[currentGroup] = {}
- # key
- else:
- try:
- key, value = line.split("=", 1)
- except ValueError:
- raise ParsingError("Invalid line: " + line, filename)
-
- key = key.strip() # Spaces before/after '=' should be ignored
- try:
- if debug and self.hasKey(key, currentGroup):
- raise DuplicateKeyError(key, currentGroup, filename)
- else:
- content[currentGroup][key] = value.strip()
- except (IndexError, UnboundLocalError):
- raise ParsingError("Parsing error on key, group missing", filename)
-
- fd.close()
-
- self.filename = filename
- self.tainted = False
-
- # check header
- if headers:
- for header in headers:
- if header in content:
- self.defaultGroup = header
- break
- else:
- raise ParsingError("[%s]-Header missing" % headers[0], filename)
-
- # start stuff to access the keys
- def get(self, key, group=None, locale=False, type="string", list=False, strict=False):
- # set default group
- if not group:
- group = self.defaultGroup
-
- # return key (with locale)
- if (group in self.content) and (key in self.content[group]):
- if locale:
- value = self.content[group][self.__addLocale(key, group)]
- else:
- value = self.content[group][key]
- else:
- if strict or debug:
- if group not in self.content:
- raise NoGroupError(group, self.filename)
- elif key not in self.content[group]:
- raise NoKeyError(key, group, self.filename)
- else:
- value = ""
-
- if list == True:
- values = self.getList(value)
- result = []
- else:
- values = [value]
-
- for value in values:
- if type == "boolean":
- value = self.__getBoolean(value)
- elif type == "integer":
- try:
- value = int(value)
- except ValueError:
- value = 0
- elif type == "numeric":
- try:
- value = float(value)
- except ValueError:
- value = 0.0
- elif type == "regex":
- value = re.compile(value)
- elif type == "point":
- x, y = value.split(",")
- value = int(x), int(y)
-
- if list == True:
- result.append(value)
- else:
- result = value
-
- return result
- # end stuff to access the keys
-
- # start subget
- def getList(self, string):
- if re.search(r"(? 0:
- key = key + "[" + xdg.Locale.langs[0] + "]"
-
- try:
- self.content[group][key] = value
- except KeyError:
- raise NoGroupError(group, self.filename)
-
- self.tainted = (value == self.get(key, group))
-
- def addGroup(self, group):
- if self.hasGroup(group):
- if debug:
- raise DuplicateGroupError(group, self.filename)
- else:
- self.content[group] = {}
- self.tainted = True
-
- def removeGroup(self, group):
- existed = group in self.content
- if existed:
- del self.content[group]
- self.tainted = True
- else:
- if debug:
- raise NoGroupError(group, self.filename)
- return existed
-
- def removeKey(self, key, group=None, locales=True):
- # set default group
- if not group:
- group = self.defaultGroup
-
- try:
- if locales:
- for name in list(self.content[group]):
- if re.match("^" + key + xdg.Locale.regex + "$", name) and name != key:
- del self.content[group][name]
- value = self.content[group].pop(key)
- self.tainted = True
- return value
- except KeyError as e:
- if debug:
- if e == group:
- raise NoGroupError(group, self.filename)
- else:
- raise NoKeyError(key, group, self.filename)
- else:
- return ""
-
- # misc
- def groups(self):
- return self.content.keys()
-
- def hasGroup(self, group):
- return group in self.content
-
- def hasKey(self, key, group=None):
- # set default group
- if not group:
- group = self.defaultGroup
-
- return key in self.content[group]
-
- def getFileName(self):
- return self.filename
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Locale.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Locale.py
deleted file mode 100644
index d0a70d2..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Locale.py
+++ /dev/null
@@ -1,79 +0,0 @@
-"""
-Helper Module for Locale settings
-
-This module is based on a ROX module (LGPL):
-
-http://cvs.sourceforge.net/viewcvs.py/rox/ROX-Lib2/python/rox/i18n.py?rev=1.3&view=log
-"""
-
-import os
-from locale import normalize
-
-regex = r"(\[([a-zA-Z]+)(_[a-zA-Z]+)?(\.[a-zA-Z0-9-]+)?(@[a-zA-Z]+)?\])?"
-
-def _expand_lang(locale):
- locale = normalize(locale)
- COMPONENT_CODESET = 1 << 0
- COMPONENT_MODIFIER = 1 << 1
- COMPONENT_TERRITORY = 1 << 2
- # split up the locale into its base components
- mask = 0
- pos = locale.find('@')
- if pos >= 0:
- modifier = locale[pos:]
- locale = locale[:pos]
- mask |= COMPONENT_MODIFIER
- else:
- modifier = ''
- pos = locale.find('.')
- codeset = ''
- if pos >= 0:
- locale = locale[:pos]
- pos = locale.find('_')
- if pos >= 0:
- territory = locale[pos:]
- locale = locale[:pos]
- mask |= COMPONENT_TERRITORY
- else:
- territory = ''
- language = locale
- ret = []
- for i in range(mask+1):
- if not (i & ~mask): # if all components for this combo exist ...
- val = language
- if i & COMPONENT_TERRITORY: val += territory
- if i & COMPONENT_CODESET: val += codeset
- if i & COMPONENT_MODIFIER: val += modifier
- ret.append(val)
- ret.reverse()
- return ret
-
-def expand_languages(languages=None):
- # Get some reasonable defaults for arguments that were not supplied
- if languages is None:
- languages = []
- for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
- val = os.environ.get(envar)
- if val:
- languages = val.split(':')
- break
- #if 'C' not in languages:
- # languages.append('C')
-
- # now normalize and expand the languages
- nelangs = []
- for lang in languages:
- for nelang in _expand_lang(lang):
- if nelang not in nelangs:
- nelangs.append(nelang)
- return nelangs
-
-def update(language=None):
- global langs
- if language:
- langs = expand_languages([language])
- else:
- langs = expand_languages()
-
-langs = []
-update()
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Menu.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Menu.py
deleted file mode 100644
index fcf1ac1..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Menu.py
+++ /dev/null
@@ -1,1125 +0,0 @@
-"""
-Implementation of the XDG Menu Specification
-http://standards.freedesktop.org/menu-spec/
-
-Example code:
-
-from xdg.Menu import parse, Menu, MenuEntry
-
-def print_menu(menu, tab=0):
- for submenu in menu.Entries:
- if isinstance(submenu, Menu):
- print ("\t" * tab) + unicode(submenu)
- print_menu(submenu, tab+1)
- elif isinstance(submenu, MenuEntry):
- print ("\t" * tab) + unicode(submenu.DesktopEntry)
-
-print_menu(parse())
-"""
-
-import os
-import locale
-import subprocess
-import ast
-try:
- import xml.etree.cElementTree as etree
-except ImportError:
- import xml.etree.ElementTree as etree
-
-from .BaseDirectory import xdg_data_dirs, xdg_config_dirs
-from . import DesktopEntry, Locale, Config
-from .Exceptions import ParsingError
-from .util import PY3
-
-
-def _strxfrm(s):
- """Wrapper around locale.strxfrm that accepts unicode strings on Python 2.
-
- See Python bug #2481.
- """
- if (not PY3) and isinstance(s, unicode):
- s = s.encode('utf-8')
- return locale.strxfrm(s)
-
-
-DELETED = "Deleted"
-NO_DISPLAY = "NoDisplay"
-HIDDEN = "Hidden"
-EMPTY = "Empty"
-NOT_SHOW_IN = "NotShowIn"
-NO_EXEC = "NoExec"
-
-
-class Menu:
- """Menu containing sub menus under menu.Entries
-
- Contains both Menu and MenuEntry items.
- """
- def __init__(self):
- # Public stuff
- self.Name = ""
- self.Directory = None
- self.Entries = []
- self.Doc = ""
- self.Filename = ""
- self.Depth = 0
- self.Parent = None
- self.NotInXml = False
-
- # Can be True, False, DELETED, NO_DISPLAY, HIDDEN, EMPTY or NOT_SHOW_IN
- self.Show = True
- self.Visible = 0
-
- # Private stuff, only needed for parsing
- self.AppDirs = []
- self.DefaultLayout = None
- self.Deleted = None
- self.Directories = []
- self.DirectoryDirs = []
- self.Layout = None
- self.MenuEntries = []
- self.Moves = []
- self.OnlyUnallocated = None
- self.Rules = []
- self.Submenus = []
-
- def __str__(self):
- return self.Name
-
- def __add__(self, other):
- for dir in other.AppDirs:
- self.AppDirs.append(dir)
-
- for dir in other.DirectoryDirs:
- self.DirectoryDirs.append(dir)
-
- for directory in other.Directories:
- self.Directories.append(directory)
-
- if other.Deleted is not None:
- self.Deleted = other.Deleted
-
- if other.OnlyUnallocated is not None:
- self.OnlyUnallocated = other.OnlyUnallocated
-
- if other.Layout:
- self.Layout = other.Layout
-
- if other.DefaultLayout:
- self.DefaultLayout = other.DefaultLayout
-
- for rule in other.Rules:
- self.Rules.append(rule)
-
- for move in other.Moves:
- self.Moves.append(move)
-
- for submenu in other.Submenus:
- self.addSubmenu(submenu)
-
- return self
-
- # FIXME: Performance: cache getName()
- def __cmp__(self, other):
- return locale.strcoll(self.getName(), other.getName())
-
- def _key(self):
- """Key function for locale-aware sorting."""
- return _strxfrm(self.getName())
-
- def __lt__(self, other):
- try:
- other = other._key()
- except AttributeError:
- pass
- return self._key() < other
-
- def __eq__(self, other):
- try:
- return self.Name == unicode(other)
- except NameError: # unicode() becomes str() in Python 3
- return self.Name == str(other)
-
- """ PUBLIC STUFF """
- def getEntries(self, show_hidden=False):
- """Interator for a list of Entries visible to the user."""
- for entry in self.Entries:
- if show_hidden:
- yield entry
- elif entry.Show is True:
- yield entry
-
- # FIXME: Add searchEntry/seaqrchMenu function
- # search for name/comment/genericname/desktopfileid
- # return multiple items
-
- def getMenuEntry(self, desktopfileid, deep=False):
- """Searches for a MenuEntry with a given DesktopFileID."""
- for menuentry in self.MenuEntries:
- if menuentry.DesktopFileID == desktopfileid:
- return menuentry
- if deep:
- for submenu in self.Submenus:
- submenu.getMenuEntry(desktopfileid, deep)
-
- def getMenu(self, path):
- """Searches for a Menu with a given path."""
- array = path.split("/", 1)
- for submenu in self.Submenus:
- if submenu.Name == array[0]:
- if len(array) > 1:
- return submenu.getMenu(array[1])
- else:
- return submenu
-
- def getPath(self, org=False, toplevel=False):
- """Returns this menu's path in the menu structure."""
- parent = self
- names = []
- while 1:
- if org:
- names.append(parent.Name)
- else:
- names.append(parent.getName())
- if parent.Depth > 0:
- parent = parent.Parent
- else:
- break
- names.reverse()
- path = ""
- if not toplevel:
- names.pop(0)
- for name in names:
- path = os.path.join(path, name)
- return path
-
- def getName(self):
- """Returns the menu's localised name."""
- try:
- return self.Directory.DesktopEntry.getName()
- except AttributeError:
- return self.Name
-
- def getGenericName(self):
- """Returns the menu's generic name."""
- try:
- return self.Directory.DesktopEntry.getGenericName()
- except AttributeError:
- return ""
-
- def getComment(self):
- """Returns the menu's comment text."""
- try:
- return self.Directory.DesktopEntry.getComment()
- except AttributeError:
- return ""
-
- def getIcon(self):
- """Returns the menu's icon, filename or simple name"""
- try:
- return self.Directory.DesktopEntry.getIcon()
- except AttributeError:
- return ""
-
- def sort(self):
- self.Entries = []
- self.Visible = 0
-
- for submenu in self.Submenus:
- submenu.sort()
-
- _submenus = set()
- _entries = set()
-
- for order in self.Layout.order:
- if order[0] == "Filename":
- _entries.add(order[1])
- elif order[0] == "Menuname":
- _submenus.add(order[1])
-
- for order in self.Layout.order:
- if order[0] == "Separator":
- separator = Separator(self)
- if len(self.Entries) > 0 and isinstance(self.Entries[-1], Separator):
- separator.Show = False
- self.Entries.append(separator)
- elif order[0] == "Filename":
- menuentry = self.getMenuEntry(order[1])
- if menuentry:
- self.Entries.append(menuentry)
- elif order[0] == "Menuname":
- submenu = self.getMenu(order[1])
- if submenu:
- if submenu.Layout.inline:
- self.merge_inline(submenu)
- else:
- self.Entries.append(submenu)
- elif order[0] == "Merge":
- if order[1] == "files" or order[1] == "all":
- self.MenuEntries.sort()
- for menuentry in self.MenuEntries:
- if menuentry.DesktopFileID not in _entries:
- self.Entries.append(menuentry)
- elif order[1] == "menus" or order[1] == "all":
- self.Submenus.sort()
- for submenu in self.Submenus:
- if submenu.Name not in _submenus:
- if submenu.Layout.inline:
- self.merge_inline(submenu)
- else:
- self.Entries.append(submenu)
-
- # getHidden / NoDisplay / OnlyShowIn / NotOnlyShowIn / Deleted / NoExec
- for entry in self.Entries:
- entry.Show = True
- self.Visible += 1
- if isinstance(entry, Menu):
- if entry.Deleted is True:
- entry.Show = DELETED
- self.Visible -= 1
- elif isinstance(entry.Directory, MenuEntry):
- if entry.Directory.DesktopEntry.getNoDisplay():
- entry.Show = NO_DISPLAY
- self.Visible -= 1
- elif entry.Directory.DesktopEntry.getHidden():
- entry.Show = HIDDEN
- self.Visible -= 1
- elif isinstance(entry, MenuEntry):
- if entry.DesktopEntry.getNoDisplay():
- entry.Show = NO_DISPLAY
- self.Visible -= 1
- elif entry.DesktopEntry.getHidden():
- entry.Show = HIDDEN
- self.Visible -= 1
- elif entry.DesktopEntry.getTryExec() and not entry.DesktopEntry.findTryExec():
- entry.Show = NO_EXEC
- self.Visible -= 1
- elif xdg.Config.windowmanager:
- if (entry.DesktopEntry.OnlyShowIn != [] and (
- xdg.Config.windowmanager not in entry.DesktopEntry.OnlyShowIn
- )
- ) or (
- xdg.Config.windowmanager in entry.DesktopEntry.NotShowIn
- ):
- entry.Show = NOT_SHOW_IN
- self.Visible -= 1
- elif isinstance(entry, Separator):
- self.Visible -= 1
- # remove separators at the beginning and at the end
- if len(self.Entries) > 0:
- if isinstance(self.Entries[0], Separator):
- self.Entries[0].Show = False
- if len(self.Entries) > 1:
- if isinstance(self.Entries[-1], Separator):
- self.Entries[-1].Show = False
-
- # show_empty tag
- for entry in self.Entries[:]:
- if isinstance(entry, Menu) and not entry.Layout.show_empty and entry.Visible == 0:
- entry.Show = EMPTY
- self.Visible -= 1
- if entry.NotInXml is True:
- self.Entries.remove(entry)
-
- """ PRIVATE STUFF """
- def addSubmenu(self, newmenu):
- for submenu in self.Submenus:
- if submenu == newmenu:
- submenu += newmenu
- break
- else:
- self.Submenus.append(newmenu)
- newmenu.Parent = self
- newmenu.Depth = self.Depth + 1
-
- # inline tags
- def merge_inline(self, submenu):
- """Appends a submenu's entries to this menu
- See the section of the spec about the "inline" attribute
- """
- if len(submenu.Entries) == 1 and submenu.Layout.inline_alias:
- menuentry = submenu.Entries[0]
- menuentry.DesktopEntry.set("Name", submenu.getName(), locale=True)
- menuentry.DesktopEntry.set("GenericName", submenu.getGenericName(), locale=True)
- menuentry.DesktopEntry.set("Comment", submenu.getComment(), locale=True)
- self.Entries.append(menuentry)
- elif len(submenu.Entries) <= submenu.Layout.inline_limit or submenu.Layout.inline_limit == 0:
- if submenu.Layout.inline_header:
- header = Header(submenu.getName(), submenu.getGenericName(), submenu.getComment())
- self.Entries.append(header)
- for entry in submenu.Entries:
- self.Entries.append(entry)
- else:
- self.Entries.append(submenu)
-
-
-class Move:
- "A move operation"
- def __init__(self, old="", new=""):
- self.Old = old
- self.New = new
-
- def __cmp__(self, other):
- return cmp(self.Old, other.Old)
-
-
-class Layout:
- "Menu Layout class"
- def __init__(self, show_empty=False, inline=False, inline_limit=4,
- inline_header=True, inline_alias=False):
- self.show_empty = show_empty
- self.inline = inline
- self.inline_limit = inline_limit
- self.inline_header = inline_header
- self.inline_alias = inline_alias
- self._order = []
- self._default_order = [
- ['Merge', 'menus'],
- ['Merge', 'files']
- ]
-
- @property
- def order(self):
- return self._order if self._order else self._default_order
-
- @order.setter
- def order(self, order):
- self._order = order
-
-
-class Rule:
- """Include / Exclude Rules Class"""
-
- TYPE_INCLUDE, TYPE_EXCLUDE = 0, 1
-
- @classmethod
- def fromFilename(cls, type, filename):
- tree = ast.Expression(
- body=ast.Compare(
- left=ast.Str(filename),
- ops=[ast.Eq()],
- comparators=[ast.Attribute(
- value=ast.Name(id='menuentry', ctx=ast.Load()),
- attr='DesktopFileID',
- ctx=ast.Load()
- )]
- ),
- lineno=1, col_offset=0
- )
- ast.fix_missing_locations(tree)
- rule = Rule(type, tree)
- return rule
-
- def __init__(self, type, expression):
- # Type is TYPE_INCLUDE or TYPE_EXCLUDE
- self.Type = type
- # expression is ast.Expression
- self.expression = expression
- self.code = compile(self.expression, '', 'eval')
-
- def __str__(self):
- return ast.dump(self.expression)
-
- def apply(self, menuentries, run):
- for menuentry in menuentries:
- if run == 2 and (menuentry.MatchedInclude is True or
- menuentry.Allocated is True):
- continue
- if eval(self.code):
- if self.Type is Rule.TYPE_INCLUDE:
- menuentry.Add = True
- menuentry.MatchedInclude = True
- else:
- menuentry.Add = False
- return menuentries
-
-
-class MenuEntry:
- "Wrapper for 'Menu Style' Desktop Entries"
-
- TYPE_USER = "User"
- TYPE_SYSTEM = "System"
- TYPE_BOTH = "Both"
-
- def __init__(self, filename, dir="", prefix=""):
- # Create entry
- self.DesktopEntry = DesktopEntry(os.path.join(dir, filename))
- self.setAttributes(filename, dir, prefix)
-
- # Can True, False DELETED, HIDDEN, EMPTY, NOT_SHOW_IN or NO_EXEC
- self.Show = True
-
- # Semi-Private
- self.Original = None
- self.Parents = []
-
- # Private Stuff
- self.Allocated = False
- self.Add = False
- self.MatchedInclude = False
-
- # Caching
- self.Categories = self.DesktopEntry.getCategories()
-
- def save(self):
- """Save any changes to the desktop entry."""
- if self.DesktopEntry.tainted:
- self.DesktopEntry.write()
-
- def getDir(self):
- """Return the directory containing the desktop entry file."""
- return self.DesktopEntry.filename.replace(self.Filename, '')
-
- def getType(self):
- """Return the type of MenuEntry, System/User/Both"""
- if not xdg.Config.root_mode:
- if self.Original:
- return self.TYPE_BOTH
- elif xdg_data_dirs[0] in self.DesktopEntry.filename:
- return self.TYPE_USER
- else:
- return self.TYPE_SYSTEM
- else:
- return self.TYPE_USER
-
- def setAttributes(self, filename, dir="", prefix=""):
- self.Filename = filename
- self.Prefix = prefix
- self.DesktopFileID = os.path.join(prefix, filename).replace("/", "-")
-
- if not os.path.isabs(self.DesktopEntry.filename):
- self.__setFilename()
-
- def updateAttributes(self):
- if self.getType() == self.TYPE_SYSTEM:
- self.Original = MenuEntry(self.Filename, self.getDir(), self.Prefix)
- self.__setFilename()
-
- def __setFilename(self):
- if not xdg.Config.root_mode:
- path = xdg_data_dirs[0]
- else:
- path = xdg_data_dirs[1]
-
- if self.DesktopEntry.getType() == "Application":
- dir_ = os.path.join(path, "applications")
- else:
- dir_ = os.path.join(path, "desktop-directories")
-
- self.DesktopEntry.filename = os.path.join(dir_, self.Filename)
-
- def __cmp__(self, other):
- return locale.strcoll(self.DesktopEntry.getName(), other.DesktopEntry.getName())
-
- def _key(self):
- """Key function for locale-aware sorting."""
- return _strxfrm(self.DesktopEntry.getName())
-
- def __lt__(self, other):
- try:
- other = other._key()
- except AttributeError:
- pass
- return self._key() < other
-
- def __eq__(self, other):
- if self.DesktopFileID == str(other):
- return True
- else:
- return False
-
- def __repr__(self):
- return self.DesktopFileID
-
-
-class Separator:
- "Just a dummy class for Separators"
- def __init__(self, parent):
- self.Parent = parent
- self.Show = True
-
-
-class Header:
- "Class for Inline Headers"
- def __init__(self, name, generic_name, comment):
- self.Name = name
- self.GenericName = generic_name
- self.Comment = comment
-
- def __str__(self):
- return self.Name
-
-
-TYPE_DIR, TYPE_FILE = 0, 1
-
-
-def _check_file_path(value, filename, type):
- path = os.path.dirname(filename)
- if not os.path.isabs(value):
- value = os.path.join(path, value)
- value = os.path.abspath(value)
- if not os.path.exists(value):
- return False
- if type == TYPE_DIR and os.path.isdir(value):
- return value
- if type == TYPE_FILE and os.path.isfile(value):
- return value
- return False
-
-
-def _get_menu_file_path(filename):
- dirs = list(xdg_config_dirs)
- if xdg.Config.root_mode is True:
- dirs.pop(0)
- for d in dirs:
- menuname = os.path.join(d, "menus", filename)
- if os.path.isfile(menuname):
- return menuname
-
-
-def _to_bool(value):
- if isinstance(value, bool):
- return value
- return value.lower() == "true"
-
-
-# remove duplicate entries from a list
-def _dedupe(_list):
- _set = {}
- _list.reverse()
- _list = [_set.setdefault(e, e) for e in _list if e not in _set]
- _list.reverse()
- return _list
-
-
-class XMLMenuBuilder(object):
-
- def __init__(self, debug=False):
- self.debug = debug
-
- def parse(self, filename=None):
- """Load an applications.menu file.
-
- filename : str, optional
- The default is ``$XDG_CONFIG_DIRS/menus/${XDG_MENU_PREFIX}applications.menu``.
- """
- # convert to absolute path
- if filename and not os.path.isabs(filename):
- filename = _get_menu_file_path(filename)
- # use default if no filename given
- if not filename:
- candidate = os.environ.get('XDG_MENU_PREFIX', '') + "applications.menu"
- filename = _get_menu_file_path(candidate)
- if not filename:
- raise ParsingError('File not found', "/etc/xdg/menus/%s" % candidate)
- # check if it is a .menu file
- if not filename.endswith(".menu"):
- raise ParsingError('Not a .menu file', filename)
- # create xml parser
- try:
- tree = etree.parse(filename)
- except:
- raise ParsingError('Not a valid .menu file', filename)
-
- # parse menufile
- self._merged_files = set()
- self._directory_dirs = set()
- self.cache = MenuEntryCache()
-
- menu = self.parse_menu(tree.getroot(), filename)
- menu.tree = tree
- menu.filename = filename
-
- self.handle_moves(menu)
- self.post_parse(menu)
-
- # generate the menu
- self.generate_not_only_allocated(menu)
- self.generate_only_allocated(menu)
-
- # and finally sort
- menu.sort()
-
- return menu
-
- def parse_menu(self, node, filename):
- menu = Menu()
- self.parse_node(node, filename, menu)
- return menu
-
- def parse_node(self, node, filename, parent=None):
- num_children = len(node)
- for child in node:
- tag, text = child.tag, child.text
- text = text.strip() if text else None
- if tag == 'Menu':
- menu = self.parse_menu(child, filename)
- parent.addSubmenu(menu)
- elif tag == 'AppDir' and text:
- self.parse_app_dir(text, filename, parent)
- elif tag == 'DefaultAppDirs':
- self.parse_default_app_dir(filename, parent)
- elif tag == 'DirectoryDir' and text:
- self.parse_directory_dir(text, filename, parent)
- elif tag == 'DefaultDirectoryDirs':
- self.parse_default_directory_dir(filename, parent)
- elif tag == 'Name' and text:
- parent.Name = text
- elif tag == 'Directory' and text:
- parent.Directories.append(text)
- elif tag == 'OnlyUnallocated':
- parent.OnlyUnallocated = True
- elif tag == 'NotOnlyUnallocated':
- parent.OnlyUnallocated = False
- elif tag == 'Deleted':
- parent.Deleted = True
- elif tag == 'NotDeleted':
- parent.Deleted = False
- elif tag == 'Include' or tag == 'Exclude':
- parent.Rules.append(self.parse_rule(child))
- elif tag == 'MergeFile':
- if child.attrib.get("type", None) == "parent":
- self.parse_merge_file("applications.menu", child, filename, parent)
- elif text:
- self.parse_merge_file(text, child, filename, parent)
- elif tag == 'MergeDir' and text:
- self.parse_merge_dir(text, child, filename, parent)
- elif tag == 'DefaultMergeDirs':
- self.parse_default_merge_dirs(child, filename, parent)
- elif tag == 'Move':
- parent.Moves.append(self.parse_move(child))
- elif tag == 'Layout':
- if num_children > 1:
- parent.Layout = self.parse_layout(child)
- elif tag == 'DefaultLayout':
- if num_children > 1:
- parent.DefaultLayout = self.parse_layout(child)
- elif tag == 'LegacyDir' and text:
- self.parse_legacy_dir(text, child.attrib.get("prefix", ""), filename, parent)
- elif tag == 'KDELegacyDirs':
- self.parse_kde_legacy_dirs(filename, parent)
-
- def parse_layout(self, node):
- layout = Layout(
- show_empty=_to_bool(node.attrib.get("show_empty", False)),
- inline=_to_bool(node.attrib.get("inline", False)),
- inline_limit=int(node.attrib.get("inline_limit", 4)),
- inline_header=_to_bool(node.attrib.get("inline_header", True)),
- inline_alias=_to_bool(node.attrib.get("inline_alias", False))
- )
- for child in node:
- tag, text = child.tag, child.text
- text = text.strip() if text else None
- if tag == "Menuname" and text:
- layout.order.append([
- "Menuname",
- text,
- _to_bool(child.attrib.get("show_empty", False)),
- _to_bool(child.attrib.get("inline", False)),
- int(child.attrib.get("inline_limit", 4)),
- _to_bool(child.attrib.get("inline_header", True)),
- _to_bool(child.attrib.get("inline_alias", False))
- ])
- elif tag == "Separator":
- layout.order.append(['Separator'])
- elif tag == "Filename" and text:
- layout.order.append(["Filename", text])
- elif tag == "Merge":
- layout.order.append([
- "Merge",
- child.attrib.get("type", "all")
- ])
- return layout
-
- def parse_move(self, node):
- old, new = "", ""
- for child in node:
- tag, text = child.tag, child.text
- text = text.strip() if text else None
- if tag == "Old" and text:
- old = text
- elif tag == "New" and text:
- new = text
- return Move(old, new)
-
- # ---------- parsing
-
- def parse_rule(self, node):
- type = Rule.TYPE_INCLUDE if node.tag == 'Include' else Rule.TYPE_EXCLUDE
- tree = ast.Expression(lineno=1, col_offset=0)
- expr = self.parse_bool_op(node, ast.Or())
- if expr:
- tree.body = expr
- else:
- tree.body = ast.Name('False', ast.Load())
- ast.fix_missing_locations(tree)
- return Rule(type, tree)
-
- def parse_bool_op(self, node, operator):
- values = []
- for child in node:
- rule = self.parse_rule_node(child)
- if rule:
- values.append(rule)
- num_values = len(values)
- if num_values > 1:
- return ast.BoolOp(operator, values)
- elif num_values == 1:
- return values[0]
- return None
-
- def parse_rule_node(self, node):
- tag = node.tag
- if tag == 'Or':
- return self.parse_bool_op(node, ast.Or())
- elif tag == 'And':
- return self.parse_bool_op(node, ast.And())
- elif tag == 'Not':
- expr = self.parse_bool_op(node, ast.Or())
- return ast.UnaryOp(ast.Not(), expr) if expr else None
- elif tag == 'All':
- return ast.Name('True', ast.Load())
- elif tag == 'Category':
- category = node.text
- return ast.Compare(
- left=ast.Str(category),
- ops=[ast.In()],
- comparators=[ast.Attribute(
- value=ast.Name(id='menuentry', ctx=ast.Load()),
- attr='Categories',
- ctx=ast.Load()
- )]
- )
- elif tag == 'Filename':
- filename = node.text
- return ast.Compare(
- left=ast.Str(filename),
- ops=[ast.Eq()],
- comparators=[ast.Attribute(
- value=ast.Name(id='menuentry', ctx=ast.Load()),
- attr='DesktopFileID',
- ctx=ast.Load()
- )]
- )
-
- # ---------- App/Directory Dir Stuff
-
- def parse_app_dir(self, value, filename, parent):
- value = _check_file_path(value, filename, TYPE_DIR)
- if value:
- parent.AppDirs.append(value)
-
- def parse_default_app_dir(self, filename, parent):
- for d in reversed(xdg_data_dirs):
- self.parse_app_dir(os.path.join(d, "applications"), filename, parent)
-
- def parse_directory_dir(self, value, filename, parent):
- value = _check_file_path(value, filename, TYPE_DIR)
- if value:
- parent.DirectoryDirs.append(value)
-
- def parse_default_directory_dir(self, filename, parent):
- for d in reversed(xdg_data_dirs):
- self.parse_directory_dir(os.path.join(d, "desktop-directories"), filename, parent)
-
- # ---------- Merge Stuff
-
- def parse_merge_file(self, value, child, filename, parent):
- if child.attrib.get("type", None) == "parent":
- for d in xdg_config_dirs:
- rel_file = filename.replace(d, "").strip("/")
- if rel_file != filename:
- for p in xdg_config_dirs:
- if d == p:
- continue
- if os.path.isfile(os.path.join(p, rel_file)):
- self.merge_file(os.path.join(p, rel_file), child, parent)
- break
- else:
- value = _check_file_path(value, filename, TYPE_FILE)
- if value:
- self.merge_file(value, child, parent)
-
- def parse_merge_dir(self, value, child, filename, parent):
- value = _check_file_path(value, filename, TYPE_DIR)
- if value:
- for item in os.listdir(value):
- try:
- if item.endswith(".menu"):
- self.merge_file(os.path.join(value, item), child, parent)
- except UnicodeDecodeError:
- continue
-
- def parse_default_merge_dirs(self, child, filename, parent):
- basename = os.path.splitext(os.path.basename(filename))[0]
- for d in reversed(xdg_config_dirs):
- self.parse_merge_dir(os.path.join(d, "menus", basename + "-merged"), child, filename, parent)
-
- def merge_file(self, filename, child, parent):
- # check for infinite loops
- if filename in self._merged_files:
- if self.debug:
- raise ParsingError('Infinite MergeFile loop detected', filename)
- else:
- return
- self._merged_files.add(filename)
- # load file
- try:
- tree = etree.parse(filename)
- except IOError:
- if self.debug:
- raise ParsingError('File not found', filename)
- else:
- return
- except:
- if self.debug:
- raise ParsingError('Not a valid .menu file', filename)
- else:
- return
- root = tree.getroot()
- self.parse_node(root, filename, parent)
-
- # ---------- Legacy Dir Stuff
-
- def parse_legacy_dir(self, dir_, prefix, filename, parent):
- m = self.merge_legacy_dir(dir_, prefix, filename, parent)
- if m:
- parent += m
-
- def merge_legacy_dir(self, dir_, prefix, filename, parent):
- dir_ = _check_file_path(dir_, filename, TYPE_DIR)
- if dir_ and dir_ not in self._directory_dirs:
- self._directory_dirs.add(dir_)
- m = Menu()
- m.AppDirs.append(dir_)
- m.DirectoryDirs.append(dir_)
- m.Name = os.path.basename(dir_)
- m.NotInXml = True
-
- for item in os.listdir(dir_):
- try:
- if item == ".directory":
- m.Directories.append(item)
- elif os.path.isdir(os.path.join(dir_, item)):
- m.addSubmenu(self.merge_legacy_dir(
- os.path.join(dir_, item),
- prefix,
- filename,
- parent
- ))
- except UnicodeDecodeError:
- continue
-
- self.cache.add_menu_entries([dir_], prefix, True)
- menuentries = self.cache.get_menu_entries([dir_], False)
-
- for menuentry in menuentries:
- categories = menuentry.Categories
- if len(categories) == 0:
- r = Rule.fromFilename(Rule.TYPE_INCLUDE, menuentry.DesktopFileID)
- m.Rules.append(r)
- if not dir_ in parent.AppDirs:
- categories.append("Legacy")
- menuentry.Categories = categories
-
- return m
-
- def parse_kde_legacy_dirs(self, filename, parent):
- try:
- proc = subprocess.Popen(
- ['kde-config', '--path', 'apps'],
- stdout=subprocess.PIPE,
- universal_newlines=True
- )
- output = proc.communicate()[0].splitlines()
- except OSError:
- # If kde-config doesn't exist, ignore this.
- return
- try:
- for dir_ in output[0].split(":"):
- self.parse_legacy_dir(dir_, "kde", filename, parent)
- except IndexError:
- pass
-
- def post_parse(self, menu):
- # unallocated / deleted
- if menu.Deleted is None:
- menu.Deleted = False
- if menu.OnlyUnallocated is None:
- menu.OnlyUnallocated = False
-
- # Layout Tags
- if not menu.Layout or not menu.DefaultLayout:
- if menu.DefaultLayout:
- menu.Layout = menu.DefaultLayout
- elif menu.Layout:
- if menu.Depth > 0:
- menu.DefaultLayout = menu.Parent.DefaultLayout
- else:
- menu.DefaultLayout = Layout()
- else:
- if menu.Depth > 0:
- menu.Layout = menu.Parent.DefaultLayout
- menu.DefaultLayout = menu.Parent.DefaultLayout
- else:
- menu.Layout = Layout()
- menu.DefaultLayout = Layout()
-
- # add parent's app/directory dirs
- if menu.Depth > 0:
- menu.AppDirs = menu.Parent.AppDirs + menu.AppDirs
- menu.DirectoryDirs = menu.Parent.DirectoryDirs + menu.DirectoryDirs
-
- # remove duplicates
- menu.Directories = _dedupe(menu.Directories)
- menu.DirectoryDirs = _dedupe(menu.DirectoryDirs)
- menu.AppDirs = _dedupe(menu.AppDirs)
-
- # go recursive through all menus
- for submenu in menu.Submenus:
- self.post_parse(submenu)
-
- # reverse so handling is easier
- menu.Directories.reverse()
- menu.DirectoryDirs.reverse()
- menu.AppDirs.reverse()
-
- # get the valid .directory file out of the list
- for directory in menu.Directories:
- for dir in menu.DirectoryDirs:
- if os.path.isfile(os.path.join(dir, directory)):
- menuentry = MenuEntry(directory, dir)
- if not menu.Directory:
- menu.Directory = menuentry
- elif menuentry.Type == MenuEntry.TYPE_SYSTEM:
- if menu.Directory.Type == MenuEntry.TYPE_USER:
- menu.Directory.Original = menuentry
- if menu.Directory:
- break
-
- # Finally generate the menu
- def generate_not_only_allocated(self, menu):
- for submenu in menu.Submenus:
- self.generate_not_only_allocated(submenu)
-
- if menu.OnlyUnallocated is False:
- self.cache.add_menu_entries(menu.AppDirs)
- menuentries = []
- for rule in menu.Rules:
- menuentries = rule.apply(self.cache.get_menu_entries(menu.AppDirs), 1)
-
- for menuentry in menuentries:
- if menuentry.Add is True:
- menuentry.Parents.append(menu)
- menuentry.Add = False
- menuentry.Allocated = True
- menu.MenuEntries.append(menuentry)
-
- def generate_only_allocated(self, menu):
- for submenu in menu.Submenus:
- self.generate_only_allocated(submenu)
-
- if menu.OnlyUnallocated is True:
- self.cache.add_menu_entries(menu.AppDirs)
- menuentries = []
- for rule in menu.Rules:
- menuentries = rule.apply(self.cache.get_menu_entries(menu.AppDirs), 2)
- for menuentry in menuentries:
- if menuentry.Add is True:
- menuentry.Parents.append(menu)
- # menuentry.Add = False
- # menuentry.Allocated = True
- menu.MenuEntries.append(menuentry)
-
- def handle_moves(self, menu):
- for submenu in menu.Submenus:
- self.handle_moves(submenu)
- # parse move operations
- for move in menu.Moves:
- move_from_menu = menu.getMenu(move.Old)
- if move_from_menu:
- # FIXME: this is assigned, but never used...
- move_to_menu = menu.getMenu(move.New)
-
- menus = move.New.split("/")
- oldparent = None
- while len(menus) > 0:
- if not oldparent:
- oldparent = menu
- newmenu = oldparent.getMenu(menus[0])
- if not newmenu:
- newmenu = Menu()
- newmenu.Name = menus[0]
- if len(menus) > 1:
- newmenu.NotInXml = True
- oldparent.addSubmenu(newmenu)
- oldparent = newmenu
- menus.pop(0)
-
- newmenu += move_from_menu
- move_from_menu.Parent.Submenus.remove(move_from_menu)
-
-
-class MenuEntryCache:
- "Class to cache Desktop Entries"
- def __init__(self):
- self.cacheEntries = {}
- self.cacheEntries['legacy'] = []
- self.cache = {}
-
- def add_menu_entries(self, dirs, prefix="", legacy=False):
- for dir_ in dirs:
- if not dir_ in self.cacheEntries:
- self.cacheEntries[dir_] = []
- self.__addFiles(dir_, "", prefix, legacy)
-
- def __addFiles(self, dir_, subdir, prefix, legacy):
- for item in os.listdir(os.path.join(dir_, subdir)):
- if item.endswith(".desktop"):
- try:
- menuentry = MenuEntry(os.path.join(subdir, item), dir_, prefix)
- except ParsingError:
- continue
-
- self.cacheEntries[dir_].append(menuentry)
- if legacy:
- self.cacheEntries['legacy'].append(menuentry)
- elif os.path.isdir(os.path.join(dir_, subdir, item)) and not legacy:
- self.__addFiles(dir_, os.path.join(subdir, item), prefix, legacy)
-
- def get_menu_entries(self, dirs, legacy=True):
- entries = []
- ids = set()
- # handle legacy items
- appdirs = dirs[:]
- if legacy:
- appdirs.append("legacy")
- # cache the results again
- key = "".join(appdirs)
- try:
- return self.cache[key]
- except KeyError:
- pass
- for dir_ in appdirs:
- for menuentry in self.cacheEntries[dir_]:
- try:
- if menuentry.DesktopFileID not in ids:
- ids.add(menuentry.DesktopFileID)
- entries.append(menuentry)
- elif menuentry.getType() == MenuEntry.TYPE_SYSTEM:
- # FIXME: This is only 99% correct, but still...
- idx = entries.index(menuentry)
- entry = entries[idx]
- if entry.getType() == MenuEntry.TYPE_USER:
- entry.Original = menuentry
- except UnicodeDecodeError:
- continue
- self.cache[key] = entries
- return entries
-
-
-def parse(filename=None, debug=False):
- """Helper function.
- Equivalent to calling xdg.Menu.XMLMenuBuilder().parse(filename)
- """
- return XMLMenuBuilder(debug).parse(filename)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/MenuEditor.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/MenuEditor.py
deleted file mode 100644
index 2c68515..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/MenuEditor.py
+++ /dev/null
@@ -1,541 +0,0 @@
-""" CLass to edit XDG Menus """
-import os
-try:
- import xml.etree.cElementTree as etree
-except ImportError:
- import xml.etree.ElementTree as etree
-
-from .Menu import Menu, MenuEntry, Layout, Separator, XMLMenuBuilder
-from .BaseDirectory import xdg_config_dirs, xdg_data_dirs
-from .Exceptions import ParsingError
-from .Config import setRootMode
-
-# XML-Cleanups: Move / Exclude
-# FIXME: proper reverte/delete
-# FIXME: pass AppDirs/DirectoryDirs around in the edit/move functions
-# FIXME: catch Exceptions
-# FIXME: copy functions
-# FIXME: More Layout stuff
-# FIXME: unod/redo function / remove menu...
-# FIXME: Advanced MenuEditing Stuff: LegacyDir/MergeFile
-# Complex Rules/Deleted/OnlyAllocated/AppDirs/DirectoryDirs
-
-
-class MenuEditor(object):
-
- def __init__(self, menu=None, filename=None, root=False):
- self.menu = None
- self.filename = None
- self.tree = None
- self.parser = XMLMenuBuilder()
- self.parse(menu, filename, root)
-
- # fix for creating two menus with the same name on the fly
- self.filenames = []
-
- def parse(self, menu=None, filename=None, root=False):
- if root:
- setRootMode(True)
-
- if isinstance(menu, Menu):
- self.menu = menu
- elif menu:
- self.menu = self.parser.parse(menu)
- else:
- self.menu = self.parser.parse()
-
- if root:
- self.filename = self.menu.Filename
- elif filename:
- self.filename = filename
- else:
- self.filename = os.path.join(xdg_config_dirs[0], "menus", os.path.split(self.menu.Filename)[1])
-
- try:
- self.tree = etree.parse(self.filename)
- except IOError:
- root = etree.fromtring("""
-
-
-""" % self.menu.Filename)
- self.tree = etree.ElementTree(root)
- except ParsingError:
- raise ParsingError('Not a valid .menu file', self.filename)
-
- #FIXME: is this needed with etree ?
- self.__remove_whitespace_nodes(self.tree)
-
- def save(self):
- self.__saveEntries(self.menu)
- self.__saveMenu()
-
- def createMenuEntry(self, parent, name, command=None, genericname=None, comment=None, icon=None, terminal=None, after=None, before=None):
- menuentry = MenuEntry(self.__getFileName(name, ".desktop"))
- menuentry = self.editMenuEntry(menuentry, name, genericname, comment, command, icon, terminal)
-
- self.__addEntry(parent, menuentry, after, before)
-
- self.menu.sort()
-
- return menuentry
-
- def createMenu(self, parent, name, genericname=None, comment=None, icon=None, after=None, before=None):
- menu = Menu()
-
- menu.Parent = parent
- menu.Depth = parent.Depth + 1
- menu.Layout = parent.DefaultLayout
- menu.DefaultLayout = parent.DefaultLayout
-
- menu = self.editMenu(menu, name, genericname, comment, icon)
-
- self.__addEntry(parent, menu, after, before)
-
- self.menu.sort()
-
- return menu
-
- def createSeparator(self, parent, after=None, before=None):
- separator = Separator(parent)
-
- self.__addEntry(parent, separator, after, before)
-
- self.menu.sort()
-
- return separator
-
- def moveMenuEntry(self, menuentry, oldparent, newparent, after=None, before=None):
- self.__deleteEntry(oldparent, menuentry, after, before)
- self.__addEntry(newparent, menuentry, after, before)
-
- self.menu.sort()
-
- return menuentry
-
- def moveMenu(self, menu, oldparent, newparent, after=None, before=None):
- self.__deleteEntry(oldparent, menu, after, before)
- self.__addEntry(newparent, menu, after, before)
-
- root_menu = self.__getXmlMenu(self.menu.Name)
- if oldparent.getPath(True) != newparent.getPath(True):
- self.__addXmlMove(root_menu, os.path.join(oldparent.getPath(True), menu.Name), os.path.join(newparent.getPath(True), menu.Name))
-
- self.menu.sort()
-
- return menu
-
- def moveSeparator(self, separator, parent, after=None, before=None):
- self.__deleteEntry(parent, separator, after, before)
- self.__addEntry(parent, separator, after, before)
-
- self.menu.sort()
-
- return separator
-
- def copyMenuEntry(self, menuentry, oldparent, newparent, after=None, before=None):
- self.__addEntry(newparent, menuentry, after, before)
-
- self.menu.sort()
-
- return menuentry
-
- def editMenuEntry(self, menuentry, name=None, genericname=None, comment=None, command=None, icon=None, terminal=None, nodisplay=None, hidden=None):
- deskentry = menuentry.DesktopEntry
-
- if name:
- if not deskentry.hasKey("Name"):
- deskentry.set("Name", name)
- deskentry.set("Name", name, locale=True)
- if comment:
- if not deskentry.hasKey("Comment"):
- deskentry.set("Comment", comment)
- deskentry.set("Comment", comment, locale=True)
- if genericname:
- if not deskentry.hasKey("GenericName"):
- deskentry.set("GenericName", genericname)
- deskentry.set("GenericName", genericname, locale=True)
- if command:
- deskentry.set("Exec", command)
- if icon:
- deskentry.set("Icon", icon)
-
- if terminal:
- deskentry.set("Terminal", "true")
- elif not terminal:
- deskentry.set("Terminal", "false")
-
- if nodisplay is True:
- deskentry.set("NoDisplay", "true")
- elif nodisplay is False:
- deskentry.set("NoDisplay", "false")
-
- if hidden is True:
- deskentry.set("Hidden", "true")
- elif hidden is False:
- deskentry.set("Hidden", "false")
-
- menuentry.updateAttributes()
-
- if len(menuentry.Parents) > 0:
- self.menu.sort()
-
- return menuentry
-
- def editMenu(self, menu, name=None, genericname=None, comment=None, icon=None, nodisplay=None, hidden=None):
- # Hack for legacy dirs
- if isinstance(menu.Directory, MenuEntry) and menu.Directory.Filename == ".directory":
- xml_menu = self.__getXmlMenu(menu.getPath(True, True))
- self.__addXmlTextElement(xml_menu, 'Directory', menu.Name + ".directory")
- menu.Directory.setAttributes(menu.Name + ".directory")
- # Hack for New Entries
- elif not isinstance(menu.Directory, MenuEntry):
- if not name:
- name = menu.Name
- filename = self.__getFileName(name, ".directory").replace("/", "")
- if not menu.Name:
- menu.Name = filename.replace(".directory", "")
- xml_menu = self.__getXmlMenu(menu.getPath(True, True))
- self.__addXmlTextElement(xml_menu, 'Directory', filename)
- menu.Directory = MenuEntry(filename)
-
- deskentry = menu.Directory.DesktopEntry
-
- if name:
- if not deskentry.hasKey("Name"):
- deskentry.set("Name", name)
- deskentry.set("Name", name, locale=True)
- if genericname:
- if not deskentry.hasKey("GenericName"):
- deskentry.set("GenericName", genericname)
- deskentry.set("GenericName", genericname, locale=True)
- if comment:
- if not deskentry.hasKey("Comment"):
- deskentry.set("Comment", comment)
- deskentry.set("Comment", comment, locale=True)
- if icon:
- deskentry.set("Icon", icon)
-
- if nodisplay is True:
- deskentry.set("NoDisplay", "true")
- elif nodisplay is False:
- deskentry.set("NoDisplay", "false")
-
- if hidden is True:
- deskentry.set("Hidden", "true")
- elif hidden is False:
- deskentry.set("Hidden", "false")
-
- menu.Directory.updateAttributes()
-
- if isinstance(menu.Parent, Menu):
- self.menu.sort()
-
- return menu
-
- def hideMenuEntry(self, menuentry):
- self.editMenuEntry(menuentry, nodisplay=True)
-
- def unhideMenuEntry(self, menuentry):
- self.editMenuEntry(menuentry, nodisplay=False, hidden=False)
-
- def hideMenu(self, menu):
- self.editMenu(menu, nodisplay=True)
-
- def unhideMenu(self, menu):
- self.editMenu(menu, nodisplay=False, hidden=False)
- xml_menu = self.__getXmlMenu(menu.getPath(True, True), False)
- deleted = xml_menu.findall('Deleted')
- not_deleted = xml_menu.findall('NotDeleted')
- for node in deleted + not_deleted:
- xml_menu.remove(node)
-
- def deleteMenuEntry(self, menuentry):
- if self.getAction(menuentry) == "delete":
- self.__deleteFile(menuentry.DesktopEntry.filename)
- for parent in menuentry.Parents:
- self.__deleteEntry(parent, menuentry)
- self.menu.sort()
- return menuentry
-
- def revertMenuEntry(self, menuentry):
- if self.getAction(menuentry) == "revert":
- self.__deleteFile(menuentry.DesktopEntry.filename)
- menuentry.Original.Parents = []
- for parent in menuentry.Parents:
- index = parent.Entries.index(menuentry)
- parent.Entries[index] = menuentry.Original
- index = parent.MenuEntries.index(menuentry)
- parent.MenuEntries[index] = menuentry.Original
- menuentry.Original.Parents.append(parent)
- self.menu.sort()
- return menuentry
-
- def deleteMenu(self, menu):
- if self.getAction(menu) == "delete":
- self.__deleteFile(menu.Directory.DesktopEntry.filename)
- self.__deleteEntry(menu.Parent, menu)
- xml_menu = self.__getXmlMenu(menu.getPath(True, True))
- parent = self.__get_parent_node(xml_menu)
- parent.remove(xml_menu)
- self.menu.sort()
- return menu
-
- def revertMenu(self, menu):
- if self.getAction(menu) == "revert":
- self.__deleteFile(menu.Directory.DesktopEntry.filename)
- menu.Directory = menu.Directory.Original
- self.menu.sort()
- return menu
-
- def deleteSeparator(self, separator):
- self.__deleteEntry(separator.Parent, separator, after=True)
-
- self.menu.sort()
-
- return separator
-
- """ Private Stuff """
- def getAction(self, entry):
- if isinstance(entry, Menu):
- if not isinstance(entry.Directory, MenuEntry):
- return "none"
- elif entry.Directory.getType() == "Both":
- return "revert"
- elif entry.Directory.getType() == "User" and (
- len(entry.Submenus) + len(entry.MenuEntries)
- ) == 0:
- return "delete"
-
- elif isinstance(entry, MenuEntry):
- if entry.getType() == "Both":
- return "revert"
- elif entry.getType() == "User":
- return "delete"
- else:
- return "none"
-
- return "none"
-
- def __saveEntries(self, menu):
- if not menu:
- menu = self.menu
- if isinstance(menu.Directory, MenuEntry):
- menu.Directory.save()
- for entry in menu.getEntries(hidden=True):
- if isinstance(entry, MenuEntry):
- entry.save()
- elif isinstance(entry, Menu):
- self.__saveEntries(entry)
-
- def __saveMenu(self):
- if not os.path.isdir(os.path.dirname(self.filename)):
- os.makedirs(os.path.dirname(self.filename))
- self.tree.write(self.filename, encoding='utf-8')
-
- def __getFileName(self, name, extension):
- postfix = 0
- while 1:
- if postfix == 0:
- filename = name + extension
- else:
- filename = name + "-" + str(postfix) + extension
- if extension == ".desktop":
- dir = "applications"
- elif extension == ".directory":
- dir = "desktop-directories"
- if not filename in self.filenames and not os.path.isfile(
- os.path.join(xdg_data_dirs[0], dir, filename)
- ):
- self.filenames.append(filename)
- break
- else:
- postfix += 1
-
- return filename
-
- def __getXmlMenu(self, path, create=True, element=None):
- # FIXME: we should also return the menu's parent,
- # to avoid looking for it later on
- # @see Element.getiterator()
- if not element:
- element = self.tree
-
- if "/" in path:
- (name, path) = path.split("/", 1)
- else:
- name = path
- path = ""
-
- found = None
- for node in element.findall("Menu"):
- name_node = node.find('Name')
- if name_node.text == name:
- if path:
- found = self.__getXmlMenu(path, create, node)
- else:
- found = node
- if found:
- break
- if not found and create:
- node = self.__addXmlMenuElement(element, name)
- if path:
- found = self.__getXmlMenu(path, create, node)
- else:
- found = node
-
- return found
-
- def __addXmlMenuElement(self, element, name):
- menu_node = etree.SubElement('Menu', element)
- name_node = etree.SubElement('Name', menu_node)
- name_node.text = name
- return menu_node
-
- def __addXmlTextElement(self, element, name, text):
- node = etree.SubElement(name, element)
- node.text = text
- return node
-
- def __addXmlFilename(self, element, filename, type_="Include"):
- # remove old filenames
- includes = element.findall('Include')
- excludes = element.findall('Exclude')
- rules = includes + excludes
- for rule in rules:
- #FIXME: this finds only Rules whose FIRST child is a Filename element
- if rule[0].tag == "Filename" and rule[0].text == filename:
- element.remove(rule)
- # shouldn't it remove all occurences, like the following:
- #filename_nodes = rule.findall('.//Filename'):
- #for fn in filename_nodes:
- #if fn.text == filename:
- ##element.remove(rule)
- #parent = self.__get_parent_node(fn)
- #parent.remove(fn)
-
- # add new filename
- node = etree.SubElement(type_, element)
- self.__addXmlTextElement(node, 'Filename', filename)
- return node
-
- def __addXmlMove(self, element, old, new):
- node = etree.SubElement("Move", element)
- self.__addXmlTextElement(node, 'Old', old)
- self.__addXmlTextElement(node, 'New', new)
- return node
-
- def __addXmlLayout(self, element, layout):
- # remove old layout
- for node in element.findall("Layout"):
- element.remove(node)
-
- # add new layout
- node = etree.SubElement("Layout", element)
- for order in layout.order:
- if order[0] == "Separator":
- child = etree.SubElement("Separator", node)
- elif order[0] == "Filename":
- child = self.__addXmlTextElement(node, "Filename", order[1])
- elif order[0] == "Menuname":
- child = self.__addXmlTextElement(node, "Menuname", order[1])
- elif order[0] == "Merge":
- child = etree.SubElement("Merge", node)
- child.attrib["type"] = order[1]
- return node
-
- def __addLayout(self, parent):
- layout = Layout()
- layout.order = []
- layout.show_empty = parent.Layout.show_empty
- layout.inline = parent.Layout.inline
- layout.inline_header = parent.Layout.inline_header
- layout.inline_alias = parent.Layout.inline_alias
- layout.inline_limit = parent.Layout.inline_limit
-
- layout.order.append(["Merge", "menus"])
- for entry in parent.Entries:
- if isinstance(entry, Menu):
- layout.parseMenuname(entry.Name)
- elif isinstance(entry, MenuEntry):
- layout.parseFilename(entry.DesktopFileID)
- elif isinstance(entry, Separator):
- layout.parseSeparator()
- layout.order.append(["Merge", "files"])
-
- parent.Layout = layout
-
- return layout
-
- def __addEntry(self, parent, entry, after=None, before=None):
- if after or before:
- if after:
- index = parent.Entries.index(after) + 1
- elif before:
- index = parent.Entries.index(before)
- parent.Entries.insert(index, entry)
- else:
- parent.Entries.append(entry)
-
- xml_parent = self.__getXmlMenu(parent.getPath(True, True))
-
- if isinstance(entry, MenuEntry):
- parent.MenuEntries.append(entry)
- entry.Parents.append(parent)
- self.__addXmlFilename(xml_parent, entry.DesktopFileID, "Include")
- elif isinstance(entry, Menu):
- parent.addSubmenu(entry)
-
- if after or before:
- self.__addLayout(parent)
- self.__addXmlLayout(xml_parent, parent.Layout)
-
- def __deleteEntry(self, parent, entry, after=None, before=None):
- parent.Entries.remove(entry)
-
- xml_parent = self.__getXmlMenu(parent.getPath(True, True))
-
- if isinstance(entry, MenuEntry):
- entry.Parents.remove(parent)
- parent.MenuEntries.remove(entry)
- self.__addXmlFilename(xml_parent, entry.DesktopFileID, "Exclude")
- elif isinstance(entry, Menu):
- parent.Submenus.remove(entry)
-
- if after or before:
- self.__addLayout(parent)
- self.__addXmlLayout(xml_parent, parent.Layout)
-
- def __deleteFile(self, filename):
- try:
- os.remove(filename)
- except OSError:
- pass
- try:
- self.filenames.remove(filename)
- except ValueError:
- pass
-
- def __remove_whitespace_nodes(self, node):
- for child in node:
- text = child.text.strip()
- if not text:
- child.text = ''
- tail = child.tail.strip()
- if not tail:
- child.tail = ''
- if len(child):
- self.__remove_whilespace_nodes(child)
-
- def __get_parent_node(self, node):
- # elements in ElementTree doesn't hold a reference to their parent
- for parent, child in self.__iter_parent():
- if child is node:
- return child
-
- def __iter_parent(self):
- for parent in self.tree.getiterator():
- for child in parent:
- yield parent, child
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Mime.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Mime.py
deleted file mode 100644
index 60c4efd..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/Mime.py
+++ /dev/null
@@ -1,780 +0,0 @@
-"""
-This module is based on a rox module (LGPL):
-
-http://cvs.sourceforge.net/viewcvs.py/rox/ROX-Lib2/python/rox/mime.py?rev=1.21&view=log
-
-This module provides access to the shared MIME database.
-
-types is a dictionary of all known MIME types, indexed by the type name, e.g.
-types['application/x-python']
-
-Applications can install information about MIME types by storing an
-XML file as /packages/.xml and running the
-update-mime-database command, which is provided by the freedesktop.org
-shared mime database package.
-
-See http://www.freedesktop.org/standards/shared-mime-info-spec/ for
-information about the format of these files.
-
-(based on version 0.13)
-"""
-
-import os
-import re
-import stat
-import sys
-import fnmatch
-
-from . import BaseDirectory, Locale
-
-from .dom import minidom, XML_NAMESPACE
-from collections import defaultdict
-
-FREE_NS = 'http://www.freedesktop.org/standards/shared-mime-info'
-
-types = {} # Maps MIME names to type objects
-
-exts = None # Maps extensions to types
-globs = None # List of (glob, type) pairs
-literals = None # Maps liternal names to types
-magic = None
-
-PY3 = (sys.version_info[0] >= 3)
-
-def _get_node_data(node):
- """Get text of XML node"""
- return ''.join([n.nodeValue for n in node.childNodes]).strip()
-
-def lookup(media, subtype = None):
- """Get the MIMEtype object for the given type.
-
- This remains for backwards compatibility; calling MIMEtype now does
- the same thing.
-
- The name can either be passed as one part ('text/plain'), or as two
- ('text', 'plain').
- """
- return MIMEtype(media, subtype)
-
-class MIMEtype(object):
- """Class holding data about a MIME type.
-
- Calling the class will return a cached instance, so there is only one
- instance for each MIME type. The name can either be passed as one part
- ('text/plain'), or as two ('text', 'plain').
- """
- def __new__(cls, media, subtype=None):
- if subtype is None and '/' in media:
- media, subtype = media.split('/', 1)
- assert '/' not in subtype
- media = media.lower()
- subtype = subtype.lower()
-
- try:
- return types[(media, subtype)]
- except KeyError:
- mtype = super(MIMEtype, cls).__new__(cls)
- mtype._init(media, subtype)
- types[(media, subtype)] = mtype
- return mtype
-
- # If this is done in __init__, it is automatically called again each time
- # the MIMEtype is returned by __new__, which we don't want. So we call it
- # explicitly only when we construct a new instance.
- def _init(self, media, subtype):
- self.media = media
- self.subtype = subtype
- self._comment = None
-
- def _load(self):
- "Loads comment for current language. Use get_comment() instead."
- resource = os.path.join('mime', self.media, self.subtype + '.xml')
- for path in BaseDirectory.load_data_paths(resource):
- doc = minidom.parse(path)
- if doc is None:
- continue
- for comment in doc.documentElement.getElementsByTagNameNS(FREE_NS, 'comment'):
- lang = comment.getAttributeNS(XML_NAMESPACE, 'lang') or 'en'
- goodness = 1 + (lang in xdg.Locale.langs)
- if goodness > self._comment[0]:
- self._comment = (goodness, _get_node_data(comment))
- if goodness == 2: return
-
- # FIXME: add get_icon method
- def get_comment(self):
- """Returns comment for current language, loading it if needed."""
- # Should we ever reload?
- if self._comment is None:
- self._comment = (0, str(self))
- self._load()
- return self._comment[1]
-
- def canonical(self):
- """Returns the canonical MimeType object if this is an alias."""
- update_cache()
- s = str(self)
- if s in aliases:
- return lookup(aliases[s])
- return self
-
- def inherits_from(self):
- """Returns a set of Mime types which this inherits from."""
- update_cache()
- return set(lookup(t) for t in inheritance[str(self)])
-
- def __str__(self):
- return self.media + '/' + self.subtype
-
- def __repr__(self):
- return 'MIMEtype(%r, %r)' % (self.media, self.subtype)
-
- def __hash__(self):
- return hash(self.media) ^ hash(self.subtype)
-
-class UnknownMagicRuleFormat(ValueError):
- pass
-
-class DiscardMagicRules(Exception):
- "Raised when __NOMAGIC__ is found, and caught to discard previous rules."
- pass
-
-class MagicRule:
- also = None
-
- def __init__(self, start, value, mask, word, range):
- self.start = start
- self.value = value
- self.mask = mask
- self.word = word
- self.range = range
-
- rule_ending_re = re.compile(br'(?:~(\d+))?(?:\+(\d+))?\n$')
-
- @classmethod
- def from_file(cls, f):
- """Read a rule from the binary magics file. Returns a 2-tuple of
- the nesting depth and the MagicRule."""
- line = f.readline()
- #print line
-
- # [indent] '>'
- nest_depth, line = line.split(b'>', 1)
- nest_depth = int(nest_depth) if nest_depth else 0
-
- # start-offset '='
- start, line = line.split(b'=', 1)
- start = int(start)
-
- if line == b'__NOMAGIC__\n':
- raise DiscardMagicRules
-
- # value length (2 bytes, big endian)
- if sys.version_info[0] >= 3:
- lenvalue = int.from_bytes(line[:2], byteorder='big')
- else:
- lenvalue = (ord(line[0])<<8)+ord(line[1])
- line = line[2:]
-
- # value
- # This can contain newlines, so we may need to read more lines
- while len(line) <= lenvalue:
- line += f.readline()
- value, line = line[:lenvalue], line[lenvalue:]
-
- # ['&' mask]
- if line.startswith(b'&'):
- # This can contain newlines, so we may need to read more lines
- while len(line) <= lenvalue:
- line += f.readline()
- mask, line = line[1:lenvalue+1], line[lenvalue+1:]
- else:
- mask = None
-
- # ['~' word-size] ['+' range-length]
- ending = cls.rule_ending_re.match(line)
- if not ending:
- # Per the spec, this will be caught and ignored, to allow
- # for future extensions.
- raise UnknownMagicRuleFormat(repr(line))
-
- word, range = ending.groups()
- word = int(word) if (word is not None) else 1
- range = int(range) if (range is not None) else 1
-
- return nest_depth, cls(start, value, mask, word, range)
-
- def maxlen(self):
- l = self.start + len(self.value) + self.range
- if self.also:
- return max(l, self.also.maxlen())
- return l
-
- def match(self, buffer):
- if self.match0(buffer):
- if self.also:
- return self.also.match(buffer)
- return True
-
- def match0(self, buffer):
- l=len(buffer)
- lenvalue = len(self.value)
- for o in range(self.range):
- s=self.start+o
- e=s+lenvalue
- if l [(priority, rule), ...]
-
- def merge_file(self, fname):
- """Read a magic binary file, and add its rules to this MagicDB."""
- with open(fname, 'rb') as f:
- line = f.readline()
- if line != b'MIME-Magic\0\n':
- raise IOError('Not a MIME magic file')
-
- while True:
- shead = f.readline().decode('ascii')
- #print(shead)
- if not shead:
- break
- if shead[0] != '[' or shead[-2:] != ']\n':
- raise ValueError('Malformed section heading', shead)
- pri, tname = shead[1:-2].split(':')
- #print shead[1:-2]
- pri = int(pri)
- mtype = lookup(tname)
- try:
- rule = MagicMatchAny.from_file(f)
- except DiscardMagicRules:
- self.bytype.pop(mtype, None)
- rule = MagicMatchAny.from_file(f)
- if rule is None:
- continue
- #print rule
-
- self.bytype[mtype].append((pri, rule))
-
- def finalise(self):
- """Prepare the MagicDB for matching.
-
- This should be called after all rules have been merged into it.
- """
- maxlen = 0
- self.alltypes = [] # (priority, mimetype, rule)
-
- for mtype, rules in self.bytype.items():
- for pri, rule in rules:
- self.alltypes.append((pri, mtype, rule))
- maxlen = max(maxlen, rule.maxlen())
-
- self.maxlen = maxlen # Number of bytes to read from files
- self.alltypes.sort(key=lambda x: x[0], reverse=True)
-
- def match_data(self, data, max_pri=100, min_pri=0, possible=None):
- """Do magic sniffing on some bytes.
-
- max_pri & min_pri can be used to specify the maximum & minimum priority
- rules to look for. possible can be a list of mimetypes to check, or None
- (the default) to check all mimetypes until one matches.
-
- Returns the MIMEtype found, or None if no entries match.
- """
- if possible is not None:
- types = []
- for mt in possible:
- for pri, rule in self.bytype[mt]:
- types.append((pri, mt, rule))
- types.sort(key=lambda x: x[0])
- else:
- types = self.alltypes
-
- for priority, mimetype, rule in types:
- #print priority, max_pri, min_pri
- if priority > max_pri:
- continue
- if priority < min_pri:
- break
-
- if rule.match(data):
- return mimetype
-
- def match(self, path, max_pri=100, min_pri=0, possible=None):
- """Read data from the file and do magic sniffing on it.
-
- max_pri & min_pri can be used to specify the maximum & minimum priority
- rules to look for. possible can be a list of mimetypes to check, or None
- (the default) to check all mimetypes until one matches.
-
- Returns the MIMEtype found, or None if no entries match. Raises IOError
- if the file can't be opened.
- """
- with open(path, 'rb') as f:
- buf = f.read(self.maxlen)
- return self.match_data(buf, max_pri, min_pri, possible)
-
- def __repr__(self):
- return '' % len(self.alltypes)
-
-class GlobDB(object):
- def __init__(self):
- """Prepare the GlobDB. It can't actually be used until .finalise() is
- called, but merge_file() can be used to add data before that.
- """
- # Maps mimetype to {(weight, glob, flags), ...}
- self.allglobs = defaultdict(set)
-
- def merge_file(self, path):
- """Loads name matching information from a globs2 file."""#
- allglobs = self.allglobs
- with open(path) as f:
- for line in f:
- if line.startswith('#'): continue # Comment
-
- fields = line[:-1].split(':')
- weight, type_name, pattern = fields[:3]
- weight = int(weight)
- mtype = lookup(type_name)
- if len(fields) > 3:
- flags = fields[3].split(',')
- else:
- flags = ()
-
- if pattern == '__NOGLOBS__':
- # This signals to discard any previous globs
- allglobs.pop(mtype, None)
- continue
-
- allglobs[mtype].add((weight, pattern, tuple(flags)))
-
- def finalise(self):
- """Prepare the GlobDB for matching.
-
- This should be called after all files have been merged into it.
- """
- self.exts = defaultdict(list) # Maps extensions to [(type, weight),...]
- self.cased_exts = defaultdict(list)
- self.globs = [] # List of (regex, type, weight) triplets
- self.literals = {} # Maps literal names to (type, weight)
- self.cased_literals = {}
-
- for mtype, globs in self.allglobs.items():
- mtype = mtype.canonical()
- for weight, pattern, flags in globs:
-
- cased = 'cs' in flags
-
- if pattern.startswith('*.'):
- # *.foo -- extension pattern
- rest = pattern[2:]
- if not ('*' in rest or '[' in rest or '?' in rest):
- if cased:
- self.cased_exts[rest].append((mtype, weight))
- else:
- self.exts[rest.lower()].append((mtype, weight))
- continue
-
- if ('*' in pattern or '[' in pattern or '?' in pattern):
- # Translate the glob pattern to a regex & compile it
- re_flags = 0 if cased else re.I
- pattern = re.compile(fnmatch.translate(pattern), flags=re_flags)
- self.globs.append((pattern, mtype, weight))
- else:
- # No wildcards - literal pattern
- if cased:
- self.cased_literals[pattern] = (mtype, weight)
- else:
- self.literals[pattern.lower()] = (mtype, weight)
-
- # Sort globs by weight & length
- self.globs.sort(reverse=True, key=lambda x: (x[2], len(x[0].pattern)) )
-
- def first_match(self, path):
- """Return the first match found for a given path, or None if no match
- is found."""
- try:
- return next(self._match_path(path))[0]
- except StopIteration:
- return None
-
- def all_matches(self, path):
- """Return a list of (MIMEtype, glob weight) pairs for the path."""
- return list(self._match_path(path))
-
- def _match_path(self, path):
- """Yields pairs of (mimetype, glob weight)."""
- leaf = os.path.basename(path)
-
- # Literals (no wildcards)
- if leaf in self.cased_literals:
- yield self.cased_literals[leaf]
-
- lleaf = leaf.lower()
- if lleaf in self.literals:
- yield self.literals[lleaf]
-
- # Extensions
- ext = leaf
- while 1:
- p = ext.find('.')
- if p < 0: break
- ext = ext[p + 1:]
- if ext in self.cased_exts:
- for res in self.cased_exts[ext]:
- yield res
- ext = lleaf
- while 1:
- p = ext.find('.')
- if p < 0: break
- ext = ext[p+1:]
- if ext in self.exts:
- for res in self.exts[ext]:
- yield res
-
- # Other globs
- for (regex, mime_type, weight) in self.globs:
- if regex.match(leaf):
- yield (mime_type, weight)
-
-# Some well-known types
-text = lookup('text', 'plain')
-octet_stream = lookup('application', 'octet-stream')
-inode_block = lookup('inode', 'blockdevice')
-inode_char = lookup('inode', 'chardevice')
-inode_dir = lookup('inode', 'directory')
-inode_fifo = lookup('inode', 'fifo')
-inode_socket = lookup('inode', 'socket')
-inode_symlink = lookup('inode', 'symlink')
-inode_door = lookup('inode', 'door')
-app_exe = lookup('application', 'executable')
-
-_cache_uptodate = False
-
-def _cache_database():
- global globs, magic, aliases, inheritance, _cache_uptodate
-
- _cache_uptodate = True
-
- aliases = {} # Maps alias Mime types to canonical names
- inheritance = defaultdict(set) # Maps to sets of parent mime types.
-
- # Load aliases
- for path in BaseDirectory.load_data_paths(os.path.join('mime', 'aliases')):
- with open(path, 'r') as f:
- for line in f:
- alias, canonical = line.strip().split(None, 1)
- aliases[alias] = canonical
-
- # Load filename patterns (globs)
- globs = GlobDB()
- for path in BaseDirectory.load_data_paths(os.path.join('mime', 'globs2')):
- globs.merge_file(path)
- globs.finalise()
-
- # Load magic sniffing data
- magic = MagicDB()
- for path in BaseDirectory.load_data_paths(os.path.join('mime', 'magic')):
- magic.merge_file(path)
- magic.finalise()
-
- # Load subclasses
- for path in BaseDirectory.load_data_paths(os.path.join('mime', 'subclasses')):
- with open(path, 'r') as f:
- for line in f:
- sub, parent = line.strip().split(None, 1)
- inheritance[sub].add(parent)
-
-def update_cache():
- if not _cache_uptodate:
- _cache_database()
-
-def get_type_by_name(path):
- """Returns type of file by its name, or None if not known"""
- update_cache()
- return globs.first_match(path)
-
-def get_type_by_contents(path, max_pri=100, min_pri=0):
- """Returns type of file by its contents, or None if not known"""
- update_cache()
-
- return magic.match(path, max_pri, min_pri)
-
-def get_type_by_data(data, max_pri=100, min_pri=0):
- """Returns type of the data, which should be bytes."""
- update_cache()
-
- return magic.match_data(data, max_pri, min_pri)
-
-def _get_type_by_stat(st_mode):
- """Match special filesystem objects to Mimetypes."""
- if stat.S_ISDIR(st_mode): return inode_dir
- elif stat.S_ISCHR(st_mode): return inode_char
- elif stat.S_ISBLK(st_mode): return inode_block
- elif stat.S_ISFIFO(st_mode): return inode_fifo
- elif stat.S_ISLNK(st_mode): return inode_symlink
- elif stat.S_ISSOCK(st_mode): return inode_socket
- return inode_door
-
-def get_type(path, follow=True, name_pri=100):
- """Returns type of file indicated by path.
-
- This function is *deprecated* - :func:`get_type2` is more accurate.
-
- :param path: pathname to check (need not exist)
- :param follow: when reading file, follow symbolic links
- :param name_pri: Priority to do name matches. 100=override magic
-
- This tries to use the contents of the file, and falls back to the name. It
- can also handle special filesystem objects like directories and sockets.
- """
- update_cache()
-
- try:
- if follow:
- st = os.stat(path)
- else:
- st = os.lstat(path)
- except:
- t = get_type_by_name(path)
- return t or text
-
- if stat.S_ISREG(st.st_mode):
- # Regular file
- t = get_type_by_contents(path, min_pri=name_pri)
- if not t: t = get_type_by_name(path)
- if not t: t = get_type_by_contents(path, max_pri=name_pri)
- if t is None:
- if stat.S_IMODE(st.st_mode) & 0o111:
- return app_exe
- else:
- return text
- return t
- else:
- return _get_type_by_stat(st.st_mode)
-
-def get_type2(path, follow=True):
- """Find the MIMEtype of a file using the XDG recommended checking order.
-
- This first checks the filename, then uses file contents if the name doesn't
- give an unambiguous MIMEtype. It can also handle special filesystem objects
- like directories and sockets.
-
- :param path: file path to examine (need not exist)
- :param follow: whether to follow symlinks
-
- :rtype: :class:`MIMEtype`
-
- .. versionadded:: 1.0
- """
- update_cache()
-
- try:
- st = os.stat(path) if follow else os.lstat(path)
- except OSError:
- return get_type_by_name(path) or octet_stream
-
- if not stat.S_ISREG(st.st_mode):
- # Special filesystem objects
- return _get_type_by_stat(st.st_mode)
-
- mtypes = sorted(globs.all_matches(path), key=(lambda x: x[1]), reverse=True)
- if mtypes:
- max_weight = mtypes[0][1]
- i = 1
- for mt, w in mtypes[1:]:
- if w < max_weight:
- break
- i += 1
- mtypes = mtypes[:i]
- if len(mtypes) == 1:
- return mtypes[0][0]
-
- possible = [mt for mt,w in mtypes]
- else:
- possible = None # Try all magic matches
-
- try:
- t = magic.match(path, possible=possible)
- except IOError:
- t = None
-
- if t:
- return t
- elif mtypes:
- return mtypes[0][0]
- elif stat.S_IMODE(st.st_mode) & 0o111:
- return app_exe
- else:
- return text if is_text_file(path) else octet_stream
-
-def is_text_file(path):
- """Guess whether a file contains text or binary data.
-
- Heuristic: binary if the first 32 bytes include ASCII control characters.
- This rule may change in future versions.
-
- .. versionadded:: 1.0
- """
- try:
- f = open(path, 'rb')
- except IOError:
- return False
-
- with f:
- return _is_text(f.read(32))
-
-if PY3:
- def _is_text(data):
- return not any(b <= 0x8 or 0xe <= b < 0x20 or b == 0x7f for b in data)
-else:
- def _is_text(data):
- return not any(b <= '\x08' or '\x0e' <= b < '\x20' or b == '\x7f' \
- for b in data)
-
-_mime2ext_cache = None
-_mime2ext_cache_uptodate = False
-
-def get_extensions(mimetype):
- """Retrieve the set of filename extensions matching a given MIMEtype.
-
- Extensions are returned without a leading dot, e.g. 'py'. If no extensions
- are registered for the MIMEtype, returns an empty set.
-
- The extensions are stored in a cache the first time this is called.
-
- .. versionadded:: 1.0
- """
- global _mime2ext_cache, _mime2ext_cache_uptodate
- update_cache()
- if not _mime2ext_cache_uptodate:
- _mime2ext_cache = defaultdict(set)
- for ext, mtypes in globs.exts.items():
- for mtype, prio in mtypes:
- _mime2ext_cache[mtype].add(ext)
- _mime2ext_cache_uptodate = True
-
- return _mime2ext_cache[mimetype]
-
-
-def install_mime_info(application, package_file):
- """Copy 'package_file' as ``~/.local/share/mime/packages/.xml.``
- If package_file is None, install ``/.xml``.
- If already installed, does nothing. May overwrite an existing
- file with the same name (if the contents are different)"""
- application += '.xml'
-
- new_data = open(package_file).read()
-
- # See if the file is already installed
- package_dir = os.path.join('mime', 'packages')
- resource = os.path.join(package_dir, application)
- for x in BaseDirectory.load_data_paths(resource):
- try:
- old_data = open(x).read()
- except:
- continue
- if old_data == new_data:
- return # Already installed
-
- global _cache_uptodate
- _cache_uptodate = False
-
- # Not already installed; add a new copy
- # Create the directory structure...
- new_file = os.path.join(BaseDirectory.save_data_path(package_dir), application)
-
- # Write the file...
- open(new_file, 'w').write(new_data)
-
- # Update the database...
- command = 'update-mime-database'
- if os.spawnlp(os.P_WAIT, command, command, BaseDirectory.save_data_path('mime')):
- os.unlink(new_file)
- raise Exception("The '%s' command returned an error code!\n" \
- "Make sure you have the freedesktop.org shared MIME package:\n" \
- "http://standards.freedesktop.org/shared-mime-info/" % command)
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/RecentFiles.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/RecentFiles.py
deleted file mode 100644
index fbe608c..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/RecentFiles.py
+++ /dev/null
@@ -1,181 +0,0 @@
-"""
-Implementation of the XDG Recent File Storage Specification
-http://standards.freedesktop.org/recent-file-spec
-"""
-
-import xml.dom.minidom, xml.sax.saxutils
-import os, time, fcntl
-from .Exceptions import ParsingError
-
-class RecentFiles:
- def __init__(self):
- self.RecentFiles = []
- self.filename = ""
-
- def parse(self, filename=None):
- """Parse a list of recently used files.
-
- filename defaults to ``~/.recently-used``.
- """
- if not filename:
- filename = os.path.join(os.getenv("HOME"), ".recently-used")
-
- try:
- doc = xml.dom.minidom.parse(filename)
- except IOError:
- raise ParsingError('File not found', filename)
- except xml.parsers.expat.ExpatError:
- raise ParsingError('Not a valid .menu file', filename)
-
- self.filename = filename
-
- for child in doc.childNodes:
- if child.nodeType == xml.dom.Node.ELEMENT_NODE:
- if child.tagName == "RecentFiles":
- for recent in child.childNodes:
- if recent.nodeType == xml.dom.Node.ELEMENT_NODE:
- if recent.tagName == "RecentItem":
- self.__parseRecentItem(recent)
-
- self.sort()
-
- def __parseRecentItem(self, item):
- recent = RecentFile()
- self.RecentFiles.append(recent)
-
- for attribute in item.childNodes:
- if attribute.nodeType == xml.dom.Node.ELEMENT_NODE:
- if attribute.tagName == "URI":
- recent.URI = attribute.childNodes[0].nodeValue
- elif attribute.tagName == "Mime-Type":
- recent.MimeType = attribute.childNodes[0].nodeValue
- elif attribute.tagName == "Timestamp":
- recent.Timestamp = int(attribute.childNodes[0].nodeValue)
- elif attribute.tagName == "Private":
- recent.Prviate = True
- elif attribute.tagName == "Groups":
-
- for group in attribute.childNodes:
- if group.nodeType == xml.dom.Node.ELEMENT_NODE:
- if group.tagName == "Group":
- recent.Groups.append(group.childNodes[0].nodeValue)
-
- def write(self, filename=None):
- """Write the list of recently used files to disk.
-
- If the instance is already associated with a file, filename can be
- omitted to save it there again.
- """
- if not filename and not self.filename:
- raise ParsingError('File not found', filename)
- elif not filename:
- filename = self.filename
-
- f = open(filename, "w")
- fcntl.lockf(f, fcntl.LOCK_EX)
- f.write('\n')
- f.write("\n")
-
- for r in self.RecentFiles:
- f.write(" \n")
- f.write(" %s\n" % xml.sax.saxutils.escape(r.URI))
- f.write(" %s\n" % r.MimeType)
- f.write(" %s\n" % r.Timestamp)
- if r.Private == True:
- f.write(" \n")
- if len(r.Groups) > 0:
- f.write(" \n")
- for group in r.Groups:
- f.write(" %s\n" % group)
- f.write(" \n")
- f.write(" \n")
-
- f.write("\n")
- fcntl.lockf(f, fcntl.LOCK_UN)
- f.close()
-
- def getFiles(self, mimetypes=None, groups=None, limit=0):
- """Get a list of recently used files.
-
- The parameters can be used to filter by mime types, by group, or to
- limit the number of items returned. By default, the entire list is
- returned, except for items marked private.
- """
- tmp = []
- i = 0
- for item in self.RecentFiles:
- if groups:
- for group in groups:
- if group in item.Groups:
- tmp.append(item)
- i += 1
- elif mimetypes:
- for mimetype in mimetypes:
- if mimetype == item.MimeType:
- tmp.append(item)
- i += 1
- else:
- if item.Private == False:
- tmp.append(item)
- i += 1
- if limit != 0 and i == limit:
- break
-
- return tmp
-
- def addFile(self, item, mimetype, groups=None, private=False):
- """Add a recently used file.
-
- item should be the URI of the file, typically starting with ``file:///``.
- """
- # check if entry already there
- if item in self.RecentFiles:
- index = self.RecentFiles.index(item)
- recent = self.RecentFiles[index]
- else:
- # delete if more then 500 files
- if len(self.RecentFiles) == 500:
- self.RecentFiles.pop()
- # add entry
- recent = RecentFile()
- self.RecentFiles.append(recent)
-
- recent.URI = item
- recent.MimeType = mimetype
- recent.Timestamp = int(time.time())
- recent.Private = private
- if groups:
- recent.Groups = groups
-
- self.sort()
-
- def deleteFile(self, item):
- """Remove a recently used file, by URI, from the list.
- """
- if item in self.RecentFiles:
- self.RecentFiles.remove(item)
-
- def sort(self):
- self.RecentFiles.sort()
- self.RecentFiles.reverse()
-
-
-class RecentFile:
- def __init__(self):
- self.URI = ""
- self.MimeType = ""
- self.Timestamp = ""
- self.Private = False
- self.Groups = []
-
- def __cmp__(self, other):
- return cmp(self.Timestamp, other.Timestamp)
-
- def __lt__ (self, other):
- return self.Timestamp < other.Timestamp
-
- def __eq__(self, other):
- return self.URI == str(other)
-
- def __str__(self):
- return self.URI
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/__init__.py
deleted file mode 100644
index b5a117e..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-__all__ = [ "BaseDirectory", "DesktopEntry", "Menu", "Exceptions", "IniFile", "IconTheme", "Locale", "Config", "Mime", "RecentFiles", "MenuEditor" ]
-
-__version__ = "0.26"
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/util.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/util.py
deleted file mode 100644
index 1637aa5..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/icons/mixins/xdg/util.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import sys
-
-PY3 = sys.version_info[0] >= 3
-
-if PY3:
- def u(s):
- return s
-else:
- # Unicode-like literals
- def u(s):
- return s.decode('utf-8')
-
-try:
- # which() is available from Python 3.3
- from shutil import which
-except ImportError:
- import os
- # This is a copy of which() from Python 3.3
- def which(cmd, mode=os.F_OK | os.X_OK, path=None):
- """Given a command, mode, and a PATH string, return the path which
- conforms to the given mode on the PATH, or None if there is no such
- file.
-
- `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
- of os.environ.get("PATH"), or can be overridden with a custom search
- path.
-
- """
- # Check that a given file can be accessed with the correct mode.
- # Additionally check that `file` is not a directory, as on Windows
- # directories pass the os.access check.
- def _access_check(fn, mode):
- return (os.path.exists(fn) and os.access(fn, mode)
- and not os.path.isdir(fn))
-
- # If we're given a path with a directory part, look it up directly rather
- # than referring to PATH directories. This includes checking relative to the
- # current directory, e.g. ./script
- if os.path.dirname(cmd):
- if _access_check(cmd, mode):
- return cmd
- return None
-
- path = (path or os.environ.get("PATH", os.defpath)).split(os.pathsep)
-
- if sys.platform == "win32":
- # The current directory takes precedence on Windows.
- if not os.curdir in path:
- path.insert(0, os.curdir)
-
- # PATHEXT is necessary to check on Windows.
- pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
- # See if the given file matches any of the expected path extensions.
- # This will allow us to short circuit when given "python.exe".
- # If it does match, only test that one, otherwise we have to try
- # others.
- if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
- files = [cmd]
- else:
- files = [cmd + ext for ext in pathext]
- else:
- # On other platforms you don't have things like PATHEXT to tell you
- # what file suffixes are executable, so just pass on cmd as-is.
- files = [cmd]
-
- seen = set()
- for dir in path:
- normdir = os.path.normcase(dir)
- if not normdir in seen:
- seen.add(normdir)
- for thefile in files:
- name = os.path.join(dir, thefile)
- if _access_check(name, mode):
- return name
- return None
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/path.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/path.py
deleted file mode 100644
index ecce282..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/path.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Python imports
-import os
-
-# Lib imports
-
-# Application imports
-
-
-class Path:
- def get_home(self):
- return os.path.expanduser("~") + self.subpath
-
- def get_path(self):
- return f"/{'/'.join(self.path)}" if self.path else f"/{''.join(self.path)}"
-
- def get_path_list(self):
- return self.path
-
- def push_to_path(self, dir):
- self.path.append(dir)
- self.load_directory()
-
- def pop_from_path(self):
- try:
- self.path.pop()
-
- if not self.go_past_home:
- if self.get_home() not in self.get_path():
- self.set_to_home()
-
- self.load_directory()
- except Exception as e:
- pass
-
- def set_path(self, path):
- if path == self.get_path():
- return
-
- if os.path.isdir(path):
- self.path = list( filter(None, path.replace("\\", "/").split('/')) )
- self.load_directory()
- return True
-
- return False
-
- def set_path_with_sub_path(self, sub_path):
- path = os.path.join(self.get_home(), sub_path)
- if path == self.get_path():
- return False
-
- if os.path.isdir(path):
- self.path = list( filter(None, path.replace("\\", "/").split('/')) )
- self.load_directory()
- return True
-
- return False
-
- def set_to_home(self):
- home = os.path.expanduser("~") + self.subpath
- path = list( filter(None, home.replace("\\", "/").split('/')) )
- self.path = path
- self.load_directory()
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/tab.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/tab.py
deleted file mode 100644
index 70acaed..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/tab.py
+++ /dev/null
@@ -1,246 +0,0 @@
-# Python imports
-import hashlib, re
-from os import listdir
-from os.path import isdir, isfile, join
-
-from random import randint
-
-
-# Lib imports
-
-
-# Application imports
-from .utils.settings import Settings
-from .utils.launcher import Launcher
-from .utils.filehandler import FileHandler
-
-from .icons.icon import Icon
-from .path import Path
-
-
-class Tab(Settings, FileHandler, Launcher, Icon, Path):
- def __init__(self):
- self.logger = None
- self._id_length = 10
-
- self._id = ""
- self._wid = None
- self._dir_watcher = None
- self._hide_hidden = self.HIDE_HIDDEN_FILES
- self._files = []
- self._dirs = []
- self._vids = []
- self._images = []
- self._desktop = []
- self._ungrouped = []
- self._hidden = []
-
- self._generate_id()
- self.set_to_home()
-
- def load_directory(self):
- path = self.get_path()
- self._dirs = []
- self._vids = []
- self._images = []
- self._desktop = []
- self._ungrouped = []
- self._hidden = []
- self._files = []
-
- if not isdir(path):
- self.set_to_home()
- return ""
-
- for f in listdir(path):
- file = join(path, f)
- if self._hide_hidden:
- if f.startswith('.'):
- self._hidden.append(f)
- continue
-
- if isfile(file):
- lowerName = file.lower()
- if lowerName.endswith(self.fvideos):
- self._vids.append(f)
- elif lowerName.endswith(self.fimages):
- self._images.append(f)
- elif lowerName.endswith((".desktop",)):
- self._desktop.append(f)
- else:
- self._ungrouped.append(f)
- else:
- self._dirs.append(f)
-
- self._dirs.sort(key=self._natural_keys)
- self._vids.sort(key=self._natural_keys)
- self._images.sort(key=self._natural_keys)
- self._desktop.sort(key=self._natural_keys)
- self._ungrouped.sort(key=self._natural_keys)
-
- self._files = self._dirs + self._vids + self._images + self._desktop + self._ungrouped
-
- def is_folder_locked(self, hash):
- if self.lock_folder:
- path_parts = self.get_path().split('/')
- file = self.get_path_part_from_hash(hash)
-
- # Insure chilren folders are locked too.
- lockedFolderInPath = False
- for folder in self.locked_folders:
- if folder in path_parts:
- lockedFolderInPath = True
- break
-
- return (file in self.locked_folders or lockedFolderInPath)
- else:
- return False
-
-
- def get_not_hidden_count(self):
- return len(self._files) + \
- len(self._dirs) + \
- len(self._vids) + \
- len(self._images) + \
- len(self._desktop) + \
- len(self._ungrouped)
-
- def get_hidden_count(self):
- return len(self._hidden)
-
- def get_files_count(self):
- return len(self._files)
-
- def get_path_part_from_hash(self, hash):
- files = self.get_files()
- file = None
-
- for f in files:
- if hash == f[1]:
- file = f[0]
- break
-
- return file
-
- def get_files_formatted(self):
- files = self._hash_set(self._files),
- dirs = self._hash_set(self._dirs),
- videos = self.get_videos(),
- images = self._hash_set(self._images),
- desktops = self._hash_set(self._desktop),
- ungrouped = self._hash_set(self._ungrouped)
- hidden = self._hash_set(self._hidden)
-
- return {
- 'path_head': self.get_path(),
- 'list': {
- 'files': files,
- 'dirs': dirs,
- 'videos': videos,
- 'images': images,
- 'desktops': desktops,
- 'ungrouped': ungrouped,
- 'hidden': hidden
- }
- }
-
- def get_pixbuf_icon_str_combo(self):
- data = []
- dir = self.get_current_directory()
- for file in self._files:
- icon = self.create_icon(dir, file).get_pixbuf()
- data.append([icon, file])
-
- return data
-
-
- def get_gtk_icon_str_combo(self):
- data = []
- dir = self.get_current_directory()
- for file in self._files:
- icon = self.create_icon(dir, file)
- data.append([icon, file[0]])
-
- return data
-
- def get_current_directory(self):
- return self.get_path()
-
- def get_current_sub_path(self):
- path = self.get_path()
- home = f"{self.get_home()}/"
- return path.replace(home, "")
-
- def get_end_of_path(self):
- parts = self.get_current_directory().split("/")
- size = len(parts)
- return parts[size - 1]
-
-
- def set_hiding_hidden(self, state):
- self._hide_hidden = state
-
- def is_hiding_hidden(self):
- return self._hide_hidden
-
- def get_dot_dots(self):
- return self._hash_set(['.', '..'])
-
- def get_files(self):
- return self._hash_set(self._files)
-
- def get_dirs(self):
- return self._hash_set(self._dirs)
-
- def get_videos(self):
- return self._hash_set(self._vids)
-
- def get_images(self):
- return self._hash_set(self._images)
-
- def get_desktops(self):
- return self._hash_set(self._desktop)
-
- def get_ungrouped(self):
- return self._hash_set(self._ungrouped)
-
- def get_hidden(self):
- return self._hash_set(self._hidden)
-
- def get_id(self):
- return self._id
-
- def set_wid(self, _wid):
- self._wid = _wid
-
- def get_wid(self):
- return self._wid
-
- def set_dir_watcher(self, watcher):
- self._dir_watcher = watcher
-
- def get_dir_watcher(self):
- return self._dir_watcher
-
- def _atoi(self, text):
- return int(text) if text.isdigit() else text
-
- def _natural_keys(self, text):
- return [ self._atoi(c) for c in re.split('(\d+)',text) ]
-
- def _hash_text(self, text):
- return hashlib.sha256(str.encode(text)).hexdigest()[:18]
-
- def _hash_set(self, arry):
- data = []
- for arr in arry:
- data.append([arr, self._hash_text(arr)])
- return data
-
- def _random_with_N_digits(self, n):
- range_start = 10**(n-1)
- range_end = (10**n)-1
- return randint(range_start, range_end)
-
- def _generate_id(self):
- self._id = str(self._random_with_N_digits(self._id_length))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/__init__.py
deleted file mode 100644
index aad0ae1..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Utils module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/filehandler.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/filehandler.py
deleted file mode 100644
index 105782a..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/filehandler.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# Python imports
-import os, shutil
-
-# Lib imports
-
-# Application imports
-
-
-
-
-class FileHandler:
- def create_file(self, nFile, type):
- try:
- if TYPE == "dir":
- os.mkdir(nFile)
- elif TYPE == "file":
- open(nFile, 'a').close()
- except Exception as e:
- print("An error occured creating the file/dir:")
- print(repr(e))
- return False
-
- return True
-
- def update_file(self, oFile, nFile):
- try:
- print(f"Renaming: {oFile} --> {nFile}")
- os.rename(oFile, nFile)
- except Exception as e:
- print("An error occured renaming the file:")
- print(repr(e))
- return False
-
- return True
-
- def delete_file(self, toDeleteFile):
- try:
- print(f"Deleting: {toDeleteFile}")
- if os.path.exists(toDeleteFile):
- if os.path.isfile(toDeleteFile):
- os.remove(toDeleteFile)
- elif os.path.isdir(toDeleteFile):
- shutil.rmtree(toDeleteFile)
- else:
- print("An error occured deleting the file:")
- return False
- else:
- print("The folder/file does not exist")
- return False
- except Exception as e:
- print("An error occured deleting the file:")
- print(repr(e))
- return False
-
- return True
-
- def move_file(self, fFile, tFile):
- try:
- print(f"Moving: {fFile} --> {tFile}")
- if os.path.exists(fFile) and not os.path.exists(tFile):
- if not tFile.endswith("/"):
- tFile += "/"
-
- shutil.move(fFile, tFile)
- else:
- print("The folder/file does not exist")
- return False
- except Exception as e:
- print("An error occured moving the file:")
- print(repr(e))
- return False
-
- return True
-
- def copy_file(self,fFile, tFile, symlinks=False, ignore=None):
- try:
- if os.path.isdir(fFile):
- shutil.copytree(fFile, tFile, symlinks, ignore)
- else:
- shutil.copy2(fFile, tFile)
- except Exception as e:
- print("An error occured copying the file:")
- print(repr(e))
- return False
-
- return True
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/launcher.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/launcher.py
deleted file mode 100644
index 22a14e3..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/launcher.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# System import
-import os, threading, subprocess
-
-
-# Lib imports
-
-
-# Apoplication imports
-
-
-def threaded(fn):
- def wrapper(*args, **kwargs):
- threading.Thread(target=fn, args=args, kwargs=kwargs).start()
- return wrapper
-
-
-class Launcher:
- def open_file_locally(self, file):
- lowerName = file.lower()
- command = []
-
- if lowerName.endswith(self.fvideos):
- command = [self.media_app]
-
- if "mplayer" in self.media_app:
- command += self.mplayer_options
-
- command += [file]
- elif lowerName.endswith(self.fimages):
- command = [self.image_app, file]
- elif lowerName.endswith(self.fmusic):
- command = [self.music_app, file]
- elif lowerName.endswith(self.foffice):
- command = [self.office_app, file]
- elif lowerName.endswith(self.ftext):
- command = [self.text_app, file]
- elif lowerName.endswith(self.fpdf):
- command = [self.pdf_app, file]
- elif lowerName.endswith("placeholder-until-i-can-get-a-use-pref-fm-flag"):
- command = [self.file_manager_app, file]
- else:
- command = ["xdg-open", file]
-
- self.execute(command, use_shell=False)
-
-
- def execute(self, command, start_dir=os.getenv("HOME"), use_os_system=None, use_shell=True):
- self.logger.debug(command)
- if use_os_system:
- os.system(command)
- else:
- subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=True, stdout=None, stderr=None, close_fds=True)
-
- def execute_and_return_thread_handler(self, command, start_dir=os.getenv("HOME"), use_shell=True):
- DEVNULL = open(os.devnull, 'w')
- return subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
-
- @threaded
- def app_chooser_exec(self, app_info, uris):
- app_info.launch_uris_async(uris)
-
- def remux_video(self, hash, file):
- remux_vid_pth = self.REMUX_FOLDER + "/" + hash + ".mp4"
- self.logger.debug(remux_vid_pth)
-
- if not os.path.isfile(remux_vid_pth):
- self.check_remux_space()
-
- command = ["ffmpeg", "-i", file, "-hide_banner", "-movflags", "+faststart"]
- if file.endswith("mkv"):
- command += ["-codec", "copy", "-strict", "-2"]
- if file.endswith("avi"):
- command += ["-c:v", "libx264", "-crf", "21", "-c:a", "aac", "-b:a", "192k", "-ac", "2"]
- if file.endswith("wmv"):
- command += ["-c:v", "libx264", "-crf", "23", "-c:a", "aac", "-strict", "-2", "-q:a", "100"]
- if file.endswith("f4v") or file.endswith("flv"):
- command += ["-vcodec", "copy"]
-
- command += [remux_vid_pth]
- try:
- proc = subprocess.Popen(command)
- proc.wait()
- except Exception as e:
- self.logger.debug(message)
- self.logger.debug(e)
- return False
-
- return True
-
- def check_remux_space(self):
- limit = self.remux_folder_max_disk_usage
- try:
- limit = int(limit)
- except Exception as e:
- self.logger.debug(e)
- return
-
- usage = self.get_remux_folder_usage(self.REMUX_FOLDER)
- if usage > limit:
- files = os.listdir(self.REMUX_FOLDER)
- for file in files:
- fp = os.path.join(self.REMUX_FOLDER, file)
- os.unlink(fp)
-
-
- def get_remux_folder_usage(self, start_path = "."):
- total_size = 0
- for dirpath, dirnames, filenames in os.walk(start_path):
- for f in filenames:
- fp = os.path.join(dirpath, f)
- if not os.path.islink(fp): # Skip if it is symbolic link
- total_size += os.path.getsize(fp)
-
- return total_size
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/settings.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/settings.py
deleted file mode 100644
index e4d9323..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/tabs/utils/settings.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# System import
-import json
-import os
-from os import path
-
-# Lib imports
-
-
-# Apoplication imports
-
-
-
-class Settings:
- logger = None
-
- USR_SOLARFM = "/usr/share/solarfm"
- USER_HOME = path.expanduser('~')
- CONFIG_PATH = f"{USER_HOME}/.config/solarfm"
- CONFIG_FILE = f"{CONFIG_PATH}/settings.json"
- HIDE_HIDDEN_FILES = True
-
- GTK_ORIENTATION = 1 # HORIZONTAL (0) VERTICAL (1)
- DEFAULT_ICONS = f"{CONFIG_PATH}/icons"
- DEFAULT_ICON = f"{DEFAULT_ICONS}/text.png"
- FFMPG_THUMBNLR = f"{CONFIG_PATH}/ffmpegthumbnailer" # Thumbnail generator binary
- REMUX_FOLDER = f"{USER_HOME}/.remuxs" # Remuxed files folder
-
- STEAM_BASE_URL = "https://steamcdn-a.akamaihd.net/steam/apps/"
- ICON_DIRS = ["/usr/share/pixmaps", "/usr/share/icons", f"{USER_HOME}/.icons" ,]
- BASE_THUMBS_PTH = f"{USER_HOME}/.thumbnails" # Used for thumbnail generation
- ABS_THUMBS_PTH = f"{BASE_THUMBS_PTH}/normal" # Used for thumbnail generation
- STEAM_ICONS_PTH = f"{BASE_THUMBS_PTH}/steam_icons"
- CONTAINER_ICON_WH = [128, 128]
- VIDEO_ICON_WH = [128, 64]
- SYS_ICON_WH = [56, 56]
-
- # CONTAINER_ICON_WH = [128, 128]
- # VIDEO_ICON_WH = [96, 48]
- # SYS_ICON_WH = [96, 96]
-
- subpath = ""
- go_past_home = None
- lock_folder = None
- locked_folders = None
- mplayer_options = None
- music_app = None
- media_app = None
- image_app = None
- office_app = None
- pdf_app = None
- text_app = None
- file_manager_app = None
- remux_folder_max_disk_usage = None
-
- if path.isfile(CONFIG_FILE):
- with open(CONFIG_FILE) as infile:
- settings = json.load(infile)["settings"]
-
- subpath = settings["base_of_home"]
- HIDE_HIDDEN_FILES = True if settings["hide_hidden_files"] == "true" else False
- FFMPG_THUMBNLR = FFMPG_THUMBNLR if settings["thumbnailer_path"] == "" else settings["thumbnailer_path"]
- go_past_home = True if settings["go_past_home"] == "" else settings["go_past_home"]
- lock_folder = True if settings["lock_folder"] == "true" else False
- locked_folders = settings["locked_folders"].split("::::")
- mplayer_options = settings["mplayer_options"].split()
- music_app = settings["music_app"]
- media_app = settings["media_app"]
- image_app = settings["image_app"]
- office_app = settings["office_app"]
- pdf_app = settings["pdf_app"]
- text_app = settings["text_app"]
- file_manager_app = settings["file_manager_app"]
- terminal_app = settings["terminal_app"]
- remux_folder_max_disk_usage = settings["remux_folder_max_disk_usage"]
-
- # Filters
- fvideos = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
- foffice = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
- fimages = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
- ftext = ('.txt', '.text', '.sh', '.cfg', '.conf')
- fmusic = ('.psf', '.mp3', '.ogg', '.flac', '.m4a')
- fpdf = ('.pdf')
-
-
- # Dir structure check
- if not path.isdir(REMUX_FOLDER):
- os.mkdir(REMUX_FOLDER)
-
- if not path.isdir(BASE_THUMBS_PTH):
- os.mkdir(BASE_THUMBS_PTH)
-
- if not path.isdir(ABS_THUMBS_PTH):
- os.mkdir(ABS_THUMBS_PTH)
-
- if not path.isdir(STEAM_ICONS_PTH):
- os.mkdir(STEAM_ICONS_PTH)
-
- if not os.path.exists(DEFAULT_ICONS):
- DEFAULT_ICONS = f"{USR_SOLARFM}/icons"
- DEFAULT_ICON = f"{DEFAULT_ICONS}/text.png"
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/window.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/window.py
deleted file mode 100644
index 9a09233..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/shellfm/windows/window.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Python imports
-from random import randint
-
-
-# Lib imports
-
-
-# Application imports
-from .tabs.tab import Tab
-
-
-class Window:
- def __init__(self):
- self._id_length = 10
- self._id = ""
- self._name = ""
- self._nickname = ""
- self._isHidden = False
- self._tabs = []
-
- self._generate_id()
- self._set_name()
-
-
- def create_tab(self):
- tab = Tab()
- self._tabs.append(tab)
- return tab
-
- def pop_tab(self):
- self._tabs.pop()
-
- def delete_tab_by_id(self, vid):
- for tab in self._tabs:
- if tab.get_id() == vid:
- self._tabs.remove(tab)
- break
-
-
- def get_tab_by_id(self, vid):
- for tab in self._tabs:
- if tab.get_id() == vid:
- return tab
-
- def get_tab_by_index(self, index):
- return self._tabs[index]
-
- def get_tabs_count(self):
- return len(self._tabs)
-
- def get_all_tabs(self):
- return self._tabs
-
- def get_id(self):
- return self._id
-
- def get_name(self):
- return self._name
-
- def get_nickname(self):
- return self._nickname
-
- def is_hidden(self):
- return self._isHidden
-
- def list_files_from_tabs(self):
- for tab in self._tabs:
- print(tab.get_files())
-
-
- def set_nickname(self, nickname):
- self._nickname = f"{nickname}"
-
- def set_is_hidden(self, state):
- self._isHidden = f"{state}"
-
- def _set_name(self):
- self._name = "window_" + self.get_id()
-
-
- def _random_with_N_digits(self, n):
- range_start = 10**(n-1)
- range_end = (10**n)-1
- return randint(range_start, range_end)
-
- def _generate_id(self):
- self._id = str(self._random_with_N_digits(self._id_length))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/__init__.py
deleted file mode 100755
index 5c16e50..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Trasher module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/trash.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/trash.py
deleted file mode 100755
index 4210f9c..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/trash.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Python imports
-import os
-
-# Lib imports
-
-# Application imports
-
-
-
-
-class Trash(object):
- """Base Trash class."""
-
- def size_dir(self, sdir):
- """Get the size of a directory. Based on code found online."""
- size = os.path.getsize(sdir)
-
- for item in os.listdir(sdir):
- item = os.path.join(sdir, item)
-
- if os.path.isfile(item):
- size = size + os.path.getsize(item)
- elif os.path.isdir(item):
- size = size + self.size_dir(item)
-
- return size
-
- def regenerate(self):
- """Regenerate the trash and recreate metadata."""
- pass # Some backends don’t need regeneration.
-
- def empty(self, verbose):
- """Empty the trash."""
- raise NotImplementedError(_('Backend didn’t implement this functionality'))
-
- def list(self, human=True):
- """List the trash contents."""
- raise NotImplementedError(_('Backend didn’t implement this functionality'))
-
- def trash(self, filepath, verbose):
- """Move specified file to trash."""
- raise NotImplementedError(_('Backend didn’t implement this functionality'))
-
- def restore(self, filename, verbose):
- """Restore a file from trash."""
- raise NotImplementedError(_('Backend didn’t \ implement this functionality'))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/xdgtrash.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/xdgtrash.py
deleted file mode 100755
index 02ff013..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/trasher/xdgtrash.py
+++ /dev/null
@@ -1,161 +0,0 @@
-from .trash import Trash
-import shutil
-import os
-import os.path
-import datetime
-import sys
-import logging
-
-try:
- import configparser
-except ImportError:
- import ConfigParser as configparser
-
-
-
-
-class XDGTrash(Trash):
- """XDG trash backend."""
- def __init__(self):
- self.trashdir = None
- self.filedir = None
- self.infodir = None
-
- if os.getenv('XDG_DATA_HOME') is None:
- self.trashdir = os.path.expanduser('~/.local/share/Trash')
- else:
- self.trashdir = os.getenv('XDG_DATA_HOME') + '/Trash'
-
- try:
- if not os.path.exists(self.trashdir):
- os.mkdir(self.trashdir)
- except OSError:
- self.trashdir = os.path.join('tmp' 'TRASH')
- raise('Couldn’t access the proper directory, temporary trash is in in /tmp/TRASH')
-
- self.filedir = self.trashdir + '/files/'
- self.infodir = self.trashdir + '/info/'
-
- def regenerate(self):
- """Regenerate the trash and recreate metadata."""
- print('Regenerating the trash and recreating metadata...')
- zerosize = False
-
- if not os.path.exists(self.trashdir):
- os.mkdir(self.trashdir)
- zerosize = True
-
- if ((not os.path.exists(self.filedir)) or
- (not os.path.exists(self.infodir))):
- os.mkdir(self.filedir)
- os.mkdir(self.infodir)
- zerosize = True
- if not zerosize:
- trashsize = (self.size_dir(self.filedir) + self.size_dir(self.infodir))
- else:
- trashsize = 0
-
- infofile = '[Cached]\nSize=' + str(trashsize) + '\n'
- fh = open(os.path.join(self.trashdir, 'metadata'), 'w')
- fh.write(infofile)
- fh.close()
-
- def empty(self, verbose):
- """Empty the trash."""
- print('emptying (verbose={})'.format(verbose))
- shutil.rmtree(self.filedir)
- shutil.rmtree(self.infodir)
- self.regenerate()
- if verbose:
- sys.stderr.write(_('emptied the trash\n'))
-
- def list(self, human=True):
- """List the trash contents."""
- if human:
- print('listing contents (on stdout; human=True)')
- else:
- print('listing contents (return; human=False)')
- dirs = []
- files = []
- for f in os.listdir(self.filedir):
- if os.path.isdir(self.filedir + f):
- dirs.append(f)
- else:
- files.append(f)
-
- dirs.sort()
- files.sort()
-
- allfiles = []
- for i in dirs:
- allfiles.append(i + '/')
- for i in files:
- allfiles.append(i)
- if human:
- if allfiles != []:
- print('\n'.join(allfiles))
- else:
- return allfiles
-
- def trash(self, filepath, verbose):
- """Move specified file to trash."""
- print('trashing file {} (verbose={})'.format(filepath, verbose))
- # Filename alteration, a big mess.
- filename = os.path.basename(filepath)
- fileext = os.path.splitext(filename)
-
- tomove = filename
- collision = True
- i = 1
-
- while collision:
- if os.path.lexists(self.filedir + tomove):
- tomove = fileext[0] + ' ' + str(i) + fileext[1]
- i = i + 1
- else:
- collision = False
-
- infofile = """[Trash Info]
-Path={}
-DeletionDate={}
-""".format(os.path.realpath(filepath),
- datetime.datetime.now().strftime('%Y-%m-%dT%H:%m:%S'))
-
- os.rename(filepath, self.filedir + tomove)
-
- f = open(os.path.join(self.infodir, tomove + '.trashinfo'), 'w')
- f.write(infofile)
- f.close()
-
- self.regenerate()
-
- if verbose:
- sys.stderr.write(_('trashed \'{}\'\n').format(filename))
-
- def restore(self, filename, verbose, tocwd=False):
- """Restore a file from trash."""
- print('restoring file {} (verbose={}, tocwd={})'.format(filename, verbose, tocwd))
- info = configparser.ConfigParser()
- if os.path.exists(os.path.join(self.filedir, filename)):
- info.read(os.path.join(self.infodir, filename + '.trashinfo'))
- restname = os.path.basename(info.get('Trash Info', 'Path'))
-
- if tocwd:
- restdir = os.path.abspath('.')
- else:
- restdir = os.path.dirname(info.get('Trash Info', 'Path'))
-
- restfile = os.path.join(restdir, restname)
- if not os.path.exists(restdir):
- raise TMError('restore', 'nodir', _('no such directory: {}'
- ' -- cannot restore').format(restdir))
- os.rename(os.path.join(self.filedir, filename), restfile)
- os.remove(os.path.join(self.infodir, filename + '.trashinfo'))
- self.regenerate()
- print('restored {} to {}'.format(filename, restfile))
- if verbose:
- sys.stderr.write(_('restored {} to {}\n').format(filename, restfile))
-
- else:
- print('couldn\'t find {} in trash'.format(filename))
- raise TMError('restore', 'nofile', _('no such file in trash'))
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/__init__.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/__init__.py
deleted file mode 100644
index a8e5edd..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
- Utils module
-"""
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/logger.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/logger.py
deleted file mode 100644
index 06eed47..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/logger.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Python imports
-import os, logging
-
-# Application imports
-
-
-class Logger:
- def __init__(self, config_path):
- self._CONFIG_PATH = config_path
-
- def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True):
- """
- Create a new logging object and return it.
- :note:
- NOSET # Don't know the actual log level of this... (defaulting or literally none?)
- Log Levels (From least to most)
- Type Value
- CRITICAL 50
- ERROR 40
- WARNING 30
- INFO 20
- DEBUG 10
- :param loggerName: Sets the name of the logger object. (Used in log lines)
- :param createFile: Whether we create a log file or just pump to terminal
-
- :return: the logging object we created
- """
-
- globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
- chLogLevel = logging.CRITICAL # Prety musch the only one we change ever
- fhLogLevel = logging.DEBUG
- log = logging.getLogger(loggerName)
- log.setLevel(globalLogLvl)
-
- # Set our log output styles
- fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S')
- cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s')
-
- ch = logging.StreamHandler()
- ch.setLevel(level=chLogLevel)
- ch.setFormatter(cFormatter)
- log.addHandler(ch)
-
- if createFile:
- folder = self._CONFIG_PATH
- file = f"{folder}/application.log"
-
- if not os.path.exists(folder):
- os.mkdir(folder)
-
- fh = logging.FileHandler(file)
- fh.setLevel(level=fhLogLevel)
- fh.setFormatter(fFormatter)
- log.addHandler(fh)
-
- return log
diff --git a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/settings.py b/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/settings.py
deleted file mode 100644
index df454c7..0000000
--- a/src/debs/solarfm-0-0-1-x64/opt/SolarFM/utils/settings.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# Python imports
-import os
-from os import path
-
-# Gtk imports
-import gi, cairo
-gi.require_version('Gtk', '3.0')
-gi.require_version('Gdk', '3.0')
-
-from gi.repository import Gtk
-from gi.repository import Gdk
-
-
-# Application imports
-from .logger import Logger
-
-
-class Settings:
- def __init__(self):
- self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
- self._USER_HOME = path.expanduser('~')
- self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
- self._PLUGINS_PATH = f"{self._CONFIG_PATH}/plugins"
- self._USR_SOLARFM = f"/usr/share/{app_name.lower()}"
-
- self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css"
- self._WINDOWS_GLADE = f"{self._CONFIG_PATH}/Main_Window.glade"
- self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons"
- self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
-
- if not os.path.exists(self._CONFIG_PATH):
- os.mkdir(self._CONFIG_PATH)
- if not os.path.exists(self._PLUGINS_PATH):
- os.mkdir(self._PLUGINS_PATH)
-
- if not os.path.exists(self._WINDOWS_GLADE):
- self._WINDOWS_GLADE = f"{self._USR_SOLARFM}/Main_Window.glade"
- if not os.path.exists(self._CSS_FILE):
- self._CSS_FILE = f"{self._USR_SOLARFM}/stylesheet.css"
- if not os.path.exists(self._WINDOW_ICON):
- self._WINDOW_ICON = f"{self._USR_SOLARFM}/icons/{app_name.lower()}.png"
- if not os.path.exists(self._DEFAULT_ICONS):
- self._DEFAULT_ICONS = f"{self._USR_SOLARFM}/icons"
-
- self._success_color = "#88cc27"
- self._warning_color = "#ffa800"
- self._error_color = "#ff0000"
-
- self.main_window = None
- self.logger = Logger(self._CONFIG_PATH).get_logger()
- self.builder = Gtk.Builder()
- self.builder.add_from_file(self._WINDOWS_GLADE)
-
-
-
- def create_window(self):
- # Get window and connect signals
- self.main_window = self.builder.get_object("Main_Window")
- self._set_window_data()
-
- def _set_window_data(self):
- self.main_window.set_icon_from_file(self._WINDOW_ICON)
- screen = self.main_window.get_screen()
- visual = screen.get_rgba_visual()
-
- if visual != None and screen.is_composited():
- self.main_window.set_visual(visual)
- self.main_window.set_app_paintable(True)
- self.main_window.connect("draw", self._area_draw)
-
- # bind css file
- cssProvider = Gtk.CssProvider()
- cssProvider.load_from_path(self._CSS_FILE)
- screen = Gdk.Screen.get_default()
- styleContext = Gtk.StyleContext()
- styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
-
- def _area_draw(self, widget, cr):
- cr.set_source_rgba(0, 0, 0, 0.54)
- cr.set_operator(cairo.OPERATOR_SOURCE)
- cr.paint()
- cr.set_operator(cairo.OPERATOR_OVER)
-
- def get_monitor_data(self):
- screen = self.builder.get_object("Main_Window").get_screen()
- monitors = []
- for m in range(screen.get_n_monitors()):
- monitors.append(screen.get_monitor_geometry(m))
-
- for monitor in monitors:
- print("{}x{}+{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
-
- return monitors
-
- def get_builder(self): return self.builder
- def get_logger(self): return self.logger
- def get_main_window(self): return self.main_window
- def get_plugins_path(self): return self._PLUGINS_PATH
-
- def get_success_color(self): return self._success_color
- def get_warning_color(self): return self._warning_color
- def get_error_color(self): return self._error_color
diff --git a/src/versions/solarfm-0.0.1/solarfm.desktop b/src/debs/solarfm-0-0-1-x64/usr/share/applications/solarfm.desktop
similarity index 68%
rename from src/versions/solarfm-0.0.1/solarfm.desktop
rename to src/debs/solarfm-0-0-1-x64/usr/share/applications/solarfm.desktop
index 3ad68dc..77b2ecb 100755
--- a/src/versions/solarfm-0.0.1/solarfm.desktop
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/applications/solarfm.desktop
@@ -2,9 +2,8 @@
Name=SolarFM
GenericName=File Manager
Comment=A file manager built with Python and GObject introspection.
-Path=/home/abaddon/.local/share/solarfm
-Exec=/home/abaddon/Portable_Apps/py-venvs/flask-apps-venv/venv/bin/python /home/abaddon/.local/share/solarfm %F
-Icon=/home/abaddon/.local/share/solarfm/resources/solarfm-64x64.png
+Exec=/bin/solarfm %F
+Icon=/usr/share/solarfm/icons/solarfm.png
Type=Application
StartupNotify=true
Categories=System;FileTools;Utility;Core;GTK;FileManager;
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/Main_Window.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/Main_Window.glade
index 9878a5a..597d9be 100644
--- a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/Main_Window.glade
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/Main_Window.glade
@@ -1,1249 +1,41 @@
-
+
-
-
- False
- mouse
- splashscreen
- south
-
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
- gtk-cancel
- True
- True
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- Select
- True
- True
- True
-
-
- True
- True
- 1
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- False
- True
-
-
-
- False
- True
- 1
-
-
-
-
-
- button31
- appchooser_select_btn
-
-
-
- $(which 7za || echo 7zr) a %o %N
-
-
- False
- True
- center
- dialog
- center
- True
- True
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
- gtk-cancel
- True
- True
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- gtk-ok
- True
- True
- True
- True
-
-
- True
- True
- 1
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- vertical
-
-
- True
- False
- True
-
-
- True
- False
- Compress Commands:
- 0.20000000298023224
-
-
-
-
-
- False
- True
- 0
-
-
-
-
-
-
-
- True
- False
- Archive Format:
- 1
-
-
-
-
-
- False
- True
- 2
-
-
-
-
- True
- False
- 0
- 0
-
- 7Zip (*.7z)
- Zip (*.zip *.ZIP)
- RAR (*.rar *.RAR)
- Tar (*.tar)
- Tar bzip2 (*.tar.bz2)
- Tar Gzip (*.tar.gz *.tgz)
- Tar xz (*.tar.xz *.txz)
- Gzip (*.gz)
- XZ (*.xz)
-
-
-
-
- False
- True
- 3
-
-
-
-
- False
- True
- 0
-
-
-
-
- 72
- True
- True
- arc_command_buffer
-
-
- True
- True
- 1
-
-
-
-
- False
- True
- 2
-
-
-
-
-
- button21
- button22
-
-
-
+ TrueFalsegtk-save-as
-
+ TrueFalse
- gtk-new
+ gtk-file
-
- False
- popup
- False
- True
- center
- True
- splashscreen
- True
- True
- False
- center
-
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
-
-
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- vertical
-
-
- 500
- 26
- True
- True
- True
- gtk-edit
- New File/Dir Name...
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 20
- vertical
- True
-
-
- True
- False
-
-
- True
- False
- 15
- Folder
-
-
-
-
-
- True
- True
- 0
-
-
-
-
- True
- False
- 15
- File
-
-
-
-
-
- True
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- File/Folder
- True
-
-
- False
- False
- 1
-
-
-
-
- Create
- create
- True
- True
- True
- Create File/Folder...
- createImage
- True
-
-
-
- False
- True
- 2
-
-
-
-
- True
- True
- 1
-
-
-
-
- True
- True
- 1
-
-
-
-
-
-
- True
- False
- gtk-execute
-
-
- 120
- False
- popup
- False
- True
- center
- True
- splashscreen
- True
- True
- True
- False
- center
-
-
- False
- 5
- 5
- 5
- 5
- vertical
- 2
-
-
- False
- end
-
-
- Overwrite
- True
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- Overwrite (All)
- True
- True
- True
-
-
- True
- True
- 1
-
-
-
-
- Skip
- True
- True
- True
-
-
- True
- True
- 2
-
-
-
-
- Skip (All)
- True
- True
- True
-
-
- True
- True
- 3
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- vertical
-
-
- True
- False
- Filename already exists. Please rename or select an action.
- 0.10000000149011612
-
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
-
-
- True
- False
- Filename:
-
-
- False
- True
- 0
-
-
-
-
- True
- False
-
-
- True
- True
- 1
-
-
-
-
- False
- True
- 1
-
-
-
-
-
-
-
- True
- True
-
-
-
- False
- True
- 3
-
-
-
-
- True
- False
- 20
- top
- start
-
-
-
-
-
- Rename
- True
- False
- True
- True
-
-
-
- True
- True
- 1
- True
-
-
-
-
- Auto Rename
- True
- True
- True
-
-
-
- True
- True
- 2
- True
-
-
-
-
- Auto Rename All
- True
- True
- True
-
-
-
- True
- True
- 3
- True
-
-
-
-
- False
- True
- 4
-
-
-
-
- True
- True
- 1
-
-
-
-
-
- button5
- button6
- button7
- button8
-
-
-
-
+ TrueFalsegtk-justify-center
-
-
- 320
- False
- True
- bottom
-
-
- True
- False
- vertical
-
-
- gtk-save-as
- True
- True
- True
- True
-
-
-
- False
- True
- 0
-
-
-
-
- 600
- True
- True
- True
- in
- False
-
-
- message_view
- True
- True
- True
- False
- False
- message_buffer
-
-
-
-
- False
- True
- 1
-
-
-
-
-
-
+ TrueFalse
- gtk-open
+ gtk-save
-
+ TrueFalse
- gtk-edit
- 3
+ gtk-execute
-
+ TrueFalse
- gtk-edit
+ gtk-redo
-
+ TrueFalse
- gtk-media-forward
-
-
- False
- popup
- False
- True
- center
- True
- splashscreen
- True
- True
- False
- center
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
- Skip
- skip_renames
- True
- True
- True
- skip_img
- True
-
-
- True
- True
- 0
-
-
-
-
- gtk-cancel
- cancel_renames
- True
- True
- True
- True
-
-
- True
- True
- 1
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- vertical
-
-
- True
- False
-
-
- True
- False
- Rename:
-
-
- False
- True
- 0
-
-
-
-
- True
- False
-
-
- True
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- 500
- 26
- True
- True
- True
- gtk-edit
- To:
-
-
-
- False
- True
- 1
-
-
-
-
- Rename
- rename
- True
- True
- True
- rename_img
- True
-
-
-
- False
- True
- 2
-
-
-
-
- True
- True
- 1
-
-
-
-
-
- button1
- button2
-
+ gtk-stopTrue
@@ -1269,17 +61,18 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
gtk-apply3
-
+ 800600Falsecenter1670830
+ icons/solarfm.pngcenter
-
-
+
+ True
@@ -1287,7 +80,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
verticaltop
-
+ TrueFalse
@@ -1307,19 +100,25 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
gtk-new
+ createTrueFalse
+ New File/Folder...TrueTrue
+ gtk-open
+ openTrueFalse
+ Open...TrueTrue
+
@@ -1328,6 +127,99 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
False
+
+
+ Reload Plugins
+ True
+ False
+ image6
+ False
+
+
+
+
+
+ Terminal
+ True
+ False
+ image5
+ False
+
+
+
+
+
+ True
+ False
+ Session
+
+
+ True
+ False
+
+
+ Save Session
+ save_session
+ True
+ False
+ New File/Folder...
+ image4
+ False
+
+
+
+
+
+ Save Session As
+ save_session_as
+ True
+ False
+ New File/Folder...
+ image1
+ False
+
+
+
+
+
+ Load Session
+ load_session
+ True
+ False
+ New File/Folder...
+ image2
+ False
+
+
+
+
+
+
+
+
+
+ True
+ False
+ Debug
+
+
+ True
+ False
+
+
+ Show Errors
+ messages_popup
+ True
+ False
+ image3
+ False
+
+
+
+
+
+
+ gtk-quit
@@ -1385,17 +277,6 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
-
- gtk-delete
- delete
- True
- False
- True
- True
-
-
-
@@ -1413,34 +294,12 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
gtk-about
+ about_pageTrueFalseTrueTrue
-
-
-
-
-
-
-
-
-
- True
- False
- Debug
-
-
- True
- False
-
-
- Show Errors
- True
- False
- image1
- False
-
+
@@ -1455,11 +314,26 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
+ TrueFalse5start
+
+
+ Plugins
+ plugins_popup
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+ tggl_notebook_1
@@ -1473,7 +347,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
TrueTrue
- 0
+ 1
@@ -1489,7 +363,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
TrueTrue
- 1
+ 2
@@ -1505,7 +379,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
TrueTrue
- 2
+ 3
@@ -1521,7 +395,24 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
TrueTrue
- 3
+ 4
+
+
+
+
+ I/O
+ io_popup
+ True
+ True
+ True
+ io_img
+ True
+
+
+
+ True
+ True
+ 5
@@ -1555,7 +446,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
+ TrueFalse
@@ -1576,9 +467,9 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
- gtk-refresh
- refresh_view
+
+ gtk-add
+ create_tabTrueTrueTrue
@@ -1625,9 +516,9 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
- gtk-add
- create_tab
+
+ gtk-refresh
+ refresh_viewTrueTrueTrue
@@ -1676,6 +567,8 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
5FalseTrue
+ sfm_windows
+
@@ -1696,10 +589,25 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
+
+
+ window_1
+ True
+ True
+ edit-find-symbolic
+ False
+ False
+ Search...
+
+
+
+ False
+
+
- True
- True
+ False
+ False
@@ -1714,6 +622,8 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
5FalseTrue
+ sfm_windows
+
@@ -1734,10 +644,25 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
+
+
+ window_2
+ True
+ True
+ edit-find-symbolic
+ False
+ False
+ Search...
+
+
+
+ False
+
+
- True
- True
+ False
+ False
@@ -1766,6 +691,8 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
5FalseTrue
+ sfm_windows
+
@@ -1786,10 +713,25 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
+
+
+ window_3
+ True
+ True
+ edit-find-symbolic
+ False
+ False
+ Search...
+
+
+
+ False
+
+
- True
- True
+ False
+ False
@@ -1803,6 +745,8 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
5FalseTrue
+ sfm_windows
+
@@ -1823,10 +767,25 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
+
+
+ window_4
+ True
+ True
+ edit-find-symbolic
+ False
+ False
+ Search...
+
+
+
+ False
+
+
- True
- True
+ False
+ False
@@ -1843,7 +802,7 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
+ TrueFalse10
@@ -1897,481 +856,4 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe
-
- 240
- 420
- False
- path_entry
- bottom
- False
-
-
- True
- True
- in
- False
-
-
- True
- False
-
-
- True
- False
- vertical
- start
-
-
-
-
-
-
-
-
-
-
-
- False
- 5
- 5
- 5
- 5
- window_1
- bottom
- none
-
-
-
- 52
- True
- True
-
-
-
-
-
-
- False
- 5
- 5
- 5
- 5
- window_2
- bottom
- none
-
-
-
- 96
- True
- True
-
-
-
-
-
-
- False
- 5
- 5
- 5
- 5
- window_3
- none
-
-
-
- 96
- True
- True
-
-
-
-
-
-
- False
- 5
- 5
- 5
- 5
- window_4
- none
-
-
-
- 96
- True
- True
-
-
-
-
-
-
- True
- False
- user-trash
-
-
- True
- False
- user-trash
-
-
- False
- False
- mouse
- splashscreen
- True
- False
- False
- static
-
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
-
-
-
-
-
-
- False
- False
- 0
-
-
-
-
- True
- False
- vertical
-
-
- True
- False
- vertical
-
-
- gtk-delete
- delete
- True
- True
- True
- Delete...
- 20
- True
- True
-
-
-
- False
- True
- 11
-
-
-
-
- gtk-open
- open
- True
- True
- True
- Open...
- True
-
-
-
- False
- True
- 0
-
-
-
-
- Open With
- open_with
- True
- True
- True
- open_with_img
- True
-
-
-
- False
- True
- 1
-
-
-
-
- gtk-execute
- execute
- True
- True
- True
- True
-
-
-
- False
- True
- 2
-
-
-
-
- Execute in Terminal
- execute_in_terminal
- True
- True
- True
- exec_in_term_img
-
-
-
- False
- True
- 3
-
-
-
-
- Rename
- rename
- True
- True
- True
- Rename...
- 20
- rename_img2
- True
-
-
-
- False
- True
- 4
-
-
-
-
- gtk-cut
- cut
- True
- True
- True
- Cut...
- True
- True
-
-
-
- False
- True
- 5
-
-
-
-
- gtk-copy
- copy
- True
- True
- True
- Copy...
- True
- True
-
-
-
- False
- True
- 6
-
-
-
-
- gtk-paste
- paste
- True
- True
- True
- Paste...
- True
- True
-
-
-
- False
- True
- 7
-
-
-
-
- Go To Trash
- go_to_trash
- True
- True
- True
- Go To Trash...
- trash_img2
- True
-
-
-
- False
- True
- end
- 8
-
-
-
-
- Archive
- archive
- True
- True
- True
- Archive...
- archive_img
- True
-
-
-
- False
- True
- 9
-
-
-
-
- Trash
- trash
- True
- True
- True
- Move to Trash...
- trash_img
- True
-
-
-
- False
- True
- end
- 11
-
-
-
-
- False
- True
- 2
-
-
-
-
- False
- True
- 1
-
-
-
-
-
-
- False
- False
- True
- center
- True
- dialog
- True
- True
- True
- False
- False
- center
- warning
- Warning!
-
-
- False
- 5
- 5
- 5
- 5
- vertical
- 2
-
-
- False
- True
- end
-
-
- gtk-no
- True
- True
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- gtk-yes
- True
- True
- True
- True
- True
-
-
- True
- True
- 1
-
-
-
-
- False
- False
- 0
-
-
-
-
-
- button4
- button3
-
-
-
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/contexct_menu.json b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/contexct_menu.json
new file mode 100644
index 0000000..9e9323b
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/contexct_menu.json
@@ -0,0 +1,17 @@
+{
+ "Open Actions": {
+ "Open": ["STOCK_OPEN", "open"],
+ "Open With": ["STOCK_OPEN", "open_with"],
+ "Execute": ["STOCK_EXECUTE", "execute"],
+ "Execute in Terminal": ["STOCK_EXECUTE", "execute_in_terminal"]
+ },
+ "File Actions": {
+ "New": ["STOCK_ADD", "create"],
+ "Rename": ["STOCK_EDIT", "rename"],
+ "Cut": ["STOCK_CUT", "cut"],
+ "Copy": ["STOCK_COPY", "copy"],
+ "Copy Name": ["STOCK_COPY", "copy_name"],
+ "Paste": ["STOCK_PASTE", "paste"]
+ },
+ "Plugins": {}
+}
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3g2.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3g2.png
new file mode 100644
index 0000000..cccf50a
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3g2.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3gp.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3gp.png
new file mode 100644
index 0000000..b3fb117
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/3gp.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ai.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ai.png
new file mode 100644
index 0000000..ddb172f
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ai.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/air.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/air.png
new file mode 100644
index 0000000..076f08e
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/air.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/asf.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/asf.png
new file mode 100644
index 0000000..b700cf4
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/asf.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/avi.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/avi.png
new file mode 100644
index 0000000..f4436f7
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/avi.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/bib.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/bib.png
new file mode 100644
index 0000000..2789ca5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/bib.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/cls.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/cls.png
new file mode 100644
index 0000000..4759ad6
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/cls.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/csv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/csv.png
new file mode 100644
index 0000000..869e354
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/csv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/deb.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/deb.png
new file mode 100644
index 0000000..e5581ad
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/deb.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/djvu.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/djvu.png
new file mode 100644
index 0000000..f3ed05d
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/djvu.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dmg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dmg.png
new file mode 100644
index 0000000..b52c92c
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dmg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/doc.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/doc.png
new file mode 100644
index 0000000..8f615d1
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/doc.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/docx.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/docx.png
new file mode 100644
index 0000000..377ecc7
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/docx.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwf.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwf.png
new file mode 100644
index 0000000..349610c
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwf.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwg.png
new file mode 100644
index 0000000..5398b08
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/dwg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/eps.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/eps.png
new file mode 100644
index 0000000..10f19eb
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/eps.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/epub.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/epub.png
new file mode 100644
index 0000000..6f8a256
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/epub.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/exe.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/exe.png
new file mode 100644
index 0000000..0910322
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/exe.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f.png
new file mode 100644
index 0000000..7cfb90a
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f77.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f77.png
new file mode 100644
index 0000000..752fa8c
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f77.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f90.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f90.png
new file mode 100644
index 0000000..32c9feb
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/f90.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flac.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flac.png
new file mode 100644
index 0000000..b529135
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flac.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flv.png
new file mode 100644
index 0000000..c4e35d5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/flv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gif.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gif.png
new file mode 100644
index 0000000..7cd9773
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gif.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gz.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gz.png
new file mode 100644
index 0000000..987d4f0
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/gz.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ico.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ico.png
new file mode 100644
index 0000000..b33287e
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ico.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/indd.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/indd.png
new file mode 100644
index 0000000..24389f0
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/indd.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/iso.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/iso.png
new file mode 100644
index 0000000..de2a19f
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/iso.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpeg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpeg.png
new file mode 100644
index 0000000..b1ba768
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpeg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpg.png
new file mode 100644
index 0000000..b1ba768
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/jpg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/log.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/log.png
new file mode 100644
index 0000000..c1acea1
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/log.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4a.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4a.png
new file mode 100644
index 0000000..f8f3ada
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4a.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4v.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4v.png
new file mode 100644
index 0000000..fef795b
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/m4v.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/midi.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/midi.png
new file mode 100644
index 0000000..85132d5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/midi.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mkv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mkv.png
new file mode 100644
index 0000000..b0b1f92
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mkv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mov.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mov.png
new file mode 100644
index 0000000..9799d32
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mov.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp3.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp3.png
new file mode 100644
index 0000000..18394f5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp3.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp4.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp4.png
new file mode 100644
index 0000000..b34c7d5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mp4.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpeg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpeg.png
new file mode 100644
index 0000000..eb58ef5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpeg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpg.png
new file mode 100644
index 0000000..eb58ef5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/mpg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/msi.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/msi.png
new file mode 100644
index 0000000..95fe7d7
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/msi.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odp.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odp.png
new file mode 100644
index 0000000..69f8663
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odp.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ods.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ods.png
new file mode 100644
index 0000000..8f415a9
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ods.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odt.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odt.png
new file mode 100644
index 0000000..5e10765
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/odt.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/oga.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/oga.png
new file mode 100644
index 0000000..c236464
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/oga.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogg.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogg.png
new file mode 100644
index 0000000..1f70cb8
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogg.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogv.png
new file mode 100644
index 0000000..027dfe9
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ogv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pdf.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pdf.png
new file mode 100644
index 0000000..867f287
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pdf.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/png.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/png.png
new file mode 100644
index 0000000..9433c35
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/png.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pps.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pps.png
new file mode 100644
index 0000000..f75d9b6
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pps.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppsx.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppsx.png
new file mode 100644
index 0000000..a9fd94b
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppsx.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppt.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppt.png
new file mode 100644
index 0000000..0cb28ba
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ppt.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pptx.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pptx.png
new file mode 100644
index 0000000..d1d7785
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pptx.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/psd.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/psd.png
new file mode 100644
index 0000000..568684b
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/psd.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pub.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pub.png
new file mode 100644
index 0000000..ff27076
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/pub.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/py.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/py.png
new file mode 100644
index 0000000..4fadf04
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/py.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/qt.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/qt.png
new file mode 100644
index 0000000..839742f
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/qt.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ra.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ra.png
new file mode 100644
index 0000000..0103372
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ra.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ram.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ram.png
new file mode 100644
index 0000000..ffdfa05
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ram.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rar.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rar.png
new file mode 100644
index 0000000..96a5cd0
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rar.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rm.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rm.png
new file mode 100644
index 0000000..ae680c2
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rm.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rpm.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rpm.png
new file mode 100644
index 0000000..5f3d622
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rpm.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rtf.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rtf.png
new file mode 100644
index 0000000..c26ede1
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rtf.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rv.png
new file mode 100644
index 0000000..d7d46b5
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/rv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/skp.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/skp.png
new file mode 100644
index 0000000..778f0e3
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/skp.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/spx.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/spx.png
new file mode 100644
index 0000000..4f3d7a1
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/spx.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sql.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sql.png
new file mode 100644
index 0000000..bf6c1ab
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sql.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sty.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sty.png
new file mode 100644
index 0000000..5512ae8
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/sty.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tar.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tar.png
new file mode 100644
index 0000000..dda5cea
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tar.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tex.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tex.png
new file mode 100644
index 0000000..36bf00e
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tex.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tgz.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tgz.png
new file mode 100644
index 0000000..651d0b1
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tgz.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tiff.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tiff.png
new file mode 100644
index 0000000..b780ffa
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/tiff.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ttf.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ttf.png
new file mode 100644
index 0000000..842f566
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/ttf.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/txt.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/txt.png
new file mode 100644
index 0000000..cbae3ce
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/txt.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/vob.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/vob.png
new file mode 100644
index 0000000..70cc91d
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/vob.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wav.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wav.png
new file mode 100644
index 0000000..1dfa320
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wav.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wmv.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wmv.png
new file mode 100644
index 0000000..c120508
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/wmv.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xls.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xls.png
new file mode 100644
index 0000000..cf5a2d0
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xls.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xlsx.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xlsx.png
new file mode 100644
index 0000000..454fd5d
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xlsx.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xml.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xml.png
new file mode 100644
index 0000000..609f131
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xml.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xpi.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xpi.png
new file mode 100644
index 0000000..fd479a6
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/xpi.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/zip.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/zip.png
new file mode 100644
index 0000000..8caadb2
Binary files /dev/null and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/fileicons/zip.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/icons/solarfm.png b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/icons/solarfm.png
index 83974e1..1a403ae 100644
Binary files a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/icons/solarfm.png and b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/icons/solarfm.png differ
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/key-bindings.json b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/key-bindings.json
new file mode 100644
index 0000000..f3b10a0
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/key-bindings.json
@@ -0,0 +1,23 @@
+{
+ "keybindings": {
+ "help" : "F1",
+ "rename_files" : ["F2",
+ "e"],
+ "open_terminal" : "F4",
+ "refresh_tab" : ["F5",
+ "r"],
+ "tggl_top_main_menubar" : "h",
+ "tear_down" : "q",
+ "go_up" : "Up",
+ "go_home" : "slash",
+ "grab_focus_path_entry" : "l",
+ "open_files" : "o",
+ "show_hide_hidden_files" : "h",
+ "create_tab" : "t",
+ "keyboard_close_tab" : "w",
+ "copy_files" : "c",
+ "cut_files" : "x",
+ "paste_files" : "v",
+ "create_files" : "n"
+ }
+}
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/settings.json b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/settings.json
index c9f246f..5b9f096 100644
--- a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/settings.json
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/settings.json
@@ -1,20 +1,37 @@
{
- "settings": {
+ "config": {
"base_of_home": "",
"hide_hidden_files": "true",
"thumbnailer_path": "ffmpegthumbnailer",
+ "blender_thumbnailer_path": "",
"go_past_home": "true",
"lock_folder": "false",
"locked_folders": "venv::::flasks",
"mplayer_options": "-quiet -really-quiet -xy 1600 -geometry 50%:50%",
- "music_app": "/opt/deadbeef/bin/deadbeef",
+ "music_app": "deadbeef",
"media_app": "mpv",
- "image_app": "mirage",
+ "image_app": "mirage2",
"office_app": "libreoffice",
"pdf_app": "evince",
- "text_app": "leafpad",
- "file_manager_app": "solarfm",
+ "code_app": "atom",
+ "text_app": "mousepad",
"terminal_app": "terminator",
+ "container_icon_wh": [128, 128],
+ "video_icon_wh": [128, 64],
+ "sys_icon_wh": [56, 56],
+ "file_manager_app": "solarfm",
+ "steam_cdn_url": "https://steamcdn-a.akamaihd.net/steam/apps/",
"remux_folder_max_disk_usage": "8589934592"
- }
+ },
+ "filters": {
+ "meshs": [".dae", ".fbx", ".gltf", ".obj", ".stl"],
+ "code": [".cpp", ".css", ".c", ".go", ".html", ".htm", ".java", ".js", ".json", ".lua", ".md", ".py", ".rs", ".toml", ".xml", ".pom"],
+ "videos": [".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wmv", ".flv"],
+ "office": [".doc", ".docx", ".xls", ".xlsx", ".xlt", ".xltx", ".xlm", ".ppt", ".pptx", ".pps", ".ppsx", ".odt", ".rtf"],
+ "images": [".png", ".jpg", ".jpeg", ".gif", ".ico", ".tga", ".webp"],
+ "text": [".txt", ".text", ".sh", ".cfg", ".conf", ".log"],
+ "music": [".psf", ".mp3", ".ogg", ".flac", ".m4a"],
+ "pdf": [".pdf"]
+
+ }
}
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/about_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/about_ui.glade
new file mode 100644
index 0000000..f559f6c
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/about_ui.glade
@@ -0,0 +1,390 @@
+
+
+
+
+
+ 320
+ 480
+ False
+ 5
+ center-on-parent
+ ../icons/solarfm.png
+ dialog
+ True
+ True
+ False
+ center
+ SolarFM
+ 0.0.1
+ Copyright (C) 2021 GPL2
+ by ITDominator
+ https://code.itdominator.com/itdominator/SolarFM
+ SolarFM - Copyright (C) 2021 ITDominator GPL2
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
+ Lead Developer:
+ ITDominator <1itdominator@gmail.com>
+
+
+SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspection.
+ translator-credits
+ ../icons/solarfm-64x64.png
+ True
+ custom
+
+
+ False
+
+
+ False
+
+
+ False
+ False
+ 0
+
+
+
+
+
+
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/appchooser_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/appchooser_ui.glade
new file mode 100644
index 0000000..6959306
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/appchooser_ui.glade
@@ -0,0 +1,75 @@
+
+
+
+
+
+ False
+ mouse
+ splashscreen
+ south
+
+
+
+ False
+ vertical
+ 2
+
+
+ False
+ end
+
+
+ gtk-cancel
+ True
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+
+
+
+
+ Select
+ True
+ True
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ False
+ False
+ True
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ button31
+ appchooser_select_btn
+
+
+
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/file_exists_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/file_exists_ui.glade
new file mode 100644
index 0000000..70d7291
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/file_exists_ui.glade
@@ -0,0 +1,337 @@
+
+
+
+
+
+ 120
+ False
+ False
+ True
+ center-always
+ True
+ dialog
+ True
+ True
+ True
+ False
+ False
+ center
+
+
+ False
+ 5
+ 5
+ 5
+ 5
+ vertical
+ 2
+
+
+ False
+ end
+
+
+ Overwrite
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+
+
+
+
+ Overwrite (All)
+ True
+ True
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ Skip
+ True
+ True
+ True
+
+
+ True
+ True
+ 2
+
+
+
+
+ Skip (All)
+ True
+ True
+ True
+
+
+ True
+ True
+ 3
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ Filename already exists. Please rename or select an action.
+ 0.10000000149011612
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 15
+ 10
+
+
+ True
+ False
+ Moving From:
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 0
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ False
+ 20
+ 10
+
+
+ True
+ False
+ Moving To:
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ False
+ 0
+
+
+ True
+ True
+ 4
+
+
+
+
+ True
+ False
+ 20
+
+
+ True
+ False
+ Filename:
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 5
+
+
+
+
+ True
+ True
+
+
+
+ False
+ True
+ 6
+
+
+
+
+ True
+ False
+ 20
+ top
+ start
+
+
+
+
+
+ Rename
+ True
+ False
+ True
+ True
+
+
+
+ True
+ True
+ 1
+ True
+
+
+
+
+ Auto Rename
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+ True
+
+
+
+
+ Auto Rename All
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 3
+ True
+
+
+
+
+ False
+ True
+ 7
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+ button5
+ button6
+ button7
+ button8
+
+
+
+
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/new_file_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/new_file_ui.glade
new file mode 100644
index 0000000..8b11ea8
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/new_file_ui.glade
@@ -0,0 +1,186 @@
+
+
+
+
+
+ True
+ False
+ gtk-new
+
+
+ False
+ False
+ True
+ center-always
+ True
+ dialog
+ True
+ True
+ False
+ False
+ center
+
+
+ False
+ 5
+ 5
+ 5
+ 5
+ vertical
+ 2
+
+
+ False
+ end
+
+
+ gtk-cancel
+ True
+ True
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+
+
+
+
+ Create
+ create
+ True
+ True
+ True
+ Create File/Folder...
+ create_img
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ 500
+ 26
+ True
+ True
+ True
+ New File/Dir Name...
+ True
+ gtk-edit
+ False
+ False
+ False
+ False
+ New File/Dir Name...
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 20
+ vertical
+ True
+
+
+ True
+ False
+
+
+ True
+ False
+ 15
+ Folder
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ 15
+ File
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ True
+ File/Folder
+ True
+
+
+ False
+ False
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ button9
+ button10
+
+
+
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/rename_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/rename_ui.glade
new file mode 100644
index 0000000..d06e7a9
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/rename_ui.glade
@@ -0,0 +1,241 @@
+
+
+
+
+
+ True
+ False
+ gtk-edit
+ 3
+
+
+ True
+ False
+ gtk-media-forward
+
+
+ False
+ False
+ True
+ center-always
+ True
+ dialog
+ True
+ True
+ False
+ False
+ center
+
+
+ False
+ 5
+ 5
+ 5
+ 5
+ vertical
+ 2
+
+
+ False
+ end
+
+
+ gtk-cancel
+ cancel_renames
+ True
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+
+
+
+
+ Skip
+ skip_renames
+ True
+ True
+ True
+ skip_img
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+
+
+ True
+ False
+ Rename:
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 500
+ 26
+ True
+ True
+ True
+ Rename To:
+ True
+ gtk-edit
+ False
+ False
+ False
+ False
+ To:
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ True
+ expand
+
+
+ Title Case
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ Upper Case
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Lower Case
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ Invert Case
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 3
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ Rename
+ rename
+ True
+ True
+ True
+ rename_img
+ True
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+ button2
+ button1
+
+
+
diff --git a/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/save_load_ui.glade b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/save_load_ui.glade
new file mode 100644
index 0000000..ba42cba
--- /dev/null
+++ b/src/debs/solarfm-0-0-1-x64/usr/share/solarfm/ui_widgets/save_load_ui.glade
@@ -0,0 +1,65 @@
+
+
+
+
+
+ False
+ dialog
+ True
+
+
+ False
+ vertical
+ 2
+
+
+ False
+ end
+
+
+ gtk-cancel
+ True
+ True
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+
+
+
+
+ gtk-ok
+ True
+ True
+ True
+ True
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ False
+ 0
+
+
+
+
+
+
+
+
+ button11
+ button12
+
+
+
diff --git a/src/versions/solarfm-0.0.1/SolarFM/tests/__init__.py b/src/versions/solarfm-0.0.1/SolarFM/tests/__init__.py
deleted file mode 100644
index fa1889d..0000000
--- a/src/versions/solarfm-0.0.1/SolarFM/tests/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
- Tests Module
-"""
diff --git a/src/versions/solarfm-0.0.1/SolarFM_exec_bin.cpp b/src/versions/solarfm-0.0.1/SolarFM_exec_bin.cpp
index f381eb5..9dc7c0b 100644
--- a/src/versions/solarfm-0.0.1/SolarFM_exec_bin.cpp
+++ b/src/versions/solarfm-0.0.1/SolarFM_exec_bin.cpp
@@ -4,7 +4,7 @@
using namespace std;
int main() {
- chdir("/opt/SolarFM/");
- system("python .");
+ chdir("/opt/");
+ system("python solarfm.zip");
return 0;
}
diff --git a/src/versions/solarfm-0.0.1/clear_pycache_dirs.sh b/src/versions/solarfm-0.0.1/clear_pycache_dirs.sh
deleted file mode 100755
index 7987a3d..0000000
--- a/src/versions/solarfm-0.0.1/clear_pycache_dirs.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-# set -o xtrace ## To debug scripts
-# set -o errexit ## To exit on error
-# set -o errunset ## To exit if a variable is referenced but not set
-
-
-function main() {
- find . -name "__pycache__" -exec rm -rf $1 {} \;
- find . -name "*.pyc" -exec rm -rf $1 {} \;
-}
-main
diff --git a/src/versions/solarfm-0.0.1/compileBin.sh b/src/versions/solarfm-0.0.1/compile_bin.sh
similarity index 100%
rename from src/versions/solarfm-0.0.1/compileBin.sh
rename to src/versions/solarfm-0.0.1/compile_bin.sh
diff --git a/user_config/usr/share/applications/solarfm.desktop b/user_config/usr/share/applications/solarfm.desktop
new file mode 100755
index 0000000..77b2ecb
--- /dev/null
+++ b/user_config/usr/share/applications/solarfm.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Name=SolarFM
+GenericName=File Manager
+Comment=A file manager built with Python and GObject introspection.
+Exec=/bin/solarfm %F
+Icon=/usr/share/solarfm/icons/solarfm.png
+Type=Application
+StartupNotify=true
+Categories=System;FileTools;Utility;Core;GTK;FileManager;
+MimeType=inode/directory;inode/mount-point;x-scheme-handler/ssh;x-scheme-handler/smb;x-scheme-handler/nfs;x-scheme-handler/ftp;x-scheme-handler/ptp;x-scheme-handler/mtp;x-scheme-handler/webdav;x-scheme-handler/http;x-scheme-handler/https;
+Terminal=false