[postr] Ported to GTK+3
- From: GermÃn Poà CaamaÃo <gpoo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [postr] Ported to GTK+3
- Date: Wed, 3 Oct 2012 23:06:03 +0000 (UTC)
commit b8d043bdd4de109f83fa15f8eeaffc7e2bbe8305
Author: GermÃn Poo-CaamaÃo <gpoo gnome org>
Date: Wed Oct 3 14:30:29 2012 -0700
Ported to GTK+3
Added catalog for Glade. To use it:
$ export GLADE_CATALOG_SEARCH_PATH=.
$ glade postr.glade
Signed-off-by: GermÃn Poo-CaamaÃo <gpoo gnome org>
nautilus/postrExtension.py | 32 +-
postr | 4 +-
src/AboutDialog.py | 18 +-
src/AuthenticationDialog.py | 33 +-
src/ContentTypeCombo.py | 20 +-
src/ErrorDialog.py | 24 +-
src/GroupSelector.py | 59 ++--
src/ImageList.py | 44 ++-
src/ImageStore.py | 32 +-
src/LicenseCombo.py | 25 +-
src/PrivacyCombo.py | 22 +-
src/ProgressDialog.py | 45 ++-
src/PyUnique.py | 36 +-
src/SafetyCombo.py | 20 +-
src/SetCombo.py | 56 ++--
src/StatusBar.py | 12 +-
src/TagsEntry.py | 19 +-
src/catalog_poster.xml | 45 +++
src/flickrest.py | 8 +-
src/postr.glade | 864 +++++++++++++++++++++++--------------------
src/postr.py | 420 ++++++++++-----------
src/proxyclient.py | 2 +-
src/util.py | 28 +-
23 files changed, 1002 insertions(+), 866 deletions(-)
---
diff --git a/nautilus/postrExtension.py b/nautilus/postrExtension.py
index 750031b..a17b79e 100644
--- a/nautilus/postrExtension.py
+++ b/nautilus/postrExtension.py
@@ -18,19 +18,19 @@
import gettext
gettext.install('postr')
-import gobject, nautilus
+from gi.repository import Nautilus, GObject
import os, os.path
from urllib import unquote
PROGRAM_NAME = 'postr'
-class PostrExtension(nautilus.MenuProvider):
+class PostrExtension(GObject.GObject, Nautilus.MenuProvider):
def __init__(self):
# The constructor must be exists, even if there is nothing
# to initialize (See Bug #374958)
#self.program = None
pass
-
+
def locate_program(self, program_name):
path_list = os.environ['PATH']
for d in path_list.split(os.path.pathsep):
@@ -51,12 +51,12 @@ class PostrExtension(nautilus.MenuProvider):
if len(files) == 0:
return
- names = [ unquote(file.get_uri()[7:]) for file in files ]
+ names = [ file.get_uri() for file in files ]
argv = [ PROGRAM_NAME ] + names
# TODO: use startup notification
- gobject.spawn_async(argv, flags=gobject.SPAWN_SEARCH_PATH)
+ GObject.spawn_async(argv, flags=GObject.SPAWN_SEARCH_PATH)
def get_file_items(self, window, files):
# Show the menu iif:
@@ -67,21 +67,27 @@ class PostrExtension(nautilus.MenuProvider):
# - Postr is installed (is in PATH)
if len(files) == 0:
return
-
- for file in files:
- if file.is_directory() or file.get_uri_scheme() != 'file':
+
+ for fd in files:
+ if fd.is_directory() or fd.get_uri_scheme() != 'file':
return
- if not file.is_mime_type("image/*"):
+ if not fd.is_mime_type("image/*"):
return
#self.program = self.locate_program(PROGRAM_NAME)
#if not self.program:
# return
- item = nautilus.MenuItem('PostrExtension::upload_files',
- _('Upload to Flickr...'),
- _('Upload the selected files into Flickr'),
- "postr")
+ item = Nautilus.MenuItem(name='PostrExtension::upload_files',
+ label=_('Upload to Flickr...'),
+ tip=_('Upload the selected files into Flickr'),
+ icon="postr")
item.connect('activate', self.upload_files, files)
return item,
+
+ def get_background_items(self, window, files):
+ # If nothing is selected, Nautils still can show a contextual
+ # menu item.
+ # This method must exist even if we have nothing to offer here.
+ return
diff --git a/postr b/postr
index 1c14caa..248db5e 100755
--- a/postr
+++ b/postr
@@ -21,8 +21,8 @@ import gettext
gettext.install('postr')
import sys
-from twisted.internet import gtk2reactor
-reactor = gtk2reactor.install()
+from twisted.internet import gtk3reactor
+reactor = gtk3reactor.install()
# Import from src first so that we can run directly from the source tree for
# development.
diff --git a/src/AboutDialog.py b/src/AboutDialog.py
index c28e829..ee71ec2 100644
--- a/src/AboutDialog.py
+++ b/src/AboutDialog.py
@@ -1,6 +1,8 @@
# Postr, a Flickr Uploader
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2006-2008 Ross Burton <ross burtonini com>
+# Copyright (C) 2012 GermÃn Poo-CaamaÃo <gpoo gnome org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -15,16 +17,18 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
+from gi.repository import Gtk, GObject
from version import __version__
-class AboutDialog(gtk.AboutDialog):
+class AboutDialog(Gtk.AboutDialog):
def __init__(self, parent=None):
- gtk.AboutDialog.__init__(self)
+ Gtk.AboutDialog.__init__(self)
self.set_transient_for(parent)
self.set_name(_('Flickr Uploader'))
- self.set_copyright(u'Copyright \u00A9 2006-2008 Ross Burton')
- self.set_authors(('Ross Burton <ross burtonini com>',))
+ self.set_copyright(u'Copyright \u00A9 2006-2008 Ross Burton\n'
+ u'Copyright \u00A9 2009-2012 GermÃn Poo-CaamaÃo')
+ self.set_authors(('Ross Burton <ross burtonini com>',
+ 'GermÃn Poo-CaamaÃo <gpoo gnome org>'))
self.set_website('http://projects.gnome.org/postr/')
self.set_logo_icon_name('postr')
self.set_version (__version__)
@@ -32,6 +36,6 @@ class AboutDialog(gtk.AboutDialog):
if __name__ == "__main__":
import gettext; gettext.install('postr')
-
+
AboutDialog().show()
- gtk.main()
+ Gtk.main()
diff --git a/src/AuthenticationDialog.py b/src/AuthenticationDialog.py
index e2fd53c..e4a0706 100644
--- a/src/AuthenticationDialog.py
+++ b/src/AuthenticationDialog.py
@@ -15,13 +15,14 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import os, gtk, gconf
+import os
+from gi.repository import Gtk, GConf, GObject
def on_url_clicked(button, url):
"""Global LinkButton handler that starts the default GNOME HTTP handler, or
firefox."""
# Get the HTTP URL handler
- client = gconf.client_get_default()
+ client = GConf.Client.get_default()
browser = client.get_string("/desktop/gnome/url-handlers/http/command") or "firefox"
# Because the world sucks and everyone hates me, just use the first word and
@@ -33,30 +34,30 @@ def on_url_clicked(button, url):
os.spawnlp(os.P_NOWAIT, browser, browser, url)
# TODO: if that didn't work fallback on x-www-browser or something
-class AuthenticationDialog(gtk.Dialog):
+class AuthenticationDialog(Gtk.Dialog):
def __init__(self, parent, url):
- gtk.Dialog.__init__(self,
+ Gtk.Dialog.__init__(self,
title=_("Flickr Uploader"), parent=parent,
- flags=gtk.DIALOG_NO_SEPARATOR,
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
- _("Continue"), gtk.RESPONSE_ACCEPT))
- vbox = gtk.VBox(spacing=8)
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT,
+ _("Continue"), Gtk.ResponseType.ACCEPT))
+ vbox = Gtk.VBox(spacing=8)
+
vbox.set_border_width(8)
-
- label = gtk.Label(_("Postr needs to login to Flickr to upload your photos. "
+
+ label = Gtk.Label(_("Postr needs to login to Flickr to upload your photos. "
"Please click on the link below to login to Flickr."))
label.set_line_wrap(True)
vbox.add(label)
- # gtk.LinkButton is only in 2.10, so use a normal button if it isn't
+ # Gtk.LinkButton is only in 2.10, so use a normal button if it isn't
# available.
- if hasattr(gtk, "LinkButton"):
- gtk.link_button_set_uri_hook(on_url_clicked)
- button = gtk.LinkButton(url, _("Login to Flickr"))
+ if hasattr(Gtk, "LinkButton"):
+ Gtk.link_button_set_uri_hook(on_url_clicked)
+ button = Gtk.LinkButton(url, _("Login to Flickr"))
else:
- button = gtk.Button(_("Login to Flickr"))
+ button = Gtk.Button(_("Login to Flickr"))
button.connect("clicked", on_url_clicked, url)
vbox.add(button)
-
+
self.vbox.add(vbox)
self.show_all()
diff --git a/src/ContentTypeCombo.py b/src/ContentTypeCombo.py
index 3064b6d..50cb54e 100644
--- a/src/ContentTypeCombo.py
+++ b/src/ContentTypeCombo.py
@@ -15,22 +15,24 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk
+from gi.repository import GObject, Gtk
+
+class ContentTypeCombo(Gtk.ComboBox):
+ __gtype_name__ = 'ContentTypeCombo'
-class ContentTypeCombo(gtk.ComboBox):
def __init__(self):
- gtk.ComboBox.__init__(self)
+ Gtk.ComboBox.__init__(self)
# Name, content_type
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
- model.set(model.append(), 0, "Photo", 1, 1)
- model.set(model.append(), 0, "Screenshot", 1, 2)
- model.set(model.append(), 0, "Other", 1, 3)
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
+ model.append(['Photo', 1])
+ model.append(['Screenshot', 2])
+ model.append(['Other', 3])
self.model = model
self.set_model(model)
self.set_active(0)
- cell = gtk.CellRendererText()
- self.pack_start(cell)
+ cell = Gtk.CellRendererText()
+ self.pack_start(cell, True)
self.add_attribute(cell, "text", 0)
def get_content_type_for_iter(self, it):
diff --git a/src/ErrorDialog.py b/src/ErrorDialog.py
index 32891f5..f6024d3 100644
--- a/src/ErrorDialog.py
+++ b/src/ErrorDialog.py
@@ -15,15 +15,17 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
+from gi.repository import Gtk, GObject
-class ErrorDialog(gtk.MessageDialog):
+class ErrorDialog(Gtk.MessageDialog):
def __init__(self, parent=None):
- gtk.MessageDialog.__init__(self, flags=gtk.DIALOG_DESTROY_WITH_PARENT,
- type=gtk.MESSAGE_ERROR,
- buttons=gtk.BUTTONS_OK,
+ Gtk.MessageDialog.__init__(self,
+ flags=Gtk.DialogFlags.DESTROY_WITH_PARENT,
+ type=Gtk.MessageType.ERROR,
+ buttons=Gtk.ButtonsType.OK,
parent=parent,
message_format=_("An error occurred"))
+ self.set_destroy_with_parent(True)
self.connect("response", lambda dialog, response: dialog.destroy())
self.expander = None
@@ -44,19 +46,19 @@ class ErrorDialog(gtk.MessageDialog):
def add_details(self, message):
# TODO: format nicer
if not self.expander:
- self.expander = gtk.Expander(_('Details'))
- self.view = gtk.TextView();
+ self.expander = Gtk.Expander(_('Details'))
+ self.view = Gtk.TextView();
self.buffer = self.view.get_buffer()
- sw = gtk.ScrolledWindow()
- sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
- sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ sw = Gtk.ScrolledWindow()
+ sw.set_shadow_type(Gtk.Shadow.ETCHED_IN)
+ sw.set_policy(Gtk.Policy.AUTOMATIC, Gtk.Policy.AUTOMATIC)
sw.add(self.view)
self.expander.add(sw)
self.expander.show_all()
- self.vbox.pack_start(self.expander)
+ self.vbox.pack_start(self.expander, True, True, 0)
iter = self.buffer.get_end_iter()
diff --git a/src/GroupSelector.py b/src/GroupSelector.py
index bcfc97e..bf29365 100644
--- a/src/GroupSelector.py
+++ b/src/GroupSelector.py
@@ -15,7 +15,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk, pango
+from gi.repository import Gtk, GObject, Pango, GdkPixbuf
from ErrorDialog import ErrorDialog
import util
@@ -24,65 +24,66 @@ import util
COL_NAME,
COL_ICON) = range(0, 4)
-class GroupSelector(gtk.TreeView):
-
+class GroupSelector(Gtk.TreeView):
+ __gtype_name__ = 'GroupSelector'
__gsignals__ = {
- 'changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
+ 'changed' : (GObject.SignalFlags.RUN_LAST, None, ())
}
-
- def __init__(self, flickr):
- self.flickr = flickr
- self.model = gtk.ListStore(gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gtk.gdk.Pixbuf)
+
+ def __init__(self):
+ self.flickr = None
+ self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN,
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GdkPixbuf.Pixbuf)
self.model.connect("row-changed", lambda model, path, iter: self.emit("changed"))
-
- gtk.TreeView.__init__(self, self.model)
-
+
+ Gtk.TreeView.__init__(self, self.model)
+
# Calculate the size of thumbnails based on the size of the text
# renderer, but provide a default in case style-set isn't called.
self.connect("style-set", self.style_set);
self.thumb_size = 24
- column = gtk.TreeViewColumn('Selected')
+ column = Gtk.TreeViewColumn('Selected')
self.append_column(column)
-
- renderer = gtk.CellRendererToggle()
+
+ renderer = Gtk.CellRendererToggle()
def toggled(r, path):
self.model[path][COL_SELECTED] = not r.get_active()
renderer.connect("toggled", toggled)
column.pack_start(renderer, False)
column.add_attribute(renderer, "active", COL_SELECTED)
-
- column = gtk.TreeViewColumn('Group')
+
+ column = Gtk.TreeViewColumn('Group')
self.append_column(column)
- renderer = gtk.CellRendererPixbuf()
+ renderer = Gtk.CellRendererPixbuf()
column.pack_start(renderer, False)
column.add_attribute(renderer, "pixbuf", COL_ICON)
-
- self.text_renderer = gtk.CellRendererText()
+
+ self.text_renderer = Gtk.CellRendererText()
column.pack_start(self.text_renderer, True)
column.add_attribute(self.text_renderer, "text", COL_NAME)
-
- self.set_size_request(-1, 24 * 3 + self.style_get_property("vertical-separator") * 6)
+
+ # FIXME: Port to GTK3
+ # self.set_size_request(-1, 24 * 3 + self.style_get_property("vertical-separator") * 6)
self.set_headers_visible(False)
self.set_search_column(COL_NAME)
- def search_func(model, column, key, iter):
+ def search_func(model, column, key, iter, user_data):
s = model.get_value(iter, column)
# This API is braindead, false=matches
return key.lower() not in s.lower()
- self.set_search_equal_func(search_func)
+ self.set_search_equal_func(search_func, None)
# TODO: enable case insensitive substring searching
-
+
def style_set(self, widget, old_style):
self.thumb_size = self.text_renderer.get_size(self, None)[3]
def update(self):
# TODO: block changed signals
self.flickr.groups_pools_getGroups().addCallbacks(self.got_groups, self.twisted_error)
-
+
def got_groups(self, rsp):
for group in rsp.findall("groups/group"):
it = self.model.append()
@@ -92,7 +93,7 @@ class GroupSelector(gtk.TreeView):
def got_thumb(thumb, it):
self.model.set (it, COL_ICON, thumb)
util.get_buddyicon(self.flickr, group, self.thumb_size).addCallback(got_thumb, it)
-
+
def twisted_error(self, failure):
dialog = ErrorDialog()
dialog.set_from_failure(failure)
diff --git a/src/ImageList.py b/src/ImageList.py
index c1706c0..8d96a56 100644
--- a/src/ImageList.py
+++ b/src/ImageList.py
@@ -1,6 +1,8 @@
# Postr, a Flickr Uploader
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2006-2008 Ross Burton <ross burtonini com>
+# Copyright (C) 2012 GermÃn Poo-CaamaÃo <gpoo gnome org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -15,8 +17,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
-import pango
+from gi.repository import Gtk, Pango, GObject, Gdk
import ImageStore
@@ -24,20 +25,22 @@ import ImageStore
(DRAG_URI,
DRAG_IMAGE) = range (0, 2)
-class ImageList(gtk.TreeView):
+class ImageList(Gtk.TreeView):
+ __gtype_name__ = 'ImageList'
+
def __init__(self):
- gtk.TreeView.__init__(self)
+ Gtk.TreeView.__init__(self)
- column = gtk.TreeViewColumn('Preview',
- gtk.CellRendererPixbuf(),
+ column = Gtk.TreeViewColumn('Preview',
+ Gtk.CellRendererPixbuf(),
pixbuf=ImageStore.COL_THUMBNAIL)
self.append_column(column)
- renderer = gtk.CellRendererText()
- renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
+ renderer = Gtk.CellRendererText()
+ renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
- column = gtk.TreeViewColumn('Info', renderer)
+ column = Gtk.TreeViewColumn('Info', renderer)
column.set_cell_data_func(renderer, self.data_func)
self.append_column(column)
@@ -45,27 +48,31 @@ class ImageList(gtk.TreeView):
self.set_enable_search(False)
selection = self.get_selection()
- selection.set_mode(gtk.SELECTION_MULTIPLE)
+ selection.set_mode(Gtk.SelectionMode.MULTIPLE)
# Setup the drag and drop
self.targets = self.drag_dest_get_target_list()
- self.targets = gtk.target_list_add_image_targets (self.targets, DRAG_IMAGE, False)
- self.targets = gtk.target_list_add_uri_targets (self.targets, DRAG_URI)
- self.drag_dest_set (gtk.DEST_DEFAULT_ALL, self.targets, gtk.gdk.ACTION_COPY)
+ if not self.targets:
+ self.targets = Gtk.TargetList.new([])
+ self.targets.add_image_targets (DRAG_IMAGE, True)
+ self.targets.add_uri_targets (DRAG_URI)
+ self.drag_dest_set (Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
+ self.drag_dest_set_target_list(self.targets)
def enable_targets(self):
"""Enable the drag and drop destination. """
- self.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.targets, gtk.gdk.ACTION_COPY)
+ self.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
+ self.drag_dest_set_target_list(self.targets)
def unable_targets(self):
"""Unable the drag and drop destination. """
self.drag_dest_unset()
- def data_func(self, column, cell, model, it):
+ def data_func(self, column, cell, model, it, data):
from xml.sax.saxutils import escape
(title, description, tags) = model.get(it, ImageStore.COL_TITLE, ImageStore.COL_DESCRIPTION, ImageStore.COL_TAGS)
-
+
if title:
info_title = title
else:
@@ -80,8 +87,7 @@ class ImageList(gtk.TreeView):
s = "<b><big>%s</big></b>\n%s\n" % (escape (info_title), escape (info_desc))
if tags:
- colour = self.style.text[gtk.STATE_INSENSITIVE].pixel
- s = s + "<span color='#%X'>%s</span>" % (colour, escape (tags))
-
+ s = s + '%s' % (escape (tags))
+
cell.set_property("markup", s)
diff --git a/src/ImageStore.py b/src/ImageStore.py
index 523c064..6b52bc1 100644
--- a/src/ImageStore.py
+++ b/src/ImageStore.py
@@ -15,7 +15,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk
+from gi.repository import GObject, Gtk, GdkPixbuf
# Column indexes
(COL_URI, # The filename of an image (can be None)
@@ -35,23 +35,23 @@ import gobject, gtk
COL_LICENSE # Iterator containing license
) = range (0, 15)
-class ImageStore (gtk.ListStore):
+class ImageStore (Gtk.ListStore):
def __init__(self):
- gtk.ListStore.__init__(self, gobject.TYPE_STRING, # COL_URI
- gobject.TYPE_INT, # COL_SIZE
- gtk.gdk.Pixbuf, # COL_IMAGE
- gtk.gdk.Pixbuf, # COL_PREVIEW
- gtk.gdk.Pixbuf, #COL_THUMBNAIL
- gobject.TYPE_STRING, # COL_TITLE
- gobject.TYPE_STRING, # COL_DESCRIPTION
- gobject.TYPE_STRING, # COL_TAGS
- gtk.TreeIter, # COL_SET
+ Gtk.ListStore.__init__(self, GObject.TYPE_STRING, # COL_URI
+ GObject.TYPE_LONG, # COL_SIZE
+ GdkPixbuf.Pixbuf, # COL_IMAGE
+ GdkPixbuf.Pixbuf, # COL_PREVIEW
+ GdkPixbuf.Pixbuf, #COL_THUMBNAIL
+ GObject.TYPE_STRING, # COL_TITLE
+ GObject.TYPE_STRING, # COL_DESCRIPTION
+ GObject.TYPE_STRING, # COL_TAGS
+ Gtk.TreeIter, # COL_SET
object, # COL_GROUPS
- gtk.TreeIter, # COL_PRIVACY
- gtk.TreeIter, # COL_SAFETY
- gobject.TYPE_BOOLEAN, # COL_VISIBLE
- gtk.TreeIter, # COL_CONTENT_TYPE
- gtk.TreeIter) # COL_LICENSE
+ Gtk.TreeIter, # COL_PRIVACY
+ Gtk.TreeIter, # COL_SAFETY
+ GObject.TYPE_BOOLEAN, # COL_VISIBLE
+ Gtk.TreeIter, # COL_CONTENT_TYPE
+ Gtk.TreeIter) # COL_LICENSE
self._dirty = False
self.connect("row-changed", self._on_row_changed)
diff --git a/src/LicenseCombo.py b/src/LicenseCombo.py
index ae606d6..91aa7c9 100644
--- a/src/LicenseCombo.py
+++ b/src/LicenseCombo.py
@@ -15,20 +15,22 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk
+from gi.repository import GObject, Gtk
-class LicenseCombo(gtk.ComboBox):
- def __init__(self, flickr):
- gtk.ComboBox.__init__(self)
- self.flickr = flickr
+class LicenseCombo(Gtk.ComboBox):
+ __gtype_name__ = 'LicenseCombo'
+
+ def __init__(self):
+ Gtk.ComboBox.__init__(self)
+ self.flickr = None
- self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
- self.model.set(self.model.append(), 0, _("Default"), 1, -1)
+ self.model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
+ self.model.append([_("Default"), -1])
self.set_model(self.model)
self.set_active(-1)
- cell = gtk.CellRendererText()
- self.pack_start(cell)
+ cell = Gtk.CellRendererText()
+ self.pack_start(cell, True)
self.add_attribute(cell, "text", 0)
def twisted_error(self, failure):
@@ -42,9 +44,8 @@ class LicenseCombo(gtk.ComboBox):
for license in rsp.findall("licenses/license"):
license_id = int(license.get("id"))
it = self.model.append()
- self.model.set(it,
- 0, license.get("name"),
- 1, license_id)
+ self.model.append([license.get("name"), license_id])
+
# Set default license to All Rights Reserved.
# I haven't found a way to get the default license
# from flickr by the API.
diff --git a/src/PrivacyCombo.py b/src/PrivacyCombo.py
index 79c79da..44051c5 100644
--- a/src/PrivacyCombo.py
+++ b/src/PrivacyCombo.py
@@ -15,23 +15,25 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk
+from gi.repository import Gtk, GObject
+
+class PrivacyCombo(Gtk.ComboBox):
+ __gtype_name__ = 'PrivacyCombo'
-class PrivacyCombo(gtk.ComboBox):
def __init__(self):
- gtk.ComboBox.__init__(self)
+ Gtk.ComboBox.__init__(self)
# Name, is_public, is_family, is_friend
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN)
- model.set(model.append(), 0, "Public", 1, True, 2, False, 3, False)
- model.set(model.append(), 0, "Family Only", 1, False, 2, True, 3, False)
- model.set(model.append(), 0, "Friends and Family Only", 1, False, 2, True, 3, True)
- model.set(model.append(), 0, "Private", 1, False, 2, False, 3, False)
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_BOOLEAN, GObject.TYPE_BOOLEAN, GObject.TYPE_BOOLEAN)
+ model.append(["Public", True, False, False])
+ model.append(["Family Only", False, True, False])
+ model.append(["Friends and Family Only", False, True, True])
+ model.append(["Private", False, False, False])
self.model = model
self.set_model(model)
self.set_active(0)
- cell = gtk.CellRendererText()
- self.pack_start(cell)
+ cell = Gtk.CellRendererText()
+ self.pack_start(cell, True)
self.add_attribute(cell, "text", 0)
# (is_public, is_family, is_friend)
diff --git a/src/ProgressDialog.py b/src/ProgressDialog.py
index 7fab482..5de412a 100644
--- a/src/ProgressDialog.py
+++ b/src/ProgressDialog.py
@@ -1,6 +1,8 @@
# Postr, a Flickr Uploader
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2006-2008 Ross Burton <ross burtonini com>
+# Copyright (C) 2012 GermÃn Poo-CaamaÃo <gpoo gnome org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -15,48 +17,49 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
+from gi.repository import Gtk, GObject
-class ProgressDialog(gtk.Dialog):
+class ProgressDialog(Gtk.Dialog):
def __init__(self, cancel_cb):
- gtk.Dialog.__init__(self, title="", flags=gtk.DIALOG_NO_SEPARATOR)
+ Gtk.Dialog.__init__(self, title="")
self.cancel_cb = cancel_cb
-
+
self.set_resizable(False)
- self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+ self.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
self.connect("response", self.on_response)
-
- vbox = gtk.VBox(False, 8)
+
+ vbox = Gtk.VBox(False, 8)
vbox.set_border_width(8)
- self.vbox.add(vbox)
-
- hbox = gtk.HBox(False, 8)
+ self.get_children()[0].add(vbox)
+
+ hbox = Gtk.HBox(False, 8)
vbox.add (hbox)
- self.thumbnail = gtk.Image()
+ self.thumbnail = Gtk.Image()
hbox.pack_start (self.thumbnail, False, False, 0)
- self.label = gtk.Label()
+ self.label = Gtk.Label()
self.label.set_alignment (0.0, 0.0)
hbox.pack_start (self.label, True, True, 0)
-
- self.image_progress = gtk.ProgressBar()
+
+ self.image_progress = Gtk.ProgressBar()
vbox.add(self.image_progress)
vbox.show_all()
def on_response(self, dialog, response):
- if response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.DELETE_EVENT:
self.cancel_cb()
-
+
if __name__ == "__main__":
- import gobject
- d = ProgressDialog()
- d.thumbnail.set_from_icon_name ("stock_internet", gtk.ICON_SIZE_DIALOG)
+ import gettext; gettext.install('postr')
+
+ d = ProgressDialog(Gtk.main_quit)
+ d.thumbnail.set_from_icon_name ("stock_internet", Gtk.IconSize.DIALOG)
d.label.set_text(_("Uploading"))
def pulse():
d.image_progress.pulse()
return True
- gobject.timeout_add(200, pulse)
+ GObject.timeout_add(200, pulse)
d.show()
- gtk.main()
+ Gtk.main()
diff --git a/src/PyUnique.py b/src/PyUnique.py
index ad9d981..907957e 100644
--- a/src/PyUnique.py
+++ b/src/PyUnique.py
@@ -20,11 +20,11 @@
#
#
-import gobject
+from gi.repository import GObject
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
-from gtk import gdk
+from gi.repository import Gdk
import time
# Set the glib main loop as the default main loop for dbus
@@ -64,29 +64,29 @@ class UniqueDBusObject(dbus.service.Object):
self.app.emit('message-received', command, data)
return "OK"
-class UniqueApp(gobject.GObject):
+class UniqueApp(GObject.GObject):
""" Base class for every single instance application."""
__gproperties__ = {
- 'is-running': (gobject.TYPE_BOOLEAN, 'is-running', 'is-running',
+ 'is-running': (GObject.TYPE_BOOLEAN, 'is-running', 'is-running',
False,
- gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
- 'name': (gobject.TYPE_STRING, 'program name', 'program name',
- None, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
- 'screen': (gobject.TYPE_OBJECT, 'screen of app', 'screen of app',
- gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
- 'startup-id': (gobject.TYPE_STRING, 'startup notification id',
+ GObject.PARAM_READWRITE | GObject.PARAM_CONSTRUCT),
+ 'name': (GObject.TYPE_STRING, 'program name', 'program name',
+ None, GObject.PARAM_READWRITE | GObject.PARAM_CONSTRUCT),
+ 'screen': (GObject.TYPE_OBJECT, 'screen of app', 'screen of app',
+ GObject.PARAM_READWRITE | GObject.PARAM_CONSTRUCT),
+ 'startup-id': (GObject.TYPE_STRING, 'startup notification id',
'startup notification id',
- None, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+ None, GObject.PARAM_READWRITE | GObject.PARAM_CONSTRUCT),
}
__gsignals__ = {
- 'message-received': (gobject.SIGNAL_RUN_LAST |
- gobject.SIGNAL_NO_RECURSE,
- gobject.TYPE_INT, # out: integer
- (gobject.TYPE_INT, # in: command id
- gobject.TYPE_STRING)), # in: command data
+ 'message-received': (GObject.SignalFlags.RUN_LAST |
+ GObject.SignalFlags.NO_RECURSE,
+ GObject.TYPE_INT, # out: integer
+ (GObject.TYPE_INT, # in: command id
+ GObject.TYPE_STRING)), # in: command data
}
# Default commands available to UniqueApp instances. More commands
@@ -98,11 +98,11 @@ class UniqueApp(gobject.GObject):
'CLOSE': -4}
def __init__(self, name, startup_id=None):
- gobject.GObject.__init__(self)
+ GObject.GObject.__init__(self)
self._is_running = False
self._name = name
- self._screen = gdk.screen_get_default()
+ self._screen = Gdk.Screen.get_default()
# TODO: Find out what the startup_id is meant to be.
self._startup_id = startup_id
diff --git a/src/SafetyCombo.py b/src/SafetyCombo.py
index 3191137..23f0c79 100644
--- a/src/SafetyCombo.py
+++ b/src/SafetyCombo.py
@@ -15,22 +15,24 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject, gtk
+from gi.repository import GObject, Gtk
+
+class SafetyCombo(Gtk.ComboBox):
+ __gtype_name__ = 'SafetyCombo'
-class SafetyCombo(gtk.ComboBox):
def __init__(self):
- gtk.ComboBox.__init__(self)
+ Gtk.ComboBox.__init__(self)
# Name, is_public, is_family, is_friend
- model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
- model.set(model.append(), 0, "Safe", 1, 1)
- model.set(model.append(), 0, "Moderate", 1, 2)
- model.set(model.append(), 0, "Restricted", 1, 3)
+ model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
+ model.append(["Safe", 1])
+ model.append(["Moderate", 2])
+ model.append(["Restricted", 3])
self.model = model
self.set_model(model)
self.set_active(0)
- cell = gtk.CellRendererText()
- self.pack_start(cell)
+ cell = Gtk.CellRendererText()
+ self.pack_start(cell, True)
self.add_attribute(cell, "text", 0)
def get_safety_for_iter(self, it):
diff --git a/src/SetCombo.py b/src/SetCombo.py
index b67fbe2..3b5cc1e 100644
--- a/src/SetCombo.py
+++ b/src/SetCombo.py
@@ -1,6 +1,8 @@
# Postr, a Flickr Uploader
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2006-2008 Ross Burton <ross burtonini com>
+# Copyright (C) 2012 GermÃn Poo-CaamaÃo <gpoo gnome org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -16,7 +18,7 @@
# St, Fifth Floor, Boston, MA 02110-1301 USA
import datetime
-import gobject, gtk
+from gi.repository import GObject, Gtk, GdkPixbuf
from twisted.web.client import getPage
_NO_PHOTOSET_ID = "-1"
@@ -26,41 +28,43 @@ _DEFAULT_NEW_PHOTOSET_NAME = datetime.datetime.strftime(datetime.datetime.today(
_("new photoset (%m-%d-%y)"))
# Column Indexes
-( COL_SETID,
+(COL_SETID,
COL_SETLABEL,
- COL_THUMBNAIL ) = range(0, 3)
+ COL_THUMBNAIL) = range(0, 3)
+
+class SetCombo(Gtk.ComboBox):
+ __gtype_name__ = 'SetCombo'
+
+ def __init__(self):
+ Gtk.ComboBox.__init__(self)
+ self.flickr = None
-class SetCombo(gtk.ComboBox):
- def __init__(self, flickr):
- gtk.ComboBox.__init__(self)
- self.flickr = flickr
-
# Calculate the size of thumbnails based on the size of the text
# renderer, but provide a default in case style-set isn't called.
+ self.text_renderer = Gtk.CellRendererText()
self.connect("style-set", self.style_set)
self.thumb_size = 24
# ID, name, thumbnail
- self.model = gtk.ListStore (gobject.TYPE_STRING, gobject.TYPE_STRING, gtk.gdk.Pixbuf)
+ self.model = Gtk.ListStore (GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf)
self.model.set (self.model.append(),
- COL_SETID, None,
+ COL_SETID, _NO_PHOTOSET_ID,
COL_SETLABEL, _NO_PHOTOSET_LABEL)
self._create_new_photoset_iter()
self.set_model(self.model)
self.set_active (-1)
- renderer = gtk.CellRendererPixbuf()
+ renderer = Gtk.CellRendererPixbuf()
self.pack_start (renderer, expand=False)
- self.set_attributes(renderer, pixbuf=COL_THUMBNAIL)
-
- self.text_renderer = gtk.CellRendererText()
+ self.add_attribute(renderer, 'pixbuf', COL_THUMBNAIL)
+
self.pack_start (self.text_renderer, expand=False)
- self.set_attributes(self.text_renderer, text=COL_SETLABEL)
+ self.add_attribute(self.text_renderer, 'text', COL_SETLABEL)
def style_set(self, widget, old_style):
self.thumb_size = self.text_renderer.get_size(self, None)[3]
-
+
def twisted_error(self, failure):
from ErrorDialog import ErrorDialog
dialog = ErrorDialog()
@@ -68,12 +72,12 @@ class SetCombo(gtk.ComboBox):
dialog.show_all()
def __got_set_thumb(self, page, it):
- loader = gtk.gdk.PixbufLoader()
+ loader = GdkPixbuf.PixbufLoader()
loader.set_size (self.thumb_size, self.thumb_size)
loader.write(page)
loader.close()
self.model.set (it, COL_THUMBNAIL, loader.get_pixbuf())
-
+
def __got_photosets(self, rsp):
"""Callback for the photosets.getList call"""
for photoset in rsp.findall("photosets/photoset"):
@@ -123,24 +127,24 @@ class SetCombo(gtk.ComboBox):
def _response_to_dialog(self, entry, dialog, response):
dialog.response(response)
- def name_new_photoset(self):
- dialog = gtk.MessageDialog(None,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_QUESTION,
- gtk.BUTTONS_OK_CANCEL,
+ def name_new_photoset(self, window=None):
+ dialog = Gtk.MessageDialog(window,
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+ Gtk.MessageType.QUESTION,
+ Gtk.ButtonsType.OK_CANCEL,
None)
dialog.set_markup(_("Name for the new photoset:"))
- entry = gtk.Entry()
+ entry = Gtk.Entry()
entry.set_text(self.new_photoset_name)
# so that you can press 'enter' to close dialog
- entry.connect("activate", self._response_to_dialog, dialog, gtk.RESPONSE_OK)
+ entry.connect("activate", self._response_to_dialog, dialog, Gtk.ResponseType.OK)
dialog.vbox.pack_end(entry, True, True, 0)
dialog.show_all()
response = dialog.run()
text = entry.get_text()
dialog.destroy()
- if response == gtk.RESPONSE_OK:
+ if response == Gtk.ResponseType.OK:
self.update_new_photoset(text.strip())
return self.new_photoset_name
diff --git a/src/StatusBar.py b/src/StatusBar.py
index ee37a38..d0f956a 100644
--- a/src/StatusBar.py
+++ b/src/StatusBar.py
@@ -15,16 +15,18 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
+from gi.repository import Gtk, GObject
from ErrorDialog import ErrorDialog
from util import greek
from xml.sax.saxutils import escape
-class StatusBar(gtk.Label):
- def __init__(self, flickr):
- gtk.Label.__init__(self)
+class StatusBar(Gtk.Label):
+ __gtype_name__ = 'StatusBar'
+
+ def __init__(self):
+ Gtk.Label.__init__(self)
+ self.flickr = None
self.set_alignment(0.0, 0.5)
- self.flickr = flickr
self.quota = None
self.to_upload = None
# In case we are offline or we can not get the max file size to
diff --git a/src/TagsEntry.py b/src/TagsEntry.py
index 9fa4fd0..abf6341 100644
--- a/src/TagsEntry.py
+++ b/src/TagsEntry.py
@@ -15,20 +15,21 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk
+from gi.repository import Gtk, GObject
_USER_POPULAR_TAGS = 200
_HOTS_TAGS = 20
_COL_TAG_NAME = 0
-class TagsEntry(gtk.Entry):
- def __init__(self, flickr):
- gtk.Entry.__init__(self)
+class TagsEntry(Gtk.Entry):
+ __gtype_name__ = 'TagsEntry'
- self.flickr = flickr
+ def __init__(self):
+ Gtk.Entry.__init__(self)
+ self.flickr = None
# Create the completion object
- self.completion = gtk.EntryCompletion()
+ self.completion = Gtk.EntryCompletion()
self.completion.set_match_func(self.__match_func, None)
self.completion.connect('match-selected', self.on_completion_match)
@@ -41,7 +42,7 @@ class TagsEntry(gtk.Entry):
self.completion.set_minimum_key_length(1)
- self.completion_model = gtk.ListStore(str)
+ self.completion_model = Gtk.ListStore(str)
self.show_all()
@@ -98,9 +99,7 @@ class TagsEntry(gtk.Entry):
'''
for tag in rsp.getiterator('tag'):
- self.completion_model.set(self.completion_model.append(),
- _COL_TAG_NAME,
- tag.text)
+ self.completion_model.append([tag.text])
self.completion.set_model(self.completion_model)
diff --git a/src/catalog_poster.xml b/src/catalog_poster.xml
new file mode 100644
index 0000000..43b3207
--- /dev/null
+++ b/src/catalog_poster.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<glade-catalog name="postr" depends="gtk+" version="1.0">
+ <glade-widget-classes>
+ <glade-widget-class title="ContentTypeCombo" name="ContentTypeCombo"
+ generic-name="ContentTypeCombo" parent="GtkComboBox"
+ icon-name="widget-gtk-combobox" />
+ <glade-widget-class title="GroupSelector" name="GroupSelector"
+ generic-name="GroupSelector" parent="GtkTreeView"
+ icon-name="widget-gtk-treeview" />
+ <glade-widget-class title="ImageList" name="ImageList"
+ generic-name="ImageList" parent="GtkTreeView"
+ icon-name="widget-gtk-treeview" />
+ <glade-widget-class title="LicenseCombo" name="LicenseCombo"
+ generic-name="LicenseCombo" parent="GtkComboBox"
+ icon-name="widget-gtk-combobox" />
+ <glade-widget-class title="PrivacyCombo" name="PrivacyCombo"
+ generic-name="PrivacyCombo" parent="GtkComboBox"
+ icon-name="widget-gtk-combobox" />
+ <glade-widget-class title="SafetyCombo" name="SafetyCombo"
+ generic-name="SafetyCombo" parent="GtkComboBox"
+ icon-name="widget-gtk-combobox" />
+ <glade-widget-class title="SetCombo" name="SetCombo"
+ generic-name="SetCombo" parent="GtkComboBox"
+ icon-name="widget-gtk-combobox" />
+ <glade-widget-class title="StatusBar" name="StatusBar"
+ generic-name="StatusBar" parent="GtkLabel"
+ icon-name="widget-gtk-label" />
+ <glade-widget-class title="TagsEntry" name="TagsEntry"
+ generic-name="TagsEntry" parent="GtkEntry"
+ icon-name="widget-gtk-entry" />
+ </glade-widget-classes>
+
+ <glade-widget-group name="postr-widgets" title="Postr Custom Widgets">
+ <glade-widget-class-ref name="ContentTypeCombo"/>
+ <glade-widget-class-ref name="GroupSelector"/>
+ <glade-widget-class-ref name="ImageList"/>
+ <glade-widget-class-ref name="LicenseCombo"/>
+ <glade-widget-class-ref name="PrivacyCombo"/>
+ <glade-widget-class-ref name="SafetyCombo"/>
+ <glade-widget-class-ref name="StatusBar"/>
+ <glade-widget-class-ref name="SetCombo"/>
+ <glade-widget-class-ref name="TagsEntry"/>
+ </glade-widget-group>
+
+</glade-catalog>
diff --git a/src/flickrest.py b/src/flickrest.py
index abf256a..9980dfd 100644
--- a/src/flickrest.py
+++ b/src/flickrest.py
@@ -16,7 +16,7 @@
# St, Fifth Floor, Boston, MA 02110-1301 USA
import logging, os, mimetools, urllib
-import gio
+from gi.repository import Gio
from twisted.internet import defer
from twisted.python.failure import Failure
import proxyclient as client
@@ -145,13 +145,13 @@ class Flickr:
for key, val in inputs.items():
lines.append("--" + boundary.encode("utf-8"))
header = 'Content-Disposition: form-data; name="%s";' % key
- if isinstance(val, gio.File):
+ if isinstance(val, Gio.File):
header += 'filename="%s";' % val.get_basename()
lines.append(header)
header = "Content-Type: application/octet-stream"
lines.append(header)
lines.append("")
- if isinstance(val, gio.File):
+ if isinstance(val, Gio.File):
contents, length, etags = val.load_contents()
lines.append(contents)
# Otherwise just hope it is string-like and encode it to
@@ -198,7 +198,7 @@ class Flickr:
if imageData:
kwargs['photo'] = imageData
else:
- kwargs['photo'] = gio.File(uri)
+ kwargs['photo'] = Gio.File.new_for_uri(uri)
(boundary, form) = self.__encodeForm(kwargs)
headers= {
diff --git a/src/postr.glade b/src/postr.glade
index f1c1053..b8bf270 100644
--- a/src/postr.glade
+++ b/src/postr.glade
@@ -1,198 +1,243 @@
-<?xml version="1.0"?>
-<glade-interface>
- <!-- interface-requires gtk+ 2.10 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <widget class="GtkWindow" id="window">
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <!-- interface-requires postr 1.0 -->
+ <object class="GtkAccelGroup" id="accelgroup1"/>
+ <object class="GtkImage" id="image1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-open</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="yalign">0.49000000953674316</property>
+ <property name="stock">gtk-remove</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-save</property>
+ </object>
+ <object class="GtkWindow" id="window">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="title" translatable="yes">Flickr Uploader</property>
<property name="default_width">640</property>
<property name="default_height">350</property>
- <signal name="delete_event" handler="on_quit_activate"/>
+ <accel-groups>
+ <group name="accelgroup1"/>
+ </accel-groups>
+ <signal name="delete-event" handler="on_quit_activate" swapped="no"/>
<child>
- <widget class="GtkVBox" id="vbox1">
+ <object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<child>
- <widget class="GtkMenuBar" id="menubar1">
+ <object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<child>
- <widget class="GtkMenuItem" id="menuitem1">
+ <object class="GtkMenuItem" id="menuitem1">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="menuitem1_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="menuitem1_menu">
+ <property name="can_focus">False</property>
<child>
- <widget class="GtkImageMenuItem" id="add_photos">
+ <object class="GtkImageMenuItem" id="add_photos">
<property name="label" translatable="yes">_Add Photos...</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
+ <property name="image">image1</property>
<property name="use_stock">False</property>
- <signal name="activate" handler="on_add_photos_activate"/>
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- <child internal-child="image">
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="stock">gtk-open</property>
- </widget>
- </child>
- </widget>
+ <signal name="activate" handler="on_add_photos_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="remove_menu">
+ <object class="GtkImageMenuItem" id="remove_menu">
<property name="label" translatable="yes">_Remove Photos</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
+ <property name="image">image3</property>
<property name="use_stock">False</property>
- <signal name="activate" handler="on_remove_activate"/>
<accelerator key="D" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- <child internal-child="image">
- <widget class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="yalign">0.49000000953674316</property>
- <property name="stock">gtk-remove</property>
- </widget>
- </child>
- </widget>
+ <signal name="activate" handler="on_remove_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator2">
+ <object class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
- </widget>
+ <property name="can_focus">False</property>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="save_session_menu">
+ <object class="GtkImageMenuItem" id="save_session_menu">
<property name="label" translatable="yes">_Save session</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
+ <property name="image">image4</property>
<property name="use_stock">False</property>
- <signal name="activate" handler="on_save_session_activate"/>
<accelerator key="S" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- <child internal-child="image">
- <widget class="GtkImage" id="image4">
- <property name="visible">True</property>
- <property name="stock">gtk-save</property>
- </widget>
- </child>
- </widget>
+ <signal name="activate" handler="on_save_session_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="load_session_menu">
+ <object class="GtkMenuItem" id="load_session_menu">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_Load session</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_load_session_activate"/>
<accelerator key="L" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- </widget>
+ <signal name="activate" handler="on_load_session_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator3">
+ <object class="GtkSeparatorMenuItem" id="separator3">
<property name="visible">True</property>
- </widget>
+ <property name="can_focus">False</property>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="switch_menu">
+ <object class="GtkMenuItem" id="switch_menu">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_Switch user...</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_switch_activate"/>
- </widget>
+ <signal name="activate" handler="on_switch_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="upload_menu">
+ <object class="GtkMenuItem" id="upload_menu">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_Upload</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_upload_activate"/>
- </widget>
+ <signal name="activate" handler="on_upload_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
+ <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
- </widget>
+ <property name="can_focus">False</property>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="quit">
+ <object class="GtkImageMenuItem" id="quit">
<property name="label">gtk-quit</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
- <signal name="activate" handler="on_quit_activate"/>
- </widget>
+ <property name="accel_group">accelgroup1</property>
+ <signal name="activate" handler="on_quit_activate" swapped="no"/>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="select2">
+ <object class="GtkMenuItem" id="select2">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Select</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_select2_activate"/>
- <child>
- <widget class="GtkMenu" id="select2_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="select2_menu">
+ <property name="can_focus">False</property>
<child>
- <widget class="GtkImageMenuItem" id="select_all">
+ <object class="GtkImageMenuItem" id="select_all">
<property name="label">gtk-select-all</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
- <signal name="activate" handler="on_select_all_activate"/>
+ <property name="accel_group">accelgroup1</property>
<accelerator key="E" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- </widget>
+ <signal name="activate" handler="on_select_all_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="deselect_all">
+ <object class="GtkMenuItem" id="deselect_all">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Dese_lect All</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_deselect_all_activate"/>
<accelerator key="E" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
- </widget>
+ <signal name="activate" handler="on_deselect_all_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="invert_selection">
+ <object class="GtkMenuItem" id="invert_selection">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_Invert Selection</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_invert_selection_activate"/>
<accelerator key="I" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- </widget>
+ <signal name="activate" handler="on_invert_selection_activate" swapped="no"/>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="menuitem4">
+ <object class="GtkMenuItem" id="menuitem4">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="menuitem4_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="menuitem4_menu">
+ <property name="can_focus">False</property>
<child>
- <widget class="GtkImageMenuItem" id="help">
- <property name="stock_id">gtk-help</property>
- <property name="label" translatable="True">_Contents</property>
+ <object class="GtkImageMenuItem" id="help">
+ <property name="label" translatable="yes">_Contents</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_help_activate"/>
- </widget>
+ <property name="use_stock">False</property>
+ <signal name="activate" handler="on_help_activate" swapped="no"/>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="about">
+ <object class="GtkImageMenuItem" id="about">
<property name="label">gtk-about</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
- <signal name="activate" handler="on_about_activate"/>
- </widget>
+ <property name="accel_group">accelgroup1</property>
+ <signal name="activate" handler="on_about_activate" swapped="no"/>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -200,24 +245,27 @@
</packing>
</child>
<child>
- <widget class="GtkEventBox" id="statusbar_box">
+ <object class="GtkEventBox" id="statusbar_box">
<property name="visible">True</property>
<property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <signal name="expose_event" handler="on_statusbar_box_expose"/>
+ <signal name="draw" handler="on_statusbar_box_draw" swapped="no"/>
<child>
- <widget class="GtkHBox" id="hbox">
+ <object class="GtkHBox" id="hbox">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">4</property>
<property name="spacing">4</property>
<child>
- <widget class="GtkImage" id="avatar_image">
+ <object class="GtkImage" id="avatar_image">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-missing-image</property>
<property name="icon-size">5</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -225,58 +273,69 @@
</packing>
</child>
<child>
- <widget class="Custom" id="statusbar">
+ <object class="StatusBar" id="statusbar">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">status_bar_new</property>
- </widget>
+ </object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
- <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <object class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
- <widget class="GtkButton" id="upload_button">
+ <object class="GtkButton" id="upload_button">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <signal name="clicked" handler="on_upload_activate"/>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_upload_activate" swapped="no"/>
<child>
- <widget class="GtkHBox" id="hbox2">
+ <object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">2</property>
<property name="spacing">6</property>
<child>
- <widget class="GtkImage" id="image2">
+ <object class="GtkImage" id="image2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-connect</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label2">
+ <object class="GtkLabel" id="label2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Upload</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">upload_button</property>
- </widget>
+ </object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -284,16 +343,16 @@
<property name="position">0</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -301,464 +360,481 @@
</packing>
</child>
<child>
- <widget class="GtkHPaned" id="hpaned1">
+ <object class="GtkHPaned" id="hpaned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="position">200</property>
<child>
- <widget class="GtkVBox" id="vbox2">
+ <object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
- <widget class="Custom" id="thumbview">
+ <object class="ImageList" id="thumbview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
- <property name="creation_function">ImageList.ImageList()</property>
- </widget>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="ImageList-selection1"/>
+ </child>
+ </object>
</child>
- </widget>
+ </object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <widget class="GtkHBox" id="hbox1">
+ <object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
- <widget class="GtkButton" id="add_button">
+ <object class="GtkButton" id="add_button">
<property name="label" translatable="yes">Add Photos...</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <signal name="clicked" handler="on_add_photos_activate"/>
- </widget>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_add_photos_activate" swapped="no"/>
+ </object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <widget class="GtkButton" id="remove_button">
+ <object class="GtkButton" id="remove_button">
<property name="label" translatable="yes">Remove Photos</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <signal name="clicked" handler="on_remove_activate"/>
- </widget>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_remove_activate" swapped="no"/>
+ </object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="resize">False</property>
<property name="shrink">False</property>
</packing>
</child>
<child>
- <widget class="GtkTable" id="info_table">
+ <object class="GtkGrid" id="info_table">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="border_width">6</property>
- <property name="n_rows">7</property>
- <property name="n_columns">3</property>
- <property name="column_spacing">4</property>
<property name="row_spacing">6</property>
+ <property name="column_spacing">4</property>
+ <child>
+ <object class="SetCombo" id="set_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="TagsEntry" id="tags_entry">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
<child>
- <widget class="Custom" id="set_combo">
+ <object class="GtkEntry" id="title_entry">
<property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="rename_button">
+ <property name="label" translatable="yes">Rename</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_rename_activate" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">set_combo_new</property>
- </widget>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="desc_view">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="wrap_mode">word</property>
+ <property name="accepts_tab">False</property>
+ </object>
+ </child>
+ </object>
<packing>
<property name="left_attach">1</property>
- <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="thumbnail_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">3</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Title:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">title_entry</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="desc_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">_Description:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tags_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Ta_gs:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="set_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Add to _Set:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
<property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkExpander" id="expander2">
+ <object class="GtkExpander" id="expander2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <object class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
- <widget class="Custom" id="group_selector">
+ <object class="GroupSelector" id="group_selector">
<property name="visible">True</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">group_selector_new</property>
- </widget>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="GroupSelector-selection"/>
+ </child>
+ </object>
</child>
- </widget>
+ </object>
</child>
- <child>
- <widget class="GtkLabel" id="label1">
+ <child type="label">
+ <object class="GtkLabel" id="label1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Send to Groups</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
+ </object>
</child>
- </widget>
+ </object>
<packing>
- <property name="right_attach">3</property>
+ <property name="left_attach">0</property>
<property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="width">3</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkExpander" id="expander1">
+ <object class="GtkExpander" id="expander1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
- <widget class="GtkTable" id="table2">
+ <object class="GtkGrid" id="table2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="n_rows">5</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">4</property>
<property name="row_spacing">6</property>
+ <property name="column_spacing">4</property>
<child>
- <widget class="GtkLabel" id="content_type_label">
+ <object class="PrivacyCombo" id="privacy_combo">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Content type:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">tags_entry</property>
- </widget>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ </object>
<packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="Custom" id="privacy_combo">
+ <object class="SafetyCombo" id="safety_combo">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">PrivacyCombo.PrivacyCombo()</property>
- </widget>
+ </object>
<packing>
<property name="left_attach">1</property>
- <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="privacy_label">
+ <object class="GtkCheckButton" id="visible_check">
+ <property name="label" translatable="yes">_Visible in search results</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Privacy:</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
- <property name="mnemonic_widget">tags_entry</property>
- </widget>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
<packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="safety_label">
+ <object class="ContentTypeCombo" id="content_type_combo">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Safety:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">tags_entry</property>
- </widget>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ </object>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="Custom" id="safety_combo">
+ <object class="LicenseCombo" id="license_combo">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">SafetyCombo.SafetyCombo()</property>
- </widget>
+ </object>
<packing>
<property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="visible_check">
- <property name="label" translatable="yes">_Visible in search results</property>
+ <object class="GtkLabel" id="privacy_label">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Privacy:</property>
<property name="use_underline">True</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </widget>
+ </object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="Custom" id="content_type_combo">
+ <object class="GtkLabel" id="safety_label">
<property name="visible">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">ContentTypeCombo.ContentTypeCombo()</property>
- </widget>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Safety:</property>
+ <property name="use_underline">True</property>
+ </object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="license_label">
+ <object class="GtkLabel" id="content_type_label">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_License:</property>
+ <property name="label" translatable="yes">_Content type:</property>
<property name="use_underline">True</property>
- <property name="mnemonic_widget">tags_entry</property>
- </widget>
+ </object>
<packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <widget class="Custom" id="license_combo">
+ <object class="GtkLabel" id="license_label">
<property name="visible">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="creation_function">license_combo_new</property>
- </widget>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_License:</property>
+ <property name="use_underline">True</property>
+ </object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
+ <property name="left_attach">0</property>
<property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
- </widget>
+ </object>
</child>
- <child>
- <widget class="GtkLabel" id="label5">
+ <child type="label">
+ <object class="GtkLabel" id="label5">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Privacy, Safety, Type and License</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
+ </object>
</child>
- </widget>
+ </object>
<packing>
- <property name="right_attach">3</property>
+ <property name="left_attach">0</property>
<property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="title_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Title:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">title_entry</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="desc_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="label" translatable="yes">_Description:</property>
- <property name="use_underline">True</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="tags_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Ta_gs:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">tags_entry</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="Custom" id="tags_entry">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="creation_function">tag_entry_new</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">3</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="title_entry">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">3</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="set_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Add to _Set:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">set_combo</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="rename_button">
- <property name="label" translatable="yes">Rename</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <signal name="clicked" handler="on_rename_activate"/>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkImage" id="thumbnail_image">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="stock">gtk-missing-image</property>
- </widget>
- <packing>
- <property name="right_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkScrolledWindow" id="scrolledwindow2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <widget class="GtkTextView" id="desc_view">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="wrap_mode">word</property>
- <property name="accepts_tab">False</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">3</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="width">3</property>
+ <property name="height">1</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
- </widget>
+ </object>
</child>
- </widget>
-</glade-interface>
+ </object>
+</interface>
diff --git a/src/postr.py b/src/postr.py
index 1d8d640..822820e 100644
--- a/src/postr.py
+++ b/src/postr.py
@@ -1,6 +1,8 @@
# Postr, a Flickr Uploader
+# -*- coding: utf-8 -*-
#
# Copyright (C) 2006-2008 Ross Burton <ross burtonini com>
+# Copyright (C) 2009-2012 GermÃn Poo-CaamaÃo <gpoo gnome org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -19,10 +21,10 @@ import logging, os, urllib
from urlparse import urlparse
from os.path import basename
-import pygtk; pygtk.require ("2.0")
-import gobject, gtk, gtk.glade, gconf, gio
-import gnome.ui
+from gi.repository import GObject, Gtk, GConf, GdkPixbuf, Gio, Gdk
+#FIXME
+#import gnome.ui
try:
import gtkspell
@@ -34,7 +36,7 @@ from AboutDialog import AboutDialog
from AuthenticationDialog import AuthenticationDialog
from ProgressDialog import ProgressDialog
from ErrorDialog import ErrorDialog
-import ImageStore, ImageList, StatusBar, PrivacyCombo, SafetyCombo, GroupSelector, ContentTypeCombo
+import ImageStore, ImageList, StatusBar, PrivacyCombo, SafetyCombo, GroupSelector, ContentTypeCombo, SetCombo, LicenseCombo, TagsEntry
from proxyclient import EXTRA_STEP_SET_ID, EXTRA_STEP_GROUPS, EXTRA_STEP_LICENSE, EXTRA_STEP_NEW_SET, UploadProgressTracker
from flickrest import Flickr
@@ -59,10 +61,11 @@ except ImportError:
ROTATED_90_CCW
) = (1, 3, 6, 8)
-_FILE_ATTRIBUTES = ",".join([gio.FILE_ATTRIBUTE_STANDARD_TYPE,
- gio.FILE_ATTRIBUTE_STANDARD_NAME,
- gio.FILE_ATTRIBUTE_STANDARD_SIZE,
- gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME])
+_FILE_ATTRIBUTES = ",".join([Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
+ Gio.FILE_ATTRIBUTE_STANDARD_NAME,
+ Gio.FILE_ATTRIBUTE_STANDARD_SIZE,
+ Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME])
+_SUPPORTED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp']
class Postr(UniqueApp):
def __init__(self):
@@ -73,17 +76,18 @@ class Postr(UniqueApp):
pass
self.is_connected = False
-
+
self.flickr = Flickr(api_key="c53cebd15ed936073134cec858036f1d",
secret="7db1b8ef68979779",
perms="write")
- self.logo_icon_size = gtk.icon_size_register("logo", 128, 128)
-
- gtk.window_set_default_icon_name("postr")
- gtk.glade.set_custom_handler(self.get_custom_handler)
- glade = gtk.glade.XML(os.path.join(os.path.dirname(__file__), "postr.glade"))
- glade.signal_autoconnect(self)
+ self.logo_icon_size = Gtk.icon_size_register("logo", 128, 128)
+
+ Gtk.Window.set_default_icon_name("postr")
+ glade = Gtk.Builder()
+ glade.add_from_file(os.path.join (os.path.dirname(__file__), "postr.glade"))
+ #Gtk.glade.set_custom_handler(self.get_custom_handler)
+ glade.connect_signals(self)
get_glade_widgets(glade, self,
("window",
@@ -109,25 +113,33 @@ class Postr(UniqueApp):
"license_combo",
"thumbview")
)
+
+ # Activate callbacks in custom widgets
+ self.group_selector.flickr = self.flickr
+ self.statusbar.flickr = self.flickr
+ self.tags_entry.flickr = self.flickr
+ self.license_combo.flickr = self.flickr
+ self.set_combo.flickr = self.flickr
+
align_labels(glade, ("title_label", "desc_label",
"tags_label", "set_label",
"privacy_label", "safety_label"))
-
+
# Just for you, Daniel.
try:
if os.getlogin() == "daniels":
self.window.set_title("Respecognise")
except Exception:
pass
-
+
self.model = ImageStore.ImageStore()
self.model.connect("row-inserted", self.on_model_changed)
self.model.connect("row-deleted", self.on_model_changed)
-
+
self.thumbview.set_model(self.model)
self.set_combo.connect("changed", self.on_set_combo_changed)
-
+
selection = self.thumbview.get_selection()
selection.connect("changed", self.on_selection_changed)
@@ -159,7 +171,7 @@ class Postr(UniqueApp):
self.thumbnail_image.clear()
self.thumbnail_image.set_size_request(128, 128)
-
+
self.change_signals = [] # List of (widget, signal ID) tuples
self.change_signals.append((self.title_entry, self.title_entry.connect('changed', self.on_field_changed, ImageStore.COL_TITLE)))
self.change_signals.append((self.desc_view.get_buffer(), self.desc_view.get_buffer().connect('changed', self.on_field_changed, ImageStore.COL_DESCRIPTION)))
@@ -170,12 +182,12 @@ class Postr(UniqueApp):
self.change_signals.append((self.visible_check, self.visible_check.connect('toggled', self.on_field_changed, ImageStore.COL_VISIBLE)))
self.change_signals.append((self.content_type_combo, self.content_type_combo.connect('changed', self.on_field_changed, ImageStore.COL_CONTENT_TYPE)))
self.change_signals.append((self.license_combo, self.license_combo.connect('changed', self.on_field_changed, ImageStore.COL_LICENSE)))
-
+
self.thumbnail_image.connect('size-allocate', self.update_thumbnail)
self.old_thumb_allocation = None
self.on_selection_changed(selection)
-
+
# The upload progress dialog
self.uploading = False
self.current_upload_it = None
@@ -193,11 +205,11 @@ class Postr(UniqueApp):
self.update_remove()
# Update the proxy configuration
- client = gconf.client_get_default()
- client.add_dir("/system/http_proxy", gconf.CLIENT_PRELOAD_RECURSIVE)
- client.notify_add("/system/http_proxy", self.proxy_changed)
+ client = GConf.Client.get_default()
+ client.add_dir("/system/http_proxy", GConf.ClientPreloadType.PRELOAD_RECURSIVE)
+ client.notify_add("/system/http_proxy", self.proxy_changed, None)
self.proxy_changed(client, 0, None, None)
-
+
# Connect to flickr, go go go
self.flickr.authenticate_1().addCallbacks(self.auth_open_url, self.twisted_error)
@@ -206,7 +218,7 @@ class Postr(UniqueApp):
def twisted_error(self, failure):
self.update_upload()
-
+
dialog = ErrorDialog(self.window)
dialog.set_from_failure(failure)
dialog.show_all()
@@ -218,7 +230,7 @@ class Postr(UniqueApp):
if host is None or host == "" or port == 0:
self.flickr.set_proxy(None)
return
-
+
if client.get_bool("/system/http_proxy/use_authentication"):
user = client.get_string("/system/http_proxy/authentication_user")
password = client.get_string("/system/http_proxy/authentication_password")
@@ -232,48 +244,6 @@ class Postr(UniqueApp):
self.flickr.set_proxy(url)
else:
self.flickr.set_proxy(None)
-
- def get_custom_handler(self, glade, function_name, widget_name, str1, str2, int1, int2):
- """libglade callback to create custom widgets."""
- handler = getattr(self, function_name, None)
- if handler:
- return handler(str1, str2, int1, int2)
- else:
- widget = eval(function_name)
- widget.show()
- return widget
-
- def group_selector_new(self, *args):
- w = GroupSelector.GroupSelector(self.flickr)
- w.show()
- return w
-
- def set_combo_new(self, *args):
- import SetCombo
- w = SetCombo.SetCombo(self.flickr)
- w.show()
- return w
-
- def license_combo_new(self, *args):
- import LicenseCombo
- w = LicenseCombo.LicenseCombo(self.flickr)
- w.show()
- return w
-
- def image_list_new(self, *args):
- """Custom widget creation function to make the image list."""
- view = ImageList.ImageList()
- view.show()
- return view
-
- def status_bar_new(self, *args):
- bar = StatusBar.StatusBar(self.flickr)
- bar.show()
- return bar
- def tag_entry_new(self, *args):
- import TagsEntry
- entry = TagsEntry.TagsEntry(self.flickr)
- return entry
def on_message_pyunique(self, instance, command, data):
""" PyUnique callback for receiving a message """
@@ -289,7 +259,7 @@ class Postr(UniqueApp):
# the model was changed, not what was changed.
self.update_upload()
self.update_remove()
-
+
def auth_open_url(self, state):
"""Callback from midway through Flickr authentication. At this point we
either have cached tokens so can carry on, or need to open a web browser
@@ -298,10 +268,10 @@ class Postr(UniqueApp):
self.connected(True)
else:
dialog = AuthenticationDialog(self.window, state['url'])
- if dialog.run() == gtk.RESPONSE_ACCEPT:
+ if dialog.run() == Gtk.ResponseType.ACCEPT:
self.flickr.authenticate_2(state).addCallbacks(self.connected, self.twisted_error)
dialog.destroy()
-
+
def connected(self, connected):
"""Callback when the Flickr authentication completes."""
self.is_connected = connected
@@ -314,13 +284,14 @@ class Postr(UniqueApp):
self.update_avatar()
self.update_tag_list()
- def on_statusbar_box_expose(self, widget, event):
+ def on_statusbar_box_draw(self, widget, cr):
"""
Expose callback for the event box containing the status bar, to paint it
in a different colour.
"""
- widget.window.draw_rectangle(widget.style.dark_gc[gtk.STATE_NORMAL], True, *event.area)
-
+ #FIXME: get the dark theme color instead
+ widget.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0.5, 0.5, 0.5, 0.6))
+
def update_upload(self):
connected = self.is_connected and self.model.iter_n_children(None) > 0
self.upload_menu.set_sensitive(connected)
@@ -338,7 +309,7 @@ class Postr(UniqueApp):
for row in self.model:
size += row[ImageStore.COL_SIZE]
self.statusbar.set_upload(size)
-
+
def update_avatar(self):
"""
Update the avatar displayed at the top of the window. Called when
@@ -356,14 +327,14 @@ class Postr(UniqueApp):
get_buddyicon(self.flickr, data).addCallbacks(get_buddyicon_cb, self.twisted_error)
# Need to call people.getInfo to get the iconserver/iconfarm
self.flickr.people_getInfo(user_id=self.flickr.get_nsid()).addCallbacks(getinfo_cb, self.twisted_error)
-
+
def on_field_changed(self, widget, column):
"""Callback when the entry fields are changed."""
- if isinstance(widget, gtk.Entry) or isinstance(widget, gtk.TextBuffer):
+ if isinstance(widget, Gtk.Entry) or isinstance(widget, Gtk.TextBuffer):
value = widget.get_property("text")
- elif isinstance(widget, gtk.ToggleButton):
+ elif isinstance(widget, Gtk.ToggleButton):
value = widget.get_active()
- elif isinstance(widget, gtk.ComboBox):
+ elif isinstance(widget, Gtk.ComboBox):
value = widget.get_active_iter()
elif isinstance(widget, GroupSelector.GroupSelector):
value = widget.get_selected_groups()
@@ -383,7 +354,7 @@ class Postr(UniqueApp):
"""Callback when the set combo is changed."""
set_it = self.set_combo.get_active_iter()
- (id, ) = self.set_combo.get_id_for_iter(set_it) if set_it else (None, )
+ (id,) = self.set_combo.get_id_for_iter(set_it) if set_it else (None,)
self._update_rename_button(id)
selection = self.thumbview.get_selection()
@@ -394,43 +365,38 @@ class Postr(UniqueApp):
def _update_rename_button(self, id):
if id == '-1':
- self.info_table.child_set(self.set_combo,
- "right-attach",
- 2)
self.rename_button.set_sensitive(True)
else:
- self.info_table.child_set(self.set_combo,
- "right-attach",
- 3)
self.rename_button.set_sensitive(False)
def on_rename_activate(self, button):
- self.set_combo.name_new_photoset()
+ self.set_combo.name_new_photoset(self.window)
def on_add_photos_activate(self, widget):
"""Callback from the File->Add Photos menu item or Add button."""
- dialog = gtk.FileChooserDialog(title=_("Add Photos"), parent=self.window,
- action=gtk.FILE_CHOOSER_ACTION_OPEN,
- buttons=(gtk.STOCK_CANCEL,
- gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN,
- gtk.RESPONSE_OK))
+ dialog = Gtk.FileChooserDialog(title=_("Add Photos"), parent=self.window,
+ action=Gtk.FileChooserAction.OPEN,
+ buttons=(Gtk.STOCK_CANCEL,
+ Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OPEN,
+ Gtk.ResponseType.OK))
dialog.set_select_multiple(True)
if self.last_folder:
dialog.set_current_folder_uri(self.last_folder)
# Add filters for all reasonable image types
- filters = gtk.FileFilter()
+ filters = Gtk.FileFilter()
filters.set_name(_("Images"))
- filters.add_mime_type("image/*")
+ for mime_type in _SUPPORTED_MIME_TYPES:
+ filters.add_mime_type(mime_type)
dialog.add_filter(filters)
- filters = gtk.FileFilter()
+ filters = Gtk.FileFilter()
filters.set_name(_("All Files"))
filters.add_pattern("*")
dialog.add_filter(filters)
# Add a preview widget
- preview = gtk.Image()
+ preview = Gtk.Image()
dialog.set_preview_widget(preview)
def get_thumbnail(uri):
@@ -438,16 +404,21 @@ class Postr(UniqueApp):
# None in case is not possible to get it or
# generate it.
- gfile = gio.File(uri)
- ginfo = gfile.query_info('time::modified,standard::content-type')
+ gfile = Gio.File.new_for_uri(uri)
+ attributes = ','.join([Gio.FILE_ATTRIBUTE_TIME_MODIFIED,
+ Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE])
+ ginfo = gfile.query_info(attributes,
+ Gio.FileQueryInfoFlags.NONE, None)
mtime = ginfo.get_modification_time()
mime = ginfo.get_content_type()
+ # FIXME: Port to GTK3
+ '''
factory = gnome.ui.ThumbnailFactory(gnome.ui.THUMBNAIL_SIZE_NORMAL)
thumb_path = factory.lookup(uri, int(mtime))
if thumb_path:
- return gtk.gdk.pixbuf_new_from_file(thumb_path)
+ return GdkPixbuf.Pixbuf.new_from_file(thumb_path)
# There is no thumbmail, we will try to generate one
# or return None if not possible
@@ -458,9 +429,10 @@ class Postr(UniqueApp):
return thumbnail
else:
return None
+ '''
+ return None
def update_preview_cb(file_chooser, preview):
- filename = file_chooser.get_preview_filename()
uri = file_chooser.get_preview_uri()
if uri:
@@ -475,48 +447,48 @@ class Postr(UniqueApp):
file_chooser.set_preview_widget_active(have_preview)
dialog.connect("update-preview", update_preview_cb, preview)
-
- if dialog.run() == gtk.RESPONSE_OK:
+
+ if dialog.run() == Gtk.ResponseType.OK:
dialog.hide()
self.last_folder = dialog.get_current_folder_uri()
for uri in dialog.get_uris():
self.add_image_uri(uri)
dialog.destroy()
-
+
def on_quit_activate(self, widget, *args):
"""Callback from File->Quit."""
if self.uploading:
- dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING, parent=self.window)
- dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT,
- gtk.STOCK_QUIT, gtk.RESPONSE_OK)
+ dialog = Gtk.MessageDialog(type=Gtk.MessageType.WARNING, parent=self.window)
+ dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT,
+ Gtk.STOCK_QUIT, Gtk.ResponseType.OK)
dialog.set_markup(_('<b>Currently Uploading</b>'))
dialog.format_secondary_text(_('Photos are still being uploaded. '
'Are you sure you want to quit? '
'You can also save your pending upload set for later.'))
- dialog.set_default_response(gtk.RESPONSE_OK)
+ dialog.set_default_response(Gtk.ResponseType.OK)
response = dialog.run()
dialog.destroy()
- if response == gtk.RESPONSE_CANCEL:
+ if response == Gtk.ResponseType.CANCEL:
return True
- elif response == gtk.RESPONSE_ACCEPT:
+ elif response == Gtk.ResponseType.ACCEPT:
self.save_upload_set()
elif self.is_connected and self.model.iter_n_children(None) > 0 and self.model.dirty():
- dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING, parent=self.window)
- dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT,
- gtk.STOCK_QUIT, gtk.RESPONSE_OK)
+ dialog = Gtk.MessageDialog(type=Gtk.MessageType.WARNING, parent=self.window)
+ dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT,
+ Gtk.STOCK_QUIT, Gtk.ResponseType.OK)
dialog.set_markup(_('<b>Photos to be uploaded</b>'))
dialog.format_secondary_text(_('There are photos pending to '
'be uploaded. '
'Are you sure you want to quit? '
'You can also save your pending upload set for later.'))
- dialog.set_default_response(gtk.RESPONSE_OK)
+ dialog.set_default_response(Gtk.ResponseType.OK)
response = dialog.run()
dialog.destroy()
- if response == gtk.RESPONSE_CANCEL:
+ if response == Gtk.ResponseType.CANCEL:
return True
- elif response == gtk.RESPONSE_ACCEPT:
+ elif response == Gtk.ResponseType.ACCEPT:
self.save_upload_set()
import twisted.internet.reactor
@@ -531,7 +503,7 @@ class Postr(UniqueApp):
def on_remove_activate(self, widget):
"""Callback from File->Remove or Remove button."""
-
+
def get_selected_iter(model, path, iter, selectList):
selectIter = model.get_iter(path)
selectList.append(selectIter)
@@ -555,7 +527,6 @@ class Postr(UniqueApp):
elif len(model) > 0:
self.thumbview.set_cursor(model[-1].path)
-
def on_select_all_activate(self, menuitem):
"""Callback from Edit->Select All."""
selection = self.thumbview.get_selection()
@@ -580,13 +551,13 @@ class Postr(UniqueApp):
"""Callback from File->Switch User."""
self.flickr.clear_cached()
self.flickr.authenticate_1().addCallbacks(self.auth_open_url, self.twisted_error)
-
+
def on_upload_activate(self, menuitem):
"""Callback from File->Upload."""
if self.uploading:
print "Upload should be disabled, currently uploading"
return
-
+
it = self.model.get_iter_first()
if it is None:
print "Upload should be disabled, no photos"
@@ -605,10 +576,10 @@ class Postr(UniqueApp):
self.upload_index = 0
self.list_failed_it = []
self.upload()
-
+
def on_help_activate(self, menuitem):
"""Callback from Help->Contents."""
- gtk.show_uri(None,"ghelp:postr",gtk.gdk.CURRENT_TIME);
+ Gtk.show_uri(None, "ghelp:postr", Gdk.CURRENT_TIME);
def on_about_activate(self, menuitem):
"""Callback from Help->About."""
@@ -616,7 +587,7 @@ class Postr(UniqueApp):
dialog.run()
dialog.destroy()
- def update_thumbnail(self, widget, allocation = None):
+ def update_thumbnail(self, widget, allocation=None):
"""Update the preview, as the selected image was changed."""
if self.current_it:
if not allocation:
@@ -636,7 +607,7 @@ class Postr(UniqueApp):
self.old_thumb_allocation = allocation
(simage,) = self.model.get(self.current_it, ImageStore.COL_PREVIEW)
-
+
tw = allocation.width
th = allocation.height
# Clamp the size to 512
@@ -646,23 +617,23 @@ class Postr(UniqueApp):
simage.get_height(),
tw, th)
- thumb = simage.scale_simple(tw, th, gtk.gdk.INTERP_BILINEAR)
+ thumb = simage.scale_simple(tw, th, GdkPixbuf.InterpType.BILINEAR)
widget.set_from_pixbuf(thumb)
def on_selection_changed(self, selection):
"""Callback when the selection was changed, to update the entries and
preview."""
- [obj.handler_block(i) for obj,i in self.change_signals]
-
+ [obj.handler_block(i) for obj, i in self.change_signals]
+
def enable_field(field, value):
field.set_sensitive(True)
- if isinstance(field, gtk.Entry):
+ if isinstance(field, Gtk.Entry):
field.set_text(value)
- elif isinstance(field, gtk.TextView):
+ elif isinstance(field, Gtk.TextView):
field.get_buffer().set_text(value)
- elif isinstance(field, gtk.ToggleButton):
+ elif isinstance(field, Gtk.ToggleButton):
field.set_active(value)
- elif isinstance(field, gtk.ComboBox):
+ elif isinstance(field, Gtk.ComboBox):
if value:
field.set_active_iter(value)
else:
@@ -674,13 +645,13 @@ class Postr(UniqueApp):
raise "Unhandled widget type %s" % field
def disable_field(field):
field.set_sensitive(False)
- if isinstance(field, gtk.Entry):
+ if isinstance(field, Gtk.Entry):
field.set_text("")
- elif isinstance(field, gtk.TextView):
+ elif isinstance(field, Gtk.TextView):
field.get_buffer().set_text("")
- elif isinstance(field, gtk.ToggleButton):
+ elif isinstance(field, Gtk.ToggleButton):
field.set_active(True)
- elif isinstance(field, gtk.ComboBox):
+ elif isinstance(field, Gtk.ComboBox):
field.set_active(-1)
elif isinstance(field, GroupSelector.GroupSelector):
field.set_selected_groups(())
@@ -732,22 +703,22 @@ class Postr(UniqueApp):
disable_field(self.license_combo)
self.thumbnail_image.set_from_icon_name("postr", self.logo_icon_size)
- [obj.handler_unblock(i) for obj,i in self.change_signals]
+ [obj.handler_unblock(i) for obj, i in self.change_signals]
def add_image_dir_file(self, gfile):
- children = gfile.enumerate_children(_FILE_ATTRIBUTES, flags=gio.FILE_QUERY_INFO_NONE)
- child_info = children.next_file()
+ children = gfile.enumerate_children(_FILE_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, None)
+ child_info = children.next_file(None)
while child_info:
file_type = child_info.get_file_type()
- if file_type == gio.FILE_TYPE_REGULAR:
+ if file_type == Gio.FileType.REGULAR:
self.add_image_fileinfo(gfile, child_info)
- elif file_type == gio.FILE_TYPE_DIRECTORY:
+ elif file_type == Gio.FileType.DIRECTORY:
dirname = os.path.join(gfile.get_uri(), child_info.get_name())
- self.add_image_dir_file(gio.File(dirname))
+ self.add_image_dir_file(Gio.File.new_for_uri(dirname))
else:
print "Unhandled file %s" % gfile.get_uri()
- child_info = children.next_file()
- children.close()
+ child_info = children.next_file(None)
+ children.close(None)
def add_image_uri(self, uri):
"""Add a file to the image list. Called by the File->Add Photo and drag
@@ -755,14 +726,23 @@ class Postr(UniqueApp):
return self.add_image_filename(uri)
def add_image_filename(self, filename):
- gfile = gio.File(filename)
- fileinfo = gfile.query_info(_FILE_ATTRIBUTES, flags=gio.FILE_QUERY_INFO_NONE)
+ gfile = Gio.File.new_for_commandline_arg(filename)
+ fileinfo = gfile.query_info(_FILE_ATTRIBUTES,
+ Gio.FileQueryInfoFlags.NONE,
+ None)
self.add_image_file(gfile, fileinfo)
def add_image_fileinfo(self, parent, fileinfo):
filename = os.path.join(parent.get_uri(), fileinfo.get_name())
- gfile = gio.File(filename)
- self.add_image_file(gfile, fileinfo)
+ gfile = Gio.File.new_for_uri(filename)
+ ginfo = gfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ Gio.FileQueryInfoFlags.NONE, None)
+ mime = ginfo.get_content_type()
+
+ if mime in _SUPPORTED_MIME_TYPES:
+ self.add_image_file(gfile, fileinfo)
+ else:
+ print 'Unsupported format (%s): %s' % (mime, filename)
def _on_preview_size_prepared(self, loader, width, height):
"""Appropriately scale the image preview to fit inside 512x512"""
@@ -781,20 +761,20 @@ class Postr(UniqueApp):
d.set_from_string(_("Image %s is too large, images must be no larger than %dMB in size.") % (gfile.get_path(), self.statusbar.maxfile))
d.show_all()
return
-
+
# TODO: we open the file three times now, which is madness, especially
# if gnome-vfs is used to read remote files. Need to find/write EXIF
# and IPTC parsers that are incremental.
# only opening the file_stream
- file_stream = gfile.read()
+ file_stream = gfile.read(None)
# First we load the image scaled to 512x512 for the preview.
try:
if gfile.is_native():
- preview = gtk.gdk.pixbuf_new_from_file_at_size(gfile.get_path(), 512, 512)
+ preview = GdkPixbuf.Pixbuf.new_from_file_at_size(gfile.get_path(), 512, 512)
else:
- loader = gtk.gdk.PixbufLoader()
+ loader = GdkPixbuf.PixbufLoader()
loader.connect("size-prepared", self._on_preview_size_prepared)
loader.write(file_stream.read())
loader.close()
@@ -804,9 +784,9 @@ class Postr(UniqueApp):
d.set_from_exception(e)
d.show_all()
return
-
+
# type 1 is beginning of file
- if not file_stream.can_seek() or not file_stream.seek(0, type=1):
+ if not file_stream.can_seek() or not file_stream.seek(0, type=1, cancellable=None):
file_stream = gfile.read()
# On a file that doesn't contain EXIF, like a PNG, this just returns an
@@ -817,28 +797,28 @@ class Postr(UniqueApp):
exif = {}
# type 1 is beginning of file
- if not file_stream.can_seek() or not file_stream.seek(0, type=1):
- file_stream = gfile.read()
+ if not file_stream.can_seek() or not file_stream.seek(0, type=1, cancellable=None):
+ file_stream = gfile.read(None)
try:
iptc = IPTCInfo(file_stream).data
except:
iptc = {}
-
+
# Rotate the preview if required. We don't need to manipulate the
# original data as Flickr will do that for us.
if "Image Orientation" in exif:
rotation = exif["Image Orientation"].values[0]
if rotation == ROTATED_180:
- preview = preview.rotate_simple(gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN)
+ preview = preview.rotate_simple(Gdk.PIXBUF_ROTATE_UPSIDEDOWN)
elif rotation == ROTATED_90_CW:
- preview = preview.rotate_simple(gtk.gdk.PIXBUF_ROTATE_CLOCKWISE)
+ preview = preview.rotate_simple(Gdk.PIXBUF_ROTATE_CLOCKWISE)
elif rotation == ROTATED_90_CCW:
- preview = preview.rotate_simple(gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
-
+ preview = preview.rotate_simple(Gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
+
# Now scale the preview to a thumbnail
sizes = get_thumb_size(preview.get_width(), preview.get_height(), 64, 64)
- thumb = preview.scale_simple(sizes[0], sizes[1], gtk.gdk.INTERP_BILINEAR)
+ thumb = preview.scale_simple(sizes[0], sizes[1], GdkPixbuf.InterpType.BILINEAR)
# Slurp data from the EXIF and IPTC tags
title_tags = (
@@ -863,15 +843,14 @@ class Postr(UniqueApp):
if value:
return value
return default
-
+
title = slurp(title_tags, os.path.splitext(fileinfo.get_display_name())[0])
desc = slurp(desc_tags)
tags = slurp(tag_tags)
-
+
self.model.set(self.model.append(),
ImageStore.COL_URI, gfile.get_uri(),
ImageStore.COL_SIZE, filesize,
- ImageStore.COL_IMAGE, None,
ImageStore.COL_PREVIEW, preview,
ImageStore.COL_THUMBNAIL, thumb,
ImageStore.COL_TITLE, title,
@@ -881,25 +860,25 @@ class Postr(UniqueApp):
self.update_statusbar()
self.update_upload()
-
+
def on_drag_data_received(self, widget, context, x, y, selection, targetType, timestamp):
"""Drag and drop callback when data is received."""
if targetType == ImageList.DRAG_IMAGE:
pixbuf = selection.get_pixbuf()
# TODO: don't scale up if the image is smaller than 512/512
-
+
# Scale the pixbuf to a preview
sizes = get_thumb_size(pixbuf.get_width(), pixbuf.get_height(), 512, 512)
- preview = pixbuf.scale_simple(sizes[0], sizes[1], gtk.gdk.INTERP_BILINEAR)
+ preview = pixbuf.scale_simple(sizes[0], sizes[1], GdkPixbuf.InterpType.BILINEAR)
# Now scale to a thumbnail
sizes = get_thumb_size(pixbuf.get_width(), pixbuf.get_height(), 64, 64)
- thumb = pixbuf.scale_simple(sizes[0], sizes[1], gtk.gdk.INTERP_BILINEAR)
+ thumb = pixbuf.scale_simple(sizes[0], sizes[1], GdkPixbuf.InterpType.BILINEAR)
# TODO: This is wrong, and should generate a PNG here and use the
# size of the PNG
size = pixbuf.get_width() * pixbuf.get_height() * pixbuf.get_n_channels()
-
+
self.model.set(self.model.append(),
ImageStore.COL_IMAGE, pixbuf,
ImageStore.COL_SIZE, size,
@@ -911,15 +890,16 @@ class Postr(UniqueApp):
ImageStore.COL_TAGS, "",
ImageStore.COL_VISIBLE, True)
-
+
elif targetType == ImageList.DRAG_URI:
for uri in selection.get_uris():
- gfile = gio.File(uri)
- fileinfo = gfile.query_info(_FILE_ATTRIBUTES)
+ gfile = Gio.File.new_for_uri(uri)
+ fileinfo = gfile.query_info(_FILE_ATTRIBUTES,
+ Gio.FileQueryInfoFlags.NONE, None)
file_type = fileinfo.get_file_type()
- if file_type == gio.FILE_TYPE_REGULAR:
+ if file_type == Gio.FileType.REGULAR:
self.add_image_file(gfile, fileinfo)
- elif file_type == gio.FILE_TYPE_DIRECTORY:
+ elif file_type == Gio.FileType.DIRECTORY:
self.add_image_dir_file(gfile)
else:
print "Unhandled file %s" % gfile.get_uri()
@@ -943,7 +923,7 @@ class Postr(UniqueApp):
# Use named args for i18n
data = {
- "index": self.upload_index+1,
+ "index": self.upload_index + 1,
"count": self.upload_count
}
progress_label = _('Uploading %(index)d of %(count)d') % data
@@ -953,14 +933,14 @@ class Postr(UniqueApp):
def add_to_set(self, rsp, set):
"""Callback from the upload method to add the picture to a set."""
- photo_id=rsp.find("photoid").text
+ photo_id = rsp.find("photoid").text
self.flickr.photosets_addPhoto(photo_id=photo_id, photoset_id=set).addErrback(self.twisted_error)
self.upload_progress_tracker.complete_extra_step(EXTRA_STEP_SET_ID)
return rsp
def add_to_groups(self, rsp, groups):
"""Callback from the upload method to add the picture to a groups."""
- photo_id=rsp.find("photoid").text
+ photo_id = rsp.find("photoid").text
for group in groups:
def error(failure):
# Code 6 means "moderated", which isn't an error
@@ -972,7 +952,7 @@ class Postr(UniqueApp):
def set_license(self, rsp, license):
"""Callback from the upload method to set license for the picture."""
- photo_id=rsp.find("photoid").text
+ photo_id = rsp.find("photoid").text
self.flickr.photos_licenses_setLicense(photo_id=photo_id,
license_id=license).addErrback(self.twisted_error)
self.upload_progress_tracker.complete_extra_step(EXTRA_STEP_LICENSE)
@@ -1100,7 +1080,7 @@ class Postr(UniqueApp):
progress_tracker=self.upload_progress_tracker)
else:
print "No filename or pixbuf stored"
- except gio.Error, (error):
+ except Gio.Error, (error):
# save the iterator and continue uploading process
self.list_failed_it.append(it)
self.current_upload_it = None
@@ -1128,7 +1108,7 @@ class Postr(UniqueApp):
self.upload_progress_tracker.complete_extra_step(EXTRA_STEP_NEW_SET)
def create_photoset_then_continue(self, rsp, photoset_name):
- photo_id=rsp.find("photoid").text
+ photo_id = rsp.find("photoid").text
create_photoset = self.flickr.photosets_create(primary_photo_id=photo_id, title=photoset_name)
create_photoset.addCallback(self._process_photoset_creation, photoset_name)
create_photoset.addErrback(self.upload_error)
@@ -1147,7 +1127,7 @@ class Postr(UniqueApp):
thumbnail = self.model.get_value(iter, ImageStore.COL_THUMBNAIL)
#Use a pixmap to create a new image
- drawable = gtk.gdk.Pixmap(self.window.window, # gtk.gdk.Drawable
+ drawable = Gdk.Pixmap(self.window.window, # Gdk.Drawable
thumbnail.get_width(),
thumbnail.get_height())
@@ -1158,24 +1138,24 @@ class Postr(UniqueApp):
0, 0) #Destination X, Y coordinate
error_icon = self.window.render_icon(
- stock_id=gtk.STOCK_DIALOG_ERROR,
- size=gtk.ICON_SIZE_DIALOG)
+ stock_id=Gtk.STOCK_DIALOG_ERROR,
+ size=Gtk.IconSize.DIALOG)
# It chose a size for the error icon proportional to the thumbnail image
size = min(int(thumbnail.get_width() * HALF_SIZE),
int(thumbnail.get_height() * HALF_SIZE))
error_icon = error_icon.scale_simple(size, size,
- gtk.gdk.INTERP_BILINEAR)
+ GdkPixbuf.InterpType.BILINEAR)
# The error icon is drawed in the bottom right edge of the image
drawable.draw_pixbuf(self.window.get_style().white_gc, #graphics context
error_icon, #the pixbuf
0, 0, #Source X,Y coordinate
- thumbnail.get_width()-size, #Destination X coordinate
- thumbnail.get_height()-size) #Destination Y coordinate
+ thumbnail.get_width() - size, #Destination X coordinate
+ thumbnail.get_height() - size) #Destination Y coordinate
- new_thumbnail = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, #color mode
+ new_thumbnail = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, #color mode
True, #has alpha
8, #bits
thumbnail.get_width(), #width
@@ -1185,7 +1165,7 @@ class Postr(UniqueApp):
drawable.get_colormap(),
0, 0, #Source X, Y coordinate
0, 0, #Destination X, Y coordinate
- -1, -1) #The full width, height
+ - 1, -1) #The full width, height
self.model.set_value(iter, ImageStore.COL_THUMBNAIL, new_thumbnail)
@@ -1203,7 +1183,7 @@ class Postr(UniqueApp):
self.thumbview.set_reorderable(False)
self.thumbview.enable_targets()
- [obj.handler_unblock(i) for obj,i in self.drag_signals]
+ [obj.handler_unblock(i) for obj, i in self.drag_signals]
def on_button_press_cb(self, thumbview, event, data=None):
if self.drop_disabled:
@@ -1211,45 +1191,43 @@ class Postr(UniqueApp):
self.thumbview.unable_targets()
self.drop_disabled = True
- [obj.handler_block(i) for obj,i in self.drag_signals]
+ [obj.handler_block(i) for obj, i in self.drag_signals]
thumbview.set_reorderable(True)
return
def on_button_release_cb(self, thumbview, event, data=None):
-
if self.drop_disabled and (not self.drag_started):
self.drop_disabled = False
thumbview.set_reorderable(False)
self.thumbview.enable_targets()
- [obj.handler_unblock(i) for obj,i in self.drag_signals]
+ [obj.handler_unblock(i) for obj, i in self.drag_signals]
return False
-
def save_upload_set(self):
- dialog = gtk.FileChooserDialog(title=None,
- action=gtk.FILE_CHOOSER_ACTION_SAVE,
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_SAVE, gtk.RESPONSE_OK))
+ dialog = Gtk.FileChooserDialog(title=None, parent=self.window,
+ action=Gtk.FileChooserAction.SAVE,
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
- dialog.set_default_response(gtk.RESPONSE_OK)
+ dialog.set_default_response(Gtk.ResponseType.OK)
default_filename = datetime.strftime(datetime.today(), "upload_saved_on_%m-%d-%y.postr")
dialog.set_current_name(default_filename)
dialog.set_do_overwrite_confirmation(True)
- filter = gtk.FileFilter()
+ filter = Gtk.FileFilter()
filter.set_name("postr upload sets")
filter.add_pattern("*.postr")
dialog.add_filter(filter)
- filter = gtk.FileFilter()
+ filter = Gtk.FileFilter()
filter.set_name("All Files")
filter.add_pattern("*")
dialog.add_filter(filter)
response = dialog.run()
- if response == gtk.RESPONSE_OK:
+ if response == Gtk.ResponseType.OK:
filename = dialog.get_filename()
dest = shelve.open(filename, 'n')
@@ -1310,7 +1288,7 @@ class Postr(UniqueApp):
else:
safety_path = None
- args = ( path,
+ args = (path,
uri,
title,
desc,
@@ -1319,29 +1297,29 @@ class Postr(UniqueApp):
groups,
privacy_path,
safety_path,
- visible )
+ visible)
return args
def load_upload_set(self):
- dialog = gtk.FileChooserDialog(title=None,
- action=gtk.FILE_CHOOSER_ACTION_OPEN,
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+ dialog = Gtk.FileChooserDialog(title=None, parent=self.window,
+ action=Gtk.FileChooserAction.OPEN,
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
- dialog.set_default_response(gtk.RESPONSE_OK)
+ dialog.set_default_response(Gtk.ResponseType.OK)
- filter = gtk.FileFilter()
+ filter = Gtk.FileFilter()
filter.set_name("postr upload sets")
filter.add_pattern("*.postr")
dialog.add_filter(filter)
- filter = gtk.FileFilter()
+ filter = Gtk.FileFilter()
filter.set_name("All Files")
filter.add_pattern("*")
dialog.add_filter(filter)
response = dialog.run()
- if response == gtk.RESPONSE_OK:
+ if response == Gtk.ResponseType.OK:
filename = dialog.get_filename()
source = shelve.open(filename, 'r')
if source:
@@ -1354,14 +1332,14 @@ class Postr(UniqueApp):
if self.flickr.get_nsid() != nsid:
markup_args = (self.flickr.get_username(), username) if self.flickr.get_username() and username else (self.flickr.get_nsid(), nsid)
markup_pattern = _("You are logged in as %s but loading\nan upload set for %s")
- confirm_dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_YES_NO)
- confirm_dialog.set_default_response(gtk.RESPONSE_YES)
+ confirm_dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO)
+ confirm_dialog.set_default_response(Gtk.ResponseType.YES)
confirm_dialog.set_markup(markup_pattern % markup_args)
confirm_dialog.format_secondary_text(_("Do you want to continue "
"with the load? You will "
"not import photoset information."))
response = confirm_dialog.run()
- if response == gtk.RESPONSE_NO:
+ if response == Gtk.ResponseType.NO:
dialog.destroy()
return
else:
@@ -1371,14 +1349,14 @@ class Postr(UniqueApp):
if source.has_key("nsid"):
source_user = source.get("username", source["nsid"])
markup_pattern = _("You are not logged in but loading\nan upload set for %s")
- confirm_dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_YES_NO)
- confirm_dialog.set_default_response(gtk.RESPONSE_YES)
+ confirm_dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO)
+ confirm_dialog.set_default_response(Gtk.ResponseType.YES)
confirm_dialog.set_markup(markup_pattern % source_user)
confirm_dialog.format_secondary_text(_("Do you want to continue "
"with the load? You will "
"not import photoset information."))
response = confirm_dialog.run()
- if response == gtk.RESPONSE_NO:
+ if response == Gtk.ResponseType.NO:
dialog.destroy()
return
else:
diff --git a/src/proxyclient.py b/src/proxyclient.py
index 9284c79..67b550f 100644
--- a/src/proxyclient.py
+++ b/src/proxyclient.py
@@ -426,7 +426,7 @@ EXTRA_STEP_FRACTION = 0.04
class UploadProgressTracker(object):
"""
- This object takes a gtk.ProgressBar object as a parameter
+ This object takes a Gtk.ProgressBar object as a parameter
and appropriately calls progress.set_fraction() as more
data gets written to the pipe.
"""
diff --git a/src/util.py b/src/util.py
index 5ad3410..bf58995 100644
--- a/src/util.py
+++ b/src/util.py
@@ -15,30 +15,31 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA
-import gtk, os
+import os
+from gi.repository import Gtk, GdkPixbuf
def greek(size):
"""Take a quantity (like 1873627) and display it in a human-readable rounded
form (like 1.8M)"""
_abbrevs = [
- (1<<50L, 'P'),
- (1<<40L, 'T'),
- (1<<30L, 'G'),
- (1<<20L, 'M'),
- (1<<10L, 'k'),
+ (1 << 50L, 'P'),
+ (1 << 40L, 'T'),
+ (1 << 30L, 'G'),
+ (1 << 20L, 'M'),
+ (1 << 10L, 'k'),
(1, '')
]
for factor, suffix in _abbrevs:
if size > factor:
break
- return "%.1f%s" % (float(size)/factor, suffix)
+ return "%.1f%s" % (float(size) / factor, suffix)
def get_widget_checked(glade, name):
"""Get widget name from glade, and if it doesn't exist raise an exception
instead of returning None."""
- widget = glade.get_widget(name)
+ widget = glade.get_object(name)
if widget is None: raise "Cannot find widget %s" % name
return widget
@@ -53,8 +54,8 @@ def get_glade_widgets (glade, object, widget_names):
def get_thumb_size(srcw, srch, dstw, dsth):
"""Scale scrw x srch to an dimensions with the same ratio that fits as
closely as possible to dstw x dsth."""
- scalew = dstw/float(srcw)
- scaleh = dsth/float(srch)
+ scalew = dstw / float(srcw)
+ scaleh = dsth / float(srch)
scale = min(scalew, scaleh)
return (int(srcw * scale), int(srch * scale))
@@ -62,7 +63,8 @@ def get_thumb_size(srcw, srch, dstw, dsth):
def align_labels(glade, names):
"""Add the list of widgets identified by names in glade to a horizontal
sizegroup."""
- group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
+ group = Gtk.SizeGroup()
+ group.set_mode(Gtk.SizeGroupMode.HORIZONTAL)
widget = [group.add_widget(get_widget_checked(glade, name)) for name in names]
@@ -87,7 +89,7 @@ def get_buddyicon(flickr, data, size=48):
__buddy_cache = bsddb3.hashopen(path, "c")
def load_thumb(page, size):
- loader = gtk.gdk.PixbufLoader()
+ loader = GdkPixbuf.PixbufLoader()
loader.set_size (size, size)
loader.write(page)
loader.close()
@@ -96,7 +98,7 @@ def get_buddyicon(flickr, data, size=48):
def got_data(page, url, size):
__buddy_cache[url] = page
return load_thumb(page, size)
-
+
if int(data.get("iconfarm")) > 0:
url = "http://farm%s.static.flickr.com/%s/buddyicons/%s.jpg" % (data.get("iconfarm"), data.get("iconserver"), data.get("nsid"))
else:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]