class MeldDoc(LabeledObjectMixin, GObject.GObject): """Base class for documents in the meld application. """ __gsignals__ = { 'file-changed': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_STRING, )), 'create-diff': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)), 'status-changed': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )), 'current-diff-changed': (GObject.SignalFlags.RUN_FIRST, None, ()), 'next-diff-changed': (GObject.SignalFlags.RUN_FIRST, None, (bool, bool)), 'close': (GObject.SignalFlags.RUN_FIRST, None, (bool, )), 'state-changed': (GObject.SignalFlags.RUN_FIRST, None, (int, int)), } def __init__(self): GObject.GObject.__init__(self) self.scheduler = FifoScheduler() self.num_panes = 0 self.main_actiongroup = None self._state = ComparisonState.Normal @property def state(self): return self._state @state.setter def state(self, value): if value == self._state: return self.emit('state-changed', self._state, value) self._state = value def get_comparison(self) -> RecentType: """Get the comparison type and URI(s) being compared""" pass def save(self): pass def save_as(self): pass def stop(self): if self.scheduler.tasks_pending(): self.scheduler.remove_task(self.scheduler.get_current_task()) def _open_files(self, selected, line=0): query_attrs = ",".join((Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) def os_open(path, uri): if not path: return if sys.platform == "win32": subprocess.Popen(["start", path], shell=True) elif sys.platform == "darwin": subprocess.Popen(["open", path]) else: Gtk.show_uri(Gdk.Screen.get_default(), uri, Gtk.get_current_event_time()) def open_cb(source, result, *data): info = source.query_info_finish(result) file_type = info.get_file_type() path, uri = source.get_path(), source.get_uri() if file_type == Gio.FileType.DIRECTORY: os_open(path, uri) elif file_type == Gio.FileType.REGULAR: content_type = info.get_content_type() # FIXME: Content types are broken on Windows with current gio if Gio.content_type_is_a(content_type, "text/plain") or \ sys.platform == "win32": if settings.get_boolean('use-system-editor'): gfile = Gio.File.new_for_path(path) if sys.platform == "win32": handler = gfile.query_default_handler(None) result = handler.launch([gfile], None) else: uri = gfile.get_uri() Gio.AppInfo.launch_default_for_uri(uri, None) else: editor = make_custom_editor_command(path, line) if editor: # TODO: If the editor is badly set up, this fails # silently subprocess.Popen(editor) else: os_open(path, uri) else: os_open(path, uri) else: # TODO: Add some kind of 'failed to open' notification pass for f in [Gio.File.new_for_path(s) for s in selected]: f.query_info_async(query_attrs, 0, GLib.PRIORITY_LOW, None, open_cb, None) def open_external(self): pass def on_refresh_activate(self, *extra): pass def on_find_activate(self, *extra): pass def on_find_next_activate(self, *extra): pass def on_find_previous_activate(self, *extra): pass def on_replace_activate(self, *extra): pass def on_file_changed(self, filename): pass def set_labels(self, lst): pass def on_container_switch_in_event(self, uimanager): """Called when the container app switches to this tab. """ self.ui_merge_id = uimanager.add_ui_from_file(self.ui_file) uimanager.insert_action_group(self.actiongroup, -1) self.popup_menu = uimanager.get_widget("/Popup") action_groups = uimanager.get_action_groups() self.main_actiongroup = [ a for a in action_groups if a.get_name() == "MainActions" ][0] uimanager.ensure_update() if hasattr(self, "focus_pane") and self.focus_pane: self.scheduler.add_task(self.focus_pane.grab_focus) def on_container_switch_out_event(self, uimanager): """Called when the container app switches away from this tab. """ uimanager.remove_action_group(self.actiongroup) uimanager.remove_ui(self.ui_merge_id) self.main_actiongroup = None self.popup_menu = None self.ui_merge_id = None def on_delete_event(self): """Called when the docs container is about to close. A doc normally returns Gtk.ResponseType.OK, but may instead return Gtk.ResponseType.CANCEL to request that the container not delete it. """ return Gtk.ResponseType.OK
def __init__(self): GObject.GObject.__init__(self) self.scheduler = FifoScheduler() self.num_panes = 0 self.main_actiongroup = None self._state = ComparisonState.Normal
class MeldDoc(LabeledObjectMixin, GObject.GObject): """Base class for documents in the meld application. """ @GObject.Signal(name='close') def close_signal(self, exit_code: int) -> None: ... @GObject.Signal(name='create-diff') def create_diff_signal( self, gfiles: object, options: object) -> None: ... @GObject.Signal('file-changed') def file_changed_signal(self, path: str) -> None: ... @GObject.Signal def tab_state_changed(self, old_state: int, new_state: int) -> None: ... def __init__(self): super().__init__() self.scheduler = FifoScheduler() self.num_panes = 0 self._state = ComparisonState.Normal @property def state(self): return self._state @state.setter def state(self, value): if value == self._state: return self.tab_state_changed.emit(self._state, value) self._state = value def get_comparison(self) -> RecentType: """Get the comparison type and URI(s) being compared""" pass def action_stop(self, *args): if self.scheduler.tasks_pending(): self.scheduler.remove_task(self.scheduler.get_current_task()) def _open_files(self, selected, line=0): query_attrs = ",".join((Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) def os_open(path, uri): if not path: return if sys.platform == "win32": subprocess.Popen(["start", path], shell=True) elif sys.platform == "darwin": subprocess.Popen(["open", path]) else: Gtk.show_uri(Gdk.Screen.get_default(), uri, Gtk.get_current_event_time()) def open_cb(source, result, *data): info = source.query_info_finish(result) file_type = info.get_file_type() path, uri = source.get_path(), source.get_uri() if file_type == Gio.FileType.DIRECTORY: os_open(path, uri) elif file_type == Gio.FileType.REGULAR: content_type = info.get_content_type() # FIXME: Content types are broken on Windows with current gio # If we can't access a content type, assume it's text. if not content_type or Gio.content_type_is_a( content_type, "text/plain"): if settings.get_boolean('use-system-editor'): gfile = Gio.File.new_for_path(path) if sys.platform == "win32": handler = gfile.query_default_handler(None) result = handler.launch([gfile], None) else: uri = gfile.get_uri() Gio.AppInfo.launch_default_for_uri( uri, None) else: editor = make_custom_editor_command(path, line) if editor: # TODO: If the editor is badly set up, this fails # silently subprocess.Popen(editor) else: os_open(path, uri) else: os_open(path, uri) else: # TODO: Add some kind of 'failed to open' notification pass for f in [Gio.File.new_for_path(s) for s in selected]: f.query_info_async(query_attrs, 0, GLib.PRIORITY_LOW, None, open_cb, None) def on_file_changed(self, filename): pass def set_labels(self, lst): pass def get_action_state(self, action_name: str): action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return return action.get_state().unpack() def set_action_state(self, action_name: str, state): # TODO: Try to do GLib.Variant things here instead of in callers action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_state(state) def set_action_enabled(self, action_name, enabled): action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_enabled(enabled) def on_container_switch_in_event(self, window): """Called when the container app switches to this tab""" window.insert_action_group( 'view', getattr(self, 'view_action_group', None)) if hasattr(self, "focus_pane") and self.focus_pane: self.scheduler.add_task(self.focus_pane.grab_focus) def on_container_switch_out_event(self, window): """Called when the container app switches away from this tab""" window.insert_action_group('view', None) def on_delete_event(self): """Called when the docs container is about to close. A doc normally returns Gtk.ResponseType.OK, but may instead return Gtk.ResponseType.CANCEL to request that the container not delete it. """ return Gtk.ResponseType.OK
def __init__(self): super().__init__() self.scheduler = FifoScheduler() self.num_panes = 0 self._state = ComparisonState.Normal
class MeldDoc(LabeledObjectMixin, GObject.GObject): """Base class for documents in the meld application. """ @GObject.Signal(name='close') def close_signal(self, exit_code: int) -> None: ... @GObject.Signal(name='create-diff') def create_diff_signal(self, gfiles: object, options: object) -> None: ... @GObject.Signal('file-changed') def file_changed_signal(self, path: str) -> None: ... @GObject.Signal def tab_state_changed(self, old_state: int, new_state: int) -> None: ... def __init__(self) -> None: super().__init__() self.scheduler = FifoScheduler() self.num_panes = 0 self.view_action_group = Gio.SimpleActionGroup() self._state = ComparisonState.Normal @property def state(self) -> ComparisonState: return self._state @state.setter def state(self, value: ComparisonState) -> None: if value == self._state: return self.tab_state_changed.emit(self._state, value) self._state = value def get_comparison(self) -> RecentType: """Get the comparison type and URI(s) being compared""" pass def action_stop(self, *args) -> None: if self.scheduler.tasks_pending(): self.scheduler.remove_task(self.scheduler.get_current_task()) def _open_files(self, selected: Iterable[str], line: int = 0) -> None: query_attrs = ",".join((Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) def os_open(path: str, uri: str): if not path: return if sys.platform == "win32": subprocess.Popen(["start", path], shell=True) elif sys.platform == "darwin": subprocess.Popen(["open", path]) else: Gtk.show_uri(Gdk.Screen.get_default(), uri, Gtk.get_current_event_time()) def open_cb(source, result, *data): info = source.query_info_finish(result) file_type = info.get_file_type() path, uri = source.get_path(), source.get_uri() if file_type == Gio.FileType.DIRECTORY: os_open(path, uri) elif file_type == Gio.FileType.REGULAR: content_type = info.get_content_type() # FIXME: Content types are broken on Windows with current gio # If we can't access a content type, assume it's text. if not content_type or Gio.content_type_is_a( content_type, "text/plain"): if settings.get_boolean('use-system-editor'): gfile = Gio.File.new_for_path(path) if sys.platform == "win32": handler = gfile.query_default_handler(None) result = handler.launch([gfile], None) else: uri = gfile.get_uri() Gio.AppInfo.launch_default_for_uri(uri, None) else: editor = make_custom_editor_command(path, line) if editor: # TODO: If the editor is badly set up, this fails # silently subprocess.Popen(editor) else: os_open(path, uri) else: os_open(path, uri) else: # TODO: Add some kind of 'failed to open' notification pass for f in [Gio.File.new_for_path(s) for s in selected]: f.query_info_async(query_attrs, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, None, open_cb, None) def on_file_changed(self, filename: str): pass def set_labels(self, lst: Sequence[str]) -> None: pass def get_action_state(self, action_name: str): action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return return action.get_state().unpack() def set_action_state(self, action_name: str, state) -> None: # TODO: Try to do GLib.Variant things here instead of in callers action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_state(state) def set_action_enabled(self, action_name: str, enabled: bool) -> None: action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_enabled(enabled) def on_container_switch_in_event(self, window): """Called when the container app switches to this tab""" window.insert_action_group('view', getattr(self, 'view_action_group', None)) if hasattr(self, "focus_pane") and self.focus_pane: self.scheduler.add_task(self.focus_pane.grab_focus) def on_container_switch_out_event(self, window): """Called when the container app switches away from this tab""" window.insert_action_group('view', None) # FIXME: Here and in subclasses, on_delete_event are not real GTK+ # event handlers, and should be renamed. def on_delete_event(self) -> Gtk.ResponseType: """Called when the docs container is about to close. A doc normally returns Gtk.ResponseType.OK, but may instead return Gtk.ResponseType.CANCEL to request that the container not delete it. """ return Gtk.ResponseType.OK
def __init__(self) -> None: super().__init__() self.scheduler = FifoScheduler() self.num_panes = 0 self.view_action_group = Gio.SimpleActionGroup() self._state = ComparisonState.Normal
class MeldDoc(LabeledObjectMixin, GObject.GObject): """Base class for documents in the meld application. """ @GObject.Signal(name='close') def close_signal(self, exit_code: int) -> None: ... @GObject.Signal(name='create-diff') def create_diff_signal(self, gfiles: object, options: object) -> None: ... @GObject.Signal('file-changed') def file_changed_signal(self, path: str) -> None: ... @GObject.Signal def tab_state_changed(self, old_state: int, new_state: int) -> None: ... @GObject.Signal( name='move-diff', flags=GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION, ) def move_diff(self, direction: int) -> None: self.next_diff(direction) def __init__(self) -> None: super().__init__() self.scheduler = FifoScheduler() self.num_panes = 0 self.view_action_group = Gio.SimpleActionGroup() self._state = ComparisonState.Normal @property def state(self) -> ComparisonState: return self._state @state.setter def state(self, value: ComparisonState) -> None: if value == self._state: return self.tab_state_changed.emit(self._state, value) self._state = value def get_comparison(self) -> RecentType: """Get the comparison type and URI(s) being compared""" pass def action_stop(self, *args) -> None: if self.scheduler.tasks_pending(): self.scheduler.remove_task(self.scheduler.get_current_task()) def on_file_changed(self, filename: str): pass def set_labels(self, lst: Sequence[str]) -> None: pass def get_action_state(self, action_name: str): action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return return action.get_state().unpack() def set_action_state(self, action_name: str, state) -> None: # TODO: Try to do GLib.Variant things here instead of in callers action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_state(state) def set_action_enabled(self, action_name: str, enabled: bool) -> None: action = self.view_action_group.lookup_action(action_name) if not action: log.error(f'No action {action_name!r} found') return action.set_enabled(enabled) def on_container_switch_in_event(self, window): """Called when the container app switches to this tab""" window.insert_action_group('view', getattr(self, 'view_action_group', None)) if hasattr(self, "get_filter_visibility"): text, folder, vc = self.get_filter_visibility() else: text, folder, vc = False, False, False if hasattr(self, "get_conflict_visibility"): show_conflict_actions = self.get_conflict_visibility() else: show_conflict_actions = False window.text_filter_button.set_visible(text) window.folder_filter_button.set_visible(folder) window.vc_filter_button.set_visible(vc) window.next_conflict_button.set_visible(show_conflict_actions) window.previous_conflict_button.set_visible(show_conflict_actions) if hasattr(self, "focus_pane") and self.focus_pane: self.scheduler.add_task(self.focus_pane.grab_focus) def on_container_switch_out_event(self, window): """Called when the container app switches away from this tab""" window.insert_action_group('view', None) # FIXME: Here and in subclasses, on_delete_event are not real GTK+ # event handlers, and should be renamed. def on_delete_event(self) -> Gtk.ResponseType: """Called when the docs container is about to close. A doc normally returns Gtk.ResponseType.OK, but may instead return Gtk.ResponseType.CANCEL to request that the container not delete it. """ return Gtk.ResponseType.OK
def __init__(self): GObject.GObject.__init__(self) self.scheduler = FifoScheduler() self.num_panes = 0 self.main_actiongroup = None self._state = STATE_NORMAL
class MeldDoc(LabeledObjectMixin, GObject.GObject): """Base class for documents in the meld application. """ __gsignals__ = { 'file-changed': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_STRING,)), 'create-diff': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)), 'status-changed': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)), 'current-diff-changed': (GObject.SignalFlags.RUN_FIRST, None, ()), 'next-diff-changed': (GObject.SignalFlags.RUN_FIRST, None, (bool, bool)), 'close': (GObject.SignalFlags.RUN_FIRST, None, (bool,)), 'state-changed': (GObject.SignalFlags.RUN_FIRST, None, (int, int)), } def __init__(self): GObject.GObject.__init__(self) self.scheduler = FifoScheduler() self.num_panes = 0 self.main_actiongroup = None self._state = ComparisonState.Normal @property def state(self): return self._state @state.setter def state(self, value): if value == self._state: return self.emit('state-changed', self._state, value) self._state = value def get_comparison(self) -> RecentType: """Get the comparison type and URI(s) being compared""" pass def save(self): pass def save_as(self): pass def stop(self): if self.scheduler.tasks_pending(): self.scheduler.remove_task(self.scheduler.get_current_task()) def _open_files(self, selected, line=0): query_attrs = ",".join((Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) def os_open(path, uri): if not path: return if sys.platform == "win32": subprocess.Popen(["start", path], shell=True) elif sys.platform == "darwin": subprocess.Popen(["open", path]) else: Gtk.show_uri(Gdk.Screen.get_default(), uri, Gtk.get_current_event_time()) def open_cb(source, result, *data): info = source.query_info_finish(result) file_type = info.get_file_type() path, uri = source.get_path(), source.get_uri() if file_type == Gio.FileType.DIRECTORY: os_open(path, uri) elif file_type == Gio.FileType.REGULAR: content_type = info.get_content_type() # FIXME: Content types are broken on Windows with current gio if Gio.content_type_is_a(content_type, "text/plain") or \ sys.platform == "win32": if settings.get_boolean('use-system-editor'): gfile = Gio.File.new_for_path(path) if sys.platform == "win32": handler = gfile.query_default_handler(None) result = handler.launch([gfile], None) else: uri = gfile.get_uri() Gio.AppInfo.launch_default_for_uri( uri, None) else: editor = make_custom_editor_command(path, line) if editor: # TODO: If the editor is badly set up, this fails # silently subprocess.Popen(editor) else: os_open(path, uri) else: os_open(path, uri) else: # TODO: Add some kind of 'failed to open' notification pass for f in [Gio.File.new_for_path(s) for s in selected]: f.query_info_async(query_attrs, 0, GLib.PRIORITY_LOW, None, open_cb, None) def open_external(self): pass def on_refresh_activate(self, *extra): pass def on_find_activate(self, *extra): pass def on_find_next_activate(self, *extra): pass def on_find_previous_activate(self, *extra): pass def on_replace_activate(self, *extra): pass def on_file_changed(self, filename): pass def set_labels(self, lst): pass def on_container_switch_in_event(self, uimanager): """Called when the container app switches to this tab. """ self.ui_merge_id = uimanager.add_ui_from_file(self.ui_file) uimanager.insert_action_group(self.actiongroup, -1) self.popup_menu = uimanager.get_widget("/Popup") action_groups = uimanager.get_action_groups() self.main_actiongroup = [ a for a in action_groups if a.get_name() == "MainActions"][0] uimanager.ensure_update() if hasattr(self, "focus_pane") and self.focus_pane: self.scheduler.add_task(self.focus_pane.grab_focus) def on_container_switch_out_event(self, uimanager): """Called when the container app switches away from this tab. """ uimanager.remove_action_group(self.actiongroup) uimanager.remove_ui(self.ui_merge_id) self.main_actiongroup = None self.popup_menu = None self.ui_merge_id = None def on_delete_event(self): """Called when the docs container is about to close. A doc normally returns Gtk.ResponseType.OK, but may instead return Gtk.ResponseType.CANCEL to request that the container not delete it. """ return Gtk.ResponseType.OK