예제 #1
0
    def __init__(self,
                 fullscreen=False,
                 is_slideshow=slideshow,
                 show_library=False,
                 manga_mode=False,
                 double_page=False,
                 zoom_mode=None,
                 open_path=None,
                 open_page=1):
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)

        # ----------------------------------------------------------------
        # Attributes
        # ----------------------------------------------------------------
        self.is_in_focus = True
        self.is_fullscreen = False
        self.is_double_page = False
        self.is_manga_mode = False
        self.is_virtual_double_page = False  # I.e. a wide image is displayed
        self.width = None
        self.height = None
        self.was_out_of_focus = False
        #: Used to remember if changing to fullscreen enabled 'Hide all'
        self.hide_all_forced = False

        self._waiting_for_redraw = False

        self._image_box = gtk.HBox(False, 2)
        self._main_layout = gtk.Layout()
        self._event_handler = event.EventHandler(self)
        self._vadjust = self._main_layout.get_vadjustment()
        self._hadjust = self._main_layout.get_hadjustment()
        self._vscroll = gtk.VScrollbar(self._vadjust)
        self._hscroll = gtk.HScrollbar(self._hadjust)

        self.filehandler = file_handler.FileHandler(self)
        self.imagehandler = image_handler.ImageHandler(self)
        self.imagehandler.page_available += self._page_available
        self.thumbnailsidebar = thumbbar.ThumbnailSidebar(self)

        self.statusbar = status.Statusbar()
        self.clipboard = clipboard.Clipboard(self)
        self.slideshow = slideshow.Slideshow(self)
        self.cursor_handler = cursor_handler.CursorHandler(self)
        self.enhancer = enhance_backend.ImageEnhancer(self)
        self.lens = lens.MagnifyingLens(self)
        self.osd = osd.OnScreenDisplay(self)
        self.zoom = zoom.ZoomModel()
        self.uimanager = ui.MainUI(self)
        self.menubar = self.uimanager.get_widget('/Menu')
        self.toolbar = self.uimanager.get_widget('/Tool')
        self.popup = self.uimanager.get_widget('/Popup')
        self.actiongroup = self.uimanager.get_action_groups()[0]

        self.left_image = gtk.Image()
        self.right_image = gtk.Image()

        # ----------------------------------------------------------------
        # Setup
        # ----------------------------------------------------------------
        self.set_title(constants.APPNAME)
        self.set_size_request(300, 300)  # Avoid making the window *too* small
        self.resize(prefs['window width'], prefs['window height'])

        # Hook up keyboard shortcuts
        self._event_handler.register_key_events()

        # This is a hack to get the focus away from the toolbar so that
        # we don't activate it with space or some other key (alternative?)
        self.toolbar.set_focus_child(
            self.uimanager.get_widget('/Tool/expander'))
        self.toolbar.set_style(gtk.TOOLBAR_ICONS)
        self.toolbar.set_icon_size(gtk.ICON_SIZE_LARGE_TOOLBAR)

        self._image_box.add(self.left_image)
        self._image_box.add(self.right_image)
        self._image_box.show_all()

        self._main_layout.put(self._image_box, 0, 0)
        self.set_bg_colour(prefs['bg colour'])

        self._vadjust.step_increment = 15
        self._vadjust.page_increment = 1
        self._hadjust.step_increment = 15
        self._hadjust.page_increment = 1

        table = gtk.Table(2, 2, False)
        table.attach(self.thumbnailsidebar, 0, 1, 2, 5, gtk.FILL,
                     gtk.FILL | gtk.EXPAND, 0, 0)

        table.attach(self._main_layout, 1, 2, 2, 3, gtk.FILL | gtk.EXPAND,
                     gtk.FILL | gtk.EXPAND, 0, 0)
        table.attach(self._vscroll, 2, 3, 2, 3, gtk.FILL | gtk.SHRINK,
                     gtk.FILL | gtk.SHRINK, 0, 0)
        table.attach(self._hscroll, 1, 2, 4, 5, gtk.FILL | gtk.SHRINK,
                     gtk.FILL, 0, 0)
        table.attach(self.menubar, 0, 3, 0, 1, gtk.FILL | gtk.SHRINK, gtk.FILL,
                     0, 0)
        table.attach(self.toolbar, 0, 3, 1, 2, gtk.FILL | gtk.SHRINK, gtk.FILL,
                     0, 0)
        table.attach(self.statusbar, 0, 3, 5, 6, gtk.FILL | gtk.SHRINK,
                     gtk.FILL, 0, 0)

        if prefs['default double page'] or double_page:
            self.actiongroup.get_action('double_page').activate()

        if prefs['default manga mode'] or manga_mode:
            self.actiongroup.get_action('manga_mode').activate()

        # Determine zoom mode. If zoom_mode is passed, it overrides
        # the zoom mode preference.
        zoom_actions = {
            constants.ZOOM_MODE_BEST: 'best_fit_mode',
            constants.ZOOM_MODE_WIDTH: 'fit_width_mode',
            constants.ZOOM_MODE_HEIGHT: 'fit_height_mode',
            constants.ZOOM_MODE_SIZE: 'fit_size_mode',
            constants.ZOOM_MODE_MANUAL: 'fit_manual_mode'
        }

        if zoom_mode is not None:
            zoom_action = zoom_actions[zoom_mode]
        else:
            zoom_action = zoom_actions[prefs['zoom mode']]

        if zoom_action == 'fit_manual_mode':
            # This little ugly hack is to get the activate call on
            # 'fit_manual_mode' to actually create an event (and callback).
            # Since manual mode is the default selected radio button action
            # it won't send an event if we activate it when it is already
            # the selected one.
            self.actiongroup.get_action('best_fit_mode').activate()

        self.actiongroup.get_action(zoom_action).activate()

        if prefs['stretch']:
            self.actiongroup.get_action('stretch').activate()

        if prefs['invert smart scroll']:
            self.actiongroup.get_action('invert_scroll').activate()

        if prefs['show toolbar']:
            prefs['show toolbar'] = False
            self.actiongroup.get_action('toolbar').activate()

        if prefs['show menubar']:
            prefs['show menubar'] = False
            self.actiongroup.get_action('menubar').activate()

        if prefs['show statusbar']:
            prefs['show statusbar'] = False
            self.actiongroup.get_action('statusbar').activate()

        if prefs['show scrollbar']:
            prefs['show scrollbar'] = False
            self.actiongroup.get_action('scrollbar').activate()

        if prefs['show thumbnails']:
            prefs['show thumbnails'] = False
            self.actiongroup.get_action('thumbnails').activate()

        if prefs['hide all']:
            prefs['hide all'] = False
            self.actiongroup.get_action('hide all').activate()

        if prefs['keep transformation']:
            prefs['keep transformation'] = False
            self.actiongroup.get_action('keep_transformation').activate()
        else:
            prefs['rotation'] = 0
            prefs['vertical flip'] = False
            prefs['horizontal flip'] = False

        self.actiongroup.get_action('menu_autorotate_width').set_sensitive(
            False)
        self.actiongroup.get_action('menu_autorotate_height').set_sensitive(
            False)

        self.add(table)
        table.show()
        self._main_layout.show()
        self._display_active_widgets()

        self._main_layout.set_events(gtk.gdk.BUTTON1_MOTION_MASK
                                     | gtk.gdk.BUTTON2_MOTION_MASK
                                     | gtk.gdk.BUTTON_PRESS_MASK
                                     | gtk.gdk.BUTTON_RELEASE_MASK
                                     | gtk.gdk.POINTER_MOTION_MASK)

        self._main_layout.drag_dest_set(
            gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 0)],
            gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)

        self.connect('focus-in-event', self.gained_focus)
        self.connect('focus-out-event', self.lost_focus)
        self.connect('delete_event', self.close_program)
        self.connect('key_press_event', self._event_handler.key_press_event)
        self.connect('key_release_event',
                     self._event_handler.key_release_event)
        self.connect('configure_event', self._event_handler.resize_event)

        self._main_layout.connect('button_release_event',
                                  self._event_handler.mouse_release_event)
        self._main_layout.connect('scroll_event',
                                  self._event_handler.scroll_wheel_event)
        self._main_layout.connect('button_press_event',
                                  self._event_handler.mouse_press_event)
        self._main_layout.connect('motion_notify_event',
                                  self._event_handler.mouse_move_event)
        self._main_layout.connect('drag_data_received',
                                  self._event_handler.drag_n_drop_event)

        self.uimanager.set_sensitivities()
        self.show()

        # If MComix is set to start in fullscreen mode, it
        # cannot switch to windowed mode on Win32 unless this
        # condition is set to trigger after normal show().
        if prefs['default fullscreen'] or fullscreen:
            self.actiongroup.get_action('fullscreen').activate()

        if prefs['previous quit was quit and save']:
            fileinfo = self.filehandler.read_fileinfo_file()

            if fileinfo != None:

                open_path = fileinfo[0]
                open_page = fileinfo[1] + 1

        prefs['previous quit was quit and save'] = False

        if open_path is not None:
            self.filehandler.open_file(open_path, open_page)

        if is_slideshow:
            self.actiongroup.get_action('slideshow').activate()

        if show_library:
            self.actiongroup.get_action('library').activate()
