develop #11
| @@ -64,6 +64,8 @@ class FileSearchMixin: | ||||
|             break | ||||
|  | ||||
|     def _stop_fsearch_query(self, widget=None, eve=None): | ||||
|         self._spinner.stop() | ||||
|  | ||||
|         # NOTE: Freeze IPC consumption | ||||
|         self.pause_fifo_update  = True | ||||
|         self.search_query       = "" | ||||
| @@ -86,10 +88,10 @@ class FileSearchMixin: | ||||
|             self.search_query = query | ||||
|             target_dir = shlex.quote( self._fm_state.tab.get_current_directory() ) | ||||
|             command = ["python", f"{self.path}/utils/search.py", "-t", "file_search", "-d", f"{target_dir}", "-q", f"{query}"] | ||||
|             self._spinner.start() | ||||
|             self._list_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None) | ||||
|  | ||||
|  | ||||
|  | ||||
|     def _load_file_ui(self, data): | ||||
|         Gtk.main_iteration() | ||||
|  | ||||
|   | ||||
| @@ -64,6 +64,8 @@ class GrepSearchMixin: | ||||
|             break | ||||
|  | ||||
|     def _stop_grep_query(self, widget=None, eve=None): | ||||
|         self._spinner.stop() | ||||
|  | ||||
|         # NOTE: Freeze IPC consumption | ||||
|         self.pause_fifo_update = True | ||||
|         self.grep_query        = "" | ||||
| @@ -88,6 +90,7 @@ class GrepSearchMixin: | ||||
|  | ||||
|             target_dir = shlex.quote( self._fm_state.tab.get_current_directory() ) | ||||
|             command = ["python", f"{self.path}/utils/search.py", "-t", "grep_search", "-d", f"{target_dir}", "-q", f"{query}"] | ||||
|             self._spinner.start() | ||||
|             self._grep_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None) | ||||
|  | ||||
|     def _load_grep_ui(self, data): | ||||
|   | ||||
| @@ -28,6 +28,7 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): | ||||
|  | ||||
|         self.update_list_ui_buffer = () | ||||
|         self._search_dialog     = None | ||||
|         self._spinner           = None | ||||
|         self._active_path       = None | ||||
|         self.file_list_parent   = None | ||||
|         self.grep_list_parent   = None | ||||
| @@ -55,6 +56,7 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): | ||||
|  | ||||
|         self._search_dialog = self._builder.get_object("search_dialog") | ||||
|         self.fsearch        = self._builder.get_object("fsearch") | ||||
|         self._spinner       = self._builder.get_object("spinner") | ||||
|  | ||||
|         self.grep_list_parent = self._builder.get_object("grep_list_parent") | ||||
|         self.file_list_parent = self._builder.get_object("file_list_parent") | ||||
| @@ -72,6 +74,10 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): | ||||
|         item.set_always_show_image(True) | ||||
|         return item | ||||
|  | ||||
|     def stop_spinner(self, ret_code): | ||||
|         print(f"Return Code: {ret_code}") | ||||
|         self._spinner.stop() | ||||
|  | ||||
|  | ||||
|     def _show_page(self, widget=None, eve=None): | ||||
|         self._event_system.emit("get_current_state") | ||||
|   | ||||
| @@ -25,6 +25,17 @@ | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can-focus">False</property> | ||||
|             <property name="layout-style">end</property> | ||||
|             <child> | ||||
|               <object class="GtkSpinner" id="spinner"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can-focus">False</property> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="expand">True</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">0</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|             <child> | ||||
|               <object class="GtkButton" id="cancel_button"> | ||||
|                 <property name="label">gtk-cancel</property> | ||||
| @@ -37,7 +48,7 @@ | ||||
|               <packing> | ||||
|                 <property name="expand">True</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">0</property> | ||||
|                 <property name="position">1</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|             <child> | ||||
| @@ -52,7 +63,7 @@ | ||||
|               <packing> | ||||
|                 <property name="expand">True</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">1</property> | ||||
|                 <property name="position">2</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|           </object> | ||||
| @@ -260,6 +271,12 @@ | ||||
|             <child type="tab"> | ||||
|               <placeholder/> | ||||
|             </child> | ||||
|             <child> | ||||
|               <placeholder/> | ||||
|             </child> | ||||
|             <child type="tab"> | ||||
|               <placeholder/> | ||||
|             </child> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">True</property> | ||||
|   | ||||
| @@ -59,23 +59,27 @@ class IPCServer: | ||||
|         while True: | ||||
|             msg  = conn.recv() | ||||
|  | ||||
|             try: | ||||
|                 if "SEARCH_DONE|" in msg: | ||||
|                     ts, ret_code = msg.split("SEARCH_DONE|")[1].strip().split("|", 1) | ||||
|                     timestamp = float(ts) | ||||
|                     if self.fsearch_time_stamp or self.grep_time_stamp: | ||||
|                         if (timestamp > self.fsearch_time_stamp) or (timestamp > self.grep_time_stamp): | ||||
|                             GLib.idle_add(self.stop_spinner, (ret_code,), priority=GLib.PRIORITY_HIGH_IDLE) | ||||
|  | ||||
|                 if "SEARCH|" in msg: | ||||
|                     ts, file = msg.split("SEARCH|")[1].strip().split("|", 1) | ||||
|                 try: | ||||
|                     timestamp = float(ts) | ||||
|                     if timestamp > self.fsearch_time_stamp and file: | ||||
|                         GLib.idle_add(self._load_file_ui, file, priority=GLib.PRIORITY_LOW) | ||||
|                 except Exception as e: | ||||
|                     ... | ||||
|                     if file and (timestamp > self.fsearch_time_stamp): | ||||
|                         GLib.idle_add(self._load_file_ui, file, priority=GLib.PRIORITY_HIGH_IDLE) | ||||
|  | ||||
|                 if "GREP|" in msg: | ||||
|                     ts, data = msg.split("GREP|")[1].strip().split("|", 1) | ||||
|                 try: | ||||
|                     timestamp = float(ts) | ||||
|                     if timestamp > self.grep_time_stamp and data: | ||||
|                         GLib.idle_add(self._load_grep_ui, data, priority=GLib.PRIORITY_LOW) | ||||
|                     if data and (timestamp > self.grep_time_stamp): | ||||
|                         GLib.idle_add(self._load_grep_ui, data, priority=GLib.PRIORITY_HIGH_IDLE) | ||||
|             except Exception as e: | ||||
|                     ... | ||||
|                 print( repr(e) ) | ||||
|  | ||||
|  | ||||
|             conn.close() | ||||
|   | ||||
| @@ -82,12 +82,11 @@ def grep_search(target=None, query=None): | ||||
|                 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() | ||||
|  | ||||
|     data = f"GREP|{ts}|{json.dumps(collection, separators=(',', ':'), indent=4)}" | ||||
|     send_ipc_message(data) | ||||
|     collection = {} | ||||
|  | ||||
|  | ||||
| @@ -112,5 +111,11 @@ if __name__ == "__main__": | ||||
|         # Read arguments (If any...) | ||||
|         args = parser.parse_args() | ||||
|         search(args) | ||||
|  | ||||
|         data = f"SEARCH_DONE|{ts}|0" | ||||
|         send_ipc_message(data) | ||||
|     except Exception as e: | ||||
|         traceback.print_exc() | ||||
|  | ||||
|         data = f"SEARCH_DONE|{ts}|1" | ||||
|         send_ipc_message(data) | ||||
|   | ||||
| @@ -60,7 +60,7 @@ class Plugin(PluginBase): | ||||
|         self._queue_translate = False | ||||
|         self._watcher_running = False | ||||
|         self._vqd_attrib      = None | ||||
|         self.from_trans       = "jp" | ||||
|         self.from_trans       = "ja" | ||||
|         self.to_trans         = "en" | ||||
|         self.translate_tries  = 0 | ||||
|  | ||||
| @@ -138,14 +138,14 @@ class Plugin(PluginBase): | ||||
|  | ||||
|         self.translate_tries += 1 | ||||
|         tlink    = f"https://duckduckgo.com/translation.js?vqd={self._vqd_attrib}&query=translate&from={self.from_trans}&to={self.to_trans}" | ||||
|         response = requests.post(self.tlink, headers=self._headers, data=from_translate) | ||||
|         response = requests.post(tlink, headers=self._headers, data=from_translate) | ||||
|  | ||||
|         if response.status_code == 200: | ||||
|             data = response.json() | ||||
|             self._translate_to_buffer.set_text(data["translated"]) | ||||
|  | ||||
|             self.translate_tries = 0 | ||||
|             if "detected_language" in data.keys(): | ||||
|             if data["detected_language"]: | ||||
|                 self._detected_language_lbl.set_label(f"Detected Language: {data['detected_language']}") | ||||
|             else: | ||||
|                 self._detected_language_lbl.set_label(f"Selected Language: {self.from_trans}") | ||||
| @@ -157,7 +157,7 @@ class Plugin(PluginBase): | ||||
|             msg = f"Could not translate... Response Code: {response.status_code}" | ||||
|             self._translate_to_buffer.set_text(msg) | ||||
|  | ||||
|  | ||||
|     # NOTE: https://github.com/deedy5/duckduckgo_search/blob/72acb900a346be576f0917dd3d6c0fbd618a71bf/duckduckgo_search/utils.py | ||||
|     def get_vqd(self): | ||||
|         response = requests.post(self.vqd_link, headers=self.vqd_headers, data=self.vqd_data, timeout=10) | ||||
|         if response.status_code == 200: | ||||
|   | ||||
| @@ -13,7 +13,7 @@ function main() { | ||||
|     LINK=`xclip -selection clipboard -o` | ||||
|  | ||||
|     python "${HOME}/.config/solarfm/plugins/youtube_download/yt_dlp/__main__.py" \ | ||||
|             --cookies-from-browser firefox --write-sub --embed-sub --sub-langs en \ | ||||
|             --write-sub --embed-sub --sub-langs en \ | ||||
|             -o "${1}/%(title)s.%(ext)s" "${LINK}" | ||||
| } | ||||
| main "$@"; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ from .widgets.popups.plugins_popup_widget import PluginsPopupWidget | ||||
| from .widgets.popups.io_popup_widget import IOPopupWidget | ||||
|  | ||||
| from .widgets.context_menu_widget import ContextMenuWidget | ||||
| from .widgets.bottom_status_info_widget import BottomStatusInfoWidget | ||||
|  | ||||
| from .ui_mixin import UIMixin | ||||
|  | ||||
| @@ -56,7 +57,9 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         ... | ||||
|         self.window.connect("focus-out-event", self.unset_keys_and_data) | ||||
|         self.window.connect("key-press-event", self.on_global_key_press_controller) | ||||
|         self.window.connect("key-release-event", self.on_global_key_release_controller) | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         FileSystemActions() | ||||
| @@ -67,6 +70,7 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): | ||||
|         event_system.subscribe("clear_notebooks", self.clear_notebooks) | ||||
|         event_system.subscribe("get_current_state", self.get_current_state) | ||||
|         event_system.subscribe("go_to_path", self.go_to_path) | ||||
|         event_system.subscribe("format_to_uris", self.format_to_uris) | ||||
|         event_system.subscribe("do_action_from_menu_controls", self.do_action_from_menu_controls) | ||||
|         event_system.subscribe("set_clipboard_data", self.set_clipboard_data) | ||||
|  | ||||
| @@ -78,7 +82,7 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): | ||||
|         self.core_widget = self.builder.get_object("core_widget") | ||||
|  | ||||
|         settings.set_builder(self.builder) | ||||
|         settings.register_signals_to_builder([self,]) | ||||
|         settings.register_signals_to_builder([self,], self.builder) | ||||
|  | ||||
|     def get_core_widget(self): | ||||
|         return self.core_widget | ||||
| @@ -87,6 +91,7 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): | ||||
|     # NOTE: Really we will move these to the UI/(New) Window 'base' controller | ||||
|     #       after we're done cleaning and refactoring to use fewer mixins. | ||||
|     def _load_widgets(self): | ||||
|         BottomStatusInfoWidget() | ||||
|         IOPopupWidget() | ||||
|         MessagePopupWidget() | ||||
|         PathMenuPopupWidget() | ||||
|   | ||||
| @@ -13,8 +13,6 @@ from gi.repository import Gtk | ||||
| from shellfm.windows.controller import WindowController | ||||
| from plugins.plugins_controller import PluginsController | ||||
|  | ||||
| # from factories.split_view_widget import SplitViewWidget | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -49,21 +47,15 @@ class Controller_Data: | ||||
|         self.plugins            = PluginsController() | ||||
|         self.fm_controller_data = self.fm_controller.get_state_from_file() | ||||
|  | ||||
|  | ||||
|         # self.pane_master        = self.builder.get_object("pane_master") | ||||
|         # self.pane_master.pack1(SplitViewWidget(), True, True) | ||||
|         # self.pane_master.pack2(SplitViewWidget(), True, True) | ||||
|  | ||||
|  | ||||
|         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.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.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.notebooks          = [self.window1, self.window2, self.window3, self.window4] | ||||
|         self.selected_files     = [] | ||||
| @@ -132,6 +124,24 @@ class Controller_Data: | ||||
|         event_system.emit("update_state_info_plugins", state) | ||||
|         return state | ||||
|  | ||||
|     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 clear_console(self) -> None: | ||||
|         ''' Clears the terminal screen. ''' | ||||
|   | ||||
| @@ -72,75 +72,8 @@ class WindowMixin(TabMixin): | ||||
|     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): | ||||
|         state                = self.get_current_state() | ||||
|         selected_files       = state.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 = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) ) | ||||
|         formatted_mount_size = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) ) | ||||
|  | ||||
|         # NOTE: Hides empty trash and other desired buttons based on context. | ||||
|         if settings.get_trash_files_path() == current_directory: | ||||
|             event_system.emit("show_trash_buttons") | ||||
|         else: | ||||
|             event_system.emit("hide_trash_buttons") | ||||
|  | ||||
|         # 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(state.store, state.wid, state.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 WindowException as e: | ||||
|                     logger.debug(repr(e)) | ||||
|  | ||||
|             formatted_size = 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.is_hiding_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") | ||||
|  | ||||
|  | ||||
|         event_system.emit("set_bottom_labels", (tab,)) | ||||
|  | ||||
|     def set_window_title(self): | ||||
|         wid, tid = self.fm_controller.get_active_wid_and_tid() | ||||
|   | ||||
| @@ -0,0 +1,101 @@ | ||||
| # Python imports | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| from gi.repository import Gtk | ||||
| from gi.repository import Gio | ||||
|  | ||||
| # Application imports | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class BottomStatusInfoWidget: | ||||
|     """docstring for BottomStatusInfoWidget.""" | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(BottomStatusInfoWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/bottom_status_info_ui.glade" | ||||
|         self._builder = Gtk.Builder() | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         self._subscribe_to_events() | ||||
|         self._load_widgets() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         ... | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         ... | ||||
|  | ||||
|     def _subscribe_to_events(self): | ||||
|         event_system.subscribe("set_bottom_labels", self.set_bottom_labels) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self.bottom_status_info      = self._builder.get_object("bottom_status_info") | ||||
|         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") | ||||
|  | ||||
|         builder.expose_object(f"bottom_status_info", self.bottom_status_info) | ||||
|         builder.expose_object(f"bottom_size_label", self.bottom_size_label) | ||||
|         builder.expose_object(f"bottom_file_count_label", self.bottom_file_count_label) | ||||
|         builder.expose_object(f"bottom_path_label", self.bottom_path_label) | ||||
|  | ||||
|         builder.get_object("core_widget").add(self.bottom_status_info) | ||||
|  | ||||
|  | ||||
|     def set_bottom_labels(self, tab): | ||||
|         state                = event_system.emit_and_await("get_current_state") | ||||
|         selected_files       = state.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 = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) ) | ||||
|         formatted_mount_size = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) ) | ||||
|  | ||||
|         # NOTE: Hides empty trash and other desired buttons based on context. | ||||
|         if settings.get_trash_files_path() == current_directory: | ||||
|             event_system.emit("show_trash_buttons") | ||||
|         else: | ||||
|             event_system.emit("hide_trash_buttons") | ||||
|  | ||||
|         # 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          = event_system.emit_and_await("format_to_uris", (state.store, state.wid, state.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 WindowException as e: | ||||
|                     logger.debug(repr(e)) | ||||
|  | ||||
|             formatted_size = 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.is_hiding_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") | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -16,6 +15,7 @@ class ContextMenuWidget(Gtk.Menu): | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(ContextMenuWidget, self).__init__() | ||||
|  | ||||
|         self.builder            = settings.get_builder() | ||||
|         self._builder           = Gtk.Builder() | ||||
|         self._context_menu_data = settings.get_context_menu_data() | ||||
| @@ -32,22 +32,14 @@ class ContextMenuWidget(Gtk.Menu): | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("show_context_menu", self.show_context_menu) | ||||
|         event_system.subscribe("hide_context_menu", self.hide_context_menu) | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 logger.debug(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         self.build_context_menu() | ||||
|  | ||||
|     def _emit(self, menu_item, type): | ||||
|         event_system.emit("do_action_from_menu_controls", type) | ||||
|  | ||||
|  | ||||
|     def make_submenu(self, name, data, keys): | ||||
|         menu      = Gtk.Menu() | ||||
| @@ -94,9 +86,6 @@ class ContextMenuWidget(Gtk.Menu): | ||||
|         if plugins_entry: | ||||
|             self.builder.expose_object("context_menu_plugins", plugins_entry.get_submenu()) | ||||
|  | ||||
|     def _emit(self, menu_item, type): | ||||
|         event_system.emit("do_action_from_menu_controls", type) | ||||
|  | ||||
|     def show_context_menu(self, widget=None, eve=None): | ||||
|         self.builder.get_object("context_menu").popup_at_pointer(None) | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -16,14 +15,10 @@ class AboutWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(AboutWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/about_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|         self.about_page = self._builder.get_object("about_page") | ||||
|  | ||||
|         builder.expose_object(f"about_page", self.about_page) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
| @@ -36,21 +31,14 @@ class AboutWidget: | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("show_about_page", self.show_about_page) | ||||
|         event_system.subscribe("hide_about_page", self.hide_about_page) | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 logger.debug(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self.about_page = self._builder.get_object("about_page") | ||||
|         builder.expose_object(f"about_page", self.about_page) | ||||
|  | ||||
|  | ||||
|     def show_about_page(self, widget=None, eve=None): | ||||
|         response   = self.about_page.run() | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -16,16 +15,10 @@ class AppchooserWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(AppchooserWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/appchooser_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|         self._appchooser_menu   = self._builder.get_object("appchooser_menu") | ||||
|         self._appchooser_widget = self._builder.get_object("appchooser_widget") | ||||
|  | ||||
|         builder.expose_object(f"appchooser_menu", self._appchooser_menu) | ||||
|         builder.expose_object(f"appchooser_widget", self._appchooser_widget) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
| @@ -39,21 +32,17 @@ class AppchooserWidget: | ||||
|         event_system.subscribe("show_appchooser_menu", self.show_appchooser_menu) | ||||
|         event_system.subscribe("hide_appchooser_menu", self.hide_appchooser_menu) | ||||
|         event_system.subscribe("run_appchooser_launch", self.run_appchooser_launch) | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 print(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self._appchooser_menu   = self._builder.get_object("appchooser_menu") | ||||
|         self._appchooser_widget = self._builder.get_object("appchooser_widget") | ||||
|  | ||||
|         builder.expose_object(f"appchooser_menu", self._appchooser_menu) | ||||
|         builder.expose_object(f"appchooser_widget", self._appchooser_widget) | ||||
|  | ||||
|  | ||||
|     def show_appchooser_menu(self, widget=None, eve=None): | ||||
|         response = self._appchooser_menu.run() | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -17,12 +16,27 @@ class FileExistsWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(FileExistsWidget, self).__init__() | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/file_exists_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/file_exists_ui.glade" | ||||
|         self._builder = Gtk.Builder() | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         self._load_widgets() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         ... | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("setup_exists_data", self.setup_exists_data) | ||||
|         event_system.subscribe("show_exists_page", self.show_exists_page) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         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_diff_from   = self._builder.get_object("exists_file_diff_from") | ||||
| @@ -38,33 +52,6 @@ class FileExistsWidget: | ||||
|         builder.expose_object(f"exists_file_field", self._exists_file_field) | ||||
|         builder.expose_object(f"exists_file_rename_bttn", self._exists_file_rename_bttn) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         self._load_widgets() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         ... | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("setup_exists_data", self.setup_exists_data) | ||||
|         event_system.subscribe("show_exists_page", self.show_exists_page) | ||||
|  | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 logger.debug(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|  | ||||
|     def show_exists_page(self, widget=None, eve=None): | ||||
|         response = self.file_exists_dialog.run() | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -17,20 +16,17 @@ class MessageWidget(Gtk.MessageDialog): | ||||
|     def __init__(self): | ||||
|         super(MessageWidget, self).__init__() | ||||
|  | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         self._load_widgets() | ||||
|  | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.type = Gtk.MessageType.WARNING | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         ... | ||||
|  | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         message_area = self.get_message_area() | ||||
|         message_area.get_children()[0].set_label("Alert!") | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -18,18 +17,10 @@ class NewFileWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(NewFileWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/new_file_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|         self._new_file_menu   = self._builder.get_object("new_file_menu") | ||||
|         self._new_fname_field = self._builder.get_object("new_fname_field") | ||||
|         self._new_file_toggle_type = self._builder.get_object("new_file_toggle_type") | ||||
|  | ||||
|         builder.expose_object(f"new_file_menu", self._new_file_menu) | ||||
|         builder.expose_object(f"new_fname_field", self._new_fname_field) | ||||
|         builder.expose_object(f"new_file_toggle_type", self._new_file_toggle_type) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
| @@ -42,21 +33,19 @@ class NewFileWidget: | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("show_new_file_menu", self.show_new_file_menu) | ||||
|         event_system.subscribe("hide_new_file_menu", self.hide_new_file_menu) | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 print(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self._new_file_menu   = self._builder.get_object("new_file_menu") | ||||
|         self._new_fname_field = self._builder.get_object("new_fname_field") | ||||
|         self._new_file_toggle_type = self._builder.get_object("new_file_toggle_type") | ||||
|  | ||||
|         builder.expose_object(f"new_file_menu", self._new_file_menu) | ||||
|         builder.expose_object(f"new_fname_field", self._new_fname_field) | ||||
|         builder.expose_object(f"new_file_toggle_type", self._new_file_toggle_type) | ||||
|  | ||||
|  | ||||
|     def show_new_file_menu(self, widget=None, eve=None): | ||||
|         if widget: | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -18,18 +17,10 @@ class RenameWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(RenameWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/rename_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|         self._rename_file_menu     = self._builder.get_object("rename_file_menu") | ||||
|         self._rename_fname         = self._builder.get_object("rename_fname") | ||||
|         self._file_to_rename_label = self._builder.get_object("file_to_rename_label") | ||||
|  | ||||
|         builder.expose_object(f"rename_file_menu", self._rename_file_menu) | ||||
|         builder.expose_object(f"rename_fname", self._rename_fname) | ||||
|         builder.expose_object(f"file_to_rename_label", self._file_to_rename_label) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
| @@ -42,21 +33,19 @@ class RenameWidget: | ||||
|     def _setup_signals(self): | ||||
|         event_system.subscribe("show_rename_file_menu", self.show_rename_file_menu) | ||||
|         event_system.subscribe("hide_rename_file_menu", self.hide_rename_file_menu) | ||||
|  | ||||
|         classes  = [self] | ||||
|         handlers = {} | ||||
|         for c in classes: | ||||
|             methods = None | ||||
|             try: | ||||
|                 methods = inspect.getmembers(c, predicate=inspect.ismethod) | ||||
|                 handlers.update(methods) | ||||
|             except Exception as e: | ||||
|                 logger.debug(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|         settings.register_signals_to_builder([self,], self._builder) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self._rename_file_menu     = self._builder.get_object("rename_file_menu") | ||||
|         self._rename_fname         = self._builder.get_object("rename_fname") | ||||
|         self._file_to_rename_label = self._builder.get_object("file_to_rename_label") | ||||
|  | ||||
|         builder.expose_object(f"rename_file_menu", self._rename_file_menu) | ||||
|         builder.expose_object(f"rename_fname", self._rename_fname) | ||||
|         builder.expose_object(f"file_to_rename_label", self._file_to_rename_label) | ||||
|  | ||||
|  | ||||
|     def show_rename_file_menu(self, widget=None, eve=None): | ||||
|         if widget: | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
| import gc | ||||
|  | ||||
| # Lib imports | ||||
| @@ -17,14 +16,10 @@ class SaveLoadWidget: | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(SaveLoadWidget, self).__init__() | ||||
|  | ||||
|         _GLADE_FILE   = f"{settings.get_ui_widgets_path()}/save_load_ui.glade" | ||||
|         builder       = settings.get_builder() | ||||
|         self._builder = Gtk.Builder() | ||||
|  | ||||
|         self._builder.add_from_file(_GLADE_FILE) | ||||
|         self.save_load_dialog = self._builder.get_object("save_load_dialog") | ||||
|  | ||||
|         builder.expose_object(f"save_load_dialog", self.save_load_dialog) | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
| @@ -38,7 +33,10 @@ class SaveLoadWidget: | ||||
|         event_system.subscribe("save_load_session", self.save_load_session) | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         ... | ||||
|         builder = settings.get_builder() | ||||
|  | ||||
|         self.save_load_dialog = self._builder.get_object("save_load_dialog") | ||||
|         builder.expose_object(f"save_load_dialog", self.save_load_dialog) | ||||
|  | ||||
|  | ||||
|     def save_load_session(self, action="save_session"): | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| """ | ||||
|     FileView module | ||||
| """ | ||||
| @@ -1,71 +0,0 @@ | ||||
| # Python imports | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| from gi.repository import Gtk | ||||
|  | ||||
| # Application imports | ||||
| from shellfm.windows.tabs.tab import Tab | ||||
| from .icon_view import IconView | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class FileView(Gtk.ScrolledWindow): | ||||
|     """docstring for FileView.""" | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(FileView, self).__init__() | ||||
|         self.tab_state  = Tab() | ||||
|         self.icon_view  = IconView(self.tab_state) | ||||
|         self.tab_widget = self.create_tab_widget() | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|  | ||||
|         self.add(self.icon_view) | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_hexpand(True) | ||||
|         self.set_vexpand(True) | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         # self.connect("update-tab-title", self._update_tab_title) | ||||
|         ... | ||||
|  | ||||
|     def _update_tab_title(self, widget=None, eve=None): | ||||
|         label = self.tab_widget.get_children()[0] | ||||
|         label.set_label(f"{self.tab_state.get_end_of_path()}") | ||||
|         label.set_width_chars( len(self.tab_state.get_end_of_path()) ) | ||||
|  | ||||
|     def set_path(self, path): | ||||
|         if path: | ||||
|             self.tab_state.set_path(path) | ||||
|             self.icon_view.load_store() | ||||
|             self._update_tab_title() | ||||
|  | ||||
|     def create_tab_widget(self): | ||||
|         button_box = Gtk.ButtonBox() | ||||
|         label      = Gtk.Label() | ||||
|         close      = Gtk.Button() | ||||
|         icon       = Gtk.Image(stock=Gtk.STOCK_CLOSE) | ||||
|  | ||||
|         label.set_label(f"{self.tab_state.get_end_of_path()}") | ||||
|         label.set_width_chars(len(self.tab_state.get_end_of_path())) | ||||
|         label.set_xalign(0.0) | ||||
|  | ||||
|         close.add(icon) | ||||
|         button_box.add(label) | ||||
|         button_box.add(close) | ||||
|  | ||||
|         close.connect("released", self.close_tab) | ||||
|  | ||||
|         button_box.show_all() | ||||
|         return button_box | ||||
|  | ||||
|  | ||||
|     def close_tab(self, widget, eve=None): | ||||
|         self.get_parent().emit('close-view', (self,)) | ||||
| @@ -1,149 +0,0 @@ | ||||
| # Python imports | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| from gi.repository import Gtk | ||||
|  | ||||
| # Application imports | ||||
| from .file_view import FileView | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class FilesWidget(Gtk.Notebook): | ||||
|     """docstring for FilesWidget.""" | ||||
|  | ||||
|     ccount = 0 | ||||
|  | ||||
|     def __new__(cls, *args, **kwargs): | ||||
|         obj        = super(FilesWidget, cls).__new__(cls) | ||||
|         cls.ccount += 1 | ||||
|  | ||||
|         return obj | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(FilesWidget, self).__init__() | ||||
|  | ||||
|         self.set_group_name("file_window") | ||||
|  | ||||
|         self.NAME = f"window_{self.ccount}" | ||||
|         builder   = settings.get_builder() | ||||
|         builder.expose_object(self.NAME, self) | ||||
|  | ||||
|         self._add_action_widgets() | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|  | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_scrollable(True) | ||||
|         self.set_show_tabs(True) | ||||
|         self.set_show_border(False) | ||||
|         self.set_hexpand(True) | ||||
|  | ||||
|         self.set_margin_top(5) | ||||
|         self.set_margin_bottom(5) | ||||
|         self.set_margin_start(5) | ||||
|         self.set_margin_end(5) | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         # self.connect("close-view", self.close_view) | ||||
|         event_system.subscribe("load-window-state", self.load_window_state) | ||||
|  | ||||
|     def _add_action_widgets(self): | ||||
|         start_box = Gtk.Box() | ||||
|         end_box   = Gtk.Box() | ||||
|  | ||||
|         search = Gtk.SearchEntry() | ||||
|         search.set_placeholder_text("Search...") | ||||
|         search.connect("changed", self._do_query) | ||||
|  | ||||
|         home_btn = Gtk.Button() | ||||
|         home_btn.set_image( Gtk.Image.new_from_icon_name("gtk-home", 4) ) | ||||
|         home_btn.set_always_show_image(True) | ||||
|         home_btn.connect("released", self.do_action, ("go_home_dir")) | ||||
|  | ||||
|         up_btn = Gtk.Button() | ||||
|         up_btn.set_image( Gtk.Image.new_from_icon_name("up", 4) ) | ||||
|         up_btn.set_always_show_image(True) | ||||
|         up_btn.connect("released", self.do_action, ("go_up_dir")) | ||||
|  | ||||
|         refresh_btn = Gtk.Button() | ||||
|         refresh_btn.set_image( Gtk.Image.new_from_icon_name("gtk-refresh", 4) ) | ||||
|         refresh_btn.set_always_show_image(True) | ||||
|         refresh_btn.connect("released", self.do_action, ("refresh_dir")) | ||||
|  | ||||
|         add_btn = Gtk.Button() | ||||
|         add_btn.set_image( Gtk.Image.new_from_icon_name("add", 4) ) | ||||
|         add_btn.set_always_show_image(True) | ||||
|         add_btn.connect("released", self.create_view) | ||||
|  | ||||
|         start_box.add(home_btn) | ||||
|         start_box.add(add_btn) | ||||
|         end_box.add(search) | ||||
|         end_box.add(up_btn) | ||||
|         end_box.add(refresh_btn) | ||||
|  | ||||
|         start_box.show_all() | ||||
|         end_box.show_all() | ||||
|  | ||||
|         # PACKTYPE: 0 Start, 1 = End | ||||
|         self.set_action_widget(start_box, 0) | ||||
|         self.set_action_widget(end_box, 1) | ||||
|  | ||||
|     def _do_query(self, widget): | ||||
|         text = widget.get_text() | ||||
|         page = self.get_nth_page( self.get_current_page() ) | ||||
|         page.icon_view.search_filter(text) | ||||
|  | ||||
|  | ||||
|     def load_window_state(self, win_name=None, tabs=None): | ||||
|         if win_name == self.NAME: | ||||
|             if len(tabs) > 0: | ||||
|                 for tab in tabs: | ||||
|                     self.create_view() | ||||
|                     self.load_tab(tab) | ||||
|             else: | ||||
|                 self.create_view() | ||||
|  | ||||
|     def create_view(self, widget = None): | ||||
|         file_view = FileView() | ||||
|         index = self.append_page(file_view, file_view.tab_widget) | ||||
|         self.set_current_page(index) | ||||
|  | ||||
|         return file_view | ||||
|  | ||||
|     def load_tab(self, path = None): | ||||
|         if path: | ||||
|             file_view = self.get_nth_page( self.get_current_page() ) | ||||
|             file_view.set_path(path) | ||||
|  | ||||
|  | ||||
|     def do_action(self, widget = None, action = None): | ||||
|         file_view = self.get_nth_page( self.get_current_page() ) | ||||
|  | ||||
|         if action == "refresh_dir": | ||||
|             file_view.icon_view.refresh_dir() | ||||
|  | ||||
|         if action == "go_up_dir": | ||||
|             file_view.icon_view.go_up_dir() | ||||
|  | ||||
|         if action == "go_home_dir": | ||||
|             file_view.icon_view.go_home_dir() | ||||
|  | ||||
|  | ||||
|     def close_view(self, parent, data = None): | ||||
|         widget = data[0] | ||||
|         page   = self.page_num(widget) | ||||
|  | ||||
|         # watcher  = widget.tab_state.get_dir_watcher() | ||||
|         # watcher.cancel() | ||||
|         if self.get_n_pages() > 1: | ||||
|             self.remove_page(page) | ||||
|  | ||||
|         # NOTE: Will prob try and call a window custom signal... | ||||
|         # self.fm_controller.save_state() | ||||
|         # self.set_window_title() | ||||
| @@ -1,146 +0,0 @@ | ||||
| # Python imports | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| gi.require_version('Gdk', '3.0') | ||||
| from gi.repository import Gtk | ||||
| from gi.repository import Gdk | ||||
| from gi.repository import GdkPixbuf | ||||
| from gi.repository import Gio | ||||
|  | ||||
| # Application imports | ||||
| from .signals.icon_view_signals_mixin import IconViewSignalsMixin | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class IconView(IconViewSignalsMixin, Gtk.FlowBox): | ||||
|     """docstring for IconView.""" | ||||
|  | ||||
|     def __init__(self, _tab_state): | ||||
|         super(IconView, self).__init__() | ||||
|         self.tab_state      = _tab_state | ||||
|         self.selected_files = [] | ||||
|         self.icon_theme     = settings.get_icon_theme() | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         # self._setup_dnd() | ||||
|         self.load_store() | ||||
|  | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|     def _emmit_signal_to_file_view(self, signal_type): | ||||
|         self.get_parent().get_parent().emit(signal_type, None) | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_selection_mode(Gtk.SelectionMode.MULTIPLE) | ||||
|         self.set_valign(Gtk.Align.START) | ||||
|         self.set_column_spacing(15) | ||||
|         self.set_row_spacing(15) | ||||
|         self.set_homogeneous(True) | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         self.set_activate_on_single_click(False) | ||||
|         self.connect("child-activated", self.icon_double_click) | ||||
|  | ||||
|         # self.connect("drag-data-get",        self.on_drag_set) | ||||
|         # self.connect("drag-data-received",   self.on_drag_data_received) | ||||
|         # self.connect("drag-motion",          self.on_drag_motion) | ||||
|  | ||||
|  | ||||
|     # NOTE: This gets called by a txt box which then shows/hides the flowbox child | ||||
|     #       https://stackoverflow.com/questions/55828169/how-to-filter-gtk-flowbox-children-with-gtk-entrysearch | ||||
|     def search_filter(self, text): | ||||
|         def filter_func(fb_child, text): | ||||
|             if text.lower() in fb_child.get_name().lower(): | ||||
|                 return True | ||||
|             else: | ||||
|                 return False | ||||
|  | ||||
|         self.set_filter_func(filter_func, text) | ||||
|  | ||||
|  | ||||
|     def _setup_dnd(self): | ||||
|         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 | ||||
|         self.enable_model_drag_dest(targets, action) | ||||
|         self.enable_model_drag_source(0, targets, action) | ||||
|  | ||||
|     def _clear_children(self, widget: type) -> None: | ||||
|         ''' Clear children of a gtk widget. ''' | ||||
|         for child in widget.get_children(): | ||||
|             widget.remove(child) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| # class IconView(IconViewSignalsMixin, Gtk.IconView): | ||||
| #     """docstring for IconView.""" | ||||
| # | ||||
| #     def __init__(self, _tab_state): | ||||
| #         super(IconView, self).__init__() | ||||
| #         self.store          = None | ||||
| #         self.tab_state      = _tab_state | ||||
| #         self.selected_files = [] | ||||
| #         self.icon_theme     = Gtk.IconTheme.get_default() | ||||
| # | ||||
| #         self._setup_store() | ||||
| #         self._setup_styling() | ||||
| #         self._setup_signals() | ||||
| #         self._setup_dnd() | ||||
| #         self.load_store() | ||||
| # | ||||
| #         self.show_all() | ||||
| # | ||||
| # | ||||
| #     def _setup_store(self): | ||||
| #         self.store = Gtk.ListStore(GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, str or None) | ||||
| #         self.set_model(self.store) | ||||
| #         self.set_pixbuf_column(0) | ||||
| #         self.set_text_column(1) | ||||
| # | ||||
| #     def _setup_styling(self): | ||||
| #         self.set_item_orientation(1) | ||||
| #         self.set_selection_mode(3) | ||||
| #         self.set_item_width(96) | ||||
| #         self.set_item_padding(8) | ||||
| #         self.set_margin(12) | ||||
| #         self.set_row_spacing(18) | ||||
| #         self.set_columns(-1) | ||||
| #         self.set_spacing(12) | ||||
| #         self.set_column_spacing(18) | ||||
| # | ||||
| #     def _setup_signals(self): | ||||
| #         # self.connect("button_release_event", self.icon_single_click) | ||||
| #         self.connect("item-activated",       self.icon_double_click) | ||||
| #         self.connect("selection-changed",    self.set_selected_items) | ||||
| #         # self.connect("drag-data-get",        self.on_drag_set) | ||||
| #         # self.connect("drag-data-received",   self.on_drag_data_received) | ||||
| #         # self.connect("drag-motion",          self.on_drag_motion) | ||||
| #         pass | ||||
| # | ||||
| #     def _setup_dnd(self): | ||||
| #         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 | ||||
| #         self.enable_model_drag_dest(targets, action) | ||||
| #         self.enable_model_drag_source(0, targets, action) | ||||
| # | ||||
| #     def set_selected_items(self, icons_grid): | ||||
| #         self.selected_files = self.get_selected_items() | ||||
| @@ -1,3 +0,0 @@ | ||||
| """ | ||||
|     Signals module | ||||
| """ | ||||
| @@ -1,183 +0,0 @@ | ||||
| # Python imports | ||||
| import os | ||||
| import traceback | ||||
| import threading | ||||
| import subprocess | ||||
| import time | ||||
| from os.path import isdir | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
|  | ||||
| gi.require_version("Gtk", "3.0") | ||||
| gi.require_version('Gdk', '3.0') | ||||
| from gi.repository import Gtk | ||||
| from gi.repository import GLib | ||||
| from gi.repository import Gdk | ||||
| from gi.repository import GdkPixbuf | ||||
| from gi.repository import Gio | ||||
|  | ||||
|  | ||||
| # Application imports | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class FileView(Gtk.Box): | ||||
|     """docstring for FileView.""" | ||||
|  | ||||
|     def __init__(self, _icon = None, _label = None): | ||||
|         super(FileView, self).__init__() | ||||
|         self.icon  = None | ||||
|         self.label = _label | ||||
|  | ||||
|         self.label.set_line_wrap(True) | ||||
|         self.label.set_selectable(True) | ||||
|         self.label.set_max_width_chars(20) | ||||
|         self.label.set_justify(2) | ||||
|         self.label.set_line_wrap_mode(2) | ||||
|  | ||||
|         self.add(self.label) | ||||
|         self.set_orientation(1) | ||||
|  | ||||
|         self.show_all() | ||||
|  | ||||
|     def set_img(self, img): | ||||
|         self.icon  = img | ||||
|         self.add(img) | ||||
|         self.reorder_child(self.icon, 0) | ||||
|  | ||||
|  | ||||
|  | ||||
| class IconViewSignalsMixin: | ||||
|     """docstring for WidgetMixin""" | ||||
|  | ||||
|     def load_store(self): | ||||
|         self._clear_children(self) | ||||
|         self.search_filter("") | ||||
|  | ||||
|         dir   = self.tab_state.get_current_directory() | ||||
|         files = self.tab_state.get_files() | ||||
|  | ||||
|         for i, file in enumerate(files): | ||||
|             label = Gtk.Label(label=file[0]) | ||||
|             child = Gtk.FlowBoxChild() | ||||
|             child.set_name(file[0]) | ||||
|  | ||||
|             file_view = FileView(_label=label) | ||||
|             child.add( file_view ) | ||||
|             self.add(child) | ||||
|             self.create_icon(file_view, dir, file[0]) | ||||
|  | ||||
|     @threaded | ||||
|     def create_icon(self, file_view, dir, file): | ||||
|         icon = self.tab_state.create_icon(dir, file) | ||||
|         GLib.idle_add(self.update_store, *(file_view, icon, dir, file,)) | ||||
|  | ||||
|     def update_store(self, file_view, icon,  dir, file): | ||||
|         if not icon: | ||||
|             path = f"{dir}/{file}" | ||||
|             icon = self.get_system_thumbnail(path, self.tab_state.sys_icon_wh[0]) | ||||
|  | ||||
|         if not icon: | ||||
|             icon = GdkPixbuf.Pixbuf.new_from_file(self.tab_state.DEFAULT_ICON) | ||||
|  | ||||
|         img   = Gtk.Image.new_from_pixbuf(icon) | ||||
|         img.show() | ||||
|         file_view.set_img(img) | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|     def get_system_thumbnail(self, filename, size): | ||||
|         try: | ||||
|             gio_file  = Gio.File.new_for_path(filename) | ||||
|             info      = gio_file.query_info('standard::icon' , 0, None) | ||||
|             icon      = info.get_icon().get_names()[0] | ||||
|             icon_path = self.icon_theme.lookup_icon(icon , size , 0).get_filename() | ||||
|  | ||||
|             return GdkPixbuf.Pixbuf.new_from_file(icon_path) | ||||
|         except Exception: | ||||
|             ... | ||||
|  | ||||
|         return None | ||||
|  | ||||
|  | ||||
|     def icon_double_click(self, icons_grid, item, data=None): | ||||
|         try: | ||||
|             file_view  = item.get_children()[0] | ||||
|             file_name  = file_view.label.get_label() | ||||
|             dir        = self.tab_state.get_current_directory() | ||||
|             file       = f"{dir}/{file_name}" | ||||
|  | ||||
|             if isdir(file): | ||||
|                 self.tab_state.set_path(file) | ||||
|                 self.load_store() | ||||
|                 self._emmit_signal_to_file_view('update-tab-title') | ||||
|             else: | ||||
|                 event_system.emit("open_files", (self, file)) | ||||
|         except Exception as e: | ||||
|             traceback.print_exc() | ||||
|  | ||||
|  | ||||
|     def go_up_dir(self): | ||||
|         self.tab_state.pop_from_path() | ||||
|         self.load_store() | ||||
|         self._emmit_signal_to_file_view('update-tab-title') | ||||
|  | ||||
|     def go_home_dir(self): | ||||
|         self.tab_state.set_to_home() | ||||
|         self.load_store() | ||||
|         self._emmit_signal_to_file_view('update-tab-title') | ||||
|  | ||||
|     def go_to_path(self, path): | ||||
|         self.tab_state.set_path(path) | ||||
|         self.load_store() | ||||
|         self._emmit_signal_to_file_view('update-tab-title') | ||||
|  | ||||
|     def refresh_dir(self): | ||||
|         self.tab_state.load_directory() | ||||
|         self.load_store() | ||||
|  | ||||
|     # def 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 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 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) | ||||
| @@ -29,8 +29,6 @@ class IconGridWidget(Gtk.IconView): | ||||
|  | ||||
|         self.show_all() | ||||
|  | ||||
|     def get_store(self): | ||||
|         return self._store | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_pixbuf_column(0) | ||||
| @@ -74,3 +72,7 @@ class IconGridWidget(Gtk.IconView): | ||||
|         action           = Gdk.DragAction.COPY | ||||
|         self.enable_model_drag_dest(targets, action) | ||||
|         self.enable_model_drag_source(0, targets, action) | ||||
|  | ||||
|  | ||||
|     def get_store(self): | ||||
|         return self._store | ||||
|   | ||||
| @@ -16,6 +16,7 @@ class IOWidget(Gtk.Box): | ||||
|  | ||||
|     def __init__(self, action, file): | ||||
|         super(IOWidget, self).__init__() | ||||
|  | ||||
|         self._action    = action | ||||
|         self._file      = file | ||||
|         self._basename  = self._file.get_basename() | ||||
| @@ -59,6 +60,7 @@ class IOWidget(Gtk.Box): | ||||
|         self.add(label) | ||||
|         self.add(stats) | ||||
|  | ||||
|  | ||||
|     def do_cancel(self, widget, container, eve): | ||||
|         logger.info(f"Canceling: [{self._action}] of {self._basename} ...") | ||||
|         eve.cancel() | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -16,8 +15,8 @@ class IOPopupWidget(Gtk.Popover): | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(IOPopupWidget, self).__init__() | ||||
|         self._builder = settings.get_builder() | ||||
|  | ||||
|         self._builder = settings.get_builder() | ||||
|         self._builder.expose_object(f"io_popup", self) | ||||
|  | ||||
|         self._setup_styling() | ||||
| @@ -42,5 +41,6 @@ class IOPopupWidget(Gtk.Popover): | ||||
|         self._builder.expose_object(f"io_list", vbox) | ||||
|         self.add(vbox) | ||||
|  | ||||
|  | ||||
|     def show_io_popup(self, widget=None, eve=None): | ||||
|         self.popup() | ||||
|   | ||||
| @@ -20,9 +20,10 @@ class MessagePopupWidget(Gtk.Popover): | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(MessagePopupWidget, self).__init__() | ||||
|         self.builder = settings.get_builder() | ||||
|  | ||||
|         self.builder = settings.get_builder() | ||||
|         self.builder.expose_object(f"message_popup_widget", self) | ||||
|  | ||||
|         self._message_buffer = None | ||||
|  | ||||
|         self._setup_styling() | ||||
| @@ -40,7 +41,6 @@ class MessagePopupWidget(Gtk.Popover): | ||||
|         event_system.subscribe("show_messages_popup", self.show_messages_popup) | ||||
|         event_system.subscribe("hide_messages_popup", self.hide_messages_popup) | ||||
|  | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         self._message_buffer = Gtk.TextBuffer() | ||||
|         vbox                 = Gtk.Box() | ||||
| @@ -66,6 +66,7 @@ class MessagePopupWidget(Gtk.Popover): | ||||
|         vbox.add(scroll_window) | ||||
|         self.add(vbox) | ||||
|  | ||||
|  | ||||
|     def show_messages_popup(self): | ||||
|         self.popup() | ||||
|  | ||||
|   | ||||
| @@ -15,8 +15,8 @@ class PathMenuPopupWidget(Gtk.Popover): | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(PathMenuPopupWidget, self).__init__() | ||||
|         self.builder = settings.get_builder() | ||||
|  | ||||
|         self.builder = settings.get_builder() | ||||
|         self.builder.expose_object(f"path_menu", self) | ||||
|  | ||||
|         self._setup_styling() | ||||
| @@ -50,6 +50,7 @@ class PathMenuPopupWidget(Gtk.Popover): | ||||
|         scroll_window.show_all() | ||||
|         self.add(scroll_window) | ||||
|  | ||||
|  | ||||
|     def show_path_menu(self, widget=None, eve=None): | ||||
|         self.popup() | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| # Python imports | ||||
| import inspect | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| @@ -16,8 +15,8 @@ class PluginsPopupWidget(Gtk.Popover): | ||||
|  | ||||
|     def __init__(self): | ||||
|         super(PluginsPopupWidget, self).__init__() | ||||
|         self.builder = settings.get_builder() | ||||
|  | ||||
|         self.builder = settings.get_builder() | ||||
|         self.builder.expose_object(f"plugin_controls", self) | ||||
|  | ||||
|         self._setup_styling() | ||||
| @@ -43,6 +42,7 @@ class PluginsPopupWidget(Gtk.Popover): | ||||
|         self.builder.expose_object(f"plugin_control_list", vbox) | ||||
|         self.add(vbox) | ||||
|  | ||||
|  | ||||
|     def show_plugins_popup(self, widget=None, eve=None): | ||||
|         self.popup() | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,7 @@ class TabHeaderWidget(Gtk.ButtonBox): | ||||
|  | ||||
|     def __init__(self, tab, close_tab): | ||||
|         super(TabHeaderWidget, self).__init__() | ||||
|  | ||||
|         self._tab       = tab | ||||
|         self._close_tab = close_tab # NOTE: Close method in tab_mixin | ||||
|  | ||||
| @@ -22,6 +23,7 @@ class TabHeaderWidget(Gtk.ButtonBox): | ||||
|         self._setup_signals() | ||||
|         self._load_widgets() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_orientation(0) | ||||
|  | ||||
|   | ||||
| @@ -37,7 +37,8 @@ class Window(Gtk.ApplicationWindow): | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_default_size(1670, 830) | ||||
|         self.set_default_size(settings.get_main_window_width(), | ||||
|                                 settings.get_main_window_height()) | ||||
|         self.set_title(f"{app_name}") | ||||
|         self.set_icon_from_file( settings.get_window_icon() ) | ||||
|         self.set_gravity(5)  # 5 = CENTER | ||||
| @@ -45,11 +46,6 @@ class Window(Gtk.ApplicationWindow): | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         self.connect("delete-event", self._tear_down) | ||||
|  | ||||
|         # self.connect("focus-out-event", self._controller.unset_keys_and_data) | ||||
|         # self.connect("key-press-event", self._controller.on_global_key_press_controller) | ||||
|         # self.connect("key-release-event", self._controller.on_global_key_release_controller) | ||||
|  | ||||
|         GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down) | ||||
|  | ||||
|     def _subscribe_to_events(self): | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| """ | ||||
|     Factories Module | ||||
| """ | ||||
| @@ -1,33 +0,0 @@ | ||||
| # Python imports | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| from gi.repository import Gtk | ||||
|  | ||||
| # Application imports | ||||
| from core.widgets.fm_widget.files_widget import FilesWidget | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| class SplitViewWidget(Gtk.Paned): | ||||
|     def __init__(self): | ||||
|         super(SplitViewWidget, self).__init__() | ||||
|  | ||||
|         self._setup_styling() | ||||
|         self._setup_signals() | ||||
|         self._load_widgets() | ||||
|  | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|     def _setup_styling(self): | ||||
|         self.set_wide_handle(True) | ||||
|  | ||||
|     def _setup_signals(self): | ||||
|         ... | ||||
|  | ||||
|     def _load_widgets(self): | ||||
|         self.pack1(FilesWidget(), resize=False, shrink=False) | ||||
|         self.pack2(FilesWidget(), resize=True, shrink=False) | ||||
| @@ -35,11 +35,11 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): | ||||
|  | ||||
|     def get_icon_image(self, dir, file, full_path): | ||||
|         try: | ||||
|             thumbnl = self._get_system_thumbnail_gtk_thread(full_path, self.sys_icon_wh[0]) | ||||
|             thumbnl = None | ||||
|  | ||||
|             if file.lower().endswith(self.fmeshs):               # 3D Mesh icon | ||||
|                 ... | ||||
|             if file.lower().endswith(self.fvideos):              # Video icon | ||||
|             elif file.lower().endswith(self.fvideos):            # Video icon | ||||
|                 thumbnl = self.create_video_thumbnail(full_path) | ||||
|             elif file.lower().endswith(self.fimages):            # Image Icon | ||||
|                 thumbnl = self.create_scaled_image(full_path) | ||||
| @@ -48,9 +48,12 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): | ||||
|             elif full_path.lower().endswith( ('.desktop',) ):    # .desktop file parsing | ||||
|                 thumbnl = self.find_thumbnail_from_desktop_file(full_path) | ||||
|  | ||||
|             if not thumbnl: | ||||
|                 thumbnl = self._get_system_thumbnail_gtk_thread(full_path, self.sys_icon_wh[0]) | ||||
|                 if not thumbnl: | ||||
|                     raise IconException("No known icons found.") | ||||
|  | ||||
|  | ||||
|             return thumbnl | ||||
|         except IconException: | ||||
|             ... | ||||
|   | ||||
| @@ -46,14 +46,24 @@ class Settings(StartCheckMixin): | ||||
|  | ||||
|         if not os.path.exists(self._DEFAULT_ICONS): | ||||
|             self._DEFAULT_ICONS = f"{self._USR_PATH}/icons" | ||||
|             if not os.path.exists(self._DEFAULT_ICONS): | ||||
|                 raise MissingConfigError("Unable to find the application icons directory.") | ||||
|         if not os.path.exists(self._GLADE_FILE): | ||||
|             self._GLADE_FILE    = f"{self._USR_PATH}/Main_Window.glade" | ||||
|             if not os.path.exists(self._GLADE_FILE): | ||||
|                 raise MissingConfigError("Unable to find the application Glade file.") | ||||
|         if not os.path.exists(self._KEY_BINDINGS_FILE): | ||||
|             self._KEY_BINDINGS_FILE = f"{self._USR_PATH}/key-bindings.json" | ||||
|             if not os.path.exists(self._KEY_BINDINGS_FILE): | ||||
|                 raise MissingConfigError("Unable to find the application Keybindings file.") | ||||
|         if not os.path.exists(self._CSS_FILE): | ||||
|             self._CSS_FILE      = f"{self._USR_PATH}/stylesheet.css" | ||||
|             if not os.path.exists(self._CSS_FILE): | ||||
|                 raise MissingConfigError("Unable to find the application Stylesheet file.") | ||||
|         if not os.path.exists(self._WINDOW_ICON): | ||||
|             self._WINDOW_ICON   = f"{self._USR_PATH}/icons/{app_name.lower()}.png" | ||||
|             if not os.path.exists(self._WINDOW_ICON): | ||||
|                 raise MissingConfigError("Unable to find the application icon.") | ||||
|  | ||||
|  | ||||
|         self._UI_WIDEGTS_PATH  = f"{self._USR_PATH}/ui_widgets" | ||||
| @@ -73,6 +83,8 @@ class Settings(StartCheckMixin): | ||||
|             self._context_menu_data = json.load(file) | ||||
|  | ||||
|         self._main_window   = None | ||||
|         self._main_window_w = 1670 | ||||
|         self._main_window_h = 830 | ||||
|         self._builder       = None | ||||
|  | ||||
|         self._trace_debug   = False | ||||
| @@ -82,7 +94,7 @@ class Settings(StartCheckMixin): | ||||
|         self.load_settings() | ||||
|  | ||||
|  | ||||
|     def register_signals_to_builder(self, classes=None): | ||||
|     def register_signals_to_builder(self, classes=None, builder=None): | ||||
|         handlers = {} | ||||
|  | ||||
|         for c in classes: | ||||
| @@ -93,8 +105,7 @@ class Settings(StartCheckMixin): | ||||
|             except Exception as e: | ||||
|                 print(repr(e)) | ||||
|  | ||||
|         self._builder.connect_signals(handlers) | ||||
|  | ||||
|         builder.connect_signals(handlers) | ||||
|  | ||||
|     def get_monitor_data(self) -> list: | ||||
|         screen = self._main_window.get_screen() | ||||
| @@ -109,6 +120,8 @@ class Settings(StartCheckMixin): | ||||
|     def set_main_window(self, window): self._main_window = window | ||||
|  | ||||
|     def get_main_window(self)       -> Gtk.ApplicationWindow:  return self._main_window | ||||
|     def get_main_window_width(self) -> Gtk.ApplicationWindow:  return self._main_window_w | ||||
|     def get_main_window_height(self) -> Gtk.ApplicationWindow: return self._main_window_h | ||||
|     def get_builder(self)           -> Gtk.Builder:            return self._builder | ||||
|     def get_glade_file(self)        -> str: return self._GLADE_FILE | ||||
|     def get_icon_theme(self)        -> str: return self._ICON_THEME | ||||
|   | ||||
| @@ -790,56 +790,7 @@ | ||||
|       </packing> | ||||
|     </child> | ||||
|     <child> | ||||
|       <object class="GtkStatusbar" id="bottom_status_info"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can-focus">False</property> | ||||
|         <property name="margin-left">10</property> | ||||
|         <property name="margin-right">10</property> | ||||
|         <property name="margin-start">10</property> | ||||
|         <property name="margin-end">10</property> | ||||
|         <property name="margin-top">6</property> | ||||
|         <property name="margin-bottom">6</property> | ||||
|         <property name="spacing">15</property> | ||||
|         <property name="baseline-position">top</property> | ||||
|         <child> | ||||
|           <object class="GtkLabel" id="bottom_size_label"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can-focus">False</property> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">0</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkLabel" id="bottom_file_count_label"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can-focus">False</property> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">1</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkLabel" id="bottom_path_label"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can-focus">False</property> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">2</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|       </object> | ||||
|       <packing> | ||||
|         <property name="expand">False</property> | ||||
|         <property name="fill">True</property> | ||||
|         <property name="position">3</property> | ||||
|       </packing> | ||||
|       <placeholder/> | ||||
|     </child> | ||||
|   </object> | ||||
| </interface> | ||||
|   | ||||
| @@ -0,0 +1,50 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- Generated with glade 3.40.0 --> | ||||
| <interface> | ||||
|   <requires lib="gtk+" version="3.22"/> | ||||
|   <object class="GtkStatusbar" id="bottom_status_info"> | ||||
|     <property name="visible">True</property> | ||||
|     <property name="can-focus">False</property> | ||||
|     <property name="margin-left">10</property> | ||||
|     <property name="margin-right">10</property> | ||||
|     <property name="margin-start">10</property> | ||||
|     <property name="margin-end">10</property> | ||||
|     <property name="margin-top">6</property> | ||||
|     <property name="margin-bottom">6</property> | ||||
|     <property name="spacing">15</property> | ||||
|     <property name="baseline-position">top</property> | ||||
|     <child> | ||||
|       <object class="GtkLabel" id="bottom_size_label"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can-focus">False</property> | ||||
|       </object> | ||||
|       <packing> | ||||
|         <property name="expand">False</property> | ||||
|         <property name="fill">True</property> | ||||
|         <property name="position">0</property> | ||||
|       </packing> | ||||
|     </child> | ||||
|     <child> | ||||
|       <object class="GtkLabel" id="bottom_file_count_label"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can-focus">False</property> | ||||
|       </object> | ||||
|       <packing> | ||||
|         <property name="expand">False</property> | ||||
|         <property name="fill">True</property> | ||||
|         <property name="position">1</property> | ||||
|       </packing> | ||||
|     </child> | ||||
|     <child> | ||||
|       <object class="GtkLabel" id="bottom_path_label"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can-focus">False</property> | ||||
|       </object> | ||||
|       <packing> | ||||
|         <property name="expand">False</property> | ||||
|         <property name="fill">True</property> | ||||
|         <property name="position">2</property> | ||||
|       </packing> | ||||
|     </child> | ||||
|   </object> | ||||
| </interface> | ||||
		Reference in New Issue
	
	Block a user