Last active
January 28, 2018 22:04
-
-
Save ilikenwf/f661cb781da598660a88bbaffd4c6f5d to your computer and use it in GitHub Desktop.
AUR is a pain in the rear
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mcomix/about_dialog.py b/mcomix/about_dialog.py | |
index b31cbf4..4b2b6f3 100644 | |
--- a/mcomix/about_dialog.py | |
+++ b/mcomix/about_dialog.py | |
@@ -1,18 +1,18 @@ | |
# -*- coding: utf-8 -*- | |
"""about_dialog.py - About dialog.""" | |
-import webbrowser | |
-import gtk | |
+from gi.repository import Gtk | |
import pkg_resources | |
+import webbrowser | |
from mcomix import constants | |
from mcomix import strings | |
from mcomix import image_tools | |
-class _AboutDialog(gtk.AboutDialog): | |
+class _AboutDialog(Gtk.AboutDialog): | |
def __init__(self, window): | |
- super(_AboutDialog, self).__init__() | |
+ super(_AboutDialog, self).__init__(parent=window) | |
self.set_name(constants.APPNAME) | |
self.set_program_name(constants.APPNAME) | |
@@ -20,7 +20,7 @@ class _AboutDialog(gtk.AboutDialog): | |
self.set_website('https://sourceforge.net/p/mcomix/wiki/') | |
self.set_copyright('Copyright © 2005-2016') | |
- icon_data = pkg_resources.resource_string('mcomix.images', 'mcomix.png') | |
+ icon_data = pkg_resources.resource_string('mcomix', 'images/mcomix.png') | |
pixbuf = image_tools.load_pixbuf_data(icon_data) | |
self.set_logo(pixbuf) | |
@@ -47,11 +47,12 @@ class _AboutDialog(gtk.AboutDialog): | |
artists = [ u'%s: %s' % (name, description) for name, description in strings.ARTISTS ] | |
self.set_artists(artists) | |
- self.show_all() | |
+ self.connect('activate-link', self._on_activate_link) | |
-def open_url(dialog, url, *args): | |
- webbrowser.open(url) | |
+ self.show_all() | |
-gtk.about_dialog_set_url_hook(open_url, None) | |
+ def _on_activate_link(self, about_dialog, uri): | |
+ webbrowser.open(uri) | |
+ return True | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/archive/__init__.py b/mcomix/archive/__init__.py | |
index 809ef76..e2c8bf4 100644 | |
--- a/mcomix/archive/__init__.py | |
+++ b/mcomix/archive/__init__.py | |
@@ -1,32 +1,32 @@ | |
# -*- coding: utf-8 -*- | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import message_dialog | |
def ask_for_password(archive): | |
""" Openes an input dialog to ask for a password. Returns either | |
an Unicode string (the password), or None.""" | |
- dialog = message_dialog.MessageDialog(None, gtk.DIALOG_MODAL, | |
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL) | |
+ dialog = message_dialog.MessageDialog(None, Gtk.DialogFlags.MODAL, | |
+ Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL) | |
dialog.set_text( | |
_("The archive is password-protected:"), | |
archive + '\n\n' + | |
("Please enter the password to continue:")) | |
- dialog.set_default_response(gtk.RESPONSE_OK) | |
+ dialog.set_default_response(Gtk.ResponseType.OK) | |
dialog.set_auto_destroy(False) | |
- password_box = gtk.Entry() | |
+ password_box = Gtk.Entry() | |
password_box.set_visibility(False) | |
password_box.set_activates_default(True) | |
- dialog.get_content_area().pack_end(password_box) | |
+ dialog.get_content_area().pack_end(password_box, True, True, 0) | |
dialog.set_focus(password_box) | |
result = dialog.run() | |
password = password_box.get_text() | |
dialog.destroy() | |
- if result == gtk.RESPONSE_OK and password: | |
+ if result == Gtk.ResponseType.OK and password: | |
return password.decode('utf-8') | |
else: | |
return None | |
diff --git a/mcomix/bookmark_backend.py b/mcomix/bookmark_backend.py | |
index 2f28b67..582ec9e 100644 | |
--- a/mcomix/bookmark_backend.py | |
+++ b/mcomix/bookmark_backend.py | |
@@ -2,7 +2,7 @@ | |
import os | |
import cPickle | |
-import gtk | |
+from gi.repository import Gtk | |
import operator | |
import datetime | |
import time | |
@@ -90,11 +90,11 @@ class __BookmarksStore(object): | |
response = self.show_replace_bookmark_dialog(same_file_bookmarks, page) | |
# Delete old bookmarks | |
- if response == gtk.RESPONSE_YES: | |
+ if response == Gtk.ResponseType.YES: | |
for bookmark in same_file_bookmarks: | |
self.remove_bookmark(bookmark) | |
# Perform no action | |
- elif response not in (gtk.RESPONSE_YES, gtk.RESPONSE_NO): | |
+ elif response not in (Gtk.ResponseType.YES, Gtk.ResponseType.NO): | |
return | |
self.add_bookmark_by_values(name, path, page, numpages, | |
@@ -195,13 +195,13 @@ class __BookmarksStore(object): | |
@return RESPONSE_YES to create replace bookmarks, | |
RESPONSE_NO to create a new bookmark, RESPONSE_CANCEL to abort creating | |
a new bookmark. """ | |
- dialog = message_dialog.MessageDialog(self._window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO) | |
- dialog.add_buttons(gtk.STOCK_YES, gtk.RESPONSE_YES, | |
- gtk.STOCK_NO, gtk.RESPONSE_NO, | |
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) | |
- dialog.set_default_response(gtk.RESPONSE_YES) | |
+ dialog = message_dialog.MessageDialog(self._window, Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO) | |
+ dialog.add_buttons(Gtk.STOCK_YES, Gtk.ResponseType.YES, | |
+ Gtk.STOCK_NO, Gtk.ResponseType.NO, | |
+ Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) | |
+ dialog.set_default_response(Gtk.ResponseType.YES) | |
dialog.set_should_remember_choice('replace-existing-bookmark', | |
- (gtk.RESPONSE_YES, gtk.RESPONSE_NO)) | |
+ (Gtk.ResponseType.YES, Gtk.ResponseType.NO)) | |
pages = map(str, sorted(map(operator.attrgetter('_page'), old_bookmarks))) | |
dialog.set_text( | |
diff --git a/mcomix/bookmark_dialog.py b/mcomix/bookmark_dialog.py | |
index 9f33b4b..3fa9adb 100644 | |
--- a/mcomix/bookmark_dialog.py | |
+++ b/mcomix/bookmark_dialog.py | |
@@ -1,39 +1,38 @@ | |
"""bookmark_dialog.py - Bookmarks dialog handler.""" | |
-import gtk | |
-import gobject | |
+from gi.repository import Gdk, GdkPixbuf, Gtk, GObject | |
from mcomix import constants | |
from mcomix import bookmark_menu_item | |
-class _BookmarksDialog(gtk.Dialog): | |
+class _BookmarksDialog(Gtk.Dialog): | |
"""_BookmarksDialog lets the user remove or rearrange bookmarks.""" | |
_SORT_TYPE, _SORT_NAME, _SORT_PAGE, _SORT_ADDED = 100, 101, 102, 103 | |
def __init__(self, window, bookmarks_store): | |
- super(_BookmarksDialog, self).__init__(_('Edit Bookmarks'), window, gtk.DIALOG_DESTROY_WITH_PARENT, | |
- (gtk.STOCK_REMOVE, constants.RESPONSE_REMOVE, | |
- gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) | |
+ super(_BookmarksDialog, self).__init__(_('Edit Bookmarks'), window, Gtk.DialogFlags.DESTROY_WITH_PARENT, | |
+ (Gtk.STOCK_REMOVE, constants.RESPONSE_REMOVE, | |
+ Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) | |
self._bookmarks_store = bookmarks_store | |
self.set_resizable(True) | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
# scroll area fill to the edge (TODO window should not really be a dialog) | |
self.set_border_width(0) | |
- scrolled = gtk.ScrolledWindow() | |
+ scrolled = Gtk.ScrolledWindow() | |
scrolled.set_border_width(0) | |
- scrolled.set_shadow_type(gtk.SHADOW_IN) | |
- scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
- self.vbox.pack_start(scrolled) | |
+ scrolled.set_shadow_type(Gtk.ShadowType.IN) | |
+ scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
+ self.vbox.pack_start(scrolled, True, True, 0) | |
- self._liststore = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, | |
- gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, bookmark_menu_item._Bookmark) | |
+ self._liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, GObject.TYPE_STRING, | |
+ GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, bookmark_menu_item._Bookmark) | |
- self._treeview = gtk.TreeView(self._liststore) | |
+ self._treeview = Gtk.TreeView(self._liststore) | |
self._treeview.set_rules_hint(True) | |
self._treeview.set_reorderable(True) | |
# search by typing first few letters of name | |
@@ -44,15 +43,15 @@ class _BookmarksDialog(gtk.Dialog): | |
scrolled.add(self._treeview) | |
- cellrenderer_text = gtk.CellRendererText() | |
- cellrenderer_pbuf = gtk.CellRendererPixbuf() | |
+ cellrenderer_text = Gtk.CellRendererText() | |
+ cellrenderer_pbuf = Gtk.CellRendererPixbuf() | |
- self._icon_col = gtk.TreeViewColumn(_('Type'), cellrenderer_pbuf) | |
- self._name_col = gtk.TreeViewColumn(_('Name'), cellrenderer_text) | |
- self._page_col = gtk.TreeViewColumn(_('Page'), cellrenderer_text) | |
- self._path_col = gtk.TreeViewColumn(_('Location'), cellrenderer_text) | |
+ self._icon_col = Gtk.TreeViewColumn(_('Type'), cellrenderer_pbuf) | |
+ self._name_col = Gtk.TreeViewColumn(_('Name'), cellrenderer_text) | |
+ self._page_col = Gtk.TreeViewColumn(_('Page'), cellrenderer_text) | |
+ self._path_col = Gtk.TreeViewColumn(_('Location'), cellrenderer_text) | |
# TRANSLATORS: "Added" as in "Date Added" | |
- self._date_add_col = gtk.TreeViewColumn(_('Added'), cellrenderer_text) | |
+ self._date_add_col = Gtk.TreeViewColumn(_('Added'), cellrenderer_text) | |
self._treeview.append_column(self._icon_col) | |
self._treeview.append_column(self._name_col) | |
@@ -82,11 +81,11 @@ class _BookmarksDialog(gtk.Dialog): | |
self._path_col.set_sort_column_id(3) | |
self._date_add_col.set_sort_column_id(_BookmarksDialog._SORT_ADDED) | |
- self._icon_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) | |
- self._name_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) | |
- self._page_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) | |
- self._path_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) | |
- self._date_add_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) | |
+ self._icon_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) | |
+ self._name_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) | |
+ self._page_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) | |
+ self._path_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) | |
+ self._date_add_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) | |
# FIXME Hide extra columns. Needs UI controls to enable these. | |
self._path_col.set_visible(False) | |
@@ -154,7 +153,7 @@ class _BookmarksDialog(gtk.Dialog): | |
def _response(self, dialog, response): | |
- if response == gtk.RESPONSE_CLOSE: | |
+ if response == Gtk.ResponseType.CLOSE: | |
self._close() | |
elif response == constants.RESPONSE_REMOVE: | |
@@ -165,7 +164,7 @@ class _BookmarksDialog(gtk.Dialog): | |
def _key_press_event(self, dialog, event, *args): | |
- if event.keyval == gtk.keysyms.Delete: | |
+ if event.keyval == Gdk.KEY_Delete: | |
self._remove_selected() | |
def _close(self, *args): | |
@@ -173,7 +172,7 @@ class _BookmarksDialog(gtk.Dialog): | |
ordering.""" | |
ordering = [] | |
- treeiter = self._liststore.get_iter_root() | |
+ treeiter = self._liststore.get_iter_first() | |
while treeiter is not None: | |
bookmark = self._liststore.get_value(treeiter, 5) | |
diff --git a/mcomix/bookmark_menu.py b/mcomix/bookmark_menu.py | |
index d2f02ef..e04b9cb 100644 | |
--- a/mcomix/bookmark_menu.py | |
+++ b/mcomix/bookmark_menu.py | |
@@ -1,13 +1,13 @@ | |
"""bookmark_menu.py - Bookmarks menu.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import bookmark_backend | |
from mcomix import bookmark_dialog | |
-class BookmarksMenu(gtk.Menu): | |
+class BookmarksMenu(Gtk.Menu): | |
- """BookmarksMenu extends gtk.Menu with convenience methods relating to | |
+ """BookmarksMenu extends Gtk.Menu with convenience methods relating to | |
bookmarks. It contains fixed items for adding bookmarks etc. as well | |
as dynamic items corresponding to the current bookmarks. | |
""" | |
@@ -19,7 +19,7 @@ class BookmarksMenu(gtk.Menu): | |
self._bookmarks_store = bookmark_backend.BookmarksStore | |
self._bookmarks_store.initialize(window) | |
- self._actiongroup = gtk.ActionGroup('mcomix-bookmarks') | |
+ self._actiongroup = Gtk.ActionGroup('mcomix-bookmarks') | |
self._actiongroup.add_actions([ | |
('add_bookmark', 'mcomix-add-bookmark', _('Add _Bookmark'), | |
'<Control>D', None, self._add_current_to_bookmarks), | |
@@ -53,7 +53,7 @@ class BookmarksMenu(gtk.Menu): | |
# Add separator | |
if bookmarks: | |
- separator = gtk.SeparatorMenuItem() | |
+ separator = Gtk.SeparatorMenuItem() | |
separator.show() | |
self.append(separator) | |
diff --git a/mcomix/bookmark_menu_item.py b/mcomix/bookmark_menu_item.py | |
index 454426e..d1d428e 100644 | |
--- a/mcomix/bookmark_menu_item.py | |
+++ b/mcomix/bookmark_menu_item.py | |
@@ -1,10 +1,10 @@ | |
"""bookmark_menu_item.py - A signle bookmark item.""" | |
-import gtk | |
+from gi.repository import Gtk | |
-class _Bookmark(gtk.ImageMenuItem): | |
+class _Bookmark(Gtk.ImageMenuItem): | |
- """_Bookmark represents one bookmark. It extends the gtk.ImageMenuItem | |
+ """_Bookmark represents one bookmark. It extends the Gtk.ImageMenuItem | |
and is thus put directly in the bookmarks menu. | |
""" | |
@@ -22,10 +22,10 @@ class _Bookmark(gtk.ImageMenuItem): | |
super(_Bookmark, self).__init__(str(self), False) | |
if self._archive_type is not None: | |
- im = gtk.image_new_from_stock('mcomix-archive', gtk.ICON_SIZE_MENU) | |
+ im = Gtk.Image.new_from_stock('mcomix-archive', Gtk.IconSize.MENU) | |
else: | |
- im = gtk.image_new_from_stock('mcomix-image', gtk.ICON_SIZE_MENU) | |
+ im = Gtk.Image.new_from_stock('mcomix-image', Gtk.IconSize.MENU) | |
self.set_image(im) | |
self.connect('activate', self._load) | |
diff --git a/mcomix/callback.py b/mcomix/callback.py | |
index 09ecebc..915978b 100644 | |
--- a/mcomix/callback.py | |
+++ b/mcomix/callback.py | |
@@ -3,7 +3,7 @@ | |
import traceback | |
import weakref | |
import threading | |
-import gobject | |
+from gi.repository import GObject | |
from mcomix import log | |
@@ -33,7 +33,7 @@ class CallbackList(object): | |
return result | |
else: | |
# Call this method again in the main thread. | |
- gobject.idle_add(self.__mainthread_call, (args, kwargs)) | |
+ GObject.idle_add(self.__mainthread_call, (args, kwargs)) | |
def __iadd__(self, function): | |
""" Support for 'method += callback_function' syntax. """ | |
@@ -55,7 +55,7 @@ class CallbackList(object): | |
def __mainthread_call(self, params): | |
""" Helper function to execute code in the main thread. | |
- This will be called by gobject.idle_add, with <params> being a tuple | |
+ This will be called by GObject.idle_add, with <params> being a tuple | |
of (args, kwargs). """ | |
result = self(*params[0], **params[1]) | |
diff --git a/mcomix/clipboard.py b/mcomix/clipboard.py | |
index c197946..a31d58e 100644 | |
--- a/mcomix/clipboard.py | |
+++ b/mcomix/clipboard.py | |
@@ -1,30 +1,23 @@ | |
"""clipboard.py - Clipboard handler""" | |
-import gtk | |
-import ctypes | |
-import cStringIO | |
-import sys | |
+from gi.repository import Gdk, Gtk | |
-from mcomix import log | |
from mcomix import image_tools | |
-class Clipboard(gtk.Clipboard): | |
+class Clipboard(object): | |
"""The Clipboard takes care of all necessary copy-paste functionality | |
""" | |
def __init__(self, window): | |
- super(Clipboard, self).__init__(display=gtk.gdk.display_get_default(), | |
- selection="CLIPBOARD") | |
+ self._clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) | |
self._window = window | |
def copy(self, text, pixbuf): | |
""" Copies C{text} and C{pixbuf} to clipboard. """ | |
- if sys.platform == 'win32': | |
- self._copy_windows(pixbuf, text) | |
- else: | |
- self._copy_linux(pixbuf, text.encode('utf-8')) | |
+ self._clipboard.set_text(text, len(text)) | |
+ self._clipboard.set_image(pixbuf) | |
def copy_page(self, *args): | |
""" Copies the currently opened page and pixbuf to clipboard. """ | |
@@ -42,87 +35,7 @@ class Clipboard(gtk.Clipboard): | |
current_page_pixbufs[ 1 ], | |
self._window.is_manga_mode ) | |
- # Get path for current page | |
path = self._window.imagehandler.get_path_to_page() | |
self.copy(path, pixbuf) | |
- def _copy_windows(self, pixbuf, path): | |
- """ Copies pixbuf and path to the clipboard. | |
- Uses native Win32 API, as GTK+ doesn't seem to work. """ | |
- | |
- windll = ctypes.windll | |
- OpenClipboard = windll.user32.OpenClipboard | |
- EmptyClipboard = windll.user32.EmptyClipboard | |
- SetClipboardData = windll.user32.SetClipboardData | |
- CloseClipboard = windll.user32.CloseClipboard | |
- GlobalAlloc = windll.kernel32.GlobalAlloc | |
- GlobalLock = windll.kernel32.GlobalLock | |
- GlobalLock.restype = ctypes.c_void_p | |
- GlobalUnlock = windll.kernel32.GlobalUnlock | |
- | |
- def buffer_to_handle(buffer, buffer_size): | |
- """ Creates a memory handle for the passed data. | |
- This handle doesn't need to be freed by the application. """ | |
- global_mem = GlobalAlloc( | |
- 0x0042, # GMEM_MOVEABLE | GMEM_ZEROINIT | |
- buffer_size) | |
- lock = GlobalLock(global_mem) | |
- ctypes.memmove(lock, ctypes.addressof(buffer), buffer_size) | |
- GlobalUnlock(global_mem) | |
- | |
- return global_mem | |
- | |
- # Paste the text as Unicode string | |
- text_buffer = ctypes.create_unicode_buffer(path) | |
- text_handle = buffer_to_handle(text_buffer, | |
- ctypes.sizeof(text_buffer)) | |
- # Paste the image as Win32 DIB structure | |
- pil = image_tools.pixbuf_to_pil(pixbuf) | |
- output = cStringIO.StringIO() | |
- pil.convert("RGB").save(output, "BMP") | |
- dibdata = output.getvalue()[14:] | |
- output.close() | |
- | |
- image_buffer = ctypes.create_string_buffer(dibdata) | |
- image_handle = buffer_to_handle(image_buffer, | |
- ctypes.sizeof(image_buffer)) | |
- | |
- # Actually copy data to clipboard | |
- if OpenClipboard(self._window.window.handle): | |
- EmptyClipboard() | |
- SetClipboardData(13, # CF_UNICODETEXT | |
- text_handle) | |
- SetClipboardData(8, # CF_DIB | |
- image_handle) | |
- CloseClipboard() | |
- else: | |
- log.warning('Could not open clipboard.') | |
- | |
- def _copy_linux(self, pixbuf, path): | |
- # Register various clipboard formats for either the | |
- # text or the pixbuf. | |
- clipboard_targets = ("image/bmp", | |
- "text/plain", "STRING", "UTF8_STRING") | |
- self.set_with_data( | |
- [ (target, 0, 0) for target in clipboard_targets ], | |
- self._get_clipboard_content, | |
- self._clear_clipboard_content, | |
- (pixbuf, path)) | |
- | |
- def _get_clipboard_content(self, clipboard, selectiondata, info, data): | |
- """ Called whenever an application requests the content of the | |
- clipboard. selectiondata.target will contain one of the targets | |
- that have previously been registered. Currently, only "image/bmp" | |
- provides pixbuf data, while all other types point to the currently | |
- opened file as UTF-8 string. """ | |
- | |
- if selectiondata.target == "image/bmp": | |
- selectiondata.set_pixbuf(data[0]) | |
- else: | |
- selectiondata.set_text(data[1]) | |
- | |
- def _clear_clipboard_content(self, clipboard, data): | |
- """ Called when clipboard ownership changes. """ | |
- pass | |
- | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/comment_dialog.py b/mcomix/comment_dialog.py | |
index 21e4663..13e0996 100644 | |
--- a/mcomix/comment_dialog.py | |
+++ b/mcomix/comment_dialog.py | |
@@ -1,29 +1,29 @@ | |
"""comment.py - Comments dialog.""" | |
import os | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import i18n | |
-class _CommentsDialog(gtk.Dialog): | |
+class _CommentsDialog(Gtk.Dialog): | |
def __init__(self, window): | |
super(_CommentsDialog, self).__init__(_('Comments'), window, 0, | |
- (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) | |
+ (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) | |
self.set_resizable(True) | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
self.set_default_size(600, 550) | |
self.set_border_width(4) | |
- tag = gtk.TextTag() | |
+ tag = Gtk.TextTag() | |
tag.set_property('editable', False) | |
tag.set_property('editable-set', True) | |
tag.set_property('family', 'Monospace') | |
tag.set_property('family-set', True) | |
tag.set_property('scale', 0.9) | |
tag.set_property('scale-set', True) | |
- tag_table = gtk.TextTagTable() | |
+ tag_table = Gtk.TextTagTable() | |
tag_table.add(tag) | |
self._tag = tag | |
@@ -50,10 +50,10 @@ class _CommentsDialog(gtk.Dialog): | |
self._notebook.destroy() | |
self._notebook = None | |
- notebook = gtk.Notebook() | |
+ notebook = Gtk.Notebook() | |
notebook.set_scrollable(True) | |
notebook.set_border_width(6) | |
- self.vbox.pack_start(notebook) | |
+ self.vbox.pack_start(notebook, True, True, 0) | |
self._notebook = notebook | |
self._comments = {} | |
@@ -73,17 +73,17 @@ class _CommentsDialog(gtk.Dialog): | |
name = os.path.basename(path) | |
- page = gtk.VBox(False) | |
+ page = Gtk.VBox(False) | |
page.set_border_width(8) | |
- scrolled = gtk.ScrolledWindow() | |
- scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
- page.pack_start(scrolled) | |
+ scrolled = Gtk.ScrolledWindow() | |
+ scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
+ page.pack_start(scrolled, True, True, 0) | |
- outbox = gtk.EventBox() | |
+ outbox = Gtk.EventBox() | |
scrolled.add_with_viewport(outbox) | |
- inbox = gtk.EventBox() | |
+ inbox = Gtk.EventBox() | |
inbox.set_border_width(6) | |
outbox.add(inbox) | |
@@ -91,16 +91,16 @@ class _CommentsDialog(gtk.Dialog): | |
if text is None: | |
text = _('Could not read %s') % name | |
- text_buffer = gtk.TextBuffer(self._tag_table) | |
+ text_buffer = Gtk.TextBuffer(tag_table=self._tag_table) | |
text_buffer.set_text(i18n.to_unicode(text)) | |
text_buffer.apply_tag(self._tag, *text_buffer.get_bounds()) | |
- text_view = gtk.TextView(text_buffer) | |
+ text_view = Gtk.TextView(buffer=text_buffer) | |
inbox.add(text_view) | |
- bg_color = text_view.get_default_attributes().bg_color | |
- outbox.modify_bg(gtk.STATE_NORMAL, bg_color) | |
- tab_label = gtk.Label(i18n.to_unicode(name)) | |
- self._notebook.insert_page(page, tab_label) | |
+ bg_color = text_view.get_default_attributes().pg_bg_color | |
+ outbox.modify_bg(Gtk.StateType.NORMAL, bg_color) | |
+ tab_label = Gtk.Label(label=i18n.to_unicode(name)) | |
+ self._notebook.insert_page(page, tab_label, -1) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/constants.py b/mcomix/constants.py | |
index 5be2040..ae9798e 100644 | |
--- a/mcomix/constants.py | |
+++ b/mcomix/constants.py | |
@@ -8,7 +8,7 @@ import operator | |
from mcomix import tools | |
APPNAME = 'MComix' | |
-VERSION = '1.3.dev0' | |
+VERSION = '1.3.dev0-gtk3' | |
HOME_DIR = tools.get_home_directory() | |
CONFIG_DIR = tools.get_config_directory() | |
diff --git a/mcomix/cursor_handler.py b/mcomix/cursor_handler.py | |
index 9ddad5b..1e370b1 100644 | |
--- a/mcomix/cursor_handler.py | |
+++ b/mcomix/cursor_handler.py | |
@@ -1,7 +1,6 @@ | |
"""cursor_handler.py - Cursor handler.""" | |
-import gobject | |
-import gtk | |
+from gi.repository import Gdk, GObject | |
from mcomix import constants | |
@@ -16,14 +15,14 @@ class CursorHandler(object): | |
def set_cursor_type(self, cursor): | |
"""Set the cursor to type <cursor>. Supported cursor types are | |
available as constants in this module. If <cursor> is not one of the | |
- cursor constants above, it must be a gtk.gdk.Cursor. | |
+ cursor constants above, it must be a Gdk.Cursor. | |
""" | |
if cursor == constants.NORMAL_CURSOR: | |
mode = None | |
elif cursor == constants.GRAB_CURSOR: | |
- mode = gtk.gdk.Cursor(gtk.gdk.FLEUR) | |
+ mode = Gdk.Cursor.new(Gdk.CursorType.FLEUR) | |
elif cursor == constants.WAIT_CURSOR: | |
- mode = gtk.gdk.Cursor(gtk.gdk.WATCH) | |
+ mode = Gdk.Cursor.new(Gdk.CursorType.WATCH) | |
elif cursor == constants.NO_CURSOR: | |
mode = self._get_hidden_cursor() | |
else: | |
@@ -72,17 +71,15 @@ class CursorHandler(object): | |
def _set_hide_timer(self): | |
self._kill_timer() | |
- self._timer_id = gobject.timeout_add(2000, self._on_timeout) | |
+ self._timer_id = GObject.timeout_add(2000, self._on_timeout) | |
def _kill_timer(self): | |
if self._timer_id is not None: | |
- gobject.source_remove(self._timer_id) | |
+ GObject.source_remove(self._timer_id) | |
self._timer_id = None | |
def _get_hidden_cursor(self): | |
- pixmap = gtk.gdk.Pixmap(None, 1, 1, 1) | |
- color = gtk.gdk.Color() | |
- return gtk.gdk.Cursor(pixmap, pixmap, color, color, 0, 0) | |
+ return Gdk.Cursor.new(Gdk.CursorType.BLANK_CURSOR) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/dialog_handler.py b/mcomix/dialog_handler.py | |
index d08f3c7..297b1cd 100644 | |
--- a/mcomix/dialog_handler.py | |
+++ b/mcomix/dialog_handler.py | |
@@ -12,9 +12,11 @@ dialog_windows[ 'about-dialog' ] = [None, about_dialog._AboutDialog] | |
dialog_windows[ 'comments-dialog' ] = [None, comment_dialog._CommentsDialog] | |
dialog_windows[ 'properties-dialog' ] = [None, properties_dialog._PropertiesDialog] | |
-def open_dialog(action, window, name_of_dialog): | |
+def open_dialog(action, data): | |
"""Create and display the given dialog.""" | |
+ window, name_of_dialog = data | |
+ | |
_dialog = dialog_windows[ name_of_dialog ] | |
# if the dialog window is not created then create the window | |
diff --git a/mcomix/edit_comment_area.py b/mcomix/edit_comment_area.py | |
index 048beb8..e6b1ba1 100644 | |
--- a/mcomix/edit_comment_area.py | |
+++ b/mcomix/edit_comment_area.py | |
@@ -1,11 +1,10 @@ | |
"""edit_comment_area.py - The area in the editing window that displays comments.""" | |
import os | |
-import gtk | |
- | |
+from gi.repository import Gdk, Gtk | |
from mcomix import tools | |
-class _CommentArea(gtk.VBox): | |
+class _CommentArea(Gtk.VBox): | |
"""The area used for displaying and handling non-image files.""" | |
@@ -13,32 +12,32 @@ class _CommentArea(gtk.VBox): | |
super(_CommentArea, self).__init__() | |
self._edit_dialog = edit_dialog | |
- scrolled = gtk.ScrolledWindow() | |
- scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
- self.pack_start(scrolled) | |
+ scrolled = Gtk.ScrolledWindow() | |
+ scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
+ self.pack_start(scrolled, True, True, 0) | |
- info = gtk.Label(_('Please note that the only files that are automatically added to this list are those files in archives that MComix recognizes as comments.')) | |
+ info = Gtk.Label(label=_('Please note that the only files that are automatically added to this list are those files in archives that MComix recognizes as comments.')) | |
info.set_alignment(0.5, 0.5) | |
info.set_line_wrap(True) | |
self.pack_start(info, False, False, 10) | |
# The ListStore layout is (basename, size, full path). | |
- self._liststore = gtk.ListStore(str, str, str) | |
- self._treeview = gtk.TreeView(self._liststore) | |
+ self._liststore = Gtk.ListStore(str, str, str) | |
+ self._treeview = Gtk.TreeView(self._liststore) | |
self._treeview.set_rules_hint(True) | |
self._treeview.connect('button_press_event', self._button_press) | |
self._treeview.connect('key_press_event', self._key_press) | |
- cellrenderer = gtk.CellRendererText() | |
- column = gtk.TreeViewColumn(_('Name'), cellrenderer, text=0) | |
+ cellrenderer = Gtk.CellRendererText() | |
+ column = Gtk.TreeViewColumn(_('Name'), cellrenderer, text=0) | |
column.set_expand(True) | |
self._treeview.append_column(column) | |
- column = gtk.TreeViewColumn(_('Size'), cellrenderer, text=1) | |
+ column = Gtk.TreeViewColumn(_('Size'), cellrenderer, text=1) | |
self._treeview.append_column(column) | |
scrolled.add(self._treeview) | |
- self._ui_manager = gtk.UIManager() | |
+ self._ui_manager = Gtk.UIManager() | |
ui_description = """ | |
<ui> | |
@@ -49,9 +48,9 @@ class _CommentArea(gtk.VBox): | |
""" | |
self._ui_manager.add_ui_from_string(ui_description) | |
- actiongroup = gtk.ActionGroup('mcomix-edit-archive-comment-area') | |
+ actiongroup = Gtk.ActionGroup('mcomix-edit-archive-comment-area') | |
actiongroup.add_actions([ | |
- ('remove', gtk.STOCK_REMOVE, _('Remove from archive'), None, None, | |
+ ('remove', Gtk.STOCK_REMOVE, _('Remove from archive'), None, None, | |
self._remove_file)]) | |
self._ui_manager.insert_action_group(actiongroup, 0) | |
@@ -96,12 +95,12 @@ class _CommentArea(gtk.VBox): | |
path = path[0] | |
if event.button == 3: | |
- self._ui_manager.get_widget('/Popup').popup(None, None, None, | |
- event.button, event.time) | |
+ self._ui_manager.get_widget('/Popup').popup(None, None, None, None, | |
+ event.button, event.time) | |
def _key_press(self, iconview, event): | |
"""Handle key presses on the area.""" | |
- if event.keyval == gtk.keysyms.Delete: | |
+ if event.keyval == Gdk.KEY_Delete: | |
self._remove_file() | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/edit_dialog.py b/mcomix/edit_dialog.py | |
index 0d443c9..b33f988 100644 | |
--- a/mcomix/edit_dialog.py | |
+++ b/mcomix/edit_dialog.py | |
@@ -2,8 +2,7 @@ | |
import os | |
import tempfile | |
-import gobject | |
-import gtk | |
+from gi.repository import Gdk, Gtk, GObject | |
import re | |
from mcomix.preferences import prefs | |
@@ -17,7 +16,7 @@ from mcomix import message_dialog | |
_dialog = None | |
-class _EditArchiveDialog(gtk.Dialog): | |
+class _EditArchiveDialog(Gtk.Dialog): | |
"""The _EditArchiveDialog lets users edit archives (or directories) by | |
reordering images and removing and adding images or comment files. The | |
@@ -25,40 +24,40 @@ class _EditArchiveDialog(gtk.Dialog): | |
""" | |
def __init__(self, window): | |
- super(_EditArchiveDialog, self).__init__(_('Edit archive'), window, gtk.DIALOG_MODAL, | |
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) | |
+ super(_EditArchiveDialog, self).__init__(_('Edit archive'), window, Gtk.DialogFlags.MODAL, | |
+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) | |
- self._accept_changes_button = self.add_button(gtk.STOCK_APPLY, gtk.RESPONSE_APPLY) | |
+ self._accept_changes_button = self.add_button(Gtk.STOCK_APPLY, Gtk.ResponseType.APPLY) | |
self.kill = False # Dialog is killed. | |
self.file_handler = window.filehandler | |
self._window = window | |
self._imported_files = [] | |
- self._save_button = self.add_button(gtk.STOCK_SAVE_AS, constants.RESPONSE_SAVE_AS) | |
+ self._save_button = self.add_button(Gtk.STOCK_SAVE_AS, constants.RESPONSE_SAVE_AS) | |
self._import_button = self.add_button(_('_Import'), constants.RESPONSE_IMPORT) | |
- self._import_button.set_image(gtk.image_new_from_stock(gtk.STOCK_ADD, | |
- gtk.ICON_SIZE_BUTTON)) | |
+ self._import_button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_ADD, | |
+ Gtk.IconSize.BUTTON)) | |
self.set_border_width(4) | |
- self.resize(min(gtk.gdk.screen_get_default().get_width() - 50, 750), | |
- min(gtk.gdk.screen_get_default().get_height() - 50, 600)) | |
+ self.resize(min(Gdk.Screen.get_default().get_width() - 50, 750), | |
+ min(Gdk.Screen.get_default().get_height() - 50, 600)) | |
self.connect('response', self._response) | |
self._image_area = edit_image_area._ImageArea(self, window) | |
self._comment_area = edit_comment_area._CommentArea(self) | |
- notebook = gtk.Notebook() | |
+ notebook = Gtk.Notebook() | |
notebook.set_border_width(6) | |
- notebook.append_page(self._image_area, gtk.Label(_('Images'))) | |
- notebook.append_page(self._comment_area, gtk.Label(_('Comment files'))) | |
- self.vbox.pack_start(notebook) | |
+ notebook.append_page(self._image_area, Gtk.Label(label=_('Images'))) | |
+ notebook.append_page(self._comment_area, Gtk.Label(label=_('Comment files'))) | |
+ self.vbox.pack_start(notebook, True, True, 0) | |
self.show_all() | |
- gobject.idle_add(self._load_original_files) | |
+ GObject.idle_add(self._load_original_files) | |
def _load_original_files(self): | |
"""Load the original files from the archive or directory into | |
@@ -66,7 +65,7 @@ class _EditArchiveDialog(gtk.Dialog): | |
""" | |
self._save_button.set_sensitive(False) | |
self._import_button.set_sensitive(False) | |
- self._window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) | |
+ self._window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) | |
self._image_area.fetch_images() | |
if self.kill: # fetch_images() allows pending events to be handled. | |
@@ -82,10 +81,10 @@ class _EditArchiveDialog(gtk.Dialog): | |
def _pack_archive(self, archive_path): | |
"""Create a new archive with the chosen files.""" | |
self.set_sensitive(False) | |
- self._window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) | |
+ self._window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) | |
- while gtk.events_pending(): | |
- gtk.main_iteration_do(False) | |
+ while Gtk.events_pending(): | |
+ Gtk.main_iteration_do(False) | |
image_files = self._image_area.get_file_listing() | |
comment_files = self._comment_area.get_file_listing() | |
@@ -128,8 +127,8 @@ class _EditArchiveDialog(gtk.Dialog): | |
self._window.set_cursor(None) | |
if fail: | |
- dialog = message_dialog.MessageDialog(self._window, 0, gtk.MESSAGE_ERROR, | |
- gtk.BUTTONS_CLOSE) | |
+ dialog = message_dialog.MessageDialog(self._window, 0, Gtk.MessageType.ERROR, | |
+ Gtk.ButtonsType.CLOSE) | |
dialog.set_text( | |
_("The new archive could not be saved!"), | |
_("The original files have not been removed.")) | |
@@ -142,14 +141,14 @@ class _EditArchiveDialog(gtk.Dialog): | |
if response == constants.RESPONSE_SAVE_AS: | |
dialog = file_chooser_simple_dialog.SimpleFileChooserDialog( | |
- gtk.FILE_CHOOSER_ACTION_SAVE) | |
+ Gtk.FileChooserAction.SAVE) | |
src_path = self.file_handler.get_path_to_base() | |
dialog.set_current_directory(os.path.dirname(src_path)) | |
dialog.set_save_name('%s.cbz' % os.path.splitext( | |
os.path.basename(src_path))[0]) | |
- dialog.filechooser.set_extra_widget(gtk.Label( | |
+ dialog.filechooser.set_extra_widget(Gtk.Label(label= | |
_('Archives are stored as ZIP files.'))) | |
dialog.add_archive_filters() | |
dialog.run() | |
@@ -183,11 +182,11 @@ class _EditArchiveDialog(gtk.Dialog): | |
self._imported_files.append( path ) | |
self._comment_area.add_extra_file(path) | |
- elif response == gtk.RESPONSE_APPLY: | |
+ elif response == Gtk.ResponseType.APPLY: | |
old_image_array = self._window.imagehandler._image_files | |
- treeiter = self._image_area._liststore.get_iter_root() | |
+ treeiter = self._image_area._liststore.get_iter_first() | |
new_image_array = [] | |
@@ -223,7 +222,7 @@ class _EditArchiveDialog(gtk.Dialog): | |
def destroy(self): | |
self._image_area.cleanup() | |
- gtk.Dialog.destroy(self) | |
+ Gtk.Dialog.destroy(self) | |
def open_dialog(action, window): | |
global _dialog | |
diff --git a/mcomix/edit_image_area.py b/mcomix/edit_image_area.py | |
index d83a65e..5d548a2 100644 | |
--- a/mcomix/edit_image_area.py | |
+++ b/mcomix/edit_image_area.py | |
@@ -1,7 +1,7 @@ | |
"""edit_image_area.py - The area of the editing archive window that displays images.""" | |
import os | |
-import gtk | |
+from gi.repository import Gdk, GdkPixbuf, Gtk | |
from mcomix import image_tools | |
from mcomix import i18n | |
@@ -9,7 +9,7 @@ from mcomix import thumbnail_tools | |
from mcomix import thumbnail_view | |
from mcomix.preferences import prefs | |
-class _ImageArea(gtk.ScrolledWindow): | |
+class _ImageArea(Gtk.ScrolledWindow): | |
"""The area used for displaying and handling image files.""" | |
@@ -18,11 +18,11 @@ class _ImageArea(gtk.ScrolledWindow): | |
self._window = window | |
self._edit_dialog = edit_dialog | |
- self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
+ self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
# The ListStore layout is (thumbnail, basename, full path, thumbnail status). | |
# Basename is used as image tooltip. | |
- self._liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, bool) | |
+ self._liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, bool) | |
self._iconview = thumbnail_view.ThumbnailIconView( | |
self._liststore, | |
2, # UID | |
@@ -32,7 +32,7 @@ class _ImageArea(gtk.ScrolledWindow): | |
self._iconview.generate_thumbnail = self._generate_thumbnail | |
self._iconview.set_tooltip_column(1) | |
self._iconview.set_reorderable(True) | |
- self._iconview.set_selection_mode(gtk.SELECTION_MULTIPLE) | |
+ self._iconview.set_selection_mode(Gtk.SelectionMode.MULTIPLE) | |
self._iconview.connect('button_press_event', self._button_press) | |
self._iconview.connect('key_press_event', self._key_press) | |
self._iconview.connect_after('drag_begin', self._drag_begin) | |
@@ -43,16 +43,16 @@ class _ImageArea(gtk.ScrolledWindow): | |
size=(self._thumbnail_size, | |
self._thumbnail_size)) | |
- self._filler = gtk.gdk.Pixbuf(colorspace=gtk.gdk.COLORSPACE_RGB, | |
- has_alpha=True, bits_per_sample=8, | |
- width=self._thumbnail_size, | |
- height=self._thumbnail_size) | |
+ self._filler = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=True, bits_per_sample=8, | |
+ width=self._thumbnail_size, | |
+ height=self._thumbnail_size) | |
# Make the pixbuf transparent. | |
self._filler.fill(0) | |
self._window.imagehandler.page_available += self._on_page_available | |
- self._ui_manager = gtk.UIManager() | |
+ self._ui_manager = Gtk.UIManager() | |
ui_description = """ | |
<ui> | |
<popup name="Popup"> | |
@@ -63,9 +63,9 @@ class _ImageArea(gtk.ScrolledWindow): | |
self._ui_manager.add_ui_from_string(ui_description) | |
- actiongroup = gtk.ActionGroup('mcomix-edit-archive-image-area') | |
+ actiongroup = Gtk.ActionGroup('mcomix-edit-archive-image-area') | |
actiongroup.add_actions([ | |
- ('remove', gtk.STOCK_REMOVE, _('Remove from archive'), None, None, | |
+ ('remove', Gtk.STOCK_REMOVE, _('Remove from archive'), None, None, | |
self._remove_pages)]) | |
self._ui_manager.insert_action_group(actiongroup, 0) | |
@@ -120,12 +120,12 @@ class _ImageArea(gtk.ScrolledWindow): | |
iconview.unselect_all() | |
iconview.select_path(path) | |
- self._ui_manager.get_widget('/Popup').popup(None, None, None, | |
- event.button, event.time) | |
+ self._ui_manager.get_widget('/Popup').popup(None, None, None, None, | |
+ event.button, event.time) | |
def _key_press(self, iconview, event): | |
"""Handle key presses on the thumbnail area.""" | |
- if event.keyval == gtk.keysyms.Delete: | |
+ if event.keyval == Gdk.KEY_Delete: | |
self._remove_pages() | |
def _drag_begin(self, iconview, context): | |
@@ -134,16 +134,10 @@ class _ImageArea(gtk.ScrolledWindow): | |
might actually see where we are dropping!). | |
""" | |
path = iconview.get_cursor()[0] | |
- pixmap = iconview.create_drag_icon(path) | |
- | |
- # context.set_icon_pixmap() seems to cause crashes, so we do a | |
- # quick and dirty conversion to pixbuf. | |
- pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
- *pixmap.get_size()) | |
- pointer = pointer.get_from_drawable(pixmap, iconview.get_colormap(), | |
- 0, 0, 0, 0, *pixmap.get_size()) | |
- | |
- context.set_icon_pixbuf(pointer, -5, -5) | |
+ surface = treeview.create_row_drag_icon(path) | |
+ width, height = surface.get_width(), surface.get_height() | |
+ pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, width, height) | |
+ Gtk.drag_set_icon_pixbuf(context, pixbuf, -5, -5) | |
def cleanup(self): | |
self._iconview.stop_update() | |
diff --git a/mcomix/enhance_dialog.py b/mcomix/enhance_dialog.py | |
index 5bbd5f8..87e985f 100644 | |
--- a/mcomix/enhance_dialog.py | |
+++ b/mcomix/enhance_dialog.py | |
@@ -1,6 +1,6 @@ | |
"""enhance_dialog.py - Image enhancement dialog.""" | |
-import gtk | |
+from gi.repository import Gtk | |
import histogram | |
from mcomix.preferences import prefs | |
@@ -8,9 +8,9 @@ from mcomix import image_tools | |
_dialog = None | |
-class _EnhanceImageDialog(gtk.Dialog): | |
+class _EnhanceImageDialog(Gtk.Dialog): | |
- """A gtk.Dialog which allows modification of the values belonging to | |
+ """A Gtk.Dialog which allows modification of the values belonging to | |
an ImageEnhancer. | |
""" | |
@@ -19,49 +19,50 @@ class _EnhanceImageDialog(gtk.Dialog): | |
self._window = window | |
- reset = gtk.Button(None, gtk.STOCK_REVERT_TO_SAVED) | |
+ reset = Gtk.Button(stock=Gtk.STOCK_REVERT_TO_SAVED) | |
reset.set_tooltip_text(_('Reset to defaults.')) | |
- self.add_action_widget(reset, gtk.RESPONSE_REJECT) | |
- save = gtk.Button(None, gtk.STOCK_SAVE) | |
+ self.add_action_widget(reset, Gtk.ResponseType.REJECT) | |
+ save = Gtk.Button(stock=Gtk.STOCK_SAVE) | |
save.set_tooltip_text(_('Save the selected values as default for future files.')) | |
- self.add_action_widget(save, gtk.RESPONSE_APPLY) | |
- self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) | |
+ self.add_action_widget(save, Gtk.ResponseType.APPLY) | |
+ self.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK) | |
self.set_resizable(False) | |
self.connect('response', self._response) | |
- self.set_default_response(gtk.RESPONSE_OK) | |
+ self.set_default_response(Gtk.ResponseType.OK) | |
self._enhancer = window.enhancer | |
self._block = False | |
- vbox = gtk.VBox(False, 10) | |
+ vbox = Gtk.VBox(False, 10) | |
self.set_border_width(4) | |
vbox.set_border_width(6) | |
self.vbox.add(vbox) | |
- self._hist_image = gtk.Image() | |
+ self._hist_image = Gtk.Image() | |
self._hist_image.set_size_request(262, 170) | |
- vbox.pack_start(self._hist_image) | |
- vbox.pack_start(gtk.HSeparator()) | |
+ vbox.pack_start(self._hist_image, True, True, 0) | |
+ vbox.pack_start(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL), True, True, 0) | |
- hbox = gtk.HBox(False, 4) | |
+ hbox = Gtk.HBox(False, 4) | |
vbox.pack_start(hbox, False, False, 2) | |
- vbox_left = gtk.VBox(False, 4) | |
- vbox_right = gtk.VBox(False, 4) | |
+ vbox_left = Gtk.VBox(False, 4) | |
+ vbox_right = Gtk.VBox(False, 4) | |
hbox.pack_start(vbox_left, False, False, 2) | |
hbox.pack_start(vbox_right, True, True, 2) | |
def _create_scale(label_text): | |
- label = gtk.Label(label_text) | |
+ label = Gtk.Label(label=label_text) | |
label.set_alignment(1, 0.5) | |
label.set_use_underline(True) | |
vbox_left.pack_start(label, True, False, 2) | |
- adj = gtk.Adjustment(0.0, -1.0, 1.0, 0.01, 0.1) | |
- scale = gtk.HScale(adj) | |
+ adj = Gtk.Adjustment(0.0, -1.0, 1.0, 0.01, 0.1) | |
+ scale = Gtk.HScale.new(adj) | |
scale.set_digits(2) | |
- scale.set_value_pos(gtk.POS_RIGHT) | |
+ scale.set_value_pos(Gtk.PositionType.RIGHT) | |
scale.connect('value-changed', self._change_values) | |
- scale.set_update_policy(gtk.UPDATE_DELAYED) | |
+ # FIXME | |
+ # scale.set_update_policy(Gtk.UPDATE_DELAYED) | |
label.set_mnemonic_widget(scale) | |
vbox_right.pack_start(scale, True, False, 2) | |
return scale | |
@@ -71,10 +72,10 @@ class _EnhanceImageDialog(gtk.Dialog): | |
self._saturation_scale = _create_scale(_('S_aturation:')) | |
self._sharpness_scale = _create_scale(_('S_harpness:')) | |
- vbox.pack_start(gtk.HSeparator()) | |
+ vbox.pack_start(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL), True, True, 0) | |
self._autocontrast_button = \ | |
- gtk.CheckButton(_('_Automatically adjust contrast')) | |
+ Gtk.CheckButton.new_with_mnemonic(_('_Automatically adjust contrast')) | |
self._autocontrast_button.set_tooltip_text( | |
_('Automatically adjust contrast (both lightness and darkness), separately for each colour band.')) | |
vbox.pack_start(self._autocontrast_button, False, False, 2) | |
@@ -138,10 +139,10 @@ class _EnhanceImageDialog(gtk.Dialog): | |
def _response(self, dialog, response): | |
- if response in [gtk.RESPONSE_OK, gtk.RESPONSE_DELETE_EVENT]: | |
+ if response in [Gtk.ResponseType.OK, Gtk.ResponseType.DELETE_EVENT]: | |
_close_dialog() | |
- elif response == gtk.RESPONSE_APPLY: | |
+ elif response == Gtk.ResponseType.APPLY: | |
self._change_values(self) | |
prefs['brightness'] = self._enhancer.brightness | |
prefs['contrast'] = self._enhancer.contrast | |
@@ -149,7 +150,7 @@ class _EnhanceImageDialog(gtk.Dialog): | |
prefs['sharpness'] = self._enhancer.sharpness | |
prefs['auto contrast'] = self._enhancer.autocontrast | |
- elif response == gtk.RESPONSE_REJECT: | |
+ elif response == Gtk.ResponseType.REJECT: | |
self._block = True | |
self._brightness_scale.set_value(prefs['brightness'] - 1.0) | |
self._contrast_scale.set_value(prefs['contrast'] - 1.0) | |
diff --git a/mcomix/event.py b/mcomix/event.py | |
index b465192..9f1333e 100644 | |
--- a/mcomix/event.py | |
+++ b/mcomix/event.py | |
@@ -2,7 +2,7 @@ | |
""" | |
import urllib | |
-import gtk | |
+from gi.repository import Gdk, Gtk | |
from mcomix.preferences import prefs | |
from mcomix import constants | |
@@ -398,45 +398,45 @@ class EventHandler(object): | |
manager = keybindings.keybinding_manager(self._window) | |
# Some keys can only be pressed with certain modifiers that | |
# are irrelevant to the actual hotkey. Find out and ignore them. | |
- ALL_ACCELS_MASK = (gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK | | |
- gtk.gdk.MOD1_MASK) | |
+ ALL_ACCELS_MASK = (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK | | |
+ Gdk.ModifierType.MOD1_MASK) | |
- keymap = gtk.gdk.keymap_get_default() | |
+ keymap = Gdk.Keymap.get_default() | |
code = keymap.translate_keyboard_state( | |
- event.hardware_keycode, event.state, event.group) | |
+ event.hardware_keycode, event.get_state(), event.group) | |
- if code is not None: | |
- keyval, egroup, level, consumed = code | |
+ if code[0]: | |
+ keyval = code[1] | |
+ consumed = code[4] | |
# If the resulting key is upper case (i.e. SHIFT + key), | |
# convert it to lower case and remove SHIFT from the consumed flags | |
# to match how keys are registered (<Shift> + lowercase) | |
- if (gtk.gdk.keyval_is_upper(keyval) and | |
- not gtk.gdk.keyval_is_lower(keyval) and | |
- event.state & gtk.gdk.SHIFT_MASK): | |
- keyval = gtk.gdk.keyval_to_lower(keyval) | |
- consumed &= ~gtk.gdk.SHIFT_MASK | |
+ if (event.get_state() & Gdk.ModifierType.SHIFT_MASK and | |
+ keyval != Gdk.keyval_to_lower(keyval)): | |
+ keyval = Gdk.keyval_to_lower(keyval) | |
+ consumed &= ~Gdk.ModifierType.SHIFT_MASK | |
# 'consumed' is the modifier that was necessary to type the key | |
- manager.execute((keyval, event.state & ~consumed & ALL_ACCELS_MASK)) | |
+ manager.execute((keyval, event.get_state() & ~consumed & ALL_ACCELS_MASK)) | |
# --------------------------------------------------------------- | |
# Register CTRL for scrolling only one page instead of two | |
# pages in double page mode. This is mainly for mouse scrolling. | |
# --------------------------------------------------------------- | |
- if event.keyval in (gtk.keysyms.Control_L, gtk.keysyms.Control_R): | |
+ if event.keyval in (Gdk.KEY_Control_L, Gdk.KEY_Control_R): | |
self._window.imagehandler.force_single_step = True | |
# ---------------------------------------------------------------- | |
# We kill the signals here for the Up, Down, Space and Enter keys, | |
# or they will start fiddling with the thumbnail selector (bad). | |
# ---------------------------------------------------------------- | |
- if (event.keyval in (gtk.keysyms.Up, gtk.keysyms.Down, | |
- gtk.keysyms.space, gtk.keysyms.KP_Enter, gtk.keysyms.KP_Up, | |
- gtk.keysyms.KP_Down, gtk.keysyms.KP_Home, gtk.keysyms.KP_End, | |
- gtk.keysyms.KP_Page_Up, gtk.keysyms.KP_Page_Down) or | |
- (event.keyval == gtk.keysyms.Return and not | |
- 'GDK_MOD1_MASK' in event.state.value_names)): | |
+ if (event.keyval in (Gdk.KEY_Up, Gdk.KEY_Down, | |
+ Gdk.KEY_space, Gdk.KEY_KP_Enter, Gdk.KEY_KP_Up, | |
+ Gdk.KEY_KP_Down, Gdk.KEY_KP_Home, Gdk.KEY_KP_End, | |
+ Gdk.KEY_KP_Page_Up, Gdk.KEY_KP_Page_Down) or | |
+ (event.keyval == Gdk.KEY_Return and not | |
+ 'GDK_MOD1_MASK' in event.get_state().value_names)): | |
self._window.emit_stop_by_name('key_press_event') | |
return True | |
@@ -447,7 +447,7 @@ class EventHandler(object): | |
# --------------------------------------------------------------- | |
# Unregister CTRL for scrolling only one page in double page mode | |
# --------------------------------------------------------------- | |
- if event.keyval in (gtk.keysyms.Control_L, gtk.keysyms.Control_R): | |
+ if event.keyval in (Gdk.KEY_Control_L, Gdk.KEY_Control_R): | |
self._window.imagehandler.force_single_step = False | |
def escape_event(self): | |
@@ -462,34 +462,48 @@ class EventHandler(object): | |
wheel flips pages in best fit mode and scrolls the scrollbars | |
otherwise. | |
""" | |
- if 'GDK_BUTTON2_MASK' in event.state.value_names: | |
+ if event.get_state() & Gdk.ModifierType.BUTTON2_MASK: | |
return | |
+ has_direction, direction = event.get_scroll_direction() | |
+ if not has_direction: | |
+ direction = None | |
+ has_delta, delta_x, delta_y = event.get_scroll_deltas() | |
+ if has_delta: | |
+ if delta_y < 0: | |
+ direction = Gdk.ScrollDirection.UP | |
+ elif delta_y > 0: | |
+ direction = Gdk.ScrollDirection.DOWN | |
+ elif delta_x < 0: | |
+ direction = Gdk.ScrollDirection.LEFT | |
+ elif delta_x > 0: | |
+ direction = Gdk.ScrollDirection.RIGHT | |
+ | |
self._scroll_protection = True | |
- if event.direction == gtk.gdk.SCROLL_UP: | |
- if event.state & gtk.gdk.CONTROL_MASK: | |
+ if direction == Gdk.ScrollDirection.UP: | |
+ if event.get_state() & Gdk.ModifierType.CONTROL_MASK: | |
self._window.manual_zoom_in() | |
elif prefs['smart scroll']: | |
self._smart_scroll_up(prefs['number of pixels to scroll per mouse wheel event']) | |
else: | |
self._scroll_with_flipping(0, -prefs['number of pixels to scroll per mouse wheel event']) | |
- elif event.direction == gtk.gdk.SCROLL_DOWN: | |
- if event.state & gtk.gdk.CONTROL_MASK: | |
+ elif direction == Gdk.ScrollDirection.DOWN: | |
+ if event.get_state() & Gdk.ModifierType.CONTROL_MASK: | |
self._window.manual_zoom_out() | |
elif prefs['smart scroll']: | |
self._smart_scroll_down(prefs['number of pixels to scroll per mouse wheel event']) | |
else: | |
self._scroll_with_flipping(0, prefs['number of pixels to scroll per mouse wheel event']) | |
- elif event.direction == gtk.gdk.SCROLL_RIGHT: | |
+ elif direction == Gdk.ScrollDirection.RIGHT: | |
if not self._window.is_manga_mode: | |
self._window.flip_page(+1) | |
else: | |
self._previous_page_with_protection() | |
- elif event.direction == gtk.gdk.SCROLL_LEFT: | |
+ elif direction == Gdk.ScrollDirection.LEFT: | |
if not self._window.is_manga_mode: | |
self._previous_page_with_protection() | |
else: | |
@@ -511,11 +525,11 @@ class EventHandler(object): | |
self._window.actiongroup.get_action('lens').set_active(True) | |
elif (event.button == 3 and | |
- not event.state & gtk.gdk.MOD1_MASK and | |
- not event.state & gtk.gdk.SHIFT_MASK): | |
+ not event.get_state() & Gdk.ModifierType.MOD1_MASK and | |
+ not event.get_state() & Gdk.ModifierType.SHIFT_MASK): | |
self._window.cursor_handler.set_cursor_type(constants.NORMAL_CURSOR) | |
- self._window.popup.popup(None, None, None, event.button, | |
- event.time) | |
+ self._window.popup.popup(None, None, None, None, | |
+ event.button, event.time) | |
elif event.button == 4: | |
self._window.show_info_panel() | |
@@ -531,7 +545,7 @@ class EventHandler(object): | |
event.y_root == self._pressed_pointer_pos_y and \ | |
not self._window.was_out_of_focus: | |
- if event.state & gtk.gdk.SHIFT_MASK: | |
+ if event.get_state() & Gdk.ModifierType.SHIFT_MASK: | |
self._flip_page(10) | |
else: | |
self._flip_page(1) | |
@@ -543,9 +557,9 @@ class EventHandler(object): | |
self._window.actiongroup.get_action('lens').set_active(False) | |
elif event.button == 3: | |
- if event.state & gtk.gdk.MOD1_MASK: | |
+ if event.get_state() & Gdk.ModifierType.MOD1_MASK: | |
self._flip_page(-1) | |
- elif event.state & gtk.gdk.SHIFT_MASK: | |
+ elif event.get_state() & Gdk.ModifierType.SHIFT_MASK: | |
self._flip_page(-10) | |
def mouse_move_event(self, widget, event): | |
@@ -553,7 +567,7 @@ class EventHandler(object): | |
event = _get_latest_event_of_same_type(event) | |
- if 'GDK_BUTTON1_MASK' in event.state.value_names: | |
+ if 'GDK_BUTTON1_MASK' in event.get_state().value_names: | |
self._window.cursor_handler.set_cursor_type(constants.GRAB_CURSOR) | |
scrolled = self._window.scroll(self._last_pointer_pos_x - event.x_root, | |
self._last_pointer_pos_y - event.y_root) | |
@@ -588,7 +602,7 @@ class EventHandler(object): | |
"""Handle drag-n-drop events on the main layout area.""" | |
# The drag source is inside MComix itself, so we ignore. | |
- if (context.get_source_widget() is not None): | |
+ if (Gtk.drag_get_source_widget(context) is not None): | |
return | |
uris = selection.get_uris() | |
@@ -753,10 +767,11 @@ def _get_latest_event_of_same_type(event): | |
as <event>, or <event> itself if no such events are in the queue. All | |
events of that type will be removed from the event queue. | |
""" | |
+ return event | |
events = [] | |
- while gtk.gdk.events_pending(): | |
- queued_event = gtk.gdk.event_get() | |
+ while Gdk.events_pending(): | |
+ queued_event = Gdk.event_get() | |
if queued_event is not None: | |
diff --git a/mcomix/file_chooser_base_dialog.py b/mcomix/file_chooser_base_dialog.py | |
index e4fbf91..a6e9d81 100644 | |
--- a/mcomix/file_chooser_base_dialog.py | |
+++ b/mcomix/file_chooser_base_dialog.py | |
@@ -3,8 +3,7 @@ | |
import os | |
import mimetypes | |
import fnmatch | |
-import gtk | |
-import pango | |
+from gi.repository import Gtk, Pango | |
from mcomix.preferences import prefs | |
from mcomix import image_tools | |
@@ -19,12 +18,12 @@ from mcomix import tools | |
mimetypes.init() | |
-class _BaseFileChooserDialog(gtk.Dialog): | |
+class _BaseFileChooserDialog(Gtk.Dialog): | |
"""We roll our own FileChooserDialog because the one in GTK seems | |
buggy with the preview widget. The <action> argument dictates what type | |
- of filechooser dialog we want (i.e. it is gtk.FILE_CHOOSER_ACTION_OPEN | |
- or gtk.FILE_CHOOSER_ACTION_SAVE). | |
+ of filechooser dialog we want (i.e. it is Gtk.FileChooserAction.OPEN | |
+ or Gtk.FileChooserAction.SAVE). | |
This is a base class for the _MainFileChooserDialog, the | |
_LibraryFileChooserDialog and the SimpleFileChooserDialog. | |
@@ -36,49 +35,49 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
_last_activated_file = None | |
- def __init__(self, action=gtk.FILE_CHOOSER_ACTION_OPEN): | |
+ def __init__(self, action=Gtk.FileChooserAction.OPEN): | |
self._action = action | |
self._destroyed = False | |
- if action == gtk.FILE_CHOOSER_ACTION_OPEN: | |
+ if action == Gtk.FileChooserAction.OPEN: | |
title = _('Open') | |
- buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, | |
- gtk.STOCK_OPEN, gtk.RESPONSE_OK) | |
+ buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, | |
+ Gtk.STOCK_OPEN, Gtk.ResponseType.OK) | |
else: | |
title = _('Save') | |
- buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, | |
- gtk.STOCK_SAVE, gtk.RESPONSE_OK) | |
+ buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, | |
+ Gtk.STOCK_SAVE, Gtk.ResponseType.OK) | |
super(_BaseFileChooserDialog, self).__init__(title, None, 0, buttons) | |
- self.set_default_response(gtk.RESPONSE_OK) | |
+ self.set_default_response(Gtk.ResponseType.OK) | |
- self.filechooser = gtk.FileChooserWidget(action=action) | |
+ self.filechooser = Gtk.FileChooserWidget(action=action) | |
self.filechooser.set_size_request(680, 420) | |
- self.vbox.pack_start(self.filechooser) | |
+ self.vbox.pack_start(self.filechooser, True, True, 0) | |
self.set_border_width(4) | |
self.filechooser.set_border_width(6) | |
self.connect('response', self._response) | |
self.filechooser.connect('file_activated', self._response, | |
- gtk.RESPONSE_OK) | |
+ Gtk.ResponseType.OK) | |
- preview_box = gtk.VBox(False, 10) | |
+ preview_box = Gtk.VBox(False, 10) | |
preview_box.set_size_request(130, 0) | |
- self._preview_image = gtk.Image() | |
+ self._preview_image = Gtk.Image() | |
self._preview_image.set_size_request(130, 130) | |
- preview_box.pack_start(self._preview_image, False, False) | |
+ preview_box.pack_start(self._preview_image, False, False, 0) | |
self.filechooser.set_preview_widget(preview_box) | |
pango_scale_small = (1 / 1.2) | |
- self._namelabel = labels.FormattedLabel(weight=pango.WEIGHT_BOLD, | |
+ self._namelabel = labels.FormattedLabel(weight=Pango.Weight.BOLD, | |
scale=pango_scale_small) | |
- self._namelabel.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
- preview_box.pack_start(self._namelabel, False, False) | |
+ self._namelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
+ preview_box.pack_start(self._namelabel, False, False, 0) | |
self._sizelabel = labels.FormattedLabel(scale=pango_scale_small) | |
- self._sizelabel.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
- preview_box.pack_start(self._sizelabel, False, False) | |
+ self._sizelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
+ preview_box.pack_start(self._sizelabel, False, False, 0) | |
self.filechooser.set_use_preview_label(False) | |
preview_box.show_all() | |
self.filechooser.connect('update-preview', self._update_preview) | |
@@ -113,9 +112,9 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
"""Add a filter, called <name>, for each mime type in <mimes> and | |
each pattern in <patterns> to the filechooser. | |
""" | |
- ffilter = gtk.FileFilter() | |
+ ffilter = Gtk.FileFilter() | |
ffilter.add_custom( | |
- gtk.FILE_FILTER_FILENAME|gtk.FILE_FILTER_MIME_TYPE, | |
+ Gtk.FileFilterFlags.FILENAME | Gtk.FileFilterFlags.MIME_TYPE, | |
self._filter, (patterns, mimes)) | |
ffilter.set_name(name) | |
@@ -125,7 +124,7 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
def add_archive_filters(self): | |
"""Add archive filters to the filechooser. | |
""" | |
- ffilter = gtk.FileFilter() | |
+ ffilter = Gtk.FileFilter() | |
ffilter.set_name(_('All archives')) | |
self.filechooser.add_filter(ffilter) | |
supported_formats = archive_tools.get_supported_formats() | |
@@ -141,7 +140,7 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
def add_image_filters(self): | |
"""Add images filters to the filechooser. | |
""" | |
- ffilter = gtk.FileFilter() | |
+ ffilter = Gtk.FileFilter() | |
ffilter.set_name(_('All images')) | |
self.filechooser.add_filter(ffilter) | |
supported_formats = image_tools.get_supported_formats() | |
@@ -160,31 +159,31 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
(patterns, mimes) that should pass the test. Returns True | |
if the file passed in C{filter_info} should be displayed. """ | |
- path, uri, display, mime = filter_info | |
match_patterns, match_mimes = data | |
matches_mime = bool(filter( | |
- lambda match_mime: match_mime == mime, | |
+ lambda match_mime: match_mime == filter_info.mime_type, | |
match_mimes)) | |
matches_pattern = bool(filter( | |
- lambda match_pattern: fnmatch.fnmatch(path, match_pattern), | |
+ lambda match_pattern: fnmatch.fnmatch(filter_info.filename, match_pattern), | |
match_patterns)) | |
return matches_mime or matches_pattern | |
def collect_files_from_subdir(self, path, filter, recursive=False): | |
""" Finds archives within C{path} that match the | |
- L{gtk.FileFilter} passed in C{filter}. """ | |
+ L{Gtk.FileFilter} passed in C{filter}. """ | |
for root, dirs, files in os.walk(path): | |
for file in files: | |
full_path = os.path.join(root, file) | |
mimetype = mimetypes.guess_type(full_path)[0] or 'application/octet-stream' | |
+ filter_info = Gtk.FileFilterInfo() | |
+ filter_info.contains = Gtk.FileFilterFlags.FILENAME | Gtk.FileFilterFlags.MIME_TYPE | |
+ filter_info.filename = full_path.encode('utf-8') | |
+ filter_info.mime_type = mimetype | |
- if (filter == self._all_files_filter or | |
- filter.filter((full_path.encode('utf-8'), | |
- None, None, mimetype))): | |
- | |
+ if (filter == self._all_files_filter or filter.filter(filter_info)): | |
yield full_path | |
if not recursive: | |
@@ -203,7 +202,7 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
"""Return a list of the paths of the chosen files, or None if the | |
event only changed the current directory. | |
""" | |
- if response == gtk.RESPONSE_OK: | |
+ if response == Gtk.ResponseType.OK: | |
if not self.filechooser.get_filenames(): | |
return | |
@@ -224,19 +223,19 @@ class _BaseFileChooserDialog(gtk.Dialog): | |
# FileChooser.set_do_overwrite_confirmation() doesn't seem to | |
# work on our custom dialog, so we use a simple alternative. | |
first_path = self.filechooser.get_filenames()[0].decode('utf-8') | |
- if (self._action == gtk.FILE_CHOOSER_ACTION_SAVE and | |
+ if (self._action == Gtk.FileChooserAction.SAVE and | |
not os.path.isdir(first_path) and | |
os.path.exists(first_path)): | |
overwrite_dialog = message_dialog.MessageDialog(None, 0, | |
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL) | |
+ Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL) | |
overwrite_dialog.set_text( | |
_("A file named '%s' already exists. Do you want to replace it?") % | |
os.path.basename(first_path), | |
_('Replacing it will overwrite its contents.')) | |
response = overwrite_dialog.run() | |
- if response != gtk.RESPONSE_OK: | |
+ if response != Gtk.ResponseType.OK: | |
self.emit_stop_by_name('response') | |
return | |
diff --git a/mcomix/file_chooser_library_dialog.py b/mcomix/file_chooser_library_dialog.py | |
index c325863..c2f22f2 100644 | |
--- a/mcomix/file_chooser_library_dialog.py | |
+++ b/mcomix/file_chooser_library_dialog.py | |
@@ -1,6 +1,6 @@ | |
"""file_chooser_library_dialog.py - Custom FileChooserDialog implementations.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix.preferences import prefs | |
from mcomix import file_chooser_base_dialog | |
@@ -43,9 +43,9 @@ class _LibraryFileChooserDialog(file_chooser_base_dialog._BaseFileChooserDialog) | |
for widget in self.get_action_area().get_children(): | |
self.get_action_area().remove(widget) | |
- self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) | |
- self.add_button(gtk.STOCK_ADD, gtk.RESPONSE_OK) | |
- self.set_default_response(gtk.RESPONSE_OK) | |
+ self.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) | |
+ self.add_button(Gtk.STOCK_ADD, Gtk.ResponseType.OK) | |
+ self.set_default_response(Gtk.ResponseType.OK) | |
def should_open_recursive(self): | |
return True | |
diff --git a/mcomix/file_chooser_main_dialog.py b/mcomix/file_chooser_main_dialog.py | |
index e5ca2c3..17d7afc 100644 | |
--- a/mcomix/file_chooser_main_dialog.py | |
+++ b/mcomix/file_chooser_main_dialog.py | |
@@ -1,6 +1,6 @@ | |
"""file_chooser_main_dialog.py - Custom FileChooserDialog implementations.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix.preferences import prefs | |
from mcomix import file_chooser_base_dialog | |
diff --git a/mcomix/file_chooser_simple_dialog.py b/mcomix/file_chooser_simple_dialog.py | |
index 8ff6f3f..8edf210 100644 | |
--- a/mcomix/file_chooser_simple_dialog.py | |
+++ b/mcomix/file_chooser_simple_dialog.py | |
@@ -1,20 +1,20 @@ | |
"""file_chooser_simple_dialog.py - Custom FileChooserDialog implementations.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import file_chooser_base_dialog | |
class SimpleFileChooserDialog(file_chooser_base_dialog._BaseFileChooserDialog): | |
"""A simple filechooser dialog that is designed to be used with the | |
- gtk.Dialog.run() method. The <action> dictates what type of filechooser | |
+ Gtk.Dialog.run() method. The <action> dictates what type of filechooser | |
dialog we want (i.e. save or open). If the type is an open-dialog, we | |
use multiple selection by default. | |
""" | |
- def __init__(self, action=gtk.FILE_CHOOSER_ACTION_OPEN): | |
+ def __init__(self, action=Gtk.FileChooserAction.OPEN): | |
super(SimpleFileChooserDialog, self).__init__(action) | |
- if action == gtk.FILE_CHOOSER_ACTION_OPEN: | |
+ if action == Gtk.FileChooserAction.OPEN: | |
self.filechooser.set_select_multiple(True) | |
self._paths = None | |
diff --git a/mcomix/file_handler.py b/mcomix/file_handler.py | |
index e2eaeea..affc5c7 100644 | |
--- a/mcomix/file_handler.py | |
+++ b/mcomix/file_handler.py | |
@@ -7,7 +7,7 @@ import tempfile | |
import threading | |
import re | |
import cPickle | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix.preferences import prefs | |
from mcomix import archive_extractor | |
@@ -217,8 +217,8 @@ class FileHandler(object): | |
self._name_table.clear() | |
self.file_closed() | |
# Catch up on UI events, so we don't leave idle callbacks. | |
- while gtk.events_pending(): | |
- gtk.main_iteration_do(False) | |
+ while Gtk.events_pending(): | |
+ Gtk.main_iteration_do(False) | |
tools.garbage_collect() | |
if self._tmp_dir is not None: | |
self.thread_delete(self._tmp_dir) | |
@@ -356,11 +356,11 @@ class FileHandler(object): | |
read_date = self.last_read_page.get_date(path) | |
- dialog = message_dialog.MessageDialog(self._window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, | |
- gtk.BUTTONS_YES_NO) | |
- dialog.set_default_response(gtk.RESPONSE_YES) | |
+ dialog = message_dialog.MessageDialog(self._window, Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, | |
+ Gtk.ButtonsType.YES_NO) | |
+ dialog.set_default_response(Gtk.ResponseType.YES) | |
dialog.set_should_remember_choice('resume-from-last-read-page', | |
- (gtk.RESPONSE_YES, gtk.RESPONSE_NO)) | |
+ (Gtk.ResponseType.YES, Gtk.ResponseType.NO)) | |
dialog.set_text( | |
(_('Continue reading from page %d?') % last_read_page), | |
_('You stopped reading here on %(date)s, %(time)s. ' | |
@@ -369,7 +369,7 @@ class FileHandler(object): | |
'time': read_date.time().strftime("%X"), 'page': last_read_page}) | |
result = dialog.run() | |
- return result == gtk.RESPONSE_YES | |
+ return result == Gtk.ResponseType.YES | |
def _open_image_files(self, filelist, image_path): | |
""" Opens all files passed in C{filelist}. | |
diff --git a/mcomix/i18n.py b/mcomix/i18n.py | |
index c78486e..fa3e2ab 100644 | |
--- a/mcomix/i18n.py | |
+++ b/mcomix/i18n.py | |
@@ -82,15 +82,19 @@ def install_gettext(): | |
os.environ['LANGUAGE'] = lang | |
domain = constants.APPNAME.lower() | |
- translation = gettext.NullTranslations() | |
# Search for .mo files manually, since gettext doesn't support setuptools/pkg_resources. | |
for lang in lang_identifiers: | |
- resource = os.path.join(lang, 'LC_MESSAGES', '%s.mo' % domain) | |
- if pkg_resources.resource_exists('mcomix.messages', resource): | |
- translation = gettext.GNUTranslations( | |
- pkg_resources.resource_stream('mcomix.messages', resource)) | |
+ resource = os.path.join('messages', lang, 'LC_MESSAGES', '%s.mo' % domain) | |
+ try: | |
+ fp = pkg_resources.resource_stream('mcomix', resource) | |
+ except IOError: | |
+ pass | |
+ else: | |
+ translation = gettext.GNUTranslations(fp) | |
break | |
+ else: | |
+ translation = gettext.NullTranslations() | |
translation.install(unicode=True) | |
diff --git a/mcomix/icons.py b/mcomix/icons.py | |
index 8eeeab9..b511ef7 100644 | |
--- a/mcomix/icons.py | |
+++ b/mcomix/icons.py | |
@@ -1,6 +1,6 @@ | |
"""icons.py - Load MComix specific icons.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from pkg_resources import resource_string | |
from mcomix import image_tools | |
@@ -13,7 +13,7 @@ def mcomix_icons(): | |
sizes = ('16x16', '32x32', '48x48') | |
pixbufs = [ | |
image_tools.load_pixbuf_data( | |
- resource_string('mcomix.images', size + '/mcomix.png') | |
+ resource_string('mcomix', 'images/%s/mcomix.png' % size) | |
) for size in sizes | |
] | |
@@ -45,14 +45,14 @@ def load_icons(): | |
# Load window title icons. | |
pixbufs = mcomix_icons() | |
- gtk.window_set_default_icon_list(*pixbufs) | |
+ Gtk.Window.set_default_icon_list(pixbufs) | |
# Load application icons. | |
- factory = gtk.IconFactory() | |
+ factory = Gtk.IconFactory() | |
for filename, stockid in _icons: | |
try: | |
- icon_data = resource_string('mcomix.images', filename) | |
+ icon_data = resource_string('mcomix', 'images/%s' % filename) | |
pixbuf = image_tools.load_pixbuf_data(icon_data) | |
- iconset = gtk.IconSet(pixbuf) | |
+ iconset = Gtk.IconSet(pixbuf) | |
factory.add(stockid, iconset) | |
except Exception: | |
log.warning(_('! Could not load icon "%s"'), filename) | |
diff --git a/mcomix/image_tools.py b/mcomix/image_tools.py | |
index c89b700..77abd95 100644 | |
--- a/mcomix/image_tools.py | |
+++ b/mcomix/image_tools.py | |
@@ -5,7 +5,7 @@ import binascii | |
import re | |
import sys | |
import operator | |
-import gtk | |
+from gi.repository import GLib, GdkPixbuf, Gdk, Gtk | |
from PIL import Image | |
from PIL import ImageEnhance | |
from PIL import ImageOps | |
@@ -34,22 +34,20 @@ else: | |
log.info('Using %s for loading images (versions: %s [%s], GDK [%s])', | |
'PIL' if USE_PIL else 'GDK', | |
PIL_VERSION[0], PIL_VERSION[1], | |
- # Unfortunately gdk_pixbuf_version is not exported, | |
- # so show the GTK+ version instead. | |
- 'GTK+ ' + '.'.join(map(str, gtk.gtk_version))) | |
+ GdkPixbuf.PIXBUF_VERSION) | |
# Fallback pixbuf for missing images. | |
MISSING_IMAGE_ICON = None | |
-_missing_icon_dialog = gtk.Dialog() | |
+_missing_icon_dialog = Gtk.Dialog() | |
_missing_icon_pixbuf = _missing_icon_dialog.render_icon( | |
- gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR) | |
+ Gtk.STOCK_MISSING_IMAGE, Gtk.IconSize.LARGE_TOOLBAR) | |
MISSING_IMAGE_ICON = _missing_icon_pixbuf | |
assert MISSING_IMAGE_ICON | |
-GTK_GDK_COLOR_BLACK = gtk.gdk.color_parse('black') | |
-GTK_GDK_COLOR_WHITE = gtk.gdk.color_parse('white') | |
+GTK_GDK_COLOR_BLACK = Gdk.color_parse('black') | |
+GTK_GDK_COLOR_WHITE = Gdk.color_parse('white') | |
def rotate_pixbuf(src, rotation): | |
@@ -57,11 +55,11 @@ def rotate_pixbuf(src, rotation): | |
if 0 == rotation: | |
return src | |
if 90 == rotation: | |
- return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_CLOCKWISE) | |
+ return src.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) | |
if 180 == rotation: | |
- return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN) | |
+ return src.rotate_simple(GdkPixbuf.PixbufRotation.UPSIDEDOWN) | |
if 270 == rotation: | |
- return src.rotate_simple(gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) | |
+ return src.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) | |
raise ValueError("unsupported rotation: %s" % rotation) | |
def get_fitting_size(source_size, target_size, | |
@@ -143,9 +141,9 @@ def fit_in_rectangle(src, width, height, keep_ratio=True, scale_up=False, rotati | |
else: | |
check_size, color1, color2 = 1024, 0xFFFFFF, 0xFFFFFF | |
if width == src_width and height == src_height: | |
- # Using anything other than INTERP_NEAREST will result in a | |
- # modified image even if it's opaque and no resizing takes place. | |
- scaling_quality = gtk.gdk.INTERP_NEAREST | |
+ # Using anything other than nearest interpolation will result in a | |
+ # modified image if no resizing takes place (even if it's opaque). | |
+ scaling_quality = GdkPixbuf.InterpType.NEAREST | |
src = src.composite_color_simple(width, height, scaling_quality, | |
255, check_size, color1, color2) | |
elif width != src_width or height != src_height: | |
@@ -160,7 +158,7 @@ def add_border(pixbuf, thickness, colour=0x000000FF): | |
"""Return a pixbuf from <pixbuf> with a <thickness> px border of | |
<colour> added. | |
""" | |
- canvas = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
+ canvas = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, | |
pixbuf.get_width() + thickness * 2, | |
pixbuf.get_height() + thickness * 2) | |
canvas.fill(colour) | |
@@ -245,7 +243,7 @@ def get_most_common_edge_colour(pixbufs, edge=2): | |
height = pixbuf.get_height() | |
edge = min(edge, width, height) | |
- subpix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, | |
+ subpix = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, | |
pixbuf.get_has_alpha(), 8, edge, height) | |
if side == 'left': | |
pixbuf.copy_area(0, 0, edge, height, subpix, 0, 0) | |
@@ -293,8 +291,8 @@ def pil_to_pixbuf(im, keep_orientation=False): | |
target_mode = 'RGBA' if has_alpha else 'RGB' | |
if im.mode != target_mode: | |
im = im.convert(target_mode) | |
- pixbuf = gtk.gdk.pixbuf_new_from_data( | |
- im.tobytes(), gtk.gdk.COLORSPACE_RGB, | |
+ pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( | |
+ GLib.Bytes.new(im.tobytes()), GdkPixbuf.Colorspace.RGB, | |
has_alpha, 8, | |
im.size[0], im.size[1], | |
(4 if has_alpha else 3) * im.size[0] | |
@@ -323,7 +321,8 @@ def pixbuf_to_pil(pixbuf): | |
return im | |
def is_animation(pixbuf): | |
- return isinstance(pixbuf, gtk.gdk.PixbufAnimation) | |
+ return isinstance(pixbuf, GdkPixbuf.PixbufAnimation) | |
+ #return isinstance(pixbuf, Gtk.gdk.PixbufAnimation) | |
def static_image(pixbuf): | |
""" Returns a non-animated version of the specified pixbuf. """ | |
@@ -333,24 +332,24 @@ def static_image(pixbuf): | |
def unwrap_image(image): | |
""" Returns an object that contains the image data based on | |
- gtk.Image.get_storage_type or None if image is None or image.get_storage_type | |
- returns gtk.IMAGE_EMPTY. """ | |
+ Gtk.Image.get_storage_type or None if image is None or image.get_storage_type | |
+ returns Gtk.IMAGE_EMPTY. """ | |
if image is None: | |
return None | |
t = image.get_storage_type() | |
- if t == gtk.IMAGE_EMPTY: | |
+ if t == Gtk.IMAGE_EMPTY: | |
return None | |
- if t == gtk.IMAGE_PIXBUF: | |
+ if t == Gtk.IMAGE_PIXBUF: | |
return image.get_pixbuf() | |
- if t == gtk.IMAGE_ANIMATION: | |
+ if t == Gtk.IMAGE_ANIMATION: | |
return image.get_animation() | |
- if t == gtk.IMAGE_PIXMAP: | |
+ if t == Gtk.IMAGE_PIXMAP: | |
return image.get_pixmap() | |
- if t == gtk.IMAGE_IMAGE: | |
+ if t == Gtk.IMAGE_IMAGE: | |
return image.get_image() | |
- if t == gtk.IMAGE_STOCK: | |
+ if t == Gtk.IMAGE_STOCK: | |
return image.get_stock() | |
- if t == gtk.IMAGE_ICON_SET: | |
+ if t == Gtk.IMAGE_ICON_SET: | |
return image.get_icon_set() | |
raise ValueError() | |
@@ -364,7 +363,7 @@ def load_pixbuf(path): | |
""" Loads a pixbuf from a given image file. """ | |
if prefs['animation mode'] != constants.ANIMATION_DISABLED: | |
# Note that this branch ignores USE_PIL | |
- pixbuf = gtk.gdk.PixbufAnimation(path) | |
+ pixbuf = Gtk.gdk.PixbufAnimation(path) | |
if pixbuf.is_static_image(): | |
pixbuf = pixbuf.get_static_image() | |
return pixbuf | |
@@ -372,7 +371,7 @@ def load_pixbuf(path): | |
im = Image.open(path) | |
pixbuf = pil_to_pixbuf(im, keep_orientation=True) | |
else: | |
- pixbuf = gtk.gdk.pixbuf_new_from_file(path) | |
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) | |
return pixbuf | |
def load_pixbuf_size(path, width, height): | |
@@ -387,24 +386,24 @@ def load_pixbuf_size(path, width, height): | |
# If we could not get the image info, still try to load | |
# the image to let GdkPixbuf raise the appropriate exception. | |
if (0, 0) == (image_width, image_height): | |
- pixbuf = gtk.gdk.pixbuf_new_from_file(path) | |
+ pixbuf = Gtk.gdk.pixbuf_new_from_file(path) | |
# Work around GdkPixbuf bug: https://bugzilla.gnome.org/show_bug.cgi?id=735422 | |
elif 'GIF' == image_format: | |
- pixbuf = gtk.gdk.pixbuf_new_from_file(path) | |
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) | |
else: | |
# Don't upscale if smaller than target dimensions! | |
if image_width <= width and image_height <= height: | |
width, height = image_width, image_height | |
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(path, width, height) | |
- return fit_in_rectangle(pixbuf, width, height, scaling_quality=gtk.gdk.INTERP_BILINEAR) | |
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, width, height) | |
+ return fit_in_rectangle(pixbuf, width, height, scaling_quality=GdkPixbuf.InterpType.BILINEAR) | |
def load_pixbuf_data(imgdata): | |
""" Loads a pixbuf from the data passed in <imgdata>. """ | |
if USE_PIL: | |
pixbuf = pil_to_pixbuf(Image.open(StringIO(imgdata)), keep_orientation=True) | |
else: | |
- loader = gtk.gdk.PixbufLoader() | |
- loader.write(imgdata, len(imgdata)) | |
+ loader = GdkPixbuf.PixbufLoader() | |
+ loader.write(imgdata) | |
loader.close() | |
pixbuf = loader.get_pixbuf() | |
return pixbuf | |
@@ -435,7 +434,7 @@ def _get_png_implied_rotation(pixbuf_or_image): | |
Lookup for Exif data in the tEXt chunk. | |
""" | |
- if isinstance(pixbuf_or_image, gtk.gdk.Pixbuf): | |
+ if isinstance(pixbuf_or_image, GdkPixbuf.Pixbuf): | |
exif = pixbuf_or_image.get_option('tEXt::Raw profile type exif') | |
elif isinstance(pixbuf_or_image, Image.Image): | |
exif = pixbuf_or_image.info.get('Raw profile type exif') | |
@@ -512,8 +511,10 @@ def combine_pixbufs( pixbuf1, pixbuf2, are_in_manga_mode ): | |
new_height = max( l_source_pixbuf_height, r_source_pixbuf_height ) | |
- new_pix_buf = gtk.gdk.Pixbuf( gtk.gdk.COLORSPACE_RGB, has_alpha, | |
- bits_per_sample, new_width, new_height ) | |
+ new_pix_buf = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=has_alpha, | |
+ bits_per_sample=bits_per_sample, | |
+ width=new_width, height=new_height) | |
l_source_pixbuf.copy_area( 0, 0, l_source_pixbuf_width, | |
l_source_pixbuf_height, | |
@@ -540,6 +541,9 @@ def text_color_for_background_color(bgcolor): | |
return GTK_GDK_COLOR_BLACK if rgb_to_y_601(bgcolor) >= \ | |
65535.0 / 2.0 else GTK_GDK_COLOR_WHITE | |
+def color_to_floats_rgba(color, alpha=1.0): | |
+ return [c / 65535.0 for c in color] + [alpha] | |
+ | |
def get_image_info(path): | |
"""Return image informations: | |
(format, width, height) | |
@@ -554,9 +558,11 @@ def get_image_info(path): | |
# cannot be opened and identified. | |
im = None | |
else: | |
- info = gtk.gdk.pixbuf_get_file_info(path) | |
- if info is not None: | |
- info = info[0]['name'].upper(), info[1], info[2] | |
+ info = GdkPixbuf.Pixbuf.get_file_info(path) | |
+ if info[0] is None: | |
+ info = None | |
+ else: | |
+ info = info[0].get_name().upper(), info[1], info[2] | |
if info is None: | |
info = (_('Unknown filetype'), 0, 0) | |
return info | |
@@ -595,12 +601,12 @@ def get_supported_formats(): | |
del supported_formats[name] | |
else: | |
supported_formats = {} | |
- for format in gtk.gdk.pixbuf_get_formats(): | |
- name = format['name'].upper() | |
+ for format in GdkPixbuf.Pixbuf.get_formats(): | |
+ name = format.get_name().upper() | |
assert name not in supported_formats | |
supported_formats[name] = ( | |
- format['mime_types'], | |
- format['extensions'], | |
+ format.get_mime_types(), | |
+ format.get_extensions(), | |
) | |
return supported_formats | |
diff --git a/mcomix/images/__init__.py b/mcomix/images/__init__.py | |
deleted file mode 100644 | |
index 7fc7b50..0000000 | |
--- a/mcomix/images/__init__.py | |
+++ /dev/null | |
@@ -1 +0,0 @@ | |
-""" This file is required for setuptools packaging. """ | |
diff --git a/mcomix/keybindings.py b/mcomix/keybindings.py | |
index b7dac0d..883ee2b 100644 | |
--- a/mcomix/keybindings.py | |
+++ b/mcomix/keybindings.py | |
@@ -26,7 +26,7 @@ Each action_name can have multiple keybindings. | |
import os | |
import shutil | |
-import gtk | |
+from gi.repository import Gtk | |
import json | |
from collections import defaultdict | |
@@ -163,7 +163,7 @@ class _KeybindingManager(object): | |
""" Registers an action for a predefined keybinding name. | |
@param name: Action name, defined in L{BINDING_INFO}. | |
@param bindings: List of keybinding strings, as understood | |
- by L{gtk.accelerator_parse}. Only used if no | |
+ by L{Gtk.accelerator_parse}. Only used if no | |
bindings were loaded for this action. | |
@param callback: Function callback | |
@param args: List of arguments to pass to the callback | |
@@ -174,7 +174,7 @@ class _KeybindingManager(object): | |
# Load stored keybindings, or fall back to passed arguments | |
keycodes = self._action_to_bindings[name] | |
if keycodes == []: | |
- keycodes = [gtk.accelerator_parse(binding) for binding in bindings ] | |
+ keycodes = [Gtk.accelerator_parse(binding) for binding in bindings ] | |
for keycode in keycodes: | |
if keycode in self._binding_to_action.keys(): | |
@@ -189,7 +189,7 @@ class _KeybindingManager(object): | |
# Add gtk accelerator for labels in menu | |
if len(self._action_to_bindings[name]) > 0: | |
key, mod = self._action_to_bindings[name][0] | |
- gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % name, key, mod, True) | |
+ Gtk.AccelMap.change_entry('<Actions>/mcomix-main/%s' % name, key, mod, True) | |
self._action_to_callback[name] = (callback, args, kwargs) | |
@@ -205,7 +205,7 @@ class _KeybindingManager(object): | |
""" | |
assert name in BINDING_INFO, "'%s' isn't a valid keyboard action." % name | |
- nb = gtk.accelerator_parse(new_binding) | |
+ nb = Gtk.accelerator_parse(new_binding) | |
old_action_with_nb = self._binding_to_action.get(nb) | |
if old_action_with_nb is not None: | |
# The new key is already bound to an action, erase the action | |
@@ -214,7 +214,7 @@ class _KeybindingManager(object): | |
if old_binding and name != old_action_with_nb: | |
# The action already had a key that is now being replaced | |
- ob = gtk.accelerator_parse(old_binding) | |
+ ob = Gtk.accelerator_parse(old_binding) | |
self._binding_to_action[nb] = name | |
# Remove action bound to the key. | |
@@ -236,7 +236,7 @@ class _KeybindingManager(object): | |
""" Remove binding for an action """ | |
assert name in BINDING_INFO, "'%s' isn't a valid keyboard action." % name | |
- ob = gtk.accelerator_parse(binding) | |
+ ob = Gtk.accelerator_parse(binding) | |
self._action_to_bindings[name].remove(ob) | |
self._binding_to_action.pop(ob) | |
@@ -277,7 +277,7 @@ class _KeybindingManager(object): | |
for action, bindings in self._action_to_bindings.iteritems(): | |
if bindings is not None: | |
action_to_keys[action] = [ | |
- gtk.accelerator_name(keyval, modifiers) for | |
+ Gtk.accelerator_name(keyval, modifiers) for | |
(keyval, modifiers) in bindings | |
] | |
fp = open(constants.KEYBINDINGS_CONF_PATH, "w") | |
@@ -297,7 +297,7 @@ class _KeybindingManager(object): | |
for action in BINDING_INFO.iterkeys(): | |
if action in stored_action_bindings: | |
bindings = [ | |
- gtk.accelerator_parse(keyname) | |
+ Gtk.accelerator_parse(keyname) | |
for keyname in stored_action_bindings[action] ] | |
self._action_to_bindings[action] = bindings | |
for binding in bindings: | |
@@ -313,7 +313,7 @@ class _KeybindingManager(object): | |
""" This method deals with upgrading from MComix 1.0 and older to | |
MComix 1.01, which integrated all UI hotkeys into this class. Simply | |
remove old files and start from default values. """ | |
- gtkrc = os.path.join(constants.CONFIG_DIR, 'keybindings-gtk.rc') | |
+ gtkrc = os.path.join(constants.CONFIG_DIR, 'keybindings-Gtk.rc') | |
if os.path.isfile(gtkrc): | |
# In case the user has made modifications to his files, | |
# keep the old ones around for reference. | |
diff --git a/mcomix/keybindings_editor.py b/mcomix/keybindings_editor.py | |
index 72fe9d3..b74d203 100644 | |
--- a/mcomix/keybindings_editor.py | |
+++ b/mcomix/keybindings_editor.py | |
@@ -2,18 +2,18 @@ | |
""" Configuration tree view for the preferences dialog to edit keybindings. """ | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import keybindings | |
-class KeybindingEditorWindow(gtk.ScrolledWindow): | |
+class KeybindingEditorWindow(Gtk.ScrolledWindow): | |
def __init__(self, keymanager): | |
""" @param keymanager: KeybindingManager instance. """ | |
super(KeybindingEditorWindow, self).__init__() | |
self.set_border_width(5) | |
- self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) | |
+ self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS) | |
self.keymanager = keymanager | |
@@ -27,21 +27,21 @@ class KeybindingEditorWindow(gtk.ScrolledWindow): | |
model = [str, str, 'gboolean'] | |
model.extend( [str, ] * accel_column_num) | |
- treestore = self.treestore = gtk.TreeStore(*model) | |
+ treestore = self.treestore = Gtk.TreeStore(*model) | |
self.refresh_model() | |
- treeview = gtk.TreeView(treestore) | |
+ treeview = Gtk.TreeView(treestore) | |
- tvcol1 = gtk.TreeViewColumn(_("Name")) | |
+ tvcol1 = Gtk.TreeViewColumn(_("Name")) | |
treeview.append_column(tvcol1) | |
- cell1 = gtk.CellRendererText() | |
+ cell1 = Gtk.CellRendererText() | |
tvcol1.pack_start(cell1, True) | |
tvcol1.set_attributes(cell1, text=0, editable=2) | |
for idx in range(0, self.accel_column_num): | |
- tvc = gtk.TreeViewColumn(_("Key %d") % (idx +1)) | |
+ tvc = Gtk.TreeViewColumn(_("Key %d") % (idx +1)) | |
treeview.append_column(tvc) | |
- accel_cell = gtk.CellRendererAccel() | |
+ accel_cell = Gtk.CellRendererAccel() | |
accel_cell.connect("accel-edited", self.get_on_accel_edited(idx)) | |
accel_cell.connect("accel-cleared", self.get_on_accel_cleared(idx)) | |
tvc.pack_start(accel_cell, True) | |
@@ -79,7 +79,7 @@ class KeybindingEditorWindow(gtk.ScrolledWindow): | |
acc_list = ["", ] * self.accel_column_num | |
for idx in range(0, self.accel_column_num): | |
if len(old_bindings) > idx: | |
- acc_list[idx] = gtk.accelerator_name(*old_bindings[idx]) | |
+ acc_list[idx] = Gtk.accelerator_name(*old_bindings[idx]) | |
row = [title, action_name, True] | |
row.extend(acc_list) | |
@@ -94,7 +94,7 @@ class KeybindingEditorWindow(gtk.ScrolledWindow): | |
iter = self.treestore.get_iter(path) | |
col = column + 3 # accel cells start from 3 position | |
old_accel = self.treestore.get(iter, col)[0] | |
- new_accel = gtk.accelerator_name(accel_key, accel_mods) | |
+ new_accel = Gtk.accelerator_name(accel_key, accel_mods) | |
self.treestore.set_value(iter, col, new_accel) | |
action_name = self.treestore.get_value(iter, 1) | |
affected_action = self.keymanager.edit_accel(action_name, new_accel, old_accel) | |
@@ -112,7 +112,7 @@ class KeybindingEditorWindow(gtk.ScrolledWindow): | |
# updating gtk accelerator for label in menu | |
if self.keymanager.get_bindings_for_action(action_name)[0] == (accel_key, accel_mods): | |
- gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, | |
+ Gtk.AccelMap.change_entry('<Actions>/mcomix-main/%s' % action_name, | |
accel_key, accel_mods, True) | |
return on_accel_edited | |
@@ -128,10 +128,10 @@ class KeybindingEditorWindow(gtk.ScrolledWindow): | |
# updating gtk accelerator for label in menu | |
if len(self.keymanager.get_bindings_for_action(action_name)) == 0: | |
- gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, 0, 0, True) | |
+ Gtk.AccelMap.change_entry('<Actions>/mcomix-main/%s' % action_name, 0, 0, True) | |
else: | |
key, mods = self.keymanager.get_bindings_for_action(action_name)[0] | |
- gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, key, mods, True) | |
+ Gtk.AccelMap.change_entry('<Actions>/mcomix-main/%s' % action_name, key, mods, True) | |
self.treestore.set_value(iter, col, "") | |
return on_accel_cleared | |
diff --git a/mcomix/labels.py b/mcomix/labels.py | |
index 7b1f491..1f814e9 100644 | |
--- a/mcomix/labels.py | |
+++ b/mcomix/labels.py | |
@@ -1,47 +1,49 @@ | |
-"""labels.py - gtk.Label convenience classes.""" | |
+"""labels.py - Gtk.Label convenience classes.""" | |
-import gtk | |
-import pango | |
+from gi.repository import GLib, Gtk, Pango | |
-class FormattedLabel(gtk.Label): | |
+class FormattedLabel(Gtk.Label): | |
"""FormattedLabel keeps a label always formatted with some pango weight, | |
style and scale, even when new text is set using set_text(). | |
""" | |
- def __init__(self, text='', weight=pango.WEIGHT_NORMAL, | |
- style=pango.STYLE_NORMAL, scale=1.0): | |
- super(FormattedLabel, self).__init__(text) | |
+ _STYLES = { | |
+ Pango.Style.NORMAL : 'normal', | |
+ Pango.Style.OBLIQUE: 'oblique', | |
+ Pango.Style.ITALIC : 'italic', | |
+ } | |
+ | |
+ def __init__(self, text='', weight=Pango.Weight.NORMAL, | |
+ style=Pango.Style.NORMAL, scale=1.0): | |
+ super(FormattedLabel, self).__init__() | |
self._weight = weight | |
self._style = style | |
self._scale = scale | |
- self._format() | |
+ self.set_text(text) | |
def set_text(self, text): | |
- gtk.Label.set_text(self, text) | |
- self._format() | |
- | |
- def _format(self): | |
- text_len = len(self.get_text()) | |
- attrlist = pango.AttrList() | |
- attrlist.insert(pango.AttrWeight(self._weight, 0, text_len)) | |
- attrlist.insert(pango.AttrStyle(self._style, 0, text_len)) | |
- attrlist.insert(pango.AttrScale(self._scale, 0, text_len)) | |
- self.set_attributes(attrlist) | |
+ markup = '<span font_size="%u" font_weight="%u" font_style="%s">%s</span>' % ( | |
+ int(self._scale * 10 * 1024), | |
+ self._weight, | |
+ self._STYLES[self._style], | |
+ GLib.markup_escape_text(text) | |
+ ) | |
+ self.set_markup(markup) | |
class BoldLabel(FormattedLabel): | |
"""A FormattedLabel that is always bold and otherwise normal.""" | |
def __init__(self, text=''): | |
- super(BoldLabel, self).__init__(text=text, weight=pango.WEIGHT_BOLD) | |
+ super(BoldLabel, self).__init__(text=text, weight=Pango.Weight.BOLD) | |
class ItalicLabel(FormattedLabel): | |
"""A FormattedLabel that is always italic and otherwise normal.""" | |
def __init__(self, text=''): | |
- super(ItalicLabel, self).__init__(text=text, style=pango.STYLE_ITALIC) | |
+ super(ItalicLabel, self).__init__(text=text, style=Pango.Style.ITALIC) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/lens.py b/mcomix/lens.py | |
index 80ac9b2..4f41114 100644 | |
--- a/mcomix/lens.py | |
+++ b/mcomix/lens.py | |
@@ -1,7 +1,8 @@ | |
"""lens.py - Magnifying lens.""" | |
import math | |
-import gtk | |
+ | |
+from gi.repository import Gdk, GdkPixbuf, Gtk | |
from mcomix.preferences import prefs | |
from mcomix import image_tools | |
@@ -58,24 +59,29 @@ class MagnifyingLens(object): | |
main window layout area. | |
""" | |
if self._window.images[0].get_storage_type() not in (gtk.IMAGE_PIXBUF, | |
- gtk.IMAGE_ANIMATION): | |
+ Gtk.IMAGE_ANIMATION): | |
return | |
rectangle = self._calculate_lens_rect(x, y, prefs['lens size'], prefs['lens size']) | |
pixbuf = self._get_lens_pixbuf(x, y) | |
- # Region used to draw the pixbuf | |
- lens_region = gtk.gdk.region_rectangle(rectangle) | |
- # Combined regions (area that will be drawn to in this operation | |
- full_region = lens_region.copy() | |
+ draw_region = Gdk.Rectangle() | |
+ draw_region.x, draw_region.y, draw_region.width, draw_region.height = rectangle | |
if self._last_lens_rect: | |
- last_region = gtk.gdk.region_rectangle(self._last_lens_rect) | |
- full_region.union(last_region) | |
+ last_region = Gdk.Rectangle() | |
+ last_region.x, last_region.y, last_region.width, last_region.height = self._last_lens_rect | |
+ draw_region = Gdk.rectangle_union(draw_region, last_region) | |
+ | |
+ window = self._window._main_layout.get_bin_window() | |
+ window.begin_paint_rect(draw_region) | |
+ | |
+ self._clear_lens() | |
+ | |
+ cr = window.cairo_create() | |
+ surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, window) | |
+ cr.set_source_surface(surface, rectangle[0], rectangle[1]) | |
+ cr.paint() | |
- window = self._area.get_bin_window() | |
- window.begin_paint_region(full_region) | |
- self._clear_lens(lens_region) | |
- window.draw_pixbuf(None, pixbuf, 0, 0, *rectangle) | |
window.end_paint() | |
self._last_lens_rect = rectangle | |
@@ -98,17 +104,17 @@ class MagnifyingLens(object): | |
return lens_x, lens_y, width + 2, height + 2 | |
def _clear_lens(self, current_lens_region=None): | |
- """ Invalidates the area that was damaged by the last call to draw_lens. | |
- If <current_lens_region> is not None, this region will not be invalidated. """ | |
+ """ Invalidates the area that was damaged by the last call to draw_lens. """ | |
if not self._last_lens_rect: | |
return | |
- last_region = gtk.gdk.region_rectangle(self._last_lens_rect) | |
- if current_lens_region: | |
- last_region.subtract(current_lens_region) | |
- | |
- self._area.get_bin_window().invalidate_region(last_region, True) | |
+ window = self._window._main_layout.get_bin_window() | |
+ crect = Gdk.Rectangle() | |
+ crect.x, crect.y, crect.width, crect.height = self._last_lens_rect | |
+ window.invalidate_rect(crect, True) | |
+ window.process_updates(True) | |
+ self._last_lens_rect = None | |
def toggle(self, action): | |
"""Toggle on or off the lens depending on the state of <action>.""" | |
@@ -124,8 +130,10 @@ class MagnifyingLens(object): | |
"""Get a pixbuf containing the appropiate image data for the lens | |
where <x> and <y> are the positions of the cursor. | |
""" | |
- canvas = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
- prefs['lens size'], prefs['lens size']) | |
+ canvas = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=True, bits_per_sample=8, | |
+ width=prefs['lens size'], | |
+ height=prefs['lens size']) | |
canvas.fill(image_tools.convert_rgb16list_to_rgba8int(self._window.get_bg_colour())) | |
cb = self._window.layout.get_content_boxes() | |
source_pixbufs = self._window.imagehandler.get_pixbufs(len(cb)) | |
@@ -207,7 +215,7 @@ class MagnifyingLens(object): | |
if width < 1 or height < 1: | |
return | |
- subpixbuf = source_pixbuf.subpixbuf(int(src_x), int(src_y), | |
+ subpixbuf = source_pixbuf.new_subpixbuf(int(src_x), int(src_y), | |
int(width), int(height)) | |
subpixbuf = subpixbuf.scale_simple( | |
int(math.ceil(source_mag * subpixbuf.get_width())), | |
@@ -216,13 +224,13 @@ class MagnifyingLens(object): | |
if rotation == 90: | |
subpixbuf = subpixbuf.rotate_simple( | |
- gtk.gdk.PIXBUF_ROTATE_CLOCKWISE) | |
+ Gdk.PIXBUF_ROTATE_CLOCKWISE) | |
elif rotation == 180: | |
subpixbuf = subpixbuf.rotate_simple( | |
- gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN) | |
+ Gdk.PIXBUF_ROTATE_UPSIDEDOWN) | |
elif rotation == 270: | |
subpixbuf = subpixbuf.rotate_simple( | |
- gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) | |
+ Gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) | |
if prefs['horizontal flip']: | |
subpixbuf = subpixbuf.flip(horizontal=True) | |
if prefs['vertical flip']: | |
@@ -241,7 +249,7 @@ class MagnifyingLens(object): | |
if subpixbuf.get_has_alpha() and prefs['checkered bg for transparent images']: | |
subpixbuf = subpixbuf.composite_color_simple(subpixbuf.get_width(), subpixbuf.get_height(), | |
- gtk.gdk.INTERP_NEAREST, 255, 8, 0x777777, 0x999999) | |
+ GdkPixbuf.InterpType.NEAREST, 255, 8, 0x777777, 0x999999) | |
subpixbuf.copy_area(0, 0, subpixbuf.get_width(), | |
subpixbuf.get_height(), canvas, dest_x, dest_y) | |
diff --git a/mcomix/library/add_progress_dialog.py b/mcomix/library/add_progress_dialog.py | |
index 7d77708..243b2f1 100644 | |
--- a/mcomix/library/add_progress_dialog.py | |
+++ b/mcomix/library/add_progress_dialog.py | |
@@ -1,7 +1,7 @@ | |
"""library_add_progress_dialog.py - Progress bar for the library.""" | |
-import gtk | |
-import pango | |
+from gi.repository import Gtk | |
+from gi.repository import Pango | |
from mcomix import labels | |
@@ -10,7 +10,7 @@ _dialog = None | |
# but is represented by this ID in the library's TreeModels. | |
_COLLECTION_ALL = -1 | |
-class _AddLibraryProgressDialog(gtk.Dialog): | |
+class _AddLibraryProgressDialog(Gtk.Dialog): | |
"""Dialog with a ProgressBar that adds books to the library.""" | |
@@ -19,7 +19,7 @@ class _AddLibraryProgressDialog(gtk.Dialog): | |
<collection>, unless it is None. | |
""" | |
super(_AddLibraryProgressDialog, self).__init__(_('Adding books'), library, | |
- gtk.DIALOG_MODAL, (gtk.STOCK_STOP, gtk.RESPONSE_CLOSE)) | |
+ Gtk.DialogFlags.MODAL, (Gtk.STOCK_STOP, Gtk.ResponseType.CLOSE)) | |
self._window = window | |
self._destroy = False | |
@@ -27,32 +27,34 @@ class _AddLibraryProgressDialog(gtk.Dialog): | |
self.set_resizable(False) | |
self.set_border_width(4) | |
self.connect('response', self._response) | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
- main_box = gtk.VBox(False, 5) | |
+ main_box = Gtk.VBox(False, 5) | |
main_box.set_border_width(6) | |
- self.vbox.pack_start(main_box, False, False) | |
- hbox = gtk.HBox(False, 10) | |
+ self.vbox.pack_start(main_box, False, False, 0) | |
+ hbox = Gtk.HBox(False, 10) | |
main_box.pack_start(hbox, False, False, 5) | |
- left_box = gtk.VBox(True, 5) | |
- right_box = gtk.VBox(True, 5) | |
- hbox.pack_start(left_box, False, False) | |
- hbox.pack_start(right_box, False, False) | |
+ left_box = Gtk.VBox(True, 5) | |
+ right_box = Gtk.VBox(True, 5) | |
+ hbox.pack_start(left_box, False, False, 0) | |
+ hbox.pack_start(right_box, False, False, 0) | |
label = labels.BoldLabel(_('Added books:')) | |
label.set_alignment(1.0, 1.0) | |
- left_box.pack_start(label, True, True) | |
- number_label = gtk.Label('0') | |
+ left_box.pack_start(label, True, True, 0) | |
+ number_label = Gtk.Label(label='0') | |
number_label.set_alignment(0, 1.0) | |
- right_box.pack_start(number_label, True, True) | |
+ right_box.pack_start(number_label, True, True, 0) | |
- bar = gtk.ProgressBar() | |
- main_box.pack_start(bar, False, False) | |
+ bar = Gtk.ProgressBar() | |
+ main_box.pack_start(bar, False, False, 0) | |
added_label = labels.ItalicLabel() | |
added_label.set_alignment(0, 0.5) | |
- added_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
- main_box.pack_start(added_label, False, False) | |
+ added_label.set_width_chars(64) | |
+ added_label.set_max_width_chars(64) | |
+ added_label.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
+ main_box.pack_start(added_label, False, False, 0) | |
self.show_all() | |
total_paths_int = len(paths) | |
@@ -69,8 +71,8 @@ class _AddLibraryProgressDialog(gtk.Dialog): | |
added_label.set_text(_("Adding '%s'...") % path) | |
bar.set_fraction(total_added / total_paths_float) | |
- while gtk.events_pending(): | |
- gtk.main_iteration_do(False) | |
+ while Gtk.events_pending(): | |
+ Gtk.main_iteration_do(False) | |
if self._destroy: | |
return | |
diff --git a/mcomix/library/book_area.py b/mcomix/library/book_area.py | |
index ea6d46d..7b7cd91 100644 | |
--- a/mcomix/library/book_area.py | |
+++ b/mcomix/library/book_area.py | |
@@ -2,8 +2,7 @@ | |
import os | |
import urllib | |
-import gtk | |
-import gobject | |
+from gi.repository import Gdk, GdkPixbuf, Gtk, GObject | |
import PIL.Image as Image | |
import PIL.ImageDraw as ImageDraw | |
@@ -27,7 +26,7 @@ _dialog = None | |
_COLLECTION_ALL = -1 | |
-class _BookArea(gtk.ScrolledWindow): | |
+class _BookArea(Gtk.ScrolledWindow): | |
"""The _BookArea is the central area in the library where the book | |
covers are displayed. | |
@@ -44,16 +43,16 @@ class _BookArea(gtk.ScrolledWindow): | |
self._library.backend.book_added_to_collection += self._new_book_added | |
- self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
+ self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
# Store Cover, book ID, book path, book size, date added to library, | |
# is thumbnail loaded? | |
# The SORT_ constants must correspond to the correct column here, | |
# i.e. SORT_SIZE must be 3, since 3 is the size column in the ListStore. | |
- self._liststore = gtk.ListStore(gtk.gdk.Pixbuf, | |
- gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_INT64, | |
- gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) | |
+ self._liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, | |
+ GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT64, | |
+ GObject.TYPE_STRING, GObject.TYPE_BOOLEAN) | |
self._liststore.set_sort_func(constants.SORT_NAME, self._sort_by_name, None) | |
self._liststore.set_sort_func(constants.SORT_PATH, self._sort_by_path, None) | |
self.set_sort_order() | |
@@ -73,21 +72,25 @@ class _BookArea(gtk.ScrolledWindow): | |
self._iconview.connect('button_press_event', self._button_press) | |
self._iconview.connect('key_press_event', self._key_press) | |
self._iconview.connect('popup_menu', self._popup_menu) | |
- self._iconview.modify_base(gtk.STATE_NORMAL, gtk.gdk.Color()) # Black. | |
- self._iconview.enable_model_drag_source(0, | |
- [('book', gtk.TARGET_SAME_APP, constants.LIBRARY_DRAG_EXTERNAL_ID)], | |
- gtk.gdk.ACTION_MOVE) | |
- self._iconview.drag_dest_set(gtk.DEST_DEFAULT_ALL, | |
- [('text/uri-list', 0, constants.LIBRARY_DRAG_EXTERNAL_ID)], | |
- gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) | |
- self._iconview.set_selection_mode(gtk.SELECTION_MULTIPLE) | |
+ self._iconview.modify_base(Gtk.StateType.NORMAL, image_tools.GTK_GDK_COLOR_BLACK) | |
+ self._iconview.enable_model_drag_source( | |
+ Gdk.ModifierType.BUTTON1_MASK, | |
+ [Gtk.TargetEntry.new('book', Gtk.TargetFlags.SAME_APP, | |
+ constants.LIBRARY_DRAG_EXTERNAL_ID)], | |
+ Gdk.DragAction.MOVE) | |
+ self._iconview.drag_dest_set( | |
+ Gtk.DestDefaults.ALL, | |
+ [Gtk.TargetEntry.new('text/uri-list', 0, | |
+ constants.LIBRARY_DRAG_EXTERNAL_ID)], | |
+ Gdk.DragAction.COPY | Gdk.DragAction.MOVE) | |
+ self._iconview.set_selection_mode(Gtk.SelectionMode.MULTIPLE) | |
self.add(self._iconview) | |
self._iconview.set_margin(0) | |
self._iconview.set_row_spacing(0) | |
self._iconview.set_column_spacing(0) | |
- self._ui_manager = gtk.UIManager() | |
+ self._ui_manager = Gtk.UIManager() | |
self._tooltipstatus = status.TooltipStatusHelper(self._ui_manager, | |
self._library.get_status_bar()) | |
@@ -130,34 +133,34 @@ class _BookArea(gtk.ScrolledWindow): | |
""" | |
self._ui_manager.add_ui_from_string(ui_description) | |
- actiongroup = gtk.ActionGroup('mcomix-library-book-area') | |
+ actiongroup = Gtk.ActionGroup('mcomix-library-book-area') | |
# General book actions | |
actiongroup.add_actions([ | |
('_title', None, _('Library books'), None, None, | |
None), | |
- ('open', gtk.STOCK_OPEN, _('_Open'), None, | |
+ ('open', Gtk.STOCK_OPEN, _('_Open'), None, | |
_('Opens the selected books for viewing.'), | |
self.open_selected_book), | |
- ('open keep library', gtk.STOCK_OPEN, | |
+ ('open keep library', Gtk.STOCK_OPEN, | |
_('Open _without closing library'), None, | |
_('Opens the selected books, but keeps the library window open.'), | |
self.open_selected_book_noclose), | |
- ('add', gtk.STOCK_ADD, _('_Add...'), '<Ctrl><Shift>a', | |
+ ('add', Gtk.STOCK_ADD, _('_Add...'), '<Ctrl><Shift>a', | |
_('Add more books to the library.'), | |
lambda *args: file_chooser_library_dialog.open_library_filechooser_dialog(self._library)), | |
- ('remove from collection', gtk.STOCK_REMOVE, | |
+ ('remove from collection', Gtk.STOCK_REMOVE, | |
_('Remove from this _collection'), None, | |
_('Removes the selected books from the current collection.'), | |
self._remove_books_from_collection), | |
- ('remove from library', gtk.STOCK_REMOVE, | |
+ ('remove from library', Gtk.STOCK_REMOVE, | |
_('Remove from the _library'), None, | |
_('Completely removes the selected books from the library.'), | |
self._remove_books_from_library), | |
- ('completely remove', gtk.STOCK_DELETE, | |
+ ('completely remove', Gtk.STOCK_DELETE, | |
_('_Remove and delete from disk'), None, | |
_('Deletes the selected books from disk.'), | |
self._completely_remove_book), | |
- ('copy to clipboard', gtk.STOCK_COPY, | |
+ ('copy to clipboard', Gtk.STOCK_COPY, | |
_('_Copy'), None, | |
_('Copies the selected book\'s path to clipboard.'), | |
self._copy_selected), | |
@@ -174,9 +177,9 @@ class _BookArea(gtk.ScrolledWindow): | |
('by date added', None, _('Date added'), None, None, constants.SORT_LAST_MODIFIED)], | |
prefs['lib sort key'], self._sort_changed) | |
actiongroup.add_radio_actions([ | |
- ('ascending', gtk.STOCK_SORT_ASCENDING, _('Ascending'), None, None, | |
+ ('ascending', Gtk.STOCK_SORT_ASCENDING, _('Ascending'), None, None, | |
constants.SORT_ASCENDING), | |
- ('descending', gtk.STOCK_SORT_DESCENDING, _('Descending'), None, None, | |
+ ('descending', Gtk.STOCK_SORT_DESCENDING, _('Descending'), None, None, | |
constants.SORT_DESCENDING)], | |
prefs['lib sort order'], self._sort_changed) | |
@@ -318,9 +321,9 @@ class _BookArea(gtk.ScrolledWindow): | |
Should be one of the C{SORT_} constants from L{constants}. | |
""" | |
if prefs['lib sort order'] == constants.SORT_ASCENDING: | |
- sortorder = gtk.SORT_ASCENDING | |
+ sortorder = Gtk.SortType.ASCENDING | |
else: | |
- sortorder = gtk.SORT_DESCENDING | |
+ sortorder = Gtk.SortType.DESCENDING | |
self._liststore.set_sort_column_id(prefs['lib sort key'], sortorder) | |
@@ -389,36 +392,36 @@ class _BookArea(gtk.ScrolledWindow): | |
elif name == 'tiny': | |
prefs['library cover size'] = constants.SIZE_TINY | |
elif name == 'custom': | |
- dialog = message_dialog.MessageDialog(self._library, gtk.DIALOG_DESTROY_WITH_PARENT, | |
- gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK) | |
+ dialog = message_dialog.MessageDialog(self._library, Gtk.DialogFlags.DESTROY_WITH_PARENT, | |
+ Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.OK) | |
dialog.set_auto_destroy(False) | |
dialog.set_text(_('Set library cover size')) | |
# Add adjustment scale | |
- adjustment = gtk.Adjustment(prefs['library cover size'], 20, | |
+ adjustment = Gtk.Adjustment(prefs['library cover size'], 20, | |
constants.MAX_LIBRARY_COVER_SIZE, 10, 25, 0) | |
- cover_size_scale = gtk.HScale(adjustment) | |
+ cover_size_scale = Gtk.HScale(adjustment) | |
cover_size_scale.set_size_request(200, -1) | |
cover_size_scale.set_digits(0) | |
cover_size_scale.set_draw_value(True) | |
- cover_size_scale.set_value_pos(gtk.POS_LEFT) | |
+ cover_size_scale.set_value_pos(Gtk.PositionType.LEFT) | |
for mark in (constants.SIZE_HUGE, constants.SIZE_LARGE, | |
constants.SIZE_NORMAL, constants.SIZE_SMALL, | |
constants.SIZE_TINY): | |
- cover_size_scale.add_mark(mark, gtk.POS_TOP, None) | |
+ cover_size_scale.add_mark(mark, Gtk.PositionType.TOP, None) | |
- dialog.get_message_area().pack_end(cover_size_scale) | |
+ dialog.get_message_area().pack_end(cover_size_scale, True, True, 0) | |
response = dialog.run() | |
size = int(adjustment.get_value()) | |
dialog.destroy() | |
- if response == gtk.RESPONSE_OK: | |
+ if response == Gtk.ResponseType.OK: | |
prefs['library cover size'] = size | |
if prefs['library cover size'] != old_size: | |
self._cache.invalidate_all() | |
collection = self._library.collection_area.get_current_collection() | |
- gobject.idle_add(self.display_covers, collection) | |
+ GObject.idle_add(self.display_covers, collection) | |
def _pixbuf_size(self, border_size=_BORDER_SIZE): | |
# Don't forget the extra pixels for the border! | |
@@ -451,23 +454,23 @@ class _BookArea(gtk.ScrolledWindow): | |
return pixbuf | |
# Composite icon on the lower right corner of the book cover pixbuf. | |
- book_pixbuf = self.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_LARGE_TOOLBAR) | |
+ book_pixbuf = self.render_icon(Gtk.STOCK_APPLY, Gtk.IconSize.LARGE_TOOLBAR) | |
translation_x = pixbuf.get_width() - book_pixbuf.get_width() - 1 | |
translation_y = pixbuf.get_height() - book_pixbuf.get_height() - 1 | |
book_pixbuf.composite(pixbuf, translation_x, translation_y, | |
book_pixbuf.get_width(), book_pixbuf.get_height(), | |
translation_x, translation_y, | |
- 1.0, 1.0, gtk.gdk.INTERP_NEAREST, 0xFF) | |
+ 1.0, 1.0, GdkPixbuf.InterpType.NEAREST, 0xFF) | |
return pixbuf | |
def _get_empty_thumbnail(self): | |
""" Create an empty filler pixmap. """ | |
width, height = self._pixbuf_size() | |
- pixbuf = gtk.gdk.Pixbuf(colorspace=gtk.gdk.COLORSPACE_RGB, | |
- has_alpha=True, | |
- bits_per_sample=8, | |
- width=width, height=height) | |
+ pixbuf = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=True, | |
+ bits_per_sample=8, | |
+ width=width, height=height) | |
# Make the pixbuf transparent. | |
pixbuf.fill(0) | |
@@ -545,10 +548,10 @@ class _BookArea(gtk.ScrolledWindow): | |
if request_response: | |
choice_dialog = message_dialog.MessageDialog(self._library, 0, | |
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO) | |
- choice_dialog.set_default_response(gtk.RESPONSE_YES) | |
+ Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO) | |
+ choice_dialog.set_default_response(Gtk.ResponseType.YES) | |
choice_dialog.set_should_remember_choice('library-remove-book-from-disk', | |
- (gtk.RESPONSE_YES,)) | |
+ (Gtk.ResponseType.YES,)) | |
choice_dialog.set_text( | |
_('Remove books from the library?'), | |
_('The selected books will be removed from the library and ' | |
@@ -557,7 +560,7 @@ class _BookArea(gtk.ScrolledWindow): | |
response = choice_dialog.run() | |
# if no request is needed or the user has told us they definitely want to delete the book | |
- if not request_response or (request_response and response == gtk.RESPONSE_YES): | |
+ if not request_response or (request_response and response == Gtk.ResponseType.YES): | |
# get the array of currently selected books in the book window | |
selected_books = self._iconview.get_selected_items() | |
@@ -616,7 +619,7 @@ class _BookArea(gtk.ScrolledWindow): | |
self._set_sensitive('copy to clipboard', len(selected) == 1) | |
menu = self._ui_manager.get_widget('/library books') | |
- menu.popup(None, None, None, 3, gtk.get_current_event_time()) | |
+ menu.popup(None, None, None, None, 3, Gtk.get_current_event_time()) | |
def _set_sensitive(self, action, sensitive): | |
""" Enables the popup menu action <action> based on <sensitive>. """ | |
@@ -626,7 +629,7 @@ class _BookArea(gtk.ScrolledWindow): | |
def _key_press(self, iconview, event): | |
"""Handle key presses on the _BookArea.""" | |
- if event.keyval == gtk.keysyms.Delete: | |
+ if event.keyval == Gdk.KEY_Delete: | |
self._remove_books_from_collection() | |
def _popup_menu(self, iconview): | |
@@ -646,7 +649,7 @@ class _BookArea(gtk.ScrolledWindow): | |
automatically created when using enable_model_drag_source(), so in | |
essence it's a hack, but at least it works. | |
""" | |
- icon_path = iconview.get_cursor()[0] | |
+ icon_path = iconview.get_cursor()[1] | |
num_books = len(iconview.get_selected_items()) | |
book = self.get_book_at_path(icon_path) | |
@@ -662,8 +665,10 @@ class _BookArea(gtk.ScrolledWindow): | |
if num_books > 1: | |
cover_width = cover.get_width() | |
cover_height = cover.get_height() | |
- pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
- max(30, cover_width + 15), max(30, cover_height + 10)) | |
+ pointer = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=True, bits_per_sample=8, | |
+ width=max(30, cover_width + 15), | |
+ height=max(30, cover_height + 10)) | |
pointer.fill(0x00000000) | |
cover.composite(pointer, 0, 0, cover_width, cover_height, 0, 0, | |
1, 1, prefs['scaling quality'], 255) | |
@@ -685,7 +690,7 @@ class _BookArea(gtk.ScrolledWindow): | |
else: | |
pointer = cover | |
- context.set_icon_pixbuf(pointer, -5, -5) | |
+ Gtk.drag_set_icon_pixbuf(context, pointer, -5, -5) | |
def _drag_data_get(self, iconview, context, selection, *args): | |
"""Fill the SelectionData with (iconview) paths for the dragged books | |
diff --git a/mcomix/library/collection_area.py b/mcomix/library/collection_area.py | |
index 8036e14..89f75d3 100644 | |
--- a/mcomix/library/collection_area.py | |
+++ b/mcomix/library/collection_area.py | |
@@ -1,8 +1,7 @@ | |
"""library_collection_area.py - Comic book library window that displays the collections.""" | |
from xml.sax.saxutils import escape as xmlescape | |
-import gtk | |
-import gobject | |
+from gi.repository import Gdk, GdkPixbuf, Gtk, GObject | |
from mcomix.preferences import prefs | |
from mcomix import constants | |
@@ -17,7 +16,7 @@ _dialog = None | |
_COLLECTION_ALL = -1 | |
_COLLECTION_RECENT = -2 | |
-class _CollectionArea(gtk.ScrolledWindow): | |
+class _CollectionArea(Gtk.ScrolledWindow): | |
"""The _CollectionArea is the sidebar area in the library where | |
different collections are displayed in a tree. | |
@@ -26,10 +25,10 @@ class _CollectionArea(gtk.ScrolledWindow): | |
def __init__(self, library): | |
super(_CollectionArea, self).__init__() | |
self._library = library | |
- self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) | |
+ self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) | |
- self._treestore = gtk.TreeStore(str, int) # (Name, ID) of collections. | |
- self._treeview = gtk.TreeView(self._treestore) | |
+ self._treestore = Gtk.TreeStore(str, int) # (Name, ID) of collections. | |
+ self._treeview = Gtk.TreeView(self._treestore) | |
self._treeview.connect('cursor_changed', self._collection_selected) | |
self._treeview.connect('drag_data_received', self._drag_data_received) | |
self._treeview.connect('drag_motion', self._drag_motion) | |
@@ -41,16 +40,16 @@ class _CollectionArea(gtk.ScrolledWindow): | |
self._treeview.set_headers_visible(False) | |
self._treeview.set_rules_hint(True) | |
self._set_acceptable_drop(True) | |
- self._treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, | |
- [('collection', gtk.TARGET_SAME_WIDGET, constants.LIBRARY_DRAG_COLLECTION_ID)], | |
- gtk.gdk.ACTION_MOVE) | |
+ self._treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, | |
+ [('collection', Gtk.TargetFlags.SAME_WIDGET, constants.LIBRARY_DRAG_COLLECTION_ID)], | |
+ Gdk.DragAction.MOVE) | |
- cellrenderer = gtk.CellRendererText() | |
- column = gtk.TreeViewColumn(None, cellrenderer, markup=0) | |
+ cellrenderer = Gtk.CellRendererText() | |
+ column = Gtk.TreeViewColumn(None, cellrenderer, markup=0) | |
self._treeview.append_column(column) | |
self.add(self._treeview) | |
- self._ui_manager = gtk.UIManager() | |
+ self._ui_manager = Gtk.UIManager() | |
self._tooltipstatus = status.TooltipStatusHelper(self._ui_manager, | |
self._library.get_status_bar()) | |
ui_description = """ | |
@@ -70,26 +69,26 @@ class _CollectionArea(gtk.ScrolledWindow): | |
</ui> | |
""" | |
self._ui_manager.add_ui_from_string(ui_description) | |
- actiongroup = gtk.ActionGroup('mcomix-library-collection-area') | |
+ actiongroup = Gtk.ActionGroup('mcomix-library-collection-area') | |
actiongroup.add_actions([ | |
('_title', None, _("Library collections"), None, None, | |
lambda *args: False), | |
- ('add', gtk.STOCK_ADD, _('_Add...'), None, | |
+ ('add', Gtk.STOCK_ADD, _('_Add...'), None, | |
_('Add more books to the library.'), | |
lambda *args: file_chooser_library_dialog.open_library_filechooser_dialog(self._library)), | |
- ('new', gtk.STOCK_NEW, _('New'), None, | |
+ ('new', Gtk.STOCK_NEW, _('New'), None, | |
_('Add a new empty collection.'), | |
self.add_collection), | |
- ('rename', gtk.STOCK_EDIT, _('Re_name'), None, | |
+ ('rename', Gtk.STOCK_EDIT, _('Re_name'), None, | |
_('Renames the selected collection.'), | |
self._rename_collection), | |
- ('duplicate', gtk.STOCK_COPY, _('_Duplicate'), None, | |
+ ('duplicate', Gtk.STOCK_COPY, _('_Duplicate'), None, | |
_('Creates a duplicate of the selected collection.'), | |
self._duplicate_collection), | |
- ('cleanup', gtk.STOCK_CLEAR, _('_Clean up'), None, | |
+ ('cleanup', Gtk.STOCK_CLEAR, _('_Clean up'), None, | |
_('Removes no longer existant books from the collection.'), | |
self._clean_collection), | |
- ('remove', gtk.STOCK_REMOVE, _('_Remove'), None, | |
+ ('remove', Gtk.STOCK_REMOVE, _('_Remove'), None, | |
_('Deletes the selected collection.'), | |
self._remove_collection)]) | |
self._ui_manager.insert_action_group(actiongroup, 0) | |
@@ -146,18 +145,18 @@ class _CollectionArea(gtk.ScrolledWindow): | |
def add_collection(self, *args): | |
"""Add a new collection to the library, through a dialog.""" | |
- add_dialog = message_dialog.MessageDialog(self._library, 0, gtk.MESSAGE_INFO, | |
- gtk.BUTTONS_OK_CANCEL) | |
+ add_dialog = message_dialog.MessageDialog(self._library, 0, Gtk.MessageType.INFO, | |
+ Gtk.ButtonsType.OK_CANCEL) | |
add_dialog.set_auto_destroy(False) | |
- add_dialog.set_default_response(gtk.RESPONSE_OK) | |
+ add_dialog.set_default_response(Gtk.ResponseType.OK) | |
add_dialog.set_text( | |
_('Add new collection?'), | |
_('Please enter a name for the new collection.') | |
) | |
- box = gtk.HBox() # To get nice line-ups with the padding. | |
- add_dialog.vbox.pack_start(box) | |
- entry = gtk.Entry() | |
+ box = Gtk.HBox() # To get nice line-ups with the padding. | |
+ add_dialog.vbox.pack_start(box, True, True, 0) | |
+ entry = Gtk.Entry() | |
entry.set_activates_default(True) | |
box.pack_start(entry, True, True, 6) | |
box.show_all() | |
@@ -165,7 +164,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
response = add_dialog.run() | |
name = entry.get_text().decode('utf-8') | |
add_dialog.destroy() | |
- if response == gtk.RESPONSE_OK and name: | |
+ if response == Gtk.ResponseType.OK and name: | |
if self._library.backend.add_collection(name): | |
collection = self._library.backend.get_collection_by_name(name) | |
prefs['last library collection'] = collection.id | |
@@ -194,7 +193,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
if removed > 0: | |
collection = self._library.collection_area.get_current_collection() | |
- gobject.idle_add(self._library.book_area.display_covers, collection) | |
+ GObject.idle_add(self._library.book_area.display_covers, collection) | |
def _get_collection_at_path(self, path): | |
"""Return the collection ID of the collection at the (TreeView) | |
@@ -212,7 +211,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
collection == prefs['last library collection']): | |
return | |
prefs['last library collection'] = collection | |
- gobject.idle_add(self._library.book_area.display_covers, collection) | |
+ GObject.idle_add(self._library.book_area.display_covers, collection) | |
def _clean_collection(self, *args): | |
""" Menu item hook to clean a collection. """ | |
@@ -242,17 +241,17 @@ class _CollectionArea(gtk.ScrolledWindow): | |
except Exception: | |
return | |
rename_dialog = message_dialog.MessageDialog(self._library, 0, | |
- gtk.MESSAGE_INFO, gtk.BUTTONS_OK_CANCEL) | |
+ Gtk.MessageType.INFO, Gtk.ButtonsType.OK_CANCEL) | |
rename_dialog.set_auto_destroy(False) | |
rename_dialog.set_text( | |
_('Rename collection?'), | |
_('Please enter a new name for the selected collection.') | |
) | |
- rename_dialog.set_default_response(gtk.RESPONSE_OK) | |
+ rename_dialog.set_default_response(Gtk.ResponseType.OK) | |
- box = gtk.HBox() # To get nice line-ups with the padding. | |
- rename_dialog.vbox.pack_start(box) | |
- entry = gtk.Entry() | |
+ box = Gtk.HBox() # To get nice line-ups with the padding. | |
+ rename_dialog.vbox.pack_start(box, True, True, 0) | |
+ entry = Gtk.Entry() | |
entry.set_text(old_name) | |
entry.set_activates_default(True) | |
box.pack_start(entry, True, True, 6) | |
@@ -261,7 +260,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
response = rename_dialog.run() | |
new_name = entry.get_text() | |
rename_dialog.destroy() | |
- if response == gtk.RESPONSE_OK and new_name: | |
+ if response == Gtk.ResponseType.OK and new_name: | |
if self._library.backend.rename_collection(collection, new_name): | |
self.display_collections() | |
else: | |
@@ -325,11 +324,11 @@ class _CollectionArea(gtk.ScrolledWindow): | |
self._ui_manager.get_action('/library collections/_title').set_sensitive(False) | |
menu = self._ui_manager.get_widget('/library collections') | |
- menu.popup(None, None, None, 3, gtk.get_current_event_time()) | |
+ menu.popup(None, None, None, None, 3, Gtk.get_current_event_time()) | |
def _key_press(self, treeview, event): | |
"""Handle key presses on the _CollectionArea.""" | |
- if event.keyval == gtk.keysyms.Delete: | |
+ if event.keyval == Gdk.KEY_Delete: | |
self._remove_collection() | |
def _expand_or_collapse_row(self, treeview, path, column): | |
@@ -348,13 +347,13 @@ class _CollectionArea(gtk.ScrolledWindow): | |
drop_row = treeview.get_dest_row_at_pos(x, y) | |
if drop_row is None: # Drop "after" the last row. | |
dest_path, pos = ((len(self._treestore) - 1,), | |
- gtk.TREE_VIEW_DROP_AFTER) | |
+ Gtk.TreeViewDropPosition.AFTER) | |
else: | |
dest_path, pos = drop_row | |
src_collection = self.get_current_collection() | |
dest_collection = self._get_collection_at_path(dest_path) | |
if drag_id == constants.LIBRARY_DRAG_COLLECTION_ID: | |
- if pos in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_AFTER): | |
+ if pos in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.AFTER): | |
dest_collection = self._library.backend.get_supercollection( | |
dest_collection) | |
self._library.backend.add_collection_to_collection( | |
@@ -382,10 +381,10 @@ class _CollectionArea(gtk.ScrolledWindow): | |
drop_row = treeview.get_dest_row_at_pos(x, y) | |
src_collection = self.get_current_collection() | |
# Why isn't the drag ID passed along with drag-motion events? | |
- if context.get_source_widget() is self._treeview: # Moving collection. | |
+ if Gtk.drag_get_source_widget(context) is self._treeview: # Moving collection. | |
model, src_iter = treeview.get_selection().get_selected() | |
if drop_row is None: # Drop "after" the last row. | |
- dest_path, pos = (len(model) - 1,), gtk.TREE_VIEW_DROP_AFTER | |
+ dest_path, pos = (len(model) - 1,), Gtk.TreeViewDropPosition.AFTER | |
else: | |
dest_path, pos = drop_row | |
dest_iter = model.get_iter(dest_path) | |
@@ -394,7 +393,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
self._library.set_status_message('') | |
return | |
dest_collection = self._get_collection_at_path(dest_path) | |
- if pos in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_AFTER): | |
+ if pos in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.AFTER): | |
dest_collection = self._library.backend.get_supercollection( | |
dest_collection) | |
if (_COLLECTION_ALL in (src_collection, dest_collection) or | |
@@ -418,7 +417,7 @@ class _CollectionArea(gtk.ScrolledWindow): | |
self._library.set_status_message('') | |
return | |
dest_path, pos = drop_row | |
- if pos in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_AFTER): | |
+ if pos in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.AFTER): | |
self._set_acceptable_drop(False) | |
self._library.set_status_message('') | |
return | |
@@ -445,11 +444,11 @@ class _CollectionArea(gtk.ScrolledWindow): | |
"""Set the TreeView to accept drops if <acceptable> is True.""" | |
if acceptable: | |
self._treeview.enable_model_drag_dest( | |
- [('book', gtk.TARGET_SAME_APP, constants.LIBRARY_DRAG_BOOK_ID), | |
- ('collection', gtk.TARGET_SAME_WIDGET, constants.LIBRARY_DRAG_COLLECTION_ID)], | |
- gtk.gdk.ACTION_MOVE) | |
+ [('book', Gtk.TargetFlags.SAME_APP, constants.LIBRARY_DRAG_BOOK_ID), | |
+ ('collection', Gtk.TargetFlags.SAME_WIDGET, constants.LIBRARY_DRAG_COLLECTION_ID)], | |
+ Gdk.DragAction.MOVE) | |
else: | |
- self._treeview.enable_model_drag_dest([], gtk.gdk.ACTION_MOVE) | |
+ self._treeview.enable_model_drag_dest([], Gdk.DragAction.MOVE) | |
def _drag_begin(self, treeview, context): | |
"""Create a cursor image for drag-n-drop of collections. We use the | |
@@ -458,13 +457,9 @@ class _CollectionArea(gtk.ScrolledWindow): | |
which unfortunately isn't the default case. | |
""" | |
path = treeview.get_cursor()[0] | |
- pixmap = treeview.create_row_drag_icon(path) | |
- # context.set_icon_pixmap() seems to cause crashes, so we do a | |
- # quick and dirty conversion to pixbuf. | |
- pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
- *pixmap.get_size()) | |
- pointer = pointer.get_from_drawable(pixmap, treeview.get_colormap(), | |
- 0, 0, 0, 0, *pixmap.get_size()) | |
- context.set_icon_pixbuf(pointer, -5, -5) | |
+ surface = treeview.create_row_drag_icon(path) | |
+ width, height = surface.get_width(), surface.get_height() | |
+ pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, width, height) | |
+ Gtk.drag_set_icon_pixbuf(context, pixbuf, -5, -5) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/library/control_area.py b/mcomix/library/control_area.py | |
index 57e64a9..f6cbbe8 100644 | |
--- a/mcomix/library/control_area.py | |
+++ b/mcomix/library/control_area.py | |
@@ -2,9 +2,9 @@ | |
and displays info.""" | |
import os | |
-import gtk | |
-import gobject | |
-import pango | |
+from gi.repository import Gtk | |
+from gi.repository import GObject | |
+from gi.repository import Pango | |
from mcomix import i18n | |
from mcomix import labels | |
@@ -15,7 +15,7 @@ from mcomix.library.watchlist import WatchListDialog | |
_COLLECTION_ALL = -1 | |
-class _ControlArea(gtk.HBox): | |
+class _ControlArea(Gtk.HBox): | |
"""The _ControlArea is the bottom area of the library window where | |
information is displayed and controls such as buttons reside. | |
@@ -27,49 +27,49 @@ class _ControlArea(gtk.HBox): | |
self._library = library | |
self.set_border_width(10) | |
- borderbox = gtk.Frame() | |
- borderbox.set_shadow_type(gtk.SHADOW_ETCHED_IN) | |
+ borderbox = Gtk.Frame() | |
+ borderbox.set_shadow_type(Gtk.ShadowType.ETCHED_IN) | |
borderbox.set_size_request(350, -1) | |
- insidebox = gtk.EventBox() | |
+ insidebox = Gtk.EventBox() | |
insidebox.set_border_width(1) | |
- insidebox.set_state(gtk.STATE_ACTIVE) | |
+ insidebox.set_state(Gtk.StateType.ACTIVE) | |
- infobox = gtk.VBox(False, 5) | |
+ infobox = Gtk.VBox(False, 5) | |
infobox.set_border_width(10) | |
- self.pack_start(borderbox) | |
+ self.pack_start(borderbox, True, True, 0) | |
borderbox.add(insidebox) | |
insidebox.add(infobox) | |
self._namelabel = labels.BoldLabel() | |
self._namelabel.set_alignment(0, 0.5) | |
self._namelabel.set_selectable(True) | |
- self._namelabel.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
- infobox.pack_start(self._namelabel, False, False) | |
+ self._namelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
+ infobox.pack_start(self._namelabel, False, False, 0) | |
- self._filelabel = gtk.Label() | |
- self._filelabel.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
+ self._filelabel = Gtk.Label() | |
+ self._filelabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
self._filelabel.set_alignment(0, 0.5) | |
- infobox.pack_start(self._filelabel, False, False) | |
+ infobox.pack_start(self._filelabel, False, False, 0) | |
- self._dirlabel = gtk.Label() | |
- self._dirlabel.set_ellipsize(pango.ELLIPSIZE_MIDDLE) | |
+ self._dirlabel = Gtk.Label() | |
+ self._dirlabel.set_ellipsize(Pango.EllipsizeMode.MIDDLE) | |
self._dirlabel.set_alignment(0, 0.5) | |
self._dirlabel.set_selectable(True) | |
- infobox.pack_start(self._dirlabel, False, False) | |
+ infobox.pack_start(self._dirlabel, False, False, 0) | |
- vbox = gtk.VBox(False, 10) | |
+ vbox = Gtk.VBox(False, 10) | |
vbox.set_size_request(350, -1) | |
- self.pack_start(vbox, False) | |
+ self.pack_start(vbox, False, False, 0) | |
# First line of controls, containing the search box | |
- hbox = gtk.HBox(False) | |
- vbox.pack_start(hbox) | |
+ hbox = Gtk.HBox(False) | |
+ vbox.pack_start(hbox, True, True, 0) | |
- label = gtk.Label(_('_Search:')) | |
+ label = Gtk.Label(label=_('_Search:')) | |
label.set_use_underline(True) | |
- hbox.pack_start(label, False, False) | |
- search_entry = gtk.Entry() | |
+ hbox.pack_start(label, False, False, 0) | |
+ search_entry = Gtk.Entry() | |
search_entry.connect('activate', self._filter_books) | |
search_entry.set_tooltip_text( | |
_('Display only those books that have the specified text string ' | |
@@ -78,24 +78,28 @@ class _ControlArea(gtk.HBox): | |
label.set_mnemonic_widget(search_entry) | |
# Last line of controls, containing buttons like 'Open' | |
- hbox = gtk.HBox(False, 10) | |
- vbox.pack_end(hbox) | |
+ hbox = Gtk.HBox(False, 10) | |
+ vbox.pack_end(hbox, True, True, 0) | |
- watchlist_button = gtk.Button(_("_Watch list")) | |
- watchlist_button.set_image( | |
- gtk.image_new_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON)) | |
+ watchlist_button = Gtk.Button(label=_("_Watch list"), use_underline=True) | |
+ watchlist_button.set_always_show_image(True) | |
+ watchlist_button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_FIND, Gtk.IconSize.BUTTON)) | |
+ watchlist_button.set_image_position(Gtk.PositionType.LEFT) | |
watchlist_button.connect('clicked', | |
lambda *args: WatchListDialog(self._library)) | |
watchlist_button.set_tooltip_text( | |
_('Open the watchlist management dialog.')) | |
- hbox.pack_start(watchlist_button) | |
+ hbox.pack_start(watchlist_button, True, True, 0) | |
- self._open_button = gtk.Button(None, gtk.STOCK_OPEN) | |
+ self._open_button = Gtk.Button(label=_("_Open list"), use_underline=True) | |
+ self._open_button.set_always_show_image(True) | |
+ self._open_button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.BUTTON)) | |
+ self._open_button.set_image_position(Gtk.PositionType.LEFT) | |
self._open_button.connect('clicked', | |
self._library.book_area.open_selected_book) | |
self._open_button.set_tooltip_text(_('Open the selected book.')) | |
self._open_button.set_sensitive(False) | |
- hbox.pack_end(self._open_button) | |
+ hbox.pack_end(self._open_button, True, True, 0) | |
def update_info(self, selected): | |
"""Update the info box using the currently <selected> books from | |
@@ -155,13 +159,13 @@ class _ControlArea(gtk.HBox): | |
def _filter_books(self, entry, *args): | |
"""Display only the books in the current collection whose paths | |
- contain the string in the gtk.Entry. The string is not | |
+ contain the string in the Gtk.Entry. The string is not | |
case-sensitive. | |
""" | |
self._library.filter_string = entry.get_text().decode('utf-8') | |
if not self._library.filter_string: | |
self._library.filter_string = None | |
collection = self._library.collection_area.get_current_collection() | |
- gobject.idle_add(self._library.book_area.display_covers, collection) | |
+ GObject.idle_add(self._library.book_area.display_covers, collection) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/library/main_dialog.py b/mcomix/library/main_dialog.py | |
index 5e34c25..816d390 100644 | |
--- a/mcomix/library/main_dialog.py | |
+++ b/mcomix/library/main_dialog.py | |
@@ -1,7 +1,7 @@ | |
"""library_main_dialog.py - The library dialog window.""" | |
import os | |
-import gtk | |
+from gi.repository import Gdk, Gtk | |
from mcomix.preferences import prefs | |
from mcomix import i18n | |
@@ -20,14 +20,14 @@ _dialog = None | |
# but is represented by this ID in the library's TreeModels. | |
_COLLECTION_ALL = -1 | |
-class _LibraryDialog(gtk.Window): | |
+class _LibraryDialog(Gtk.Window): | |
"""The library window. Automatically creates and uses a new | |
library_backend.LibraryBackend when opened. | |
""" | |
def __init__(self, window, file_handler): | |
- super(_LibraryDialog, self).__init__(gtk.WINDOW_TOPLEVEL) | |
+ super(_LibraryDialog, self).__init__(Gtk.WindowType.TOPLEVEL) | |
self._window = window | |
@@ -38,8 +38,7 @@ class _LibraryDialog(gtk.Window): | |
self.filter_string = None | |
self._file_handler = file_handler | |
- self._statusbar = gtk.Statusbar() | |
- self._statusbar.set_has_resize_grip(True) | |
+ self._statusbar = Gtk.Statusbar() | |
self.backend = library_backend.LibraryBackend() | |
self.book_area = library_book_area._BookArea(self) | |
self.control_area = library_control_area._ControlArea(self) | |
@@ -47,16 +46,16 @@ class _LibraryDialog(gtk.Window): | |
self.backend.watchlist.new_files_found += self._new_files_found | |
- table = gtk.Table(2, 2, False) | |
- table.attach(self.collection_area, 0, 1, 0, 1, gtk.FILL, | |
- gtk.EXPAND|gtk.FILL) | |
- table.attach(self.book_area, 1, 2, 0, 1, gtk.EXPAND|gtk.FILL, | |
- gtk.EXPAND|gtk.FILL) | |
- table.attach(self.control_area, 0, 2, 1, 2, gtk.EXPAND|gtk.FILL, | |
- gtk.FILL) | |
+ table = Gtk.Table(2, 2, False) | |
+ table.attach(self.collection_area, 0, 1, 0, 1, Gtk.AttachOptions.FILL, | |
+ Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL) | |
+ table.attach(self.book_area, 1, 2, 0, 1, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL, | |
+ Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL) | |
+ table.attach(self.control_area, 0, 2, 1, 2, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL, | |
+ Gtk.AttachOptions.FILL) | |
if prefs['show statusbar']: | |
- table.attach(self._statusbar, 0, 2, 2, 3, gtk.FILL, gtk.FILL) | |
+ table.attach(self._statusbar, 0, 2, 2, 3, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL) | |
self.add(table) | |
self.show_all() | |
@@ -154,7 +153,7 @@ class _LibraryDialog(gtk.Window): | |
def _key_press_event(self, widget, event, *args): | |
""" Handle key press events for closing the library on Escape press. """ | |
- if event.keyval == gtk.keysyms.Escape: | |
+ if event.keyval == Gdk.KEY_Escape: | |
self.hide() | |
diff --git a/mcomix/library/watchlist.py b/mcomix/library/watchlist.py | |
index 9f44094..582ea0c 100644 | |
--- a/mcomix/library/watchlist.py | |
+++ b/mcomix/library/watchlist.py | |
@@ -1,8 +1,8 @@ | |
""" Library watch list dialog and backend classes. """ | |
import os | |
-import gtk | |
-import gobject | |
+from gi.repository import Gtk | |
+from gi.repository import GObject | |
from mcomix.library import backend_types | |
from mcomix.preferences import prefs | |
@@ -13,7 +13,7 @@ COL_COLLECTION = 0 | |
COL_COLLECTION_ID = 1 | |
COL_RECURSIVE = 2 | |
-class WatchListDialog(gtk.Dialog): | |
+class WatchListDialog(Gtk.Dialog): | |
""" Dialog for managing watched directories. """ | |
RESPONSE_SCANNOW = 1000 | |
@@ -23,68 +23,68 @@ class WatchListDialog(gtk.Dialog): | |
@param library: Dialog parent window, should be library window. | |
""" | |
super(WatchListDialog, self).__init__(_("Library watch list"), | |
- library, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL, | |
+ library, Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, | |
(_('_Scan now').encode('utf-8'), WatchListDialog.RESPONSE_SCANNOW, | |
- gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) | |
+ Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) | |
#: Stores a reference to the library | |
self.library = library | |
#: True if changes were made to the watchlist. Not 100% accurate. | |
self._changed = False | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
# Initialize treeview control showing existing watch directories | |
- self._treeview = gtk.TreeView(self._create_model()) | |
+ self._treeview = Gtk.TreeView(self._create_model()) | |
self._treeview.set_headers_visible(True) | |
self._treeview.get_selection().connect('changed', self._item_selected_cb) | |
- dir_renderer = gtk.CellRendererText() | |
- dir_column = gtk.TreeViewColumn(_("Directory"), dir_renderer) | |
+ dir_renderer = Gtk.CellRendererText() | |
+ dir_column = Gtk.TreeViewColumn(_("Directory"), dir_renderer) | |
dir_column.set_attributes(dir_renderer, text=COL_DIRECTORY) | |
dir_column.set_expand(True) | |
self._treeview.append_column(dir_column) | |
collection_model = self._create_collection_model() | |
- collection_renderer = gtk.CellRendererCombo() | |
+ collection_renderer = Gtk.CellRendererCombo() | |
collection_renderer.set_property('model', collection_model) | |
collection_renderer.set_property('text-column', COL_COLLECTION) | |
- collection_renderer.set_property('editable', gtk.TRUE) | |
- collection_renderer.set_property('has-entry', gtk.FALSE) | |
+ collection_renderer.set_property('editable', True) | |
+ collection_renderer.set_property('has-entry', False) | |
collection_renderer.connect('changed', self._collection_changed_cb, collection_model) | |
- collection_column = gtk.TreeViewColumn(_("Collection"), collection_renderer) | |
+ collection_column = Gtk.TreeViewColumn(_("Collection"), collection_renderer) | |
collection_column.set_cell_data_func(collection_renderer, | |
self._treeview_collection_id_to_name) | |
self._treeview.append_column(collection_column) | |
- recursive_renderer = gtk.CellRendererToggle() | |
+ recursive_renderer = Gtk.CellRendererToggle() | |
recursive_renderer.set_activatable(True) | |
recursive_renderer.connect('toggled', self._recursive_changed_cb) | |
- recursive_column = gtk.TreeViewColumn(_("With subdirectories"), | |
+ recursive_column = Gtk.TreeViewColumn(_("With subdirectories"), | |
recursive_renderer) | |
recursive_column.add_attribute(recursive_renderer, 'active', COL_RECURSIVE) | |
self._treeview.append_column(recursive_column) | |
- add_button = gtk.Button(_("_Add"), gtk.STOCK_ADD) | |
+ add_button = Gtk.Button(_("_Add"), Gtk.STOCK_ADD, use_underline=True) | |
add_button.connect('clicked', self._add_cb) | |
- self._remove_button = remove_button = gtk.Button(_("_Remove"), gtk.STOCK_REMOVE) | |
+ self._remove_button = remove_button = Gtk.Button(_("_Remove"), Gtk.STOCK_REMOVE, use_underline=True) | |
remove_button.set_sensitive(False) | |
remove_button.connect('clicked', self._remove_cb) | |
- button_box = gtk.VBox() | |
- button_box.pack_start(add_button, expand=False) | |
- button_box.pack_start(remove_button, expand=False, padding=2) | |
+ button_box = Gtk.VBox() | |
+ button_box.pack_start(add_button, False, True, 0) | |
+ button_box.pack_start(remove_button, False, True, 2) | |
- main_box = gtk.HBox() | |
- scroll_window = gtk.ScrolledWindow() | |
- scroll_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
+ main_box = Gtk.HBox() | |
+ scroll_window = Gtk.ScrolledWindow() | |
+ scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
scroll_window.add(self._treeview) | |
- main_box.pack_start(scroll_window, padding=2) | |
- main_box.pack_end(button_box, expand=False) | |
- self.vbox.pack_start(main_box) | |
+ main_box.pack_start(scroll_window, True, True, 2) | |
+ main_box.pack_end(button_box, False, True, 0) | |
+ self.vbox.pack_start(main_box, True, True, 0) | |
- auto_checkbox = gtk.CheckButton( | |
- _('Automatically scan for new books when library is _opened'), True) | |
+ auto_checkbox = Gtk.CheckButton( | |
+ _('Automatically scan for new books when library is _opened'), use_underline=True) | |
auto_checkbox.set_active(prefs['scan for new books on library startup']) | |
auto_checkbox.connect('toggled', self._auto_scan_toggled_cb) | |
self.vbox.pack_end(auto_checkbox, False, False, 5) | |
@@ -115,7 +115,7 @@ class WatchListDialog(gtk.Dialog): | |
def _create_model(self): | |
""" Creates a model containing all watched directories. """ | |
# Watched directory, associated library collection ID | |
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_BOOLEAN) | |
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN) | |
self._fill_model(model) | |
return model | |
@@ -133,7 +133,7 @@ class WatchListDialog(gtk.Dialog): | |
def _create_collection_model(self): | |
""" Creates a model containing all available collections. """ | |
# Collection ID, collection name | |
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) | |
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT) | |
ids = self.library.backend.get_all_collections() | |
model.append((backend_types.DefaultCollection.name, -1)) | |
@@ -157,7 +157,7 @@ class WatchListDialog(gtk.Dialog): | |
iter = model.get_iter(path) | |
# Editing the model in the CellRendererCombo callback stops the editing | |
# operation, causing GTK warnings. Delay until callback is finished. | |
- gobject.idle_add(model.set_value, iter, COL_COLLECTION_ID, new_id) | |
+ GObject.idle_add(model.set_value, iter, COL_COLLECTION_ID, new_id) | |
self._changed = True | |
@@ -175,10 +175,10 @@ class WatchListDialog(gtk.Dialog): | |
def _add_cb(self, button, *args): | |
""" Called when a new watch list entry should be added. """ | |
- filechooser = gtk.FileChooserDialog(parent=self, | |
- action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | |
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, | |
- gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) | |
+ filechooser = Gtk.FileChooserDialog(parent=self, | |
+ action=Gtk.FileChooserAction.SELECT_FOLDER, | |
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, | |
+ Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT)) | |
result = filechooser.run() | |
if filechooser.get_filename() is not None: | |
directory = filechooser.get_filename().decode('utf-8') | |
@@ -186,7 +186,7 @@ class WatchListDialog(gtk.Dialog): | |
directory = u"" | |
filechooser.destroy() | |
- if result == gtk.RESPONSE_ACCEPT \ | |
+ if result == Gtk.ResponseType.ACCEPT \ | |
and os.path.isdir(directory): | |
self.library.backend.watchlist.add_directory(directory) | |
@@ -227,7 +227,7 @@ class WatchListDialog(gtk.Dialog): | |
def _close_cb(self, dialog, response, *args): | |
""" Trigger scan for new files after watch dialog closes. """ | |
self.destroy() | |
- if response == gtk.RESPONSE_CLOSE and self._changed: | |
+ if response == Gtk.ResponseType.CLOSE and self._changed: | |
self.library.scan_for_new_files() | |
elif response == WatchListDialog.RESPONSE_SCANNOW: | |
self.library.scan_for_new_files() | |
diff --git a/mcomix/main.py b/mcomix/main.py | |
index 8d0d0bf..2e618fa 100644 | |
--- a/mcomix/main.py | |
+++ b/mcomix/main.py | |
@@ -1,10 +1,12 @@ | |
"""main.py - Main window.""" | |
+import math | |
+import operator | |
import os | |
import shutil | |
import threading | |
-import gtk | |
-import gobject | |
+ | |
+from gi.repository import GObject, Gdk, Gtk | |
from mcomix import constants | |
from mcomix import cursor_handler | |
@@ -34,11 +36,9 @@ from mcomix.library import backend, main_dialog | |
from mcomix import tools | |
from mcomix import layout | |
from mcomix import log | |
-import math | |
-import operator | |
-class MainWindow(gtk.Window): | |
+class MainWindow(Gtk.Window): | |
"""The main window, is created at start and terminates the | |
program when closed. | |
@@ -47,7 +47,7 @@ class MainWindow(gtk.Window): | |
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__(gtk.WINDOW_TOPLEVEL) | |
+ super(MainWindow, self).__init__(Gtk.WindowType.TOPLEVEL) | |
# ---------------------------------------------------------------- | |
# Attributes | |
@@ -66,13 +66,19 @@ class MainWindow(gtk.Window): | |
self._spacing = 2 | |
self._waiting_for_redraw = False | |
- self._image_box = gtk.HBox(False, 2) # XXX transitional(kept for osd.py) | |
- self._main_layout = gtk.Layout() | |
+ self._image_box = Gtk.HBox(False, 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.HScrollbar(self._hadjust), | |
- gtk.VScrollbar(self._vadjust)) | |
+ 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 | |
@@ -95,7 +101,7 @@ class MainWindow(gtk.Window): | |
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 | |
+ self.images = [Gtk.Image(), Gtk.Image()] # XXX limited to at most 2 pages | |
# ---------------------------------------------------------------- | |
# Setup | |
@@ -111,8 +117,8 @@ class MainWindow(gtk.Window): | |
# 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.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) | |
@@ -123,22 +129,22 @@ class MainWindow(gtk.Window): | |
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._scroll[constants.HEIGHT_AXIS], 2, 3, 2, 3, gtk.FILL|gtk.SHRINK, | |
- gtk.FILL|gtk.SHRINK, 0, 0) | |
- table.attach(self._scroll[constants.WIDTH_AXIS], 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) | |
+ table = Gtk.Table(2, 2, 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() | |
@@ -220,18 +226,18 @@ class MainWindow(gtk.Window): | |
self.add(table) | |
table.show() | |
- self._main_layout.show() | |
+ self._event_box.show_all() | |
- 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.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.DEST_DEFAULT_ALL, | |
- [('text/uri-list', 0, 0)], | |
- gtk.gdk.ACTION_COPY | | |
- gtk.gdk.ACTION_MOVE) | |
+ 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) | |
@@ -282,10 +288,10 @@ class MainWindow(gtk.Window): | |
# Make sure we receive *all* mouse motion events, | |
# even if a modal dialog is being shown. | |
def _on_event(event): | |
- if gtk.gdk.MOTION_NOTIFY == event.type: | |
+ if Gdk.EventType.MOTION_NOTIFY == event.type: | |
self.cursor_handler.refresh() | |
- gtk.main_do_event(event) | |
- gtk.gdk.event_handler_set(_on_event) | |
+ Gtk.main_do_event(event) | |
+ Gdk.event_handler_set(_on_event) | |
def gained_focus(self, *args): | |
self.was_out_of_focus = False | |
@@ -304,8 +310,8 @@ class MainWindow(gtk.Window): | |
# FIXME: what if scroll_to is different? | |
if not self._waiting_for_redraw: # Don't stack up redraws. | |
self._waiting_for_redraw = True | |
- gobject.idle_add(self._draw_image, scroll_to, | |
- priority=gobject.PRIORITY_HIGH_IDLE) | |
+ GObject.idle_add(self._draw_image, scroll_to, | |
+ priority=GObject.PRIORITY_HIGH_IDLE) | |
def _update_toggle_preference(self, preference, toggleaction): | |
''' Update "toggle" widget corresponding <preference>. | |
@@ -353,6 +359,8 @@ class MainWindow(gtk.Window): | |
self._update_toggles_visibility() | |
+ self.osd.clear() | |
+ | |
if not self.filehandler.file_loaded: | |
self._clear_main_area() | |
self._waiting_for_redraw = False | |
@@ -476,7 +484,7 @@ class MainWindow(gtk.Window): | |
if smartthumbbg: | |
self.thumbnailsidebar.change_thumbnail_background_color(bg_colour) | |
- self._main_layout.window.freeze_updates() | |
+ self._main_layout.get_bin_window().freeze_updates() | |
self._main_layout.set_size(*union_scaled_size) | |
content_boxes = self.layout.get_content_boxes() | |
@@ -505,7 +513,7 @@ class MainWindow(gtk.Window): | |
index = None | |
self.scroll_to_predefined(destination, index) | |
- self._main_layout.window.thaw_updates() | |
+ self._main_layout.get_bin_window().thaw_updates() | |
else: | |
# Save scroll destination for when the page becomes available. | |
self._last_scroll_destination = scroll_to | |
@@ -601,7 +609,7 @@ class MainWindow(gtk.Window): | |
self.thumbnailsidebar.hide() | |
self.thumbnailsidebar.clear() | |
self.uimanager.set_sensitivities() | |
- self.set_icon_list(*icons.mcomix_icons()) | |
+ self.set_icon_list(icons.mcomix_icons()) | |
def new_page(self, at_bottom=False): | |
"""Draw a *new* page correctly (as opposed to redrawing the same | |
@@ -750,8 +758,8 @@ class MainWindow(gtk.Window): | |
@property | |
def is_fullscreen(self): | |
- window_state = self.window.get_state() | |
- return 0 != (window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN) | |
+ window_state = self.get_window().get_state() | |
+ return 0 != (window_state & Gdk.WindowState.FULLSCREEN) | |
def change_fullscreen(self, toggleaction): | |
# Disable action until transition if complete. | |
@@ -855,8 +863,8 @@ class MainWindow(gtk.Window): | |
visible_width, visible_height = self.get_visible_area_size() | |
- hadjust_upper = max(0, self._hadjust.upper - visible_width) | |
- vadjust_upper = max(0, self._vadjust.upper - visible_height) | |
+ hadjust_upper = max(0, self._hadjust.get_upper() - visible_width) | |
+ vadjust_upper = max(0, self._vadjust.get_upper() - visible_height) | |
hadjust_lower = 0 | |
if bound is not None and self.is_manga_mode: | |
@@ -864,10 +872,10 @@ class MainWindow(gtk.Window): | |
if bound == 'first': | |
hadjust_upper = max(0, hadjust_upper - | |
- self.images[1].size_request()[0] - 2) # XXX transitional(double page limitation) | |
+ self.images[1].size_request().width - 2) # XXX transitional(double page limitation) | |
elif bound == 'second': | |
- hadjust_lower = self.images[0].size_request()[0] + 2 # XXX transitional(double page limitation) | |
+ hadjust_lower = self.images[0].size_request().width + 2 # XXX transitional(double page limitation) | |
new_hadjust = old_hadjust + x | |
new_vadjust = old_vadjust + y | |
@@ -880,6 +888,8 @@ class MainWindow(gtk.Window): | |
self._vadjust.set_value(new_vadjust) | |
self._hadjust.set_value(new_hadjust) | |
+ self._scroll[0].queue_resize_no_redraw() | |
+ self._scroll[1].queue_resize_no_redraw() | |
return old_vadjust != new_vadjust or old_hadjust != new_hadjust | |
@@ -891,10 +901,12 @@ class MainWindow(gtk.Window): | |
viewport_position = self.layout.get_viewport_box().get_position() | |
self._hadjust.set_value(viewport_position[0]) # 2D only | |
self._vadjust.set_value(viewport_position[1]) # 2D only | |
+ self._scroll[0].queue_resize_no_redraw() | |
+ self._scroll[1].queue_resize_no_redraw() | |
def update_layout_position(self): | |
self.layout.set_viewport_position( | |
- (int(round(self._hadjust.value)), int(round(self._vadjust.value)))) | |
+ (int(round(self._hadjust.get_value())), int(round(self._vadjust.get_value())))) | |
def clear(self): | |
"""Clear the currently displayed data (i.e. "close" the file).""" | |
@@ -929,7 +941,12 @@ class MainWindow(gtk.Window): | |
for widget in widget_list: | |
if widget.get_visible(): | |
axis = self._toggle_axis[widget] | |
- dimensions[axis] -= widget.size_request()[axis] | |
+ requisition = widget.size_request() | |
+ if constants.WIDTH_AXIS == axis: | |
+ size = requisition.width | |
+ elif constants.HEIGHT_AXIS == axis: | |
+ size = requisition.height | |
+ dimensions[axis] -= size | |
return tuple(dimensions) | |
@@ -948,7 +965,7 @@ class MainWindow(gtk.Window): | |
probably use the cursor_handler instead of using this method | |
directly. | |
""" | |
- self._main_layout.window.set_cursor(mode) | |
+ self._main_layout.get_bin_window().set_cursor(mode) | |
def update_title(self): | |
"""Set the title acording to current state.""" | |
@@ -972,11 +989,7 @@ class MainWindow(gtk.Window): | |
"""Set the background colour to <colour>. Colour is a sequence in the | |
format (r, g, b). Values are 16-bit. | |
""" | |
- self._main_layout.modify_bg(gtk.STATE_NORMAL, | |
- gtk.gdk.Color(colour[0], | |
- colour[1], | |
- colour[2])) | |
- | |
+ self._event_box.modify_bg(Gtk.StateType.NORMAL, Gdk.Color(*colour)) | |
if prefs['thumbnail bg uses main colour']: | |
self.thumbnailsidebar.change_thumbnail_background_color(prefs['bg colour']) | |
self._bg_colour = colour | |
@@ -995,13 +1008,12 @@ class MainWindow(gtk.Window): | |
else: | |
suggested_name = os.path.split(self.imagehandler.get_path_to_page())[-1] | |
- save_dialog = gtk.FileChooserDialog(_('Save page as'), self, | |
- gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, | |
- gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) | |
- save_dialog.set_do_overwrite_confirmation(True) | |
+ save_dialog = Gtk.FileChooserDialog(_('Save page as'), self, | |
+ Gtk.FileChooserAction.SAVE, (Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT, | |
+ Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT)) | |
save_dialog.set_current_name(suggested_name.encode('utf-8')) | |
- if save_dialog.run() == gtk.RESPONSE_ACCEPT and save_dialog.get_filename(): | |
+ if save_dialog.run() == Gtk.ResponseType.ACCEPT and save_dialog.get_filename(): | |
shutil.copy(self.imagehandler.get_path_to_page(), | |
save_dialog.get_filename().decode('utf-8')) | |
@@ -1012,18 +1024,18 @@ class MainWindow(gtk.Window): | |
a confirmation dialog. """ | |
current_file = self.imagehandler.get_real_path() | |
- dialog = message_dialog.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, | |
- gtk.BUTTONS_NONE) | |
- dialog.set_should_remember_choice('delete-opend-file', (gtk.RESPONSE_OK,)) | |
+ dialog = message_dialog.MessageDialog(self, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, | |
+ Gtk.ButtonsType.NONE) | |
+ dialog.set_should_remember_choice('delete-opend-file', (Gtk.ResponseType.OK,)) | |
dialog.set_text( | |
_('Delete "%s"?') % os.path.basename(current_file), | |
_('The file will be deleted from your harddisk.')) | |
- dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) | |
- dialog.add_button(gtk.STOCK_DELETE, gtk.RESPONSE_OK) | |
- dialog.set_default_response(gtk.RESPONSE_OK) | |
+ dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) | |
+ dialog.add_button(Gtk.STOCK_DELETE, Gtk.ResponseType.OK) | |
+ dialog.set_default_response(Gtk.ResponseType.OK) | |
result = dialog.run() | |
- if result == gtk.RESPONSE_OK: | |
+ if result == Gtk.ResponseType.OK: | |
# Go to next page/archive, and delete current file | |
if self.filehandler.archive_type is not None: | |
self.filehandler.last_read_page.clear_page(current_file) | |
@@ -1125,8 +1137,8 @@ class MainWindow(gtk.Window): | |
self.hide() | |
- if gtk.main_level() > 0: | |
- gtk.main_quit() | |
+ if Gtk.main_level() > 0: | |
+ Gtk.main_quit() | |
if prefs['auto load last file'] and self.filehandler.file_loaded: | |
prefs['path to last file'] = self.imagehandler.get_real_path() | |
diff --git a/mcomix/message_dialog.py b/mcomix/message_dialog.py | |
index 1c90f4a..dc56c93 100644 | |
--- a/mcomix/message_dialog.py | |
+++ b/mcomix/message_dialog.py | |
@@ -1,13 +1,13 @@ | |
-""" Simple extension of gtk.MessageDialog for consistent formating. Also | |
+""" Simple extension of Gtk.MessageDialog for consistent formating. Also | |
supports remembering the dialog result. | |
""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix.preferences import prefs | |
-class MessageDialog(gtk.MessageDialog): | |
+class MessageDialog(Gtk.MessageDialog): | |
def __init__(self, parent=None, flags=0, type=0, buttons=0): | |
""" Creates a dialog window. | |
@@ -29,10 +29,10 @@ class MessageDialog(gtk.MessageDialog): | |
#: Automatically destroy dialog after run? | |
self.auto_destroy = True | |
- self.remember_checkbox = gtk.CheckButton(_('Do not ask again.')) | |
+ self.remember_checkbox = Gtk.CheckButton(_('Do not ask again.')) | |
self.remember_checkbox.set_no_show_all(True) | |
self.remember_checkbox.set_can_focus(False) | |
- self.get_message_area().pack_end(self.remember_checkbox, padding=6) | |
+ self.get_message_area().pack_end(self.remember_checkbox, True, True, 6) | |
def set_text(self, primary, secondary=None): | |
""" Formats the dialog's text fields. | |
diff --git a/mcomix/messages/__init__.py b/mcomix/messages/__init__.py | |
deleted file mode 100644 | |
index 7fc7b50..0000000 | |
--- a/mcomix/messages/__init__.py | |
+++ /dev/null | |
@@ -1 +0,0 @@ | |
-""" This file is required for setuptools packaging. """ | |
diff --git a/mcomix/openwith.py b/mcomix/openwith.py | |
index 8732f52..2f0dc94 100644 | |
--- a/mcomix/openwith.py | |
+++ b/mcomix/openwith.py | |
@@ -2,8 +2,8 @@ | |
import sys | |
import os | |
import re | |
-import gtk | |
-import gobject | |
+from gi.repository import Gtk | |
+from gi.repository import GObject | |
from mcomix.preferences import prefs | |
from mcomix import message_dialog | |
@@ -266,7 +266,7 @@ class OpenWithCommand(object): | |
return context | |
-class OpenWithEditor(gtk.Dialog): | |
+class OpenWithEditor(Gtk.Dialog): | |
""" The editor for changing and creating external commands. This window | |
keeps its own internal model once initialized, and will overwrite | |
the external model (i.e. preferences) only when properly closed. """ | |
@@ -278,31 +278,31 @@ class OpenWithEditor(gtk.Dialog): | |
self._openwith = openwithmanager | |
self._changed = False | |
- self._command_tree = gtk.TreeView() | |
+ self._command_tree = Gtk.TreeView() | |
self._command_tree.get_selection().connect('changed', self._item_selected) | |
- self._add_button = gtk.Button(stock=gtk.STOCK_ADD) | |
+ self._add_button = Gtk.Button(stock=Gtk.STOCK_ADD) | |
self._add_button.connect('clicked', self._add_command) | |
- self._add_sep_button = gtk.Button(_('Add _separator')) | |
+ self._add_sep_button = Gtk.Button.new_with_mnemonic(_('Add _separator')) | |
self._add_sep_button.connect('clicked', self._add_sep_command) | |
- self._remove_button = gtk.Button(stock=gtk.STOCK_REMOVE) | |
+ self._remove_button = Gtk.Button(stock=Gtk.STOCK_REMOVE) | |
self._remove_button.connect('clicked', self._remove_command) | |
self._remove_button.set_sensitive(False) | |
- self._up_button = gtk.Button(stock=gtk.STOCK_GO_UP) | |
+ self._up_button = Gtk.Button(stock=Gtk.STOCK_GO_UP) | |
self._up_button.connect('clicked', self._up_command) | |
self._up_button.set_sensitive(False) | |
- self._down_button = gtk.Button(stock=gtk.STOCK_GO_DOWN) | |
+ self._down_button = Gtk.Button(stock=Gtk.STOCK_GO_DOWN) | |
self._down_button.connect('clicked', self._down_command) | |
self._down_button.set_sensitive(False) | |
- self._run_button = gtk.Button(_('Run _command')) | |
+ self._run_button = Gtk.Button.new_with_mnemonic(_('Run _command')) | |
self._run_button.connect('clicked', self._run_command) | |
self._run_button.set_sensitive(False) | |
- self._test_field = gtk.Entry() | |
- self._test_field.set_property('editable', gtk.FALSE) | |
- self._exec_label = gtk.Label() | |
+ self._test_field = Gtk.Entry() | |
+ self._test_field.set_property('editable', False) | |
+ self._exec_label = Gtk.Label() | |
self._exec_label.set_alignment(0, 0) | |
self._set_exec_text('') | |
- self._save_button = self.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT) | |
- self.set_default_response(gtk.RESPONSE_ACCEPT) | |
+ self._save_button = self.add_button(Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT) | |
+ self.set_default_response(Gtk.ResponseType.ACCEPT) | |
self._layout() | |
self._setup_table() | |
@@ -379,7 +379,7 @@ class OpenWithEditor(gtk.Dialog): | |
def _add_command(self, button): | |
""" Add a new empty label-command line to the list. """ | |
- row = (_('Command label'), '', '', gtk.FALSE, gtk.TRUE) | |
+ row = (_('Command label'), '', '', False, True) | |
selection = self._command_tree.get_selection() | |
if selection and selection.get_selected()[1]: | |
model, iter = selection.get_selected() | |
@@ -390,7 +390,7 @@ class OpenWithEditor(gtk.Dialog): | |
def _add_sep_command(self, button): | |
""" Adds a new separator line. """ | |
- row = ('-', '', '', gtk.FALSE, gtk.FALSE) | |
+ row = ('-', '', '', False, False) | |
selection = self._command_tree.get_selection() | |
if selection and selection.get_selected()[1]: | |
model, iter = selection.get_selected() | |
@@ -452,64 +452,64 @@ class OpenWithEditor(gtk.Dialog): | |
""" Create and lay out UI components. """ | |
# All these boxes basically are just for adding a 4px border | |
vbox = self.get_content_area() | |
- hbox = gtk.HBox() | |
- vbox.pack_start(hbox, padding=4) | |
- content = gtk.VBox() | |
+ hbox = Gtk.HBox() | |
+ vbox.pack_start(hbox, True, True, 4) | |
+ content = Gtk.VBox() | |
content.set_spacing(6) | |
- hbox.pack_start(content, padding=4) | |
+ hbox.pack_start(content, True, True, 4) | |
- scroll_window = gtk.ScrolledWindow() | |
- scroll_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
+ scroll_window = Gtk.ScrolledWindow() | |
+ scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
scroll_window.add(self._command_tree) | |
- content.pack_start(scroll_window) | |
+ content.pack_start(scroll_window, True, True, 0) | |
- buttonbox = gtk.HBox() | |
- buttonbox.pack_start(self._add_button, False) | |
- buttonbox.pack_start(self._add_sep_button, False) | |
- buttonbox.pack_start(self._remove_button, False) | |
- buttonbox.pack_start(self._up_button, False) | |
- buttonbox.pack_start(self._down_button, False) | |
- content.pack_start(buttonbox, False) | |
+ buttonbox = Gtk.HBox() | |
+ buttonbox.pack_start(self._add_button, False, False, 0) | |
+ buttonbox.pack_start(self._add_sep_button, False, False, 0) | |
+ buttonbox.pack_start(self._remove_button, False, False, 0) | |
+ buttonbox.pack_start(self._up_button, False, False, 0) | |
+ buttonbox.pack_start(self._down_button, False, False, 0) | |
+ content.pack_start(buttonbox, False, False, 0) | |
- preview_box = gtk.HBox() | |
- preview_box.pack_start(gtk.Label(_('Preview:')), False) | |
- preview_box.pack_start(self._test_field, padding=4) | |
- preview_box.pack_start(self._run_button, False) | |
- content.pack_start(preview_box, False) | |
+ preview_box = Gtk.HBox() | |
+ preview_box.pack_start(Gtk.Label(_('Preview:')), False, False, 0) | |
+ preview_box.pack_start(self._test_field, True, True, 4) | |
+ preview_box.pack_start(self._run_button, False, False, 0) | |
+ content.pack_start(preview_box, False, False, 0) | |
- content.pack_start(self._exec_label, False) | |
+ content.pack_start(self._exec_label, False, False, 0) | |
- linklabel = gtk.Label() | |
+ linklabel = Gtk.Label() | |
linklabel.set_markup(_('Please refer to the <a href="%s">external command documentation</a> ' | |
'for a list of usable variables and other hints.') % \ | |
'https://sourceforge.net/p/mcomix/wiki/External_Commands') | |
linklabel.set_alignment(0, 0) | |
- content.pack_start(linklabel, False, padding=4) | |
+ content.pack_start(linklabel, False, False, 4) | |
def _setup_table(self): | |
""" Initializes the TreeView with settings and data. """ | |
for i, label in enumerate((_('Label'), _('Command'), _('Working directory'))): | |
- renderer = gtk.CellRendererText() | |
+ renderer = Gtk.CellRendererText() | |
renderer.connect('edited', self._text_changed, i) | |
- column = gtk.TreeViewColumn(label, renderer) | |
- column.set_property('resizable', gtk.TRUE) | |
+ column = Gtk.TreeViewColumn(label, renderer) | |
+ column.set_property('resizable', True) | |
column.set_attributes(renderer, text=i, editable=4) | |
if (i == 1): | |
column.set_expand(True) # Command column should scale automatically | |
self._command_tree.append_column(column) | |
# The 'Disabled in archives' field is shown as toggle button | |
- renderer = gtk.CellRendererToggle() | |
+ renderer = Gtk.CellRendererToggle() | |
renderer.connect('toggled', self._value_changed, | |
len(self._command_tree.get_columns())) | |
- column = gtk.TreeViewColumn(_('Disabled in archives'), renderer) | |
+ column = Gtk.TreeViewColumn(_('Disabled in archives'), renderer) | |
column.set_attributes(renderer, active=len(self._command_tree.get_columns()), | |
activatable=4) | |
self._command_tree.append_column(column) | |
# Label, command, working dir, disabled for archives, line is editable | |
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, | |
- gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN) | |
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, | |
+ GObject.TYPE_BOOLEAN, GObject.TYPE_BOOLEAN) | |
for command in self._openwith.get_commands(): | |
model.append((command.get_label(), command.get_command(), command.get_cwd(), | |
command.is_disabled_for_archives(), not command.is_separator())) | |
@@ -533,7 +533,7 @@ class OpenWithEditor(gtk.Dialog): | |
model.set_value(iter, column, new_text) | |
self._changed = old_value != new_text | |
self.test_command() | |
- gobject.idle_add(delayed_set_value) | |
+ GObject.idle_add(delayed_set_value) | |
def _value_changed(self, renderer, path, column): | |
""" Called when a toggle field is changed """ | |
@@ -546,24 +546,24 @@ class OpenWithEditor(gtk.Dialog): | |
model.set_value(iter, column, value) | |
self._changed = True | |
- gobject.idle_add(delayed_set_value) | |
+ GObject.idle_add(delayed_set_value) | |
def _response(self, dialog, response): | |
- if response == gtk.RESPONSE_ACCEPT: | |
+ if response == Gtk.ResponseType.ACCEPT: | |
# The Save button is only enabled if all commands are valid | |
self.save() | |
- self.hide_all() | |
+ self.hide() | |
else: | |
if self._changed: | |
- confirm_diag = message_dialog.MessageDialog(self, gtk.DIALOG_MODAL, | |
- gtk.MESSAGE_INFO, gtk.BUTTONS_YES_NO) | |
+ confirm_diag = message_dialog.MessageDialog(self, Gtk.DialogFlags.MODAL, | |
+ Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO) | |
confirm_diag.set_text(_('Save changes to commands?'), | |
_('You have made changes to the list of external commands that ' | |
'have not been saved yet. Press "Yes" to save all changes, ' | |
'or "No" to discard them.')) | |
response = confirm_diag.run() | |
- if response == gtk.RESPONSE_YES: | |
+ if response == Gtk.ResponseType.YES: | |
self.save() | |
def _quote_if_necessary(self, arg): | |
diff --git a/mcomix/openwith_menu.py b/mcomix/openwith_menu.py | |
index cf6c907..a2943e6 100644 | |
--- a/mcomix/openwith_menu.py | |
+++ b/mcomix/openwith_menu.py | |
@@ -1,6 +1,6 @@ | |
""" openwith_menu.py - Menu shell for the Open with... menu. """ | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import openwith | |
@@ -9,7 +9,7 @@ _openwith_manager = openwith.OpenWithManager() | |
# Reference to the edit dialog (to keep only one instance) | |
_openwith_edit_diag = None | |
-class OpenWithMenu(gtk.Menu): | |
+class OpenWithMenu(Gtk.Menu): | |
def __init__(self, ui, window): | |
""" Constructor. """ | |
super(OpenWithMenu, self).__init__() | |
@@ -17,9 +17,9 @@ class OpenWithMenu(gtk.Menu): | |
self._window = window | |
self._openwith_manager = _openwith_manager | |
- actiongroup = gtk.ActionGroup('mcomix-openwith') | |
+ actiongroup = Gtk.ActionGroup('mcomix-openwith') | |
actiongroup.add_actions([ | |
- ('edit_commands', gtk.STOCK_EDIT, _('_Edit commands'), | |
+ ('edit_commands', Gtk.STOCK_EDIT, _('_Edit commands'), | |
None, None, self._edit_commands)]) | |
action = actiongroup.get_action('edit_commands') | |
@@ -44,18 +44,18 @@ class OpenWithMenu(gtk.Menu): | |
commandlist = self._openwith_manager.get_commands() | |
if len(commandlist) > 0: | |
- separator = gtk.SeparatorMenuItem() | |
+ separator = Gtk.SeparatorMenuItem() | |
separator.show() | |
self.prepend(separator) | |
for command in reversed(commandlist): | |
if not command.is_separator(): | |
- menuitem = gtk.MenuItem(command.get_label()) | |
+ menuitem = Gtk.MenuItem(command.get_label()) | |
menuitem.connect('activate', self._commandmenu_clicked, | |
command.get_command(), command.get_label(), | |
command.get_cwd(), command.is_disabled_for_archives()) | |
else: | |
- menuitem = gtk.SeparatorMenuItem() | |
+ menuitem = Gtk.SeparatorMenuItem() | |
menuitem.show() | |
self.prepend(menuitem) | |
diff --git a/mcomix/osd.py b/mcomix/osd.py | |
index f7358f0..1582360 100644 | |
--- a/mcomix/osd.py | |
+++ b/mcomix/osd.py | |
@@ -1,13 +1,14 @@ | |
""" osd.py - Onscreen display showing currently opened file. """ | |
# -*- coding: utf-8 -*- | |
-import gtk | |
-import gobject | |
-import pango | |
import textwrap | |
+from gi.repository import Gdk, Gtk, GObject | |
+from gi.repository import Pango, PangoCairo | |
+ | |
from mcomix import image_tools | |
+ | |
class OnScreenDisplay(object): | |
""" The OSD shows information such as currently opened file, archive and | |
@@ -35,8 +36,8 @@ class OnScreenDisplay(object): | |
# Set up font information | |
font = layout.get_context().get_font_description() | |
- font.set_weight(pango.WEIGHT_BOLD) | |
- layout.set_alignment(pango.ALIGN_CENTER) | |
+ font.set_weight(Pango.Weight.BOLD) | |
+ layout.set_alignment(Pango.Alignment.CENTER) | |
# Scale font to fit within the screen size | |
max_width, max_height = self._window.get_visible_area_size() | |
@@ -56,13 +57,13 @@ class OnScreenDisplay(object): | |
self._last_osd_rect = rect | |
if self._timeout_event: | |
- gobject.source_remove(self._timeout_event) | |
- self._timeout_event = gobject.timeout_add_seconds(OnScreenDisplay.TIMEOUT, self.clear) | |
+ GObject.source_remove(self._timeout_event) | |
+ self._timeout_event = GObject.timeout_add_seconds(OnScreenDisplay.TIMEOUT, self.clear) | |
def clear(self): | |
""" Removes the OSD. """ | |
if self._timeout_event: | |
- gobject.source_remove(self._timeout_event) | |
+ GObject.source_remove(self._timeout_event) | |
self._timeout_event = None | |
self._clear_osd() | |
return 0 # To unregister gobject timer event | |
@@ -80,18 +81,17 @@ class OnScreenDisplay(object): | |
return "\n".join(result) | |
- def _clear_osd(self, exclude_region=None): | |
- """ Invalidates the OSD region. C{exclude_region} will not be invalidated, even | |
- if it was part of a previous drawing operation. """ | |
+ def _clear_osd(self): | |
+ """ Clear the last OSD region. """ | |
if not self._last_osd_rect: | |
return | |
- last_region = gtk.gdk.region_rectangle(self._last_osd_rect) | |
- if exclude_region: | |
- last_region.subtract(exclude_region) | |
- self._window._main_layout.get_bin_window().invalidate_region(last_region, True) | |
- | |
+ window = self._window._main_layout.get_bin_window() | |
+ gdk_rect = Gdk.Rectangle() | |
+ gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height = self._last_osd_rect | |
+ window.invalidate_rect(gdk_rect, True) | |
+ window.process_updates(True) | |
self._last_osd_rect = None | |
def _scale_font(self, font, layout, max_width, max_height): | |
@@ -100,7 +100,7 @@ class OnScreenDisplay(object): | |
SIZE_MIN, SIZE_MAX = 10, 60 | |
for font_size in range(SIZE_MIN, SIZE_MAX, 5): | |
old_size = font.get_size() | |
- font.set_size(font_size * pango.SCALE) | |
+ font.set_size(font_size * Pango.SCALE) | |
layout.set_font_description(font) | |
if layout.get_pixel_size()[0] > max_width: | |
@@ -111,21 +111,34 @@ class OnScreenDisplay(object): | |
def _draw_osd(self, layout, rect): | |
""" Draws the text specified in C{layout} into a box at C{rect}. """ | |
- osd_region = gtk.gdk.region_rectangle(rect) | |
- draw_region = osd_region.copy() | |
+ draw_region = Gdk.Rectangle() | |
+ draw_region.x, draw_region.y, draw_region.width, draw_region.height = rect | |
if self._last_osd_rect: | |
- draw_region.union(gtk.gdk.region_rectangle(self._last_osd_rect)) | |
- | |
+ last_region = Gdk.Rectangle() | |
+ last_region.x, last_region.y, last_region.width, last_region.height = self._last_osd_rect | |
+ draw_region = Gdk.rectangle_union(draw_region, last_region) | |
+ | |
+ gdk_rect = Gdk.Rectangle() | |
+ gdk_rect.x = draw_region.x | |
+ gdk_rect.y = draw_region.y | |
+ gdk_rect.width = draw_region.width | |
+ gdk_rect.height = draw_region.height | |
window = self._window._main_layout.get_bin_window() | |
- window.begin_paint_region(draw_region) | |
- self._clear_osd(osd_region) | |
+ window.begin_paint_rect(gdk_rect) | |
+ | |
+ self._clear_osd() | |
- # Set up drawing context | |
- gc = window.new_gc(foreground=image_tools.GTK_GDK_COLOR_BLACK, | |
- background=image_tools.GTK_GDK_COLOR_BLACK) | |
+ cr = window.cairo_create() | |
+ cr.set_source_rgb(*image_tools.GTK_GDK_COLOR_BLACK.to_floats()) | |
+ cr.rectangle(*rect) | |
+ cr.fill() | |
+ extents = layout.get_extents()[0] | |
+ cr.set_source_rgb(*image_tools.GTK_GDK_COLOR_WHITE.to_floats()) | |
+ cr.translate(rect[0] + extents.x / Pango.SCALE, | |
+ rect[1] + extents.y / Pango.SCALE) | |
+ PangoCairo.update_layout(cr, layout) | |
+ PangoCairo.show_layout(cr, layout) | |
- window.draw_rectangle(gc, True, *rect) | |
- window.draw_layout(gc, rect[0] + 10, rect[1] + 10, layout, foreground=image_tools.GTK_GDK_COLOR_WHITE) | |
window.end_paint() | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/pageselect.py b/mcomix/pageselect.py | |
index 7230e49..e58516e 100644 | |
--- a/mcomix/pageselect.py | |
+++ b/mcomix/pageselect.py | |
@@ -1,13 +1,13 @@ | |
"""pageselect.py - The dialog window for the page selector.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix.preferences import prefs | |
from mcomix.worker_thread import WorkerThread | |
from mcomix import callback | |
-class Pageselector(gtk.Dialog): | |
+class Pageselector(Gtk.Dialog): | |
"""The Pageselector takes care of the popup page selector | |
""" | |
@@ -15,33 +15,31 @@ class Pageselector(gtk.Dialog): | |
def __init__(self, window): | |
self._window = window | |
super(Pageselector, self).__init__("Go to page...", window, | |
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) | |
- self.add_buttons(_('_Go'), gtk.RESPONSE_OK, | |
- _('_Cancel'), gtk.RESPONSE_CANCEL,) | |
- self.set_default_response(gtk.RESPONSE_OK) | |
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT) | |
+ self.add_buttons(_('_Go'), Gtk.ResponseType.OK, | |
+ _('_Cancel'), Gtk.ResponseType.CANCEL,) | |
+ self.set_default_response(Gtk.ResponseType.OK) | |
self.connect('response', self._response) | |
self.set_resizable(True) | |
self._number_of_pages = self._window.imagehandler.get_number_of_pages() | |
- self._selector_adjustment = gtk.Adjustment(value=self._window.imagehandler.get_current_page(), | |
+ self._selector_adjustment = Gtk.Adjustment(value=self._window.imagehandler.get_current_page(), | |
lower=1,upper=self._number_of_pages, | |
step_incr=1, page_incr=1 ) | |
- self._selector_adjustment.connect( 'value-changed', self._cb_value_changed ) | |
- | |
- self._page_selector = gtk.VScale(self._selector_adjustment) | |
+ self._page_selector = Gtk.VScale.new(self._selector_adjustment) | |
self._page_selector.set_draw_value(False) | |
self._page_selector.set_digits( 0 ) | |
- self._page_spinner = gtk.SpinButton(self._selector_adjustment) | |
+ self._page_spinner = Gtk.SpinButton.new(self._selector_adjustment, 0.0, 0) | |
self._page_spinner.connect( 'changed', self._page_text_changed ) | |
self._page_spinner.set_activates_default(True) | |
self._page_spinner.set_numeric(True) | |
- self._pages_label = gtk.Label(_(' of %s') % self._number_of_pages) | |
+ self._pages_label = Gtk.Label(label=_(' of %s') % self._number_of_pages) | |
self._pages_label.set_alignment(0, 0.5) | |
- self._image_preview = gtk.Image() | |
+ self._image_preview = Gtk.Image() | |
self._image_preview.set_size_request( | |
prefs['thumbnail size'], prefs['thumbnail size']) | |
@@ -50,21 +48,23 @@ class Pageselector(gtk.Dialog): | |
prefs['pageselector height']) | |
# Group preview image and page selector next to each other | |
- preview_box = gtk.HBox() | |
+ preview_box = Gtk.HBox() | |
preview_box.set_border_width(5) | |
preview_box.set_spacing(5) | |
- preview_box.pack_start(self._image_preview, True) | |
- preview_box.pack_end(self._page_selector, False) | |
+ preview_box.pack_start(self._image_preview, True, True, 0) | |
+ preview_box.pack_end(self._page_selector, False, True, 0) | |
# Below them, group selection spinner and current page label | |
- selection_box = gtk.HBox() | |
+ selection_box = Gtk.HBox() | |
selection_box.set_border_width(5) | |
- selection_box.pack_start(self._page_spinner, True) | |
- selection_box.pack_end(self._pages_label, False) | |
+ selection_box.pack_start(self._page_spinner, True, True, 0) | |
+ selection_box.pack_end(self._pages_label, False, True, 0) | |
- self.get_content_area().pack_start(preview_box, True) | |
- self.get_content_area().pack_end(selection_box, False) | |
+ self.get_content_area().pack_start(preview_box, True, True, 0) | |
+ self.get_content_area().pack_end(selection_box, False, True, 0) | |
self.show_all() | |
+ self._selector_adjustment.connect('value-changed', self._cb_value_changed) | |
+ | |
# Set focus on the input box. | |
self._page_spinner.select_region(0, -1) | |
self._page_spinner.grab_focus() | |
@@ -72,12 +72,12 @@ class Pageselector(gtk.Dialog): | |
# Currently displayed thumbnail page. | |
self._thumbnail_page = 0 | |
self._thread = WorkerThread(self._generate_thumbnail, name='preview') | |
- self._update_thumbnail(int(self._selector_adjustment.value)) | |
+ self._update_thumbnail(int(self._selector_adjustment.props.value)) | |
self._window.imagehandler.page_available += self._page_available | |
def _cb_value_changed(self, *args): | |
""" Called whenever the spinbox value changes. Updates the preview thumbnail. """ | |
- page = int(self._selector_adjustment.value) | |
+ page = int(self._selector_adjustment.props.value) | |
if page != self._thumbnail_page: | |
self._update_thumbnail(page) | |
@@ -88,7 +88,7 @@ class Pageselector(gtk.Dialog): | |
prefs['pageselector width'] = self.get_allocation().width | |
prefs['pageselector height'] = self.get_allocation().height | |
- self._update_thumbnail(int(self._selector_adjustment.value)) | |
+ self._update_thumbnail(int(self._selector_adjustment.props.value)) | |
def _page_text_changed(self, control, *args): | |
""" Called when the page selector has been changed. Used to instantly update | |
@@ -99,8 +99,8 @@ class Pageselector(gtk.Dialog): | |
control.set_value(page) | |
def _response(self, widget, event, *args): | |
- if event == gtk.RESPONSE_OK: | |
- self._window.set_page(int(self._selector_adjustment.value)) | |
+ if event == Gtk.ResponseType.OK: | |
+ self._window.set_page(int(self._selector_adjustment.props.value)) | |
self._window.imagehandler.page_available -= self._page_available | |
self._thread.stop() | |
@@ -130,7 +130,7 @@ class Pageselector(gtk.Dialog): | |
self._image_preview.set_from_pixbuf(pixbuf) | |
def _page_available(self, page): | |
- if page == int(self._selector_adjustment.value): | |
+ if page == int(self._selector_adjustment.props.value): | |
self._update_thumbnail(page) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/preferences.py b/mcomix/preferences.py | |
index 047893f..653e44c 100644 | |
--- a/mcomix/preferences.py | |
+++ b/mcomix/preferences.py | |
@@ -94,7 +94,7 @@ prefs = { | |
'max threads': 3, | |
'max extract threads': 1, | |
'wrap mouse scroll': False, | |
- 'scaling quality': 2, # gtk.gdk.INTERP_BILINEAR | |
+ 'scaling quality': 2, # GdkPixbuf.InterpType.BILINEAR | |
'escape quits': False, | |
'fit to size mode': constants.ZOOM_MODE_HEIGHT, | |
'fit to size px': 1800, | |
diff --git a/mcomix/preferences_dialog.py b/mcomix/preferences_dialog.py | |
index d0933d7..a84978f 100644 | |
--- a/mcomix/preferences_dialog.py | |
+++ b/mcomix/preferences_dialog.py | |
@@ -3,8 +3,7 @@ | |
"""preferences_dialog.py - Preferences dialog.""" | |
import operator | |
-import gtk | |
-import gobject | |
+from gi.repository import Gdk, GdkPixbuf, Gtk, GObject | |
from mcomix.preferences import prefs | |
from mcomix import preferences_page | |
@@ -16,7 +15,7 @@ from mcomix import keybindings_editor | |
_dialog = None | |
-class _PreferencesDialog(gtk.Dialog): | |
+class _PreferencesDialog(Gtk.Dialog): | |
"""The preferences dialog where most (but not all) settings that are | |
saved between sessions are presented to the user. | |
@@ -27,29 +26,29 @@ class _PreferencesDialog(gtk.Dialog): | |
# Button text is set later depending on active tab | |
self.reset_button = self.add_button('', constants.RESPONSE_REVERT_TO_DEFAULT) | |
- self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) | |
+ self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) | |
self._window = window | |
self.set_resizable(True) | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
self.connect('response', self._response) | |
- notebook = self.notebook = gtk.Notebook() | |
- self.vbox.pack_start(notebook) | |
+ notebook = self.notebook = Gtk.Notebook() | |
+ self.vbox.pack_start(notebook, True, True, 0) | |
self.set_border_width(4) | |
notebook.set_border_width(6) | |
appearance = self._init_appearance_tab() | |
- notebook.append_page(appearance, gtk.Label(_('Appearance'))) | |
+ notebook.append_page(appearance, Gtk.Label(label=_('Appearance'))) | |
behaviour = self._init_behaviour_tab() | |
- notebook.append_page(behaviour, gtk.Label(_('Behaviour'))) | |
+ notebook.append_page(behaviour, Gtk.Label(label=_('Behaviour'))) | |
display = self._init_display_tab() | |
- notebook.append_page(display, gtk.Label(_('Display'))) | |
+ notebook.append_page(display, Gtk.Label(label=_('Display'))) | |
advanced = self._init_advanced_tab() | |
- notebook.append_page(advanced, gtk.Label(_('Advanced'))) | |
+ notebook.append_page(advanced, Gtk.Label(label=_('Advanced'))) | |
shortcuts = self.shortcuts = self._init_shortcuts_tab() | |
- notebook.append_page(shortcuts, gtk.Label(_('Shortcuts'))) | |
+ notebook.append_page(shortcuts, Gtk.Label(label=_('Shortcuts'))) | |
notebook.connect('switch-page', self._tab_page_changed) | |
# Update the Reset button's tooltip | |
@@ -65,7 +64,7 @@ class _PreferencesDialog(gtk.Dialog): | |
page.new_section(_('User interface')) | |
- page.add_row(gtk.Label(_('Language (needs restart):')), | |
+ page.add_row(Gtk.Label(label=_('Language (needs restart):')), | |
self._create_language_control()) | |
page.add_row(self._create_pref_check_button( | |
@@ -106,7 +105,7 @@ class _PreferencesDialog(gtk.Dialog): | |
'archive thumbnail as icon', | |
_('By enabling this setting, the first page of a book will be used as application icon instead of the standard icon.'))) | |
- page.add_row(gtk.Label(_('Thumbnail size (in pixels):')), | |
+ page.add_row(Gtk.Label(label=_('Thumbnail size (in pixels):')), | |
self._create_pref_spinner('thumbnail size', | |
1, 20, 500, 1, 10, 0, None)) | |
@@ -149,24 +148,24 @@ class _PreferencesDialog(gtk.Dialog): | |
'auto open next directory', | |
_('Automatically open the first file in the next sibling directory when flipping past the last page of the last file in a directory, or the previous directory when flipping past the first page of the first file.'))) | |
- page.add_row(gtk.Label(_('Number of pixels to scroll per arrow key press:')), | |
+ page.add_row(Gtk.Label(label=_('Number of pixels to scroll per arrow key press:')), | |
self._create_pref_spinner('number of pixels to scroll per key event', | |
1, 1, 500, 1, 3, 0, | |
_('Set the number of pixels to scroll on a page when using the arrow keys.'))) | |
- page.add_row(gtk.Label(_('Number of pixels to scroll per mouse wheel turn:')), | |
+ page.add_row(Gtk.Label(label=_('Number of pixels to scroll per mouse wheel turn:')), | |
self._create_pref_spinner('number of pixels to scroll per mouse wheel event', | |
1, 1, 500, 1, 3, 0, | |
_('Set the number of pixels to scroll on a page when using a mouse wheel.'))) | |
- page.add_row(gtk.Label(_('Fraction of page to scroll ' | |
+ page.add_row(Gtk.Label(label=_('Fraction of page to scroll ' | |
'per space key press (in percent):')), | |
self._create_pref_spinner('smart scroll percentage', | |
0.01, 1, 100, 1, 5, 0, | |
_('Sets the percentage by which the page ' | |
'will be scrolled down or up when the space key is pressed.'))) | |
- page.add_row(gtk.Label(_('Number of "steps" to take before flipping the page:')), | |
+ page.add_row(Gtk.Label(label=_('Number of "steps" to take before flipping the page:')), | |
self._create_pref_spinner('number of key presses before page turn', | |
1, 1, 100, 1, 3, 0, | |
_('Set the number of "steps" needed to flip to the next or previous page. Less steps will allow for very fast page turning but you might find yourself accidentally turning pages.'))) | |
@@ -178,7 +177,7 @@ class _PreferencesDialog(gtk.Dialog): | |
'double step in double page mode', | |
_('Flip two pages, instead of one, each time we flip pages in double page mode.'))) | |
- page.add_row(gtk.Label(_('Show only one page where appropriate:')), | |
+ page.add_row(Gtk.Label(label=_('Show only one page where appropriate:')), | |
self._create_doublepage_as_one_control()) | |
page.new_section(_('Files')) | |
@@ -188,7 +187,7 @@ class _PreferencesDialog(gtk.Dialog): | |
'auto load last file', | |
_('Automatically open, on startup, the file that was open when MComix was last closed.'))) | |
- page.add_row(gtk.Label(_('Store information about recently opened files:')), | |
+ page.add_row(Gtk.Label(label=_('Store information about recently opened files:')), | |
self._create_store_recent_combobox()) | |
return page | |
@@ -211,20 +210,20 @@ class _PreferencesDialog(gtk.Dialog): | |
page.new_section(_('Fit to size mode')) | |
- page.add_row(gtk.Label(_('Fit to width or height:')), | |
+ page.add_row(Gtk.Label(label=_('Fit to width or height:')), | |
self._create_fitmode_control()) | |
- page.add_row(gtk.Label(_('Fixed size for this mode:')), | |
+ page.add_row(Gtk.Label(label=_('Fixed size for this mode:')), | |
self._create_pref_spinner('fit to size px', | |
1, 10, 10000, 10, 50, 0, None)) | |
page.new_section(_('Slideshow')) | |
- page.add_row(gtk.Label(_('Slideshow delay (in seconds):')), | |
+ page.add_row(Gtk.Label(label=_('Slideshow delay (in seconds):')), | |
self._create_pref_spinner('slideshow delay', | |
1000.0, 0.01, 3600.0, 0.1, 1, 2, None)) | |
- page.add_row(gtk.Label(_('Slideshow step (in pixels):')), | |
+ page.add_row(Gtk.Label(label=_('Slideshow step (in pixels):')), | |
self._create_pref_spinner('number of pixels to scroll per slideshow event', | |
1, -500, 500, 1, 1, 0, | |
_('Specify the number of pixels to scroll while in slideshow mode. A positive value will scroll forward, a negative value will scroll backwards, and a value of 0 will cause the slideshow to always flip to a new page.'))) | |
@@ -243,7 +242,7 @@ class _PreferencesDialog(gtk.Dialog): | |
page.new_section(_('Image quality')) | |
- page.add_row(gtk.Label(_('Scaling mode')), | |
+ page.add_row(Gtk.Label(label=_('Scaling mode')), | |
self._create_scaling_quality_combobox()) | |
return page | |
@@ -257,15 +256,15 @@ class _PreferencesDialog(gtk.Dialog): | |
page.new_section(_('File order')) | |
- page.add_row(gtk.Label(_('Sort files and directories by:')), | |
+ page.add_row(Gtk.Label(label=_('Sort files and directories by:')), | |
self._create_sort_by_control()) | |
- page.add_row(gtk.Label(_('Sort archives by:')), | |
+ page.add_row(Gtk.Label(label=_('Sort archives by:')), | |
self._create_archive_sort_by_control()) | |
page.new_section(_('Extraction and cache')) | |
- page.add_row(gtk.Label(_('Maximum number of concurrent extraction threads:')), | |
+ page.add_row(Gtk.Label(label=_('Maximum number of concurrent extraction threads:')), | |
self._create_pref_spinner('max extract threads', | |
1, 1, 16, 1, 4, 0, | |
_('Set the maximum number of concurrent threads for formats that support it.'))) | |
@@ -275,31 +274,31 @@ class _PreferencesDialog(gtk.Dialog): | |
'create thumbnails', | |
_('Store thumbnails for opened files according to the freedesktop.org specification. These thumbnails are shared by many other applications, such as most file managers.'))) | |
- page.add_row(gtk.Label(_('Maximum number of pages to store in the cache:')), | |
+ page.add_row(Gtk.Label(label=_('Maximum number of pages to store in the cache:')), | |
self._create_pref_spinner('max pages to cache', | |
1, -1, 500, 1, 3, 0, | |
_('Set the max number of pages to cache. A value of -1 will cache the entire archive.'))) | |
page.new_section(_('Magnifying Lens')) | |
- page.add_row(gtk.Label(_('Magnifying lens size (in pixels):')), | |
+ page.add_row(Gtk.Label(label=_('Magnifying lens size (in pixels):')), | |
self._create_pref_spinner('lens size', | |
1, 50, 400, 1, 10, 0, | |
_('Set the size of the magnifying lens. It is a square with a side of this many pixels.'))) | |
- page.add_row(gtk.Label(_('Magnification factor:')), | |
+ page.add_row(Gtk.Label(label=_('Magnification factor:')), | |
self._create_pref_spinner('lens magnification', | |
1, 1.1, 10.0, 0.1, 1.0, 1, | |
_('Set the magnification factor of the magnifying lens.'))) | |
page.new_section(_('Comments')) | |
- page.add_row(gtk.Label(_('Comment extensions:')), | |
+ page.add_row(Gtk.Label(label=_('Comment extensions:')), | |
self._create_extensions_entry()) | |
page.new_section(_('Animated images')) | |
- page.add_row(gtk.Label(_('Animation mode:')), | |
+ page.add_row(Gtk.Label(_('Animation mode:')), | |
self._create_animation_mode_combobox()) | |
return page | |
@@ -328,7 +327,7 @@ class _PreferencesDialog(gtk.Dialog): | |
self.reset_button.set_sensitive(len(prefs['stored dialog choices']) > 0) | |
def _response(self, dialog, response): | |
- if response == gtk.RESPONSE_CLOSE: | |
+ if response == Gtk.ResponseType.CLOSE: | |
_close_dialog() | |
elif response == constants.RESPONSE_REVERT_TO_DEFAULT: | |
@@ -353,30 +352,30 @@ class _PreferencesDialog(gtk.Dialog): | |
# Source: http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes | |
languages = [ | |
(_('Auto-detect (Default)'), 'auto'), | |
- ('Català', 'ca'), # Catalan | |
- ('čeština', 'cs'), # Czech | |
- ('Deutsch', 'de'), # German | |
- ('ελληνικά', 'el'), # Greek | |
- ('English', 'en'), # English | |
- ('Español', 'es'), # Spanish | |
- ('فارسی', 'fa'), # Persian | |
- ('Français', 'fr'), # French | |
- ('Galego', 'gl'), # Galician | |
- ('עברית', 'he'), # Hebrew | |
- ('Hrvatski jezik', 'hr'), # Croatian | |
- ('Magyar', 'hu'), # Hungarian | |
- ('Bahasa Indonesia', 'id'), # Indonesian | |
- ('Italiano', 'it'), # Italian | |
- ('日本語', 'ja'), # Japanese | |
- ('한국어', 'ko'), # Korean | |
- ('Nederlands', 'nl'), # Dutch | |
- ('Język polski', 'pl'), # Polish | |
- ('Português', 'pt_BR'), # Portuguese | |
- ('pусский язык', 'ru'), # Russian | |
- ('Svenska', 'sv'), # Swedish | |
- ('українська мова', 'uk'), # Ukrainian | |
- ('簡體中文', 'zh_CN'), # Chinese (simplified) | |
- ('正體中文', 'zh_TW')] # Chinese (traditional) | |
+ (u'Català', 'ca'), # Catalan | |
+ (u'čeština', 'cs'), # Czech | |
+ (u'Deutsch', 'de'), # German | |
+ (u'ελληνικά', 'el'), # Greek | |
+ (u'English', 'en'), # English | |
+ (u'Español', 'es'), # Spanish | |
+ (u'فارسی', 'fa'), # Persian | |
+ (u'Français', 'fr'), # French | |
+ (u'Galego', 'gl'), # Galician | |
+ (u'עברית', 'he'), # Hebrew | |
+ (u'Hrvatski jezik', 'hr'), # Croatian | |
+ (u'Magyar', 'hu'), # Hungarian | |
+ (u'Bahasa Indonesia', 'id'), # Indonesian | |
+ (u'Italiano', 'it'), # Italian | |
+ (u'日本語', 'ja'), # Japanese | |
+ (u'한국어', 'ko'), # Korean | |
+ (u'Nederlands', 'nl'), # Dutch | |
+ (u'Język polski', 'pl'), # Polish | |
+ (u'Português', 'pt_BR'), # Portuguese | |
+ (u'pусский язык', 'ru'), # Russian | |
+ (u'Svenska', 'sv'), # Swedish | |
+ (u'українська мова', 'uk'), # Ukrainian | |
+ (u'簡體中文', 'zh_CN'), # Chinese (simplified) | |
+ (u'正體中文', 'zh_TW')] # Chinese (traditional) | |
languages.sort(key=operator.itemgetter(0)) | |
box = self._create_combobox(languages, prefs['language'], | |
@@ -459,9 +458,9 @@ class _PreferencesDialog(gtk.Dialog): | |
prefs['sort order'], | |
self._sort_order_changed_cb) | |
- box = gtk.HBox() | |
- box.pack_start(sortkey_box) | |
- box.pack_start(sortorder_box) | |
+ box = Gtk.HBox() | |
+ box.pack_start(sortkey_box, True, True, 0) | |
+ box.pack_start(sortorder_box, True, True, 0) | |
label = _("Files will be opened and displayed according to the sort order " | |
"specified here. This option does not affect ordering within archives.") | |
@@ -506,9 +505,9 @@ class _PreferencesDialog(gtk.Dialog): | |
prefs['sort archive order'], | |
self._sort_archive_order_changed_cb) | |
- box = gtk.HBox() | |
- box.pack_start(sortkey_box) | |
- box.pack_start(sortorder_box) | |
+ box = Gtk.HBox() | |
+ box.pack_start(sortkey_box, True, True, 0) | |
+ box.pack_start(sortorder_box, True, True, 0) | |
label = _("Files within archives will be sorted according to the order specified here. " | |
"Natural order will sort numbered files based on their natural order, " | |
@@ -572,25 +571,25 @@ class _PreferencesDialog(gtk.Dialog): | |
and (self._window.uimanager.recent.count() > 0 | |
or self._window.filehandler.last_read_page.count() > 0)): | |
- dialog = message_dialog.MessageDialog(self, gtk.DIALOG_MODAL, | |
- gtk.MESSAGE_INFO, gtk.BUTTONS_YES_NO) | |
- dialog.set_default_response(gtk.RESPONSE_YES) | |
+ dialog = message_dialog.MessageDialog(self, Gtk.DialogFlags.MODAL, | |
+ Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO) | |
+ dialog.set_default_response(Gtk.ResponseType.YES) | |
dialog.set_text( | |
_('Delete information about recently opened files?'), | |
_('This will remove all entries from the "Recent" menu,' | |
' and clear information about last read pages.')) | |
response = dialog.run() | |
- if response == gtk.RESPONSE_YES: | |
+ if response == Gtk.ResponseType.YES: | |
self._window.uimanager.recent.remove_all() | |
self._window.filehandler.last_read_page.clear_all() | |
def _create_scaling_quality_combobox(self): | |
""" Creates combo box for image scaling quality """ | |
items = ( | |
- (_('Normal (fast)'), int(gtk.gdk.INTERP_TILES)), | |
- (_('Bilinear'), int(gtk.gdk.INTERP_BILINEAR)), | |
- (_('Hyperbolic (slow)'), int(gtk.gdk.INTERP_HYPER))) | |
+ (_('Normal (fast)'), int(GdkPixbuf.InterpType.TILES)), | |
+ (_('Bilinear'), int(GdkPixbuf.InterpType.BILINEAR)), | |
+ (_('Hyperbolic (slow)'), int(GdkPixbuf.InterpType.HYPER))) | |
selection = prefs['scaling quality'] | |
@@ -645,18 +644,18 @@ class _PreferencesDialog(gtk.Dialog): | |
be pre-selected when the control is created. | |
@param change_callback: Function that will be called when the 'changed' | |
event is triggered. | |
- @returns gtk.ComboBox | |
+ @returns Gtk.ComboBox | |
""" | |
assert options and len(options[0]) == 2, "Invalid format for options." | |
# Use the first list item to determine typing of model fields. | |
# First field is textual description, second field is value. | |
- model = gtk.ListStore(gobject.TYPE_STRING, type(options[0][1])) | |
+ model = Gtk.ListStore(GObject.TYPE_STRING, type(options[0][1])) | |
for text, value in options: | |
model.append((text, value)) | |
- box = gtk.ComboBox(model) | |
- renderer = gtk.CellRendererText() | |
+ box = Gtk.ComboBox(model=model) | |
+ renderer = Gtk.CellRendererText() | |
box.pack_start(renderer, True) | |
box.add_attribute(renderer, "text", 0) | |
@@ -676,7 +675,7 @@ class _PreferencesDialog(gtk.Dialog): | |
def _create_extensions_entry(self): | |
- entry = gtk.Entry() | |
+ entry = Gtk.Entry() | |
entry.set_size_request(200, -1) | |
entry.set_text(', '.join(prefs['comment extensions'])) | |
entry.connect('activate', self._entry_cb) | |
@@ -687,7 +686,7 @@ class _PreferencesDialog(gtk.Dialog): | |
def _create_pref_check_button(self, label, prefkey, tooltip_text): | |
- button = gtk.CheckButton(label) | |
+ button = Gtk.CheckButton(label) | |
button.set_active(prefs[prefkey]) | |
button.connect('toggled', self._check_button_cb, prefkey) | |
if tooltip_text: | |
@@ -697,11 +696,11 @@ class _PreferencesDialog(gtk.Dialog): | |
def _create_binary_pref_radio_buttons(self, label1, prefkey1, tooltip_text1, | |
label2, prefkey2, tooltip_text2): | |
- button1 = gtk.RadioButton(None, label1) | |
+ button1 = Gtk.RadioButton(label=label1) | |
button1.connect('toggled', self._check_button_cb, prefkey1) | |
if tooltip_text1: | |
button1.set_tooltip_text(tooltip_text1) | |
- button2 = gtk.RadioButton(button1, label2) | |
+ button2 = Gtk.RadioButton(group=button1, label=label2) | |
button2.connect('toggled', self._check_button_cb, prefkey2) | |
if tooltip_text2: | |
button2.set_tooltip_text(tooltip_text2) | |
@@ -710,7 +709,8 @@ class _PreferencesDialog(gtk.Dialog): | |
def _create_color_button(self, prefkey): | |
- button = gtk.ColorButton(gtk.gdk.Color(*prefs[prefkey])) | |
+ rgba = image_tools.color_to_floats_rgba(prefs[prefkey]) | |
+ button = Gtk.ColorButton.new_with_rgba(Gdk.RGBA(*rgba)) | |
button.connect('color_set', self._color_button_cb, prefkey) | |
return button | |
@@ -791,8 +791,8 @@ class _PreferencesDialog(gtk.Dialog): | |
def _create_pref_spinner(self, prefkey, scale, lower, upper, step_incr, | |
page_incr, digits, tooltip_text): | |
value = prefs[prefkey] / scale | |
- adjustment = gtk.Adjustment(value, lower, upper, step_incr, page_incr) | |
- spinner = gtk.SpinButton(adjustment, digits=digits) | |
+ adjustment = Gtk.Adjustment(value, lower, upper, step_incr, page_incr) | |
+ spinner = Gtk.SpinButton.new(adjustment, 0.0, digits) | |
spinner.set_size_request(80, -1) | |
spinner.connect('value_changed', self._spinner_cb, prefkey) | |
if tooltip_text: | |
diff --git a/mcomix/preferences_page.py b/mcomix/preferences_page.py | |
index 95bdc84..c2e3d00 100644 | |
--- a/mcomix/preferences_page.py | |
+++ b/mcomix/preferences_page.py | |
@@ -1,10 +1,10 @@ | |
"""preferences_page.py - MComix preference page.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import preferences_section | |
-class _PreferencePage(gtk.VBox): | |
+class _PreferencePage(Gtk.VBox): | |
"""The _PreferencePage is a conveniece class for making one "page" | |
in a preferences-style dialog that contains one or more | |
@@ -25,21 +25,21 @@ class _PreferencePage(gtk.VBox): | |
<header>. | |
""" | |
self._section = preferences_section._PreferenceSection(header, self._right_column_width) | |
- self.pack_start(self._section, False, False) | |
+ self.pack_start(self._section, False, False, 0) | |
def add_row(self, left_item, right_item=None): | |
"""Add a row to the page (in the latest section), containing one | |
or two items. If the left item is a label it is automatically | |
aligned properly. | |
""" | |
- if isinstance(left_item, gtk.Label): | |
+ if isinstance(left_item, Gtk.Label): | |
left_item.set_alignment(0, 0.5) | |
if right_item is None: | |
- self._section.contentbox.pack_start(left_item) | |
+ self._section.contentbox.pack_start(left_item, True, True, 0) | |
else: | |
left_box, right_box = self._section.new_split_vboxes() | |
- left_box.pack_start(left_item) | |
- right_box.pack_start(right_item) | |
+ left_box.pack_start(left_item, True, True, 0) | |
+ right_box.pack_start(right_item, True, True, 0) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/preferences_section.py b/mcomix/preferences_section.py | |
index 6360323..f12cb04 100644 | |
--- a/mcomix/preferences_section.py | |
+++ b/mcomix/preferences_section.py | |
@@ -1,10 +1,10 @@ | |
"""preferences_section.py - Preference dialog section.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import labels | |
-class _PreferenceSection(gtk.VBox): | |
+class _PreferenceSection(Gtk.VBox): | |
"""The _PreferenceSection is a convenience class for making one | |
"section" of a preference-style dialog, e.g. it has a bold header | |
@@ -18,13 +18,13 @@ class _PreferenceSection(gtk.VBox): | |
""" | |
super(_PreferenceSection, self).__init__(False, 0) | |
self._right_column_width = right_column_width | |
- self.contentbox = gtk.VBox(False, 6) | |
+ self.contentbox = Gtk.VBox(False, 6) | |
label = labels.BoldLabel(header) | |
label.set_alignment(0, 0.5) | |
- hbox = gtk.HBox(False, 0) | |
- hbox.pack_start(gtk.HBox(), False, False, 6) | |
- hbox.pack_start(self.contentbox) | |
- self.pack_start(label, False, False) | |
+ hbox = Gtk.HBox(False, 0) | |
+ hbox.pack_start(Gtk.HBox(True, True, 0), False, False, 6) | |
+ hbox.pack_start(self.contentbox, True, True, 0) | |
+ self.pack_start(label, False, False, 0) | |
self.pack_start(hbox, False, False, 6) | |
def new_split_vboxes(self): | |
@@ -34,16 +34,16 @@ class _PreferenceSection(gtk.VBox): | |
in order to make it easy for all "right column items" in a page to | |
line up nicely. | |
""" | |
- left_box = gtk.VBox(False, 6) | |
- right_box = gtk.VBox(False, 6) | |
+ left_box = Gtk.VBox(False, 6) | |
+ right_box = Gtk.VBox(False, 6) | |
if self._right_column_width != None: | |
right_box.set_size_request(self._right_column_width, -1) | |
- hbox = gtk.HBox(False, 12) | |
- hbox.pack_start(left_box) | |
- hbox.pack_start(right_box, False, False) | |
- self.contentbox.pack_start(hbox) | |
+ hbox = Gtk.HBox(False, 12) | |
+ hbox.pack_start(left_box, True, True, 0) | |
+ hbox.pack_start(right_box, False, False, 0) | |
+ self.contentbox.pack_start(hbox, True, True, 0) | |
return left_box, right_box | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/properties_dialog.py b/mcomix/properties_dialog.py | |
index 316d1df..c4d86ee 100644 | |
--- a/mcomix/properties_dialog.py | |
+++ b/mcomix/properties_dialog.py | |
@@ -1,6 +1,6 @@ | |
"""properties_dialog.py - Properties dialog that displays information about the archive/file.""" | |
-import gtk | |
+from gi.repository import Gtk | |
import os | |
import time | |
import stat | |
@@ -16,26 +16,26 @@ from mcomix import strings | |
from mcomix import properties_page | |
from mcomix import tools | |
-class _PropertiesDialog(gtk.Dialog): | |
+class _PropertiesDialog(Gtk.Dialog): | |
def __init__(self, window): | |
super(_PropertiesDialog, self).__init__(_('Properties'), window, 0, | |
- (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) | |
+ (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) | |
self._window = window | |
- self.resize(400, 400) | |
+ self.resize(500, 430) | |
self.set_resizable(True) | |
- self.set_default_response(gtk.RESPONSE_CLOSE) | |
- notebook = gtk.Notebook() | |
+ self.set_default_response(Gtk.ResponseType.CLOSE) | |
+ notebook = Gtk.Notebook() | |
self.set_border_width(4) | |
notebook.set_border_width(6) | |
- self.vbox.pack_start(notebook) | |
+ self.vbox.pack_start(notebook, True, True, 0) | |
self._archive_page = properties_page._Page() | |
- notebook.append_page(self._archive_page, gtk.Label(_('Archive'))) | |
+ notebook.append_page(self._archive_page, Gtk.Label(label=_('Archive'))) | |
self._image_page = properties_page._Page() | |
- notebook.append_page(self._image_page, gtk.Label(_('Image'))) | |
+ notebook.append_page(self._image_page, Gtk.Label(label=_('Image'))) | |
self._update_archive_page() | |
self._window.page_changed += self._on_page_change | |
self._window.filehandler.file_opened += self._on_book_change | |
diff --git a/mcomix/properties_page.py b/mcomix/properties_page.py | |
index 001ffee..73a75d6 100644 | |
--- a/mcomix/properties_page.py | |
+++ b/mcomix/properties_page.py | |
@@ -1,36 +1,36 @@ | |
"""properties_page.py - A page to put in the properties dialog window.""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import i18n | |
from mcomix import image_tools | |
from mcomix import labels | |
-class _Page(gtk.ScrolledWindow): | |
+class _Page(Gtk.ScrolledWindow): | |
- """A page to put in the gtk.Notebook. Contains info about a file (an | |
+ """A page to put in the Gtk.Notebook. Contains info about a file (an | |
image or an archive.) | |
""" | |
def __init__(self): | |
super(_Page, self).__init__() | |
- self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
- self._vbox = gtk.VBox(False, 12) | |
+ self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
+ self._vbox = Gtk.VBox(False, 12) | |
self.add_with_viewport(self._vbox) | |
self.set_border_width(12) | |
- topbox = gtk.HBox(False, 12) | |
- self._vbox.pack_start(topbox) | |
- self._thumb = gtk.Image() | |
+ topbox = Gtk.HBox(False, 12) | |
+ self._vbox.pack_start(topbox, True, True, 0) | |
+ self._thumb = Gtk.Image() | |
self._thumb.set_size_request(128, 128) | |
- topbox.pack_start(self._thumb, False, False) | |
- borderbox = gtk.Frame() | |
- borderbox.set_shadow_type(gtk.SHADOW_ETCHED_IN) | |
+ topbox.pack_start(self._thumb, False, False, 0) | |
+ borderbox = Gtk.Frame() | |
+ borderbox.set_shadow_type(Gtk.ShadowType.ETCHED_IN) | |
borderbox.set_size_request(-1, 130) | |
- topbox.pack_start(borderbox) | |
- insidebox = gtk.EventBox() | |
+ topbox.pack_start(borderbox, True, True, 0) | |
+ insidebox = Gtk.EventBox() | |
insidebox.set_border_width(1) | |
- insidebox.set_state(gtk.STATE_ACTIVE) | |
+ insidebox.set_state(Gtk.StateType.ACTIVE) | |
borderbox.add(insidebox) | |
self._insidebox = insidebox | |
self._mainbox = None | |
@@ -41,13 +41,13 @@ class _Page(gtk.ScrolledWindow): | |
self._thumb.clear() | |
if self._mainbox is not None: | |
self._mainbox.destroy() | |
- self._mainbox = gtk.VBox(False, 5) | |
+ self._mainbox = Gtk.VBox(False, 5) | |
self._mainbox.set_border_width(10) | |
self._insidebox.add(self._mainbox) | |
if self._extrabox is not None: | |
self._extrabox.destroy() | |
- self._extrabox = gtk.HBox(False, 10) | |
- self._vbox.pack_start(self._extrabox, False, False) | |
+ self._extrabox = Gtk.HBox(False, 10) | |
+ self._vbox.pack_start(self._extrabox, False, False, 0) | |
def set_thumbnail(self, pixbuf): | |
pixbuf = image_tools.add_border(pixbuf, 1) | |
@@ -60,34 +60,34 @@ class _Page(gtk.ScrolledWindow): | |
label = labels.BoldLabel(i18n.to_unicode(filename)) | |
label.set_alignment(0, 0.5) | |
label.set_selectable(True) | |
- self._mainbox.pack_start(label, False, False) | |
- self._mainbox.pack_start(gtk.VBox()) # Just to add space (better way?) | |
+ self._mainbox.pack_start(label, False, False, 0) | |
+ self._mainbox.pack_start(Gtk.VBox(True, True, 0), True, True, 0) # Just to add space (better way?) | |
def set_main_info(self, info): | |
"""Set the information in the main info box (below the filename) to | |
the values in the sequence <info>. | |
""" | |
for text in info: | |
- label = gtk.Label(text) | |
+ label = Gtk.Label(label=text) | |
label.set_alignment(0, 0.5) | |
label.set_selectable(True) | |
- self._mainbox.pack_start(label, False, False) | |
+ self._mainbox.pack_start(label, False, False, 0) | |
def set_secondary_info(self, info): | |
"""Set the information below the main info box to the values in the | |
sequence <info>. Each entry in info should be a tuple (desc, value). | |
""" | |
- left_box = gtk.VBox(True, 8) | |
- right_box = gtk.VBox(True, 8) | |
- self._extrabox.pack_start(left_box, False, False) | |
- self._extrabox.pack_start(right_box, False, False) | |
+ left_box = Gtk.VBox(True, 8) | |
+ right_box = Gtk.VBox(True, 8) | |
+ self._extrabox.pack_start(left_box, False, False, 0) | |
+ self._extrabox.pack_start(right_box, False, False, 0) | |
for desc, value in info: | |
desc_label = labels.BoldLabel('%s:' % desc) | |
desc_label.set_alignment(1.0, 1.0) | |
- left_box.pack_start(desc_label, True, True) | |
- value_label = gtk.Label(value) | |
+ left_box.pack_start(desc_label, True, True, 0) | |
+ value_label = Gtk.Label(label=value) | |
value_label.set_alignment(0, 1.0) | |
value_label.set_selectable(True) | |
- right_box.pack_start(value_label, True, True) | |
+ right_box.pack_start(value_label, True, True, 0) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/recent.py b/mcomix/recent.py | |
index 2677ac5..1244aa1 100644 | |
--- a/mcomix/recent.py | |
+++ b/mcomix/recent.py | |
@@ -2,9 +2,10 @@ | |
import urllib | |
import itertools | |
-import gtk | |
+from gi.repository import Gtk | |
+from gi.repository import Gtk | |
import glib | |
-import gobject | |
+from gi.repository import GObject | |
import sys | |
from mcomix import preferences | |
@@ -14,21 +15,21 @@ from mcomix import archive_tools | |
from mcomix import image_tools | |
from mcomix import log | |
-class RecentFilesMenu(gtk.RecentChooserMenu): | |
+class RecentFilesMenu(Gtk.RecentChooserMenu): | |
def __init__(self, ui, window): | |
+ super(RecentFilesMenu, self).__init__() | |
self._window = window | |
- self._manager = gtk.recent_manager_get_default() | |
- super(RecentFilesMenu, self).__init__(self._manager) | |
+ self._manager = Gtk.RecentManager.get_default() | |
- self.set_sort_type(gtk.RECENT_SORT_MRU) | |
+ self.set_sort_type(Gtk.RecentSortType.MRU) | |
self.set_show_tips(True) | |
# Missing icons crash GTK on Win32 | |
if sys.platform == 'win32': | |
self.set_show_icons(False) | |
self.set_show_numbers(True) | |
- rfilter = gtk.RecentFilter() | |
+ rfilter = Gtk.RecentFilter() | |
supported_formats = {} | |
supported_formats.update(image_tools.get_supported_formats()) | |
supported_formats.update(archive_tools.get_supported_formats()) | |
@@ -75,7 +76,7 @@ class RecentFilesMenu(gtk.RecentChooserMenu): | |
""" Removes all entries to recently opened files. """ | |
try: | |
self._manager.purge_items() | |
- except gobject.GError, error: | |
+ except GObject.GError, error: | |
log.debug(error) | |
diff --git a/mcomix/run.py b/mcomix/run.py | |
index c0cec69..761c890 100644 | |
--- a/mcomix/run.py | |
+++ b/mcomix/run.py | |
@@ -175,29 +175,22 @@ def run(): | |
# Check for PyGTK and PIL dependencies. | |
try: | |
- import pygtk | |
- pygtk.require('2.0') | |
+ from gi import require_version | |
- import gtk | |
- assert gtk.gtk_version >= (2, 12, 0) | |
- assert gtk.pygtk_version >= (2, 12, 0) | |
+ require_version('PangoCairo', '1.0') | |
+ require_version('Gtk', '3.0') | |
+ require_version('Gdk', '3.0') | |
- import gobject | |
- gobject.threads_init() | |
+ from gi.repository import Gdk, Gtk, GObject | |
+ | |
+ GObject.threads_init() | |
except AssertionError: | |
- log.error( _("You do not have the required versions of GTK+ and PyGTK installed.") ) | |
- log.error( _('Installed GTK+ version is: %s') % \ | |
- '.'.join([str(n) for n in gtk.gtk_version]) ) | |
- log.error( _('Required GTK+ version is: 2.12.0 or higher') ) | |
- log.error( _('Installed PyGTK version is: %s') % \ | |
- '.'.join([str(n) for n in gtk.pygtk_version]) ) | |
- log.error( _('Required PyGTK version is: 2.12.0 or higher') ) | |
+ log.error( _("You do not have the required versions of GTK+ 3.0 and PyGObject installed.") ) | |
wait_and_exit() | |
except ImportError: | |
- log.error( _('Required PyGTK version is: 2.12.0 or higher') ) | |
- log.error( _('No version of PyGTK was found on your system.') ) | |
+ log.error( _('No version of GObject was found on your system.') ) | |
log.error( _('This error might be caused by missing GTK+ libraries.') ) | |
wait_and_exit() | |
@@ -241,9 +234,13 @@ def run(): | |
# Some languages require a RTL layout | |
if preferences.prefs['language'] in ('he', 'fa'): | |
- gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL) | |
+ Gtk.widget_set_default_direction(Gtk.TextDirection.RTL) | |
+ | |
+ Gdk.set_program_class(constants.APPNAME) | |
- gtk.gdk.set_program_class(constants.APPNAME) | |
+ settings = Gtk.Settings.get_default() | |
+ # Enable icons for menu items. | |
+ settings.props.gtk_menu_images = True | |
from mcomix import main | |
window = main.MainWindow(fullscreen = opts.fullscreen, is_slideshow = opts.slideshow, | |
@@ -261,9 +258,10 @@ def run(): | |
pass | |
signal.signal(signal.SIGCHLD, on_sigchld) | |
- signal.signal(signal.SIGTERM, lambda: gobject.idle_add(window.terminate_program)) | |
+ for sig in (signal.SIGINT, signal.SIGTERM): | |
+ signal.signal(sig, lambda signum, stack: GObject.idle_add(window.terminate_program)) | |
try: | |
- gtk.main() | |
+ Gtk.main() | |
except KeyboardInterrupt: # Will not always work because of threading. | |
window.terminate_program() | |
diff --git a/mcomix/slideshow.py b/mcomix/slideshow.py | |
index a501a06..62df301 100644 | |
--- a/mcomix/slideshow.py | |
+++ b/mcomix/slideshow.py | |
@@ -1,7 +1,7 @@ | |
"""slideshow.py - Slideshow handler.""" | |
-import gtk | |
-import gobject | |
+from gi.repository import Gtk | |
+from gi.repository import GObject | |
from mcomix.preferences import prefs | |
@@ -16,13 +16,13 @@ class Slideshow(object): | |
def _start(self): | |
if not self._running: | |
- self._id = gobject.timeout_add(prefs['slideshow delay'], self._next) | |
+ self._id = GObject.timeout_add(prefs['slideshow delay'], self._next) | |
self._running = True | |
self._window.update_title() | |
def _stop(self): | |
if self._running: | |
- gobject.source_remove(self._id) | |
+ GObject.source_remove(self._id) | |
self._running = False | |
self._window.update_title() | |
@@ -39,11 +39,11 @@ class Slideshow(object): | |
"""Toggle a slideshow on or off.""" | |
if action.get_active(): | |
self._start() | |
- self._window.uimanager.get_widget('/Tool/slideshow').set_stock_id( gtk.STOCK_MEDIA_STOP ) | |
+ self._window.uimanager.get_widget('/Tool/slideshow').set_stock_id( Gtk.STOCK_MEDIA_STOP ) | |
self._window.uimanager.get_widget('/Tool/slideshow').set_tooltip_text( _('Stop slideshow') ) | |
else: | |
self._stop() | |
- self._window.uimanager.get_widget('/Tool/slideshow').set_stock_id( gtk.STOCK_MEDIA_PLAY ) | |
+ self._window.uimanager.get_widget('/Tool/slideshow').set_stock_id( Gtk.STOCK_MEDIA_PLAY ) | |
self._window.uimanager.get_widget('/Tool/slideshow').set_tooltip_text( _('Start slideshow') ) | |
def is_running(self): | |
diff --git a/mcomix/status.py b/mcomix/status.py | |
index 4d9fb18..3d5a137 100644 | |
--- a/mcomix/status.py | |
+++ b/mcomix/status.py | |
@@ -1,12 +1,12 @@ | |
"""status.py - Statusbar for main window.""" | |
-import gtk | |
+from gi.repository import Gdk, Gtk | |
from mcomix import i18n | |
from mcomix import constants | |
from mcomix.preferences import prefs | |
-class Statusbar(gtk.EventBox): | |
+class Statusbar(Gtk.EventBox): | |
SPACING = 5 | |
@@ -15,12 +15,12 @@ class Statusbar(gtk.EventBox): | |
self._loading = True | |
- # Status text, page number, file number, resolution, path, filename, filesize | |
- self.status = gtk.Statusbar() | |
+ # Status text, page number, file number, resolution, path, filename | |
+ self.status = Gtk.Statusbar() | |
self.add(self.status) | |
# Create popup menu for enabling/disabling status boxes. | |
- self.ui_manager = gtk.UIManager() | |
+ self.ui_manager = Gtk.UIManager() | |
self.tooltipstatus = TooltipStatusHelper(self.ui_manager, self.status) | |
ui_description = """ | |
<ui> | |
@@ -36,7 +36,7 @@ class Statusbar(gtk.EventBox): | |
""" | |
self.ui_manager.add_ui_from_string(ui_description) | |
- actiongroup = gtk.ActionGroup('mcomix-statusbar') | |
+ actiongroup = Gtk.ActionGroup('mcomix-statusbar') | |
actiongroup.add_toggle_actions([ | |
('pagenumber', None, _('Show page numbers'), None, None, | |
self.toggle_status_visibility), | |
@@ -54,7 +54,7 @@ class Statusbar(gtk.EventBox): | |
# Hook mouse release event | |
self.connect('button-release-event', self._button_released) | |
- self.set_events(gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK) | |
+ self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.BUTTON_RELEASE_MASK) | |
# Default status information | |
self._page_info = '' | |
@@ -138,12 +138,12 @@ class Statusbar(gtk.EventBox): | |
self.status.push(0, space + text) | |
def push(self, context_id, message): | |
- """ Compatibility with gtk.Statusbar. """ | |
+ """ Compatibility with Gtk.Statusbar. """ | |
assert context_id >= 0 | |
self.status.push(context_id + 1, message) | |
def pop(self, context_id): | |
- """ Compatibility with gtk.Statusbar. """ | |
+ """ Compatibility with Gtk.Statusbar. """ | |
assert context_id >= 0 | |
self.status.pop(context_id + 1) | |
@@ -199,8 +199,8 @@ class Statusbar(gtk.EventBox): | |
""" Triggered when a mouse button is released to open the context | |
menu. """ | |
if event.button == 3: | |
- self.ui_manager.get_widget('/Statusbar').popup(None, None, None, | |
- event.button, event.time) | |
+ self.ui_manager.get_widget('/Statusbar').popup(None, None, None, None, | |
+ event.button, event.time) | |
def _update_sensitivity(self): | |
""" Updates the action menu's sensitivity based on user preferences. """ | |
@@ -223,7 +223,7 @@ class Statusbar(gtk.EventBox): | |
class TooltipStatusHelper(object): | |
- """ Attaches to a L{gtk.UIManager} to provide statusbar tooltips when | |
+ """ Attaches to a L{Gtk.UIManager} to provide statusbar tooltips when | |
selecting menu items. """ | |
def __init__(self, uimanager, statusbar): | |
@@ -236,7 +236,7 @@ class TooltipStatusHelper(object): | |
""" Connects the widget's selection handlers to the status bar update. | |
""" | |
tooltip = action.get_property('tooltip') | |
- if isinstance(widget, gtk.MenuItem) and tooltip: | |
+ if isinstance(widget, Gtk.MenuItem) and tooltip: | |
cid = widget.connect('select', self._on_item_select, tooltip) | |
cid2 = widget.connect('deselect', self._on_item_deselect) | |
setattr(widget, 'app::connect-ids', (cid, cid2)) | |
diff --git a/mcomix/thumbbar.py b/mcomix/thumbbar.py | |
index 5b97b40..cbd5896 100644 | |
--- a/mcomix/thumbbar.py | |
+++ b/mcomix/thumbbar.py | |
@@ -1,8 +1,8 @@ | |
"""thumbbar.py - Thumbnail sidebar for main window.""" | |
import urllib | |
-import gtk | |
-import gobject | |
+from gi.repository import GObject, Gdk, GdkPixbuf, Gtk | |
+import cairo | |
from mcomix.preferences import prefs | |
from mcomix import image_tools | |
@@ -11,7 +11,7 @@ from mcomix import constants | |
from mcomix import thumbnail_view | |
-class ThumbnailSidebar(gtk.ScrolledWindow): | |
+class ThumbnailSidebar(Gtk.ScrolledWindow): | |
"""A thumbnail sidebar including scrollbar for the main window.""" | |
@@ -27,12 +27,15 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
#: Selected row in treeview | |
self._currently_selected_row = 0 | |
- self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) | |
+ self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) | |
self.get_vadjustment().step_increment = 15 | |
self.get_vadjustment().page_increment = 1 | |
+ # Disable stupid overlay scrollbars... | |
+ if hasattr(self.props, 'overlay_scrolling'): | |
+ self.props.overlay_scrolling = False | |
# models - contains data | |
- self._thumbnail_liststore = gtk.ListStore(int, gtk.gdk.Pixbuf, bool) | |
+ self._thumbnail_liststore = Gtk.ListStore(int, GdkPixbuf.Pixbuf, bool) | |
# view - responsible for laying out the columns | |
self._treeview = thumbnail_view.ThumbnailTreeView( | |
@@ -41,38 +44,37 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
1, # pixbuf | |
2, # status | |
) | |
- # Whether or not unset_flags(gtk.DOUBLE_BUFFERED) reduces flickering on | |
- # update seems to depend on various circumstances, including the OS this | |
- # code is running on, and probably scheduling/threading issues. | |
- #self._treeview.unset_flags(gtk.DOUBLE_BUFFERED) | |
self._treeview.set_headers_visible(False) | |
self._treeview.generate_thumbnail = self._generate_thumbnail | |
+ self._treeview.set_activate_on_single_click(True) | |
self._treeview.connect_after('drag_begin', self._drag_begin) | |
self._treeview.connect('drag_data_get', self._drag_data_get) | |
- self._treeview.connect('cursor-changed', self._cursor_changed_event) | |
+ self._treeview.connect('row-activated', self._row_activated_event) | |
+ self._treeview.connect('button_press_event', self._mouse_press_event) | |
+ | |
# enable drag and dropping of images from thumbnail bar to some file | |
# manager | |
- self._treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, | |
- [('text/uri-list', 0, 0)], gtk.gdk.ACTION_COPY) | |
+ self._treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, | |
+ [('text/uri-list', 0, 0)], Gdk.DragAction.COPY) | |
# Page column | |
- self._thumbnail_page_treeviewcolumn = gtk.TreeViewColumn(None) | |
+ self._thumbnail_page_treeviewcolumn = Gtk.TreeViewColumn(None) | |
self._treeview.append_column(self._thumbnail_page_treeviewcolumn) | |
- self._text_cellrenderer = gtk.CellRendererText() | |
+ self._text_cellrenderer = Gtk.CellRendererText() | |
# Right align page numbers. | |
self._text_cellrenderer.set_property('xalign', 1.0) | |
- self._thumbnail_page_treeviewcolumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
+ self._thumbnail_page_treeviewcolumn.set_sizing(Gtk.TreeViewColumnSizing.FIXED) | |
self._thumbnail_page_treeviewcolumn.pack_start(self._text_cellrenderer, False) | |
self._thumbnail_page_treeviewcolumn.add_attribute(self._text_cellrenderer, 'text', 0) | |
self._thumbnail_page_treeviewcolumn.set_visible(False) | |
# Pixbuf column | |
- self._thumbnail_image_treeviewcolumn = gtk.TreeViewColumn(None) | |
+ self._thumbnail_image_treeviewcolumn = Gtk.TreeViewColumn(None) | |
self._treeview.append_column(self._thumbnail_image_treeviewcolumn) | |
- self._pixbuf_cellrenderer = gtk.CellRendererPixbuf() | |
- self._thumbnail_image_treeviewcolumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
+ self._pixbuf_cellrenderer = Gtk.CellRendererPixbuf() | |
+ self._thumbnail_image_treeviewcolumn.set_sizing(Gtk.TreeViewColumnSizing.FIXED) | |
self._thumbnail_image_treeviewcolumn.set_fixed_width(self._pixbuf_size) | |
self._thumbnail_image_treeviewcolumn.pack_start(self._pixbuf_cellrenderer, True) | |
self._thumbnail_image_treeviewcolumn.add_attribute(self._pixbuf_cellrenderer, 'pixbuf', 1) | |
@@ -95,13 +97,13 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
number_of_pages = self._window.imagehandler.get_number_of_pages() | |
number_of_digits = tools.number_of_digits(number_of_pages) | |
self._text_cellrenderer.set_property('width-chars', number_of_digits + 1) | |
- x, y, w, h = self._text_cellrenderer.get_size(self._treeview, None) | |
+ w = self._text_cellrenderer.get_preferred_size(self._treeview)[1].width | |
self._thumbnail_page_treeviewcolumn.set_fixed_width(w) | |
self._thumbnail_page_treeviewcolumn.set_visible(visible) | |
def get_width(self): | |
"""Return the width in pixels of the ThumbnailSidebar.""" | |
- return self.size_request()[0] | |
+ return self.size_request().width | |
def show(self, *args): | |
"""Show the ThumbnailSidebar.""" | |
@@ -134,17 +136,16 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
self.set_thumbnail_background(colour) | |
# Force a redraw of the widget. | |
- self.queue_draw() | |
+ self._treeview.queue_draw() | |
- def set_thumbnail_background(self, colour): | |
+ def set_thumbnail_background(self, color): | |
- color = gtk.gdk.Color(colour[0], colour[1], colour[2]) | |
- self._pixbuf_cellrenderer.set_property('cell-background-gdk', | |
- color) | |
- self._text_cellrenderer.set_property('background-gdk', | |
- color) | |
- self._text_cellrenderer.set_property('foreground-gdk', | |
- image_tools.text_color_for_background_color(colour)) | |
+ rgba = Gdk.RGBA(*image_tools.color_to_floats_rgba(color)) | |
+ self._pixbuf_cellrenderer.set_property('cell-background-rgba', rgba) | |
+ self._text_cellrenderer.set_property('background-rgba', rgba) | |
+ fg_color = image_tools.text_color_for_background_color(color) | |
+ fg_rgba = Gdk.RGBA(*(fg_color.to_floats() + (1.0,))) | |
+ self._text_cellrenderer.set_property('foreground-rgba', fg_rgba) | |
@property | |
def _pixbuf_size(self): | |
@@ -207,23 +208,20 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
except IndexError: | |
return 0 | |
- def _cursor_changed_event(self, treeview, *args): | |
+ def _row_activated_event(self, treeview, path, column): | |
"""Handle events due to changed thumbnail selection.""" | |
+ selected_row = self._get_selected_row() | |
+ self._set_selected_row(selected_row, scroll=False) | |
+ self._window.set_page(selected_row + 1) | |
- if not self._loaded or not self._treeview.get_realized(): | |
- # Skip event processing before widget is actually ready | |
- return | |
- | |
- if not self._window.was_out_of_focus: | |
- selected_row = self._get_selected_row() | |
- self._set_selected_row(selected_row, scroll=False) | |
- self._window.set_page(selected_row + 1) | |
- else: | |
+ def _mouse_press_event(self, widget, event): | |
+ if self._window.was_out_of_focus: | |
# if the window was out of focus and the user clicks on | |
# the thumbbar then do not select that page because they | |
# more than likely have many pages open and are simply trying | |
# to give mcomix focus again | |
- self._set_selected_row(self._currently_selected_row, scroll=False) | |
+ return True | |
+ return False | |
def _drag_data_get(self, treeview, context, selection, *args): | |
"""Put the URI of the selected file into the SelectionData, so that | |
@@ -241,19 +239,18 @@ class ThumbnailSidebar(gtk.ScrolledWindow): | |
might actually see where we are dropping!). | |
""" | |
path = treeview.get_cursor()[0] | |
- pixmap = treeview.create_row_drag_icon(path) | |
- | |
- # context.set_icon_pixmap() seems to cause crashes, so we do a | |
- # quick and dirty conversion to pixbuf. | |
- pointer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | |
- *pixmap.get_size()) | |
- pointer = pointer.get_from_drawable(pixmap, treeview.get_colormap(), | |
- 0, 0, 0, 0, *pixmap.get_size()) | |
- context.set_icon_pixbuf(pointer, -5, -5) | |
+ surface = treeview.create_row_drag_icon(path) | |
+ # Because of course a cairo.Win32Surface does not have | |
+ # get_width/get_height, that would be to easy... | |
+ cr = cairo.Context(surface) | |
+ x1, y1, x2, y2 = cr.clip_extents() | |
+ width, height = x2 - x1, y2 - y1 | |
+ pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, width, height) | |
+ Gtk.drag_set_icon_pixbuf(context, pixbuf, -5, -5) | |
def _get_empty_thumbnail(self): | |
""" Create an empty filler pixmap. """ | |
- pixbuf = gtk.gdk.Pixbuf(colorspace=gtk.gdk.COLORSPACE_RGB, | |
+ pixbuf = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
has_alpha=True, | |
bits_per_sample=8, | |
width=self._pixbuf_size, | |
diff --git a/mcomix/thumbnail_tools.py b/mcomix/thumbnail_tools.py | |
index 71700d7..e157a5d 100644 | |
--- a/mcomix/thumbnail_tools.py | |
+++ b/mcomix/thumbnail_tools.py | |
@@ -214,7 +214,12 @@ class Thumbnailer(object): | |
if os.path.isfile(thumbpath): | |
os.remove(thumbpath) | |
- pixbuf.save(thumbpath, 'png', tEXt_data) | |
+ option_keys = [] | |
+ option_values = [] | |
+ for key, value in tEXt_data.items(): | |
+ option_keys.append(key) | |
+ option_values.append(value) | |
+ pixbuf.savev(thumbpath, 'png', option_keys, option_values) | |
os.chmod(thumbpath, 0600) | |
except Exception, ex: | |
diff --git a/mcomix/thumbnail_view.py b/mcomix/thumbnail_view.py | |
index 899e0bb..c7c5b08 100644 | |
--- a/mcomix/thumbnail_view.py | |
+++ b/mcomix/thumbnail_view.py | |
@@ -1,16 +1,16 @@ | |
-""" gtk.IconView subclass for dynamically generated thumbnails. """ | |
+""" Gtk.IconView subclass for dynamically generated thumbnails. """ | |
import Queue | |
-import gtk | |
-import gobject | |
+from gi.repository import Gtk | |
+from gi.repository import GObject | |
from mcomix.preferences import prefs | |
from mcomix.worker_thread import WorkerThread | |
class ThumbnailViewBase(object): | |
- """ This class provides shared functionality for gtk.TreeView and | |
- gtk.IconView. Instantiating this class directly is *impossible*, | |
+ """ This class provides shared functionality for Gtk.TreeView and | |
+ Gtk.IconView. Instantiating this class directly is *impossible*, | |
as it depends on methods provided by the view classes. """ | |
def __init__(self, uid_column, pixbuf_column, status_column): | |
@@ -39,7 +39,7 @@ class ThumbnailViewBase(object): | |
raise NotImplementedError() | |
def get_visible_range(self): | |
- """ See L{gtk.IconView.get_visible_range}. """ | |
+ """ See L{Gtk.IconView.get_visible_range}. """ | |
raise NotImplementedError() | |
def stop_update(self): | |
@@ -88,7 +88,7 @@ class ThumbnailViewBase(object): | |
uid, iter = order | |
pixbuf = self.generate_thumbnail(uid) | |
if pixbuf is not None: | |
- gobject.idle_add(self._pixbuf_finished, iter, pixbuf) | |
+ GObject.idle_add(self._pixbuf_finished, iter, pixbuf) | |
def _pixbuf_finished(self, iter, pixbuf): | |
""" Executed when a pixbuf was created, to actually insert the pixbuf | |
@@ -104,29 +104,29 @@ class ThumbnailViewBase(object): | |
# Remove this idle handler. | |
return 0 | |
-class ThumbnailIconView(gtk.IconView, ThumbnailViewBase): | |
+class ThumbnailIconView(Gtk.IconView, ThumbnailViewBase): | |
def __init__(self, model, uid_column, pixbuf_column, status_column): | |
- assert gtk.TREE_MODEL_ITERS_PERSIST == (model.get_flags() & gtk.TREE_MODEL_ITERS_PERSIST) | |
+ assert 0 != (model.get_flags() & Gtk.TreeModelFlags.ITERS_PERSIST) | |
super(ThumbnailIconView, self).__init__(model) | |
ThumbnailViewBase.__init__(self, uid_column, pixbuf_column, status_column) | |
self.set_pixbuf_column(pixbuf_column) | |
# Connect events | |
- self.connect('expose-event', self.draw_thumbnails_on_screen) | |
+ self.connect('draw', self.draw_thumbnails_on_screen) | |
def get_visible_range(self): | |
- return gtk.IconView.get_visible_range(self) | |
+ return Gtk.IconView.get_visible_range(self) | |
-class ThumbnailTreeView(gtk.TreeView, ThumbnailViewBase): | |
+class ThumbnailTreeView(Gtk.TreeView, ThumbnailViewBase): | |
def __init__(self, model, uid_column, pixbuf_column, status_column): | |
- assert gtk.TREE_MODEL_ITERS_PERSIST == (model.get_flags() & gtk.TREE_MODEL_ITERS_PERSIST) | |
+ assert 0 != (model.get_flags() & Gtk.TreeModelFlags.ITERS_PERSIST) | |
super(ThumbnailTreeView, self).__init__(model) | |
ThumbnailViewBase.__init__(self, uid_column, pixbuf_column, status_column) | |
# Connect events | |
- self.connect('expose-event', self.draw_thumbnails_on_screen) | |
+ self.connect('draw', self.draw_thumbnails_on_screen) | |
def get_visible_range(self): | |
- return gtk.TreeView.get_visible_range(self) | |
+ return Gtk.TreeView.get_visible_range(self) | |
# vim: expandtab:sw=4:ts=4 | |
diff --git a/mcomix/ui.py b/mcomix/ui.py | |
index 0e61411..e4d483f 100644 | |
--- a/mcomix/ui.py | |
+++ b/mcomix/ui.py | |
@@ -1,7 +1,7 @@ | |
"""ui.py - UI definitions for main window. | |
""" | |
-import gtk | |
+from gi.repository import Gtk | |
from mcomix import bookmark_menu | |
from mcomix import openwith_menu | |
@@ -16,7 +16,7 @@ from mcomix import file_chooser_main_dialog | |
from mcomix.preferences import prefs | |
from mcomix.library import main_dialog as library_main_dialog | |
-class MainUI(gtk.UIManager): | |
+class MainUI(Gtk.UIManager): | |
def __init__(self, window): | |
super(MainUI, self).__init__() | |
@@ -30,48 +30,48 @@ class MainUI(gtk.UIManager): | |
# ---------------------------------------------------------------- | |
# Create actions for the menus. | |
# ---------------------------------------------------------------- | |
- self._actiongroup = gtk.ActionGroup('mcomix-main') | |
+ self._actiongroup = Gtk.ActionGroup('mcomix-main') | |
self._actiongroup.add_actions([ | |
- ('copy_page', gtk.STOCK_COPY, _('_Copy'), | |
+ ('copy_page', Gtk.STOCK_COPY, _('_Copy'), | |
None, _('Copies the current page to clipboard.'), | |
window.clipboard.copy_page), | |
- ('delete', gtk.STOCK_DELETE, _('_Delete'), | |
+ ('delete', Gtk.STOCK_DELETE, _('_Delete'), | |
None, _('Deletes the current file or archive from disk.'), | |
window.delete), | |
- ('next_page', gtk.STOCK_GO_FORWARD, _('_Next page'), | |
+ ('next_page', Gtk.STOCK_GO_FORWARD, _('_Next page'), | |
None, _('Next page'), _action_lambda(window.flip_page, +1)), | |
- ('previous_page', gtk.STOCK_GO_BACK, _('_Previous page'), | |
+ ('previous_page', Gtk.STOCK_GO_BACK, _('_Previous page'), | |
None, _('Previous page'), _action_lambda(window.flip_page, -1)), | |
- ('first_page', gtk.STOCK_GOTO_FIRST, _('_First page'), | |
+ ('first_page', Gtk.STOCK_GOTO_FIRST, _('_First page'), | |
None, _('First page'), _action_lambda(window.first_page)), | |
- ('last_page', gtk.STOCK_GOTO_LAST, _('_Last page'), | |
+ ('last_page', Gtk.STOCK_GOTO_LAST, _('_Last page'), | |
None, _('Last page'), _action_lambda(window.last_page)), | |
- ('go_to', gtk.STOCK_JUMP_TO, _('_Go to page...'), | |
+ ('go_to', Gtk.STOCK_JUMP_TO, _('_Go to page...'), | |
None, _('Go to page...'), window.page_select), | |
- ('refresh_archive', gtk.STOCK_REFRESH, _('Re_fresh'), | |
+ ('refresh_archive', Gtk.STOCK_REFRESH, _('Re_fresh'), | |
None, _('Reloads the currently opened files or archive.'), | |
window.filehandler.refresh_file), | |
- ('next_archive', gtk.STOCK_MEDIA_NEXT, _('Next _archive'), | |
+ ('next_archive', Gtk.STOCK_MEDIA_NEXT, _('Next _archive'), | |
None, _('Next archive'), window.filehandler._open_next_archive), | |
- ('previous_archive', gtk.STOCK_MEDIA_PREVIOUS, _('Previous a_rchive'), | |
+ ('previous_archive', Gtk.STOCK_MEDIA_PREVIOUS, _('Previous a_rchive'), | |
None, _('Previous archive'), window.filehandler._open_previous_archive), | |
- ('next_directory', gtk.STOCK_REDO, _('Next directory'), | |
+ ('next_directory', Gtk.STOCK_REDO, _('Next directory'), | |
None, _('Next directory'), window.filehandler.open_next_directory), | |
- ('previous_directory', gtk.STOCK_UNDO, _('Previous directory'), | |
+ ('previous_directory', Gtk.STOCK_UNDO, _('Previous directory'), | |
None, _('Previous directory'), window.filehandler.open_previous_directory), | |
- ('zoom_in', gtk.STOCK_ZOOM_IN, _('Zoom _In'), | |
+ ('zoom_in', Gtk.STOCK_ZOOM_IN, _('Zoom _In'), | |
None, None, window.manual_zoom_in), | |
- ('zoom_out', gtk.STOCK_ZOOM_OUT, _('Zoom _Out'), | |
+ ('zoom_out', Gtk.STOCK_ZOOM_OUT, _('Zoom _Out'), | |
None, None, window.manual_zoom_out), | |
- ('zoom_original', gtk.STOCK_ZOOM_100, _('_Normal Size'), | |
+ ('zoom_original', Gtk.STOCK_ZOOM_100, _('_Normal Size'), | |
None, None, window.manual_zoom_original), | |
- ('minimize', gtk.STOCK_LEAVE_FULLSCREEN, _('Mi_nimize'), | |
+ ('minimize', Gtk.STOCK_LEAVE_FULLSCREEN, _('Mi_nimize'), | |
None, None, window.minimize), | |
- ('close', gtk.STOCK_CLOSE, _('_Close'), | |
+ ('close', Gtk.STOCK_CLOSE, _('_Close'), | |
None, _('Closes all opened files.'), _action_lambda(window.filehandler.close_file)), | |
- ('quit', gtk.STOCK_QUIT, _('_Quit'), | |
+ ('quit', Gtk.STOCK_QUIT, _('_Quit'), | |
None, None, window.close_program), | |
- ('save_and_quit', gtk.STOCK_QUIT, _('_Save and quit'), | |
+ ('save_and_quit', Gtk.STOCK_QUIT, _('_Save and quit'), | |
None, _('Quits and restores the currently opened file next time the program starts.'), | |
window.save_and_terminate_program), | |
('rotate_90', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), | |
@@ -84,21 +84,21 @@ class MainUI(gtk.UIManager): | |
None, None, window.flip_horizontally), | |
('flip_vert', 'mcomix-flip-vertical', _('Flip _vertically'), | |
None, None, window.flip_vertically), | |
- ('extract_page', gtk.STOCK_SAVE_AS, _('Save _As'), | |
+ ('extract_page', Gtk.STOCK_SAVE_AS, _('Save _As'), | |
None, None, window.extract_page), | |
('menu_zoom', 'mcomix-zoom', _('_Zoom')), | |
- ('menu_recent', gtk.STOCK_DND_MULTIPLE, _('_Recent')), | |
+ ('menu_recent', Gtk.STOCK_FILE, _('_Recent')), | |
('menu_bookmarks_popup', 'comix-add-bookmark', _('_Bookmarks')), | |
('menu_bookmarks', None, _('_Bookmarks')), | |
('menu_toolbars', None, _('T_oolbars')), | |
('menu_edit', None, _('_Edit')), | |
- ('menu_open_with', gtk.STOCK_OPEN, _('Open _with'), ''), | |
- ('menu_open_with_popup', gtk.STOCK_OPEN, _('Open _with'), ''), | |
+ ('menu_open_with', Gtk.STOCK_OPEN, _('Open _with'), ''), | |
+ ('menu_open_with_popup', Gtk.STOCK_OPEN, _('Open _with'), ''), | |
('menu_file', None, _('_File')), | |
('menu_view', None, _('_View')), | |
('menu_view_popup', 'comix-image', _('_View')), | |
('menu_go', None, _('_Go')), | |
- ('menu_go_popup', gtk.STOCK_GO_FORWARD, _('_Go')), | |
+ ('menu_go_popup', Gtk.STOCK_GO_FORWARD, _('_Go')), | |
('menu_tools', None, _('_Tools')), | |
('menu_help', None, _('_Help')), | |
('menu_transform', 'mcomix-transform', _('_Transform image')), | |
@@ -108,7 +108,7 @@ class MainUI(gtk.UIManager): | |
('expander', None, None, None, None, None)]) | |
self._actiongroup.add_toggle_actions([ | |
- ('fullscreen', gtk.STOCK_FULLSCREEN, _('_Fullscreen'), | |
+ ('fullscreen', Gtk.STOCK_FULLSCREEN, _('_Fullscreen'), | |
None, _('Fullscreen mode'), window.change_fullscreen), | |
('double_page', 'mcomix-double-page', _('_Double page mode'), | |
None, _('Double page mode'), window.change_double_page), | |
@@ -126,12 +126,12 @@ class MainUI(gtk.UIManager): | |
None, None, window.change_hide_all), | |
('manga_mode', 'mcomix-manga', _('_Manga mode'), | |
None, _('Manga mode'), window.change_manga_mode), | |
- ('invert_scroll', gtk.STOCK_UNDO, _('Invert smart scroll'), | |
+ ('invert_scroll', Gtk.STOCK_UNDO, _('Invert smart scroll'), | |
None, _('Invert smart scrolling direction.'), window.change_invert_scroll), | |
('keep_transformation', None, _('_Keep transformation'), | |
None, _('Keeps the currently selected transformation for the next pages.'), | |
window.change_keep_transformation), | |
- ('slideshow', gtk.STOCK_MEDIA_PLAY, _('Start _slideshow'), | |
+ ('slideshow', Gtk.STOCK_MEDIA_PLAY, _('Start _slideshow'), | |
None, _('Start slideshow'), window.slideshow.toggle), | |
('lens', 'mcomix-lens', _('Magnifying _lens'), | |
None, _('Magnifying lens'), window.lens.toggle), | |
@@ -169,7 +169,7 @@ class MainUI(gtk.UIManager): | |
prefs['auto rotate depending on size'], window.change_autorotation) | |
self._actiongroup.add_actions([ | |
- ('about', gtk.STOCK_ABOUT, _('_About'), | |
+ ('about', Gtk.STOCK_ABOUT, _('_About'), | |
None, None, dialog_handler.open_dialog)], (window, 'about-dialog')) | |
self._actiongroup.add_actions([ | |
@@ -177,19 +177,19 @@ class MainUI(gtk.UIManager): | |
None, None, dialog_handler.open_dialog)], (window, 'comments-dialog')) | |
self._actiongroup.add_actions([ | |
- ('properties', gtk.STOCK_PROPERTIES, _('Proper_ties'), | |
+ ('properties', Gtk.STOCK_PROPERTIES, _('Proper_ties'), | |
None, None, dialog_handler.open_dialog)], (window,'properties-dialog')) | |
self._actiongroup.add_actions([ | |
- ('preferences', gtk.STOCK_PREFERENCES, _('Pr_eferences'), | |
- None, None, preferences_dialog.open_dialog)], (window)) | |
+ ('preferences', Gtk.STOCK_PREFERENCES, _('Pr_eferences'), | |
+ None, None, preferences_dialog.open_dialog)], window) | |
# Some actions added separately since they need extra arguments. | |
self._actiongroup.add_actions([ | |
- ('edit_archive', gtk.STOCK_EDIT, _('_Edit archive...'), | |
+ ('edit_archive', Gtk.STOCK_EDIT, _('_Edit archive...'), | |
None, _('Opens the archive editor.'), | |
edit_dialog.open_dialog), | |
- ('open', gtk.STOCK_OPEN, _('_Open...'), | |
+ ('open', Gtk.STOCK_OPEN, _('_Open...'), | |
None, None, file_chooser_main_dialog.open_main_filechooser_dialog), | |
('enhance_image', 'mcomix-enhance-image', _('En_hance image...'), | |
None, None, enhance_dialog.open_dialog)], window) | |
@@ -199,7 +199,7 @@ class MainUI(gtk.UIManager): | |
None, None, library_main_dialog.open_dialog)], window) | |
# fix some gtk magic: removing unreqired accelerators | |
- gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % 'close', 0, 0, True) | |
+ Gtk.AccelMap.change_entry('<Actions>/mcomix-main/%s' % 'close', 0, 0, True) | |
ui_description = """ | |
<ui> | |
diff --git a/setup.py b/setup.py | |
index 01ffe93..ea87667 100755 | |
--- a/setup.py | |
+++ b/setup.py | |
@@ -17,6 +17,7 @@ import setuptools | |
from mcomix import constants | |
+ | |
def get_data_patterns(directory, *patterns): | |
""" Build a list of patterns for all subdirectories of <directory> | |
to be passed into package_data. """ | |
@@ -44,11 +45,10 @@ images.extend([ os.path.basename(img) | |
setuptools.setup( | |
name = constants.APPNAME.lower(), | |
version = constants.VERSION, | |
- packages = ['mcomix', 'mcomix.archive', 'mcomix.library', | |
- 'mcomix.messages', 'mcomix.images', 'mcomix.win32'], | |
+ packages = ['mcomix', 'mcomix.archive', 'mcomix.library', 'mcomix.win32'], | |
package_data = { | |
- 'mcomix.messages' : get_data_patterns('mcomix/messages', '*.mo'), | |
- 'mcomix.images' : images }, | |
+ 'mcomix' : get_data_patterns('mcomix/messages', '*.mo') + images, | |
+ }, | |
entry_points = { | |
'console_scripts' : [ 'mcomix = mcomix.run:run' ], | |
'setuptools.installation': [ 'eggsecutable=mcomix.run:run' ], | |
diff --git a/test/test_image_tools.py b/test/test_image_tools.py | |
index a1f6c16..7558545 100644 | |
--- a/test/test_image_tools.py | |
+++ b/test/test_image_tools.py | |
@@ -5,7 +5,7 @@ import os | |
import sys | |
import tempfile | |
-import gtk, gobject | |
+from gi.repository import GdkPixbuf, GObject | |
from collections import namedtuple | |
from PIL import Image, ImageDraw | |
@@ -81,8 +81,9 @@ def get_image_path(basename): | |
return get_testfile_path('images', basename) | |
def new_pixbuf(size, with_alpha, fill_colour): | |
- pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, | |
- with_alpha, 8, size[0], size[1]) | |
+ pixbuf = GdkPixbuf.Pixbuf.new(colorspace=GdkPixbuf.Colorspace.RGB, | |
+ has_alpha=with_alpha, bits_per_sample=8, | |
+ width=size[0], height=size[1]) | |
pixbuf.fill(fill_colour) | |
return pixbuf | |
@@ -128,9 +129,9 @@ def hexdump(data, group_size=4): | |
return [line for line in xhexdump(data, group_size=group_size)] | |
def composite_image(im1, im2): | |
- if isinstance(im1, gtk.gdk.Pixbuf): | |
+ if isinstance(im1, GdkPixbuf.Pixbuf): | |
im1 = image_tools.pixbuf_to_pil(im1) | |
- if isinstance(im2, gtk.gdk.Pixbuf): | |
+ if isinstance(im2, GdkPixbuf.Pixbuf): | |
im2 = image_tools.pixbuf_to_pil(im2) | |
im = Image.new('RGBA', | |
(im1.size[0] + im2.size[0], | |
@@ -167,7 +168,7 @@ class ImageToolsTest(object): | |
'diff': diff_fmt % args, | |
}) | |
def info(im): | |
- if isinstance(im, gtk.gdk.Pixbuf): | |
+ if isinstance(im, GdkPixbuf.Pixbuf): | |
width, stride = im.get_width(), im.get_rowstride() | |
line_size = width * im.get_n_channels() | |
if stride == line_size: | |
@@ -182,6 +183,8 @@ class ImageToolsTest(object): | |
break | |
pixels += line | |
leftover = io.read(stride - line_size) | |
+ if not leftover: | |
+ break | |
assert len(leftover) == (stride - line_size) | |
mode = 'RGBA' if im.get_has_alpha() else 'RGB' | |
return mode, (im.get_width(), im.get_height()), pixels | |
@@ -250,7 +253,7 @@ class ImageToolsTest(object): | |
if self.use_pil: | |
exception = IOError | |
else: | |
- exception = gobject.GError | |
+ exception = GObject.GError | |
self.assertRaises(exception, image_tools.load_pixbuf, os.devnull) | |
def test_load_pixbuf_size_basic(self): | |
@@ -324,7 +327,7 @@ class ImageToolsTest(object): | |
if self.use_pil: | |
exception = IOError | |
else: | |
- exception = gobject.GError | |
+ exception = GObject.GError | |
self.assertRaises(exception, image_tools.load_pixbuf_size, os.devnull, 50, 50) | |
# Expose a rounding error bug in load_pixbuf_size. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment