Add cropping left, center, right for browse

This commit is contained in:
Sean Davis 2013-07-17 21:28:32 -04:00
parent 67b8da685b
commit c4867ba7c3
3 changed files with 280 additions and 16 deletions

View File

@ -3,6 +3,207 @@
<!-- interface-requires gtk+ 3.0 -->
<!-- interface-requires mugshot_window 1.0 -->
<!-- interface-local-resource-path ../media -->
<object class="GtkBox" id="box8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkFrame" id="frame9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkImage" id="file_chooser_preview">
<property name="width_request">128</property>
<property name="height_request">128</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">64</property>
<property name="icon_name">image-loading</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Preview&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="crop_center">
<property name="label" translatable="yes">Center</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_crop_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="crop_left">
<property name="label" translatable="yes">Left</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">crop_center</property>
<signal name="toggled" handler="on_crop_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="crop_right">
<property name="label" translatable="yes">Right</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">crop_center</property>
<signal name="toggled" handler="on_crop_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Crop&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<object class="GtkFileChooserDialog" id="filechooserdialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="role">GtkFileChooserDialog</property>
<property name="icon_name">mugshot</property>
<property name="type_hint">dialog</property>
<property name="transient_for">mugshot_window</property>
<property name="create_folders">False</property>
<property name="local_only">False</property>
<property name="preview_widget">box8</property>
<property name="use_preview_label">False</property>
<signal name="update-preview" handler="on_filechooserdialog_update_preview" swapped="no"/>
<child internal-child="vbox">
<object class="GtkBox" id="filechooserdialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="filechooserdialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label">gtk-apply</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-6">button1</action-widget>
<action-widget response="-10">button2</action-widget>
</action-widgets>
</object>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>

View File

@ -26,6 +26,8 @@ import subprocess
# DBUS interface is used to update pidgin buddyicon when pidgin is running.
import dbus
import tempfile
from gi.repository import Gtk, Gdk, GdkPixbuf # pylint: disable=E0611
import logging
logger = logging.getLogger('mugshot')
@ -171,6 +173,20 @@ class MugshotWindow(Window):
# Stock photo browser
self.stock_browser = builder.get_object('stock_browser')
self.iconview = builder.get_object('stock_iconview')
# File Chooser Dialog
self.chooser = builder.get_object('filechooserdialog')
self.crop_center = builder.get_object('crop_center')
self.crop_left = builder.get_object('crop_left')
self.crop_right = builder.get_object('crop_right')
self.file_chooser_preview = builder.get_object('file_chooser_preview')
# Add a filter for only image files.
image_filter = Gtk.FileFilter()
image_filter.set_name('Images')
image_filter.add_mime_type('image/*')
self.chooser.add_filter(image_filter)
self.tmpfile = None
# Populate all of the widgets.
self.init_user_details()
@ -692,26 +708,69 @@ class MugshotWindow(Window):
# = Image Browser ======================================================== #
def on_image_from_browse_activate(self, widget):
"""Browse for a user profile image."""
# Initialize a GtkFileChooserDialog.
chooser = Gtk.FileChooserDialog(_("Select an image"), self,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OK, Gtk.ResponseType.OK))
# Add a filter for only image files.
image_filter = Gtk.FileFilter()
image_filter.set_name('Images')
image_filter.add_mime_type('image/*')
chooser.add_filter(image_filter)
# Run the dialog, grab the filename if confirmed, then hide the dialog.
response = chooser.run()
if response == Gtk.ResponseType.OK:
response = self.chooser.run()
if response == Gtk.ResponseType.APPLY:
# Update the user image, store the path for committing later.
self.updated_image = chooser.get_filename()
if self.tmpfile and os.path.isfile(self.tmpfile.name):
os.remove(self.tmpfile.name)
self.tmpfile = tempfile.NamedTemporaryFile(delete=False)
self.tmpfile.close()
self.updated_image = self.tmpfile.name
self.filechooser_preview_pixbuf.savev(self.updated_image, "png", [], [])
logger.debug("Selected %s" % self.updated_image)
self.set_user_image(self.updated_image)
chooser.hide()
self.chooser.hide()
def on_filechooserdialog_update_preview(self, widget):
filename = widget.get_filename()
if not filename:
self.file_chooser_preview.set_from_icon_name('folder', 128)
return
if not os.path.isfile(filename):
self.file_chooser_preview.set_from_icon_name('folder', 128)
return
filechooser_pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
# Get the image dimensions.
height = filechooser_pixbuf.get_height()
width = filechooser_pixbuf.get_width()
start_x = 0
start_y = 0
if self.crop_center.get_active():
# Calculate a balanced center.
if width > height:
start_x = (width-height)/2
width = height
else:
start_y = (height-width)/2
height = width
elif self.crop_left.get_active():
start_x = 0
if width > height:
width = height
else:
start_y = (height-width)/2
height = width
elif self.crop_right.get_active():
if width > height:
start_x = width-height
width = height
else:
start_y = (height-width)/2
height = width
# Create a new cropped pixbuf.
self.filechooser_preview_pixbuf = filechooser_pixbuf.new_subpixbuf(start_x, start_y, width, height)
scaled = self.filechooser_preview_pixbuf.scale_simple(128, 128, GdkPixbuf.InterpType.HYPER)
self.file_chooser_preview.set_from_pixbuf(scaled)
def on_crop_changed(self, widget, data=None):
if widget.get_active():
self.on_filechooserdialog_update_preview(self.chooser)
# = Password Entry ======================================================= #
def get_password(self):

View File

@ -20,6 +20,8 @@ from gi.repository import Gio, Gtk # pylint: disable=E0611
import logging
logger = logging.getLogger('mugshot_lib')
import os
from . helpers import get_builder, show_uri, get_help_uri
# This class is meant to be subclassed by MugshotWindow. It provides
@ -82,6 +84,8 @@ class Window(Gtk.Window):
def on_destroy(self, widget, data=None):
"""Called when the MugshotWindow is closed."""
# Clean up code for saving application state should be added here.
if self.tmpfile and os.path.isfile(self.tmpfile.name):
os.remove(self.tmpfile.name)
Gtk.main_quit()
def on_preferences_changed(self, settings, key, data=None):