Exemple #1
0
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
Exemple #2
0
 def __init__(self):
     GObject.GObject.__init__(self)
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self.main_actiongroup = None
     self._state = ComparisonState.Normal
Exemple #3
0
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
Exemple #4
0
 def __init__(self):
     super().__init__()
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self._state = ComparisonState.Normal
Exemple #5
0
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
Exemple #6
0
 def __init__(self) -> None:
     super().__init__()
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self.view_action_group = Gio.SimpleActionGroup()
     self._state = ComparisonState.Normal
Exemple #7
0
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
Exemple #8
0
 def __init__(self):
     GObject.GObject.__init__(self)
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self.main_actiongroup = None
     self._state = STATE_NORMAL
Exemple #9
0
 def __init__(self):
     GObject.GObject.__init__(self)
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self.main_actiongroup = None
     self._state = ComparisonState.Normal
Exemple #10
0
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
Exemple #11
0
 def __init__(self):
     super().__init__()
     self.scheduler = FifoScheduler()
     self.num_panes = 0
     self._state = ComparisonState.Normal