예제 #2
0
    def __init__(self,
                 fullscreen=False,
                 is_slideshow=slideshow,
                 show_library=False,
                 manga_mode=False,
                 double_page=False,
                 zoom_mode=None,
                 open_path=None,
                 open_page=1):
        super(MainWindow, self).__init__(type=Gtk.WindowType.TOPLEVEL)

        # ----------------------------------------------------------------
        # Attributes
        # ----------------------------------------------------------------
        # Used to detect window fullscreen state transitions.
        self.was_fullscreen = False
        self.is_manga_mode = False
        self.previous_size = (None, None)
        self.was_out_of_focus = False
        #: Used to remember if changing to fullscreen enabled 'Hide all'
        self.hide_all_forced = False
        # Remember last scroll destination.
        self._last_scroll_destination = constants.SCROLL_TO_START

        self.layout = _dummy_layout()
        self._spacing = 2
        self._waiting_for_redraw = False

        self._image_box = Gtk.HBox(
            homogeneous=False, spacing=2)  # XXX transitional(kept for osd.py)
        self._main_layout = Gtk.Layout()
        # Wrap main layout into an event box so
        # we  can change its background color.
        self._event_box = Gtk.EventBox()
        self._event_box.add(self._main_layout)
        self._event_handler = event.EventHandler(self)
        self._vadjust = self._main_layout.get_vadjustment()
        self._hadjust = self._main_layout.get_hadjustment()
        self._scroll = (
            Gtk.Scrollbar.new(Gtk.Orientation.HORIZONTAL, self._hadjust),
            Gtk.Scrollbar.new(Gtk.Orientation.VERTICAL, self._vadjust),
        )

        self.filehandler = file_handler.FileHandler(self)
        self.filehandler.file_closed += self._on_file_closed
        self.filehandler.file_opened += self._on_file_opened
        self.imagehandler = image_handler.ImageHandler(self)
        self.imagehandler.page_available += self._page_available
        self.thumbnailsidebar = thumbbar.ThumbnailSidebar(self)

        self.statusbar = status.Statusbar()
        self.clipboard = clipboard.Clipboard(self)
        self.slideshow = slideshow.Slideshow(self)
        self.cursor_handler = cursor_handler.CursorHandler(self)
        self.enhancer = enhance_backend.ImageEnhancer(self)
        self.lens = lens.MagnifyingLens(self)
        self.osd = osd.OnScreenDisplay(self)
        self.zoom = zoom.ZoomModel()
        self.uimanager = ui.MainUI(self)
        self.menubar = self.uimanager.get_widget('/Menu')
        self.toolbar = self.uimanager.get_widget('/Tool')
        self.popup = self.uimanager.get_widget('/Popup')
        self.actiongroup = self.uimanager.get_action_groups()[0]

        self.images = [Gtk.Image(),
                       Gtk.Image()]  # XXX limited to at most 2 pages

        # ----------------------------------------------------------------
        # Setup
        # ----------------------------------------------------------------
        self.set_title(constants.APPNAME)
        self.set_size_request(300, 300)  # Avoid making the window *too* small
        self.restore_window_geometry()

        # Hook up keyboard shortcuts
        self._event_handler.register_key_events()

        # This is a hack to get the focus away from the toolbar so that
        # we don't activate it with space or some other key (alternative?)
        self.toolbar.set_focus_child(
            self.uimanager.get_widget('/Tool/expander'))
        self.toolbar.set_style(Gtk.ToolbarStyle.ICONS)
        self.toolbar.set_icon_size(Gtk.IconSize.LARGE_TOOLBAR)

        for img in self.images:
            self._main_layout.put(img, 0, 0)
        self.set_bg_color(prefs['bg colour'])

        self._vadjust.step_increment = 15
        self._vadjust.page_increment = 1
        self._hadjust.step_increment = 15
        self._hadjust.page_increment = 1

        table = Gtk.Table(n_rows=2, n_columns=2, homogeneous=False)
        table.attach(self.thumbnailsidebar, 0, 1, 2, 5, Gtk.AttachOptions.FILL,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, 0, 0)

        table.attach(self._event_box, 1, 2, 2, 3,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, 0, 0)
        table.attach(self._scroll[constants.HEIGHT_AXIS], 2, 3, 2, 3,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK, 0, 0)
        table.attach(self._scroll[constants.WIDTH_AXIS], 1, 2, 4, 5,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
                     Gtk.AttachOptions.FILL, 0, 0)
        table.attach(self.menubar, 0, 3, 0, 1,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
                     Gtk.AttachOptions.FILL, 0, 0)
        table.attach(self.toolbar, 0, 3, 1, 2,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
                     Gtk.AttachOptions.FILL, 0, 0)
        table.attach(self.statusbar, 0, 3, 5, 6,
                     Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
                     Gtk.AttachOptions.FILL, 0, 0)

        if prefs['default double page'] or double_page:
            self.actiongroup.get_action('double_page').activate()

        if prefs['default manga mode'] or manga_mode:
            self.actiongroup.get_action('manga_mode').activate()

        # Determine zoom mode. If zoom_mode is passed, it overrides
        # the zoom mode preference.
        zoom_actions = {
            constants.ZOOM_MODE_BEST: 'best_fit_mode',
            constants.ZOOM_MODE_WIDTH: 'fit_width_mode',
            constants.ZOOM_MODE_HEIGHT: 'fit_height_mode',
            constants.ZOOM_MODE_SIZE: 'fit_size_mode',
            constants.ZOOM_MODE_MANUAL: 'fit_manual_mode'
        }

        if zoom_mode is not None:
            zoom_action = zoom_actions[zoom_mode]
        else:
            zoom_action = zoom_actions[prefs['zoom mode']]

        if zoom_action == 'fit_manual_mode':
            # This little ugly hack is to get the activate call on
            # 'fit_manual_mode' to actually create an event (and callback).
            # Since manual mode is the default selected radio button action
            # it won't send an event if we activate it when it is already
            # the selected one.
            self.actiongroup.get_action('best_fit_mode').activate()

        self.actiongroup.get_action(zoom_action).activate()

        if prefs['stretch']:
            self.actiongroup.get_action('stretch').activate()

        if prefs['invert smart scroll']:
            self.actiongroup.get_action('invert_scroll').activate()

        if prefs['keep transformation']:
            prefs['keep transformation'] = False
            self.actiongroup.get_action('keep_transformation').activate()
        else:
            prefs['rotation'] = 0
            prefs['vertical flip'] = False
            prefs['horizontal flip'] = False

        # List of "toggles" than can be shown/hidden by the user.
        self._toggle_list = (
            # Preference        Action        Widget(s)
            ('show menubar', 'menubar', (self.menubar, )),
            ('show scrollbar', 'scrollbar', self._scroll),
            ('show statusbar', 'statusbar', (self.statusbar, )),
            ('show thumbnails', 'thumbnails', (self.thumbnailsidebar, )),
            ('show toolbar', 'toolbar', (self.toolbar, )),
        )

        # Each "toggle" widget "eats" part of the main layout visible area.
        self._toggle_axis = {
            self.thumbnailsidebar: constants.WIDTH_AXIS,
            self._scroll[constants.HEIGHT_AXIS]: constants.WIDTH_AXIS,
            self._scroll[constants.WIDTH_AXIS]: constants.HEIGHT_AXIS,
            self.statusbar: constants.HEIGHT_AXIS,
            self.toolbar: constants.HEIGHT_AXIS,
            self.menubar: constants.HEIGHT_AXIS,
        }

        # Start with all "toggle" widgets hidden to avoid ugly transitions.
        for preference, action, widget_list in self._toggle_list:
            for widget in widget_list:
                widget.hide()

        toggleaction = self.actiongroup.get_action('hide_all')
        toggleaction.set_active(prefs['hide all'])

        # Sync each "toggle" widget active state with its preference.
        for preference, action, widget_list in self._toggle_list:
            self.actiongroup.get_action(action).set_active(prefs[preference])

        self.actiongroup.get_action('menu_autorotate_width').set_sensitive(
            False)
        self.actiongroup.get_action('menu_autorotate_height').set_sensitive(
            False)

        self.add(table)
        table.show()
        self._event_box.show_all()

        self._main_layout.set_events(Gdk.EventMask.BUTTON1_MOTION_MASK
                                     | Gdk.EventMask.BUTTON2_MOTION_MASK
                                     | Gdk.EventMask.BUTTON_PRESS_MASK
                                     | Gdk.EventMask.BUTTON_RELEASE_MASK
                                     | Gdk.EventMask.POINTER_MOTION_MASK)

        self._main_layout.drag_dest_set(
            Gtk.DestDefaults.ALL, [Gtk.TargetEntry.new('text/uri-list', 0, 0)],
            Gdk.DragAction.COPY | Gdk.DragAction.MOVE)

        self.connect('focus-in-event', self.gained_focus)
        self.connect('focus-out-event', self.lost_focus)
        self.connect('delete_event', self.close_program)
        self.connect('key_press_event', self._event_handler.key_press_event)
        self.connect('key_release_event',
                     self._event_handler.key_release_event)
        self.connect('configure_event', self._event_handler.resize_event)
        self.connect('window-state-event',
                     self._event_handler.window_state_event)

        self._main_layout.connect('button_release_event',
                                  self._event_handler.mouse_release_event)
        self._main_layout.connect('scroll_event',
                                  self._event_handler.scroll_wheel_event)
        self._main_layout.connect('button_press_event',
                                  self._event_handler.mouse_press_event)
        self._main_layout.connect('motion_notify_event',
                                  self._event_handler.mouse_move_event)
        self._main_layout.connect('drag_data_received',
                                  self._event_handler.drag_n_drop_event)

        self.uimanager.set_sensitivities()
        self.show()

        if prefs['default fullscreen'] or fullscreen:
            toggleaction = self.actiongroup.get_action('fullscreen')
            toggleaction.set_active(True)

        if prefs['previous quit was quit and save']:
            fileinfo = self.filehandler.read_fileinfo_file()

            if fileinfo != None:

                open_path = fileinfo[0]
                open_page = fileinfo[1] + 1

        prefs['previous quit was quit and save'] = False

        if open_path is not None:
            self.filehandler.open_file(open_path)

        if is_slideshow:
            self.actiongroup.get_action('slideshow').activate()

        if show_library:
            self.actiongroup.get_action('library').activate()

        self.cursor_handler.auto_hide_on()

        # Make sure we receive *all* mouse motion events,
        # even if a modal dialog is being shown.
        def _on_event(event):
            if Gdk.EventType.MOTION_NOTIFY == event.type:
                self.cursor_handler.refresh()
            Gtk.main_do_event(event)

        Gdk.event_handler_set(_on_event)

        self.styleprovider = None
        self.load_style(prefs['userstyle'])