Add cropping left, center, right for browse
This commit is contained in:
parent
67b8da685b
commit
c4867ba7c3
|
@ -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"><b>Preview</b></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"><b>Crop</b></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>
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue