diff --git a/.quickly b/.quickly deleted file mode 100644 index adb7c31..0000000 --- a/.quickly +++ /dev/null @@ -1,6 +0,0 @@ -project = mugshot -version = 12.08.1 -template = ubuntu-application -dependencies = -lp_id = mugshot -ppa = mugshot-ppa diff --git a/build/lib.linux-x86_64-2.7/mugshot/CameraMugshotDialog.py b/build/lib.linux-x86_64-2.7/mugshot/CameraMugshotDialog.py deleted file mode 100644 index c09e4f5..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot/CameraMugshotDialog.py +++ /dev/null @@ -1,343 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -from locale import gettext as _ - -import logging -logger = logging.getLogger('mugshot') - -from gi.repository import Gtk, GdkX11, GObject, Gst, GstVideo, GdkPixbuf -import cairo - -import tempfile, os - -from mugshot_lib.CameraDialog import CameraDialog - -class CameraMugshotDialog(CameraDialog): - __gtype_name__ = "CameraMugshotDialog" - - def finish_initializing(self, builder): # pylint: disable=E1002 - """Set up the camera dialog""" - super(CameraMugshotDialog, self).finish_initializing(builder) - - # Initialize Gst or nothing will work. - Gst.init(None) - - # Pack the video widget into the dialog. - vbox = builder.get_object('camera_box') - self.video_window = Gtk.DrawingArea() - self.video_window.connect("realize",self.__on_video_window_realized) - vbox.pack_start(self.video_window, True, True, 0) - self.video_window.show() - - # Prepare the camerabin element. - self.camerabin = Gst.ElementFactory.make("camerabin", "camera-source") - if self.camerabin: - bus = self.camerabin.get_bus() - bus.add_signal_watch() - bus.enable_sync_message_emission() - bus.connect("message", self._on_message) - bus.connect("sync-message::element", self._on_sync_message) - self.realized = False - self.draw_handler = self.video_window.connect('draw', self.on_draw) - # If the camera fails to load, show an error on the screen. - else: - devices = [] - for device in os.listdir('/dev/'): - if device.startswith('video'): devices.append(device) - logger.error(_('Camera failed to load. Devices: %s') % '; '.join(devices)) - self.draw_handler = self.video_window.connect('draw', self.on_failed_draw) - self.realized = True - - # Essential widgets - self.record_button = builder.get_object('camera_record') - self.apply_button = builder.get_object('camera_apply') - - # Store the temporary filename to be used. - self.filename = None - - self.show_all() - - def on_failed_draw(self, widget, ctx): - """Display a message that the camera failed to load.""" - # Get the height and width of the drawing area. - alloc = widget.get_allocation() - height = alloc.height - width = alloc.width - - # Make the background black. - ctx.set_source_rgb(0,0,0) - ctx.paint() - - # Set the font details. - font_size = 20 - font_color = (255,255,255) - font_name = "Sans" - - # Translators: Please include the newline, required to fit the message. - message = _("Sorry, but your camera\nfailed to initialize.") - - # Draw the message to the drawing area. - ctx.set_source_rgb(*font_color) - ctx.select_font_face(font_name, cairo.FONT_SLANT_NORMAL, - cairo.FONT_WEIGHT_NORMAL) - ctx.set_font_size(font_size) - ctx.move_to(10,(height-font_size)/2) - ctx.show_text(message.split('\n')[0]) - ctx.move_to(10,(height-font_size)/2+font_size) - ctx.show_text(message.split('\n')[1]) - - def on_draw(self, widget, ctx): - """Display a message that the camera is initializing on first draw. - Afterwards, blank the drawing area to clear the message.""" - # Get the height and width of the drawing area. - alloc = widget.get_allocation() - height = alloc.height - width = alloc.width - - # Set the font details. - font_size = 20 - font_color = (255,255,255) - font_name = "Sans" - - # Translators: Please include the newline, required to fit the message. - message = _("Please wait while your\ncamera is initialized.") - - # Draw the message to the drawing area. - ctx.set_source_rgb(*font_color) - ctx.select_font_face(font_name, cairo.FONT_SLANT_NORMAL, - cairo.FONT_WEIGHT_NORMAL) - ctx.set_font_size(font_size) - ctx.move_to(10,(height-font_size)/2) - ctx.show_text(message.split('\n')[0]) - ctx.move_to(10,(height-font_size)/2+font_size) - ctx.show_text(message.split('\n')[1]) - - # Redefine on_draw to blank the drawing area next time. - def on_draw(self, widget, ctx): - ctx.set_source_rgb(0,0,0) - ctx.paint() - # Redefine on_draw once more to do nothing else. - def on_draw(self, widget, ctx): - pass - - def play(self): - """Start the camera streaming and display the output. It is necessary - to start the camera playing before using most other functions.""" - if not self.realized: - self._set_video_window_id() - if not self.realized: - logger.error(_("Cannot display camera output. Ignoring play command")) - else: - if self.camerabin: - self.camerabin.set_state(Gst.State.PLAYING) - - def pause(self): - """Pause the camera output. It will cause the image to "freeze". - Use play() to start the camera playing again. Note that calling pause - before play may cause errors on certain camera.""" - if self.camerabin: - self.camerabin.set_state(Gst.State.PAUSED) - - def take_picture(self, filename): - """take_picture - grab a frame from the webcam and save it to - 'filename. - - If play is not called before take_picture, - an error may occur. If take_picture is called immediately after play, - the camera may not be fully initialized, and an error may occur. - - Connect to the signal "image-captured" to be alerted when the picture - is saved.""" - self.camerabin.set_property("location", filename) - self.camerabin.emit("start-capture") - - def stop(self): - """Stop the camera streaming and display the output.""" - self.camerabin.set_state(Gst.State.NULL) - - def _on_message(self, bus, message): - """Internal signal handler for bus messages. - May be useful to extend in a base class to handle messages - produced from custom behaviors. - - arguments - - bus: the bus from which the message was sent, typically self.bux - message: the message sent""" - # Ignore if there is no message. - if message is None: - return - - # Get the message type. - t = message.type - - # Initial load, wait until camera is ready before enabling capture. - if t == Gst.MessageType.ASYNC_DONE: - self.record_button.set_sensitive(True) - - if t == Gst.MessageType.ELEMENT: - # Keep the camera working after several pictures are taken. - if message.get_structure().get_name() == "image-captured": - self.camerabin.set_state(Gst.Sate.NULL) - self.camerabin.set_state(Gst.State.PLAYING) - self.emit("image-captured", self.filename) - - # Enable interface elements once the images are finished saving. - elif message.get_structure().get_name() == "image-done": - self.apply_button.set_sensitive(True) - self.record_button.set_sensitive(True) - self.pause() - - # Stop the stream if the EOS (end of stream) message is received. - if t == Gst.MessageType.EOS: - self.camerabin.set_state(Gst.State.NULL) - - # Capture and report any error received. - elif t == Gst.MessageType.ERROR: - err, debug = message.parse_error() - logger.error("%s" % err, debug) - - def _on_sync_message(self, bus, message): - """ _on_sync_message - internal signal handler for bus messages. - May be useful to extend in a base class to handle messages - produced from custom behaviors. - - arguments - - bus: the bus from which the message was sent, typically self.bux - message: the message sent - - """ - # Ignore empty messages. - if message.get_structure() is None: - return - message_name = message.get_structure().get_name() - # Embed the gstreamer element into our window. - if message_name == "prepare-window-handle": - imagesink = message.src - imagesink.set_property("force-aspect-ratio", True) - imagesink.set_window_handle(self.video_window.get_window().get_xid()) - - def __on_video_window_realized(self, widget, data=None): - """Internal signal handler, used to set up the xid for the drawing area - in a thread safe manner. Do not call directly.""" - self._set_video_window_id() - - def _set_video_window_id(self): - """Set the window ID only if not previously configured.""" - if not self.realized and self.video_window.get_window() is not None: - x = self.video_window.get_window().get_xid() - self.realized = True - - def on_camera_record_clicked(self, widget): - """When the camera record/retry button is clicked: - Record: Pause the video, start the capture, enable apply and retry. - Retry: Restart the video stream.""" - # Remove any previous temporary file. - if self.filename and os.path.isfile(self.filename): - os.remove(self.filename) - - # Retry action. - if self.apply_button.get_sensitive(): - self.record_button.set_label(Gtk.STOCK_MEDIA_RECORD) - self.apply_button.set_sensitive(False) - self.play() - - # Record (Capture) action. - else: - # Create a new temporary file. - tmpfile = tempfile.NamedTemporaryFile(delete=False) - tmpfile.close() - self.filename = tmpfile.name - - # Capture the current image. - self.take_picture(self.filename) - - # Set the record button to retry, and disable it until the capture - # finishes. - self.record_button.set_label(_("Retry")) - self.record_button.set_sensitive(False) - - def on_camera_apply_clicked(self, widget): - """When the camera Apply button is clicked, crop the current photo and - emit a signal to let the main application know there is a new file - available. Then close the camera dialog.""" - self.center_crop(self.filename) - self.emit("apply", self.filename) - self.hide() - - def on_camera_cancel_clicked(self, widget): - """When the Cancel button is clicked, just hide the dialog.""" - self.hide() - - def on_camera_mugshot_dialog_destroy(self, widget, data=None): - """When the application exits, remove the current temporary file and - stop the gstreamer element.""" - # Clear away the temp file. - if self.filename and os.path.isfile(self.filename): - os.remove(self.filename) - # Clean up the camera before exiting - self.camerabin.set_state(Gst.State.NULL) - - def on_camera_mugshot_dialog_hide(self, widget, data=None): - """When the dialog is hidden, pause the camera recording.""" - self.pause() - - def on_camera_mugshot_dialog_show(self, widget, data=None): - """When the dialog is shown, set the record button to record, disable - the apply button, and start the camera.""" - self.record_button.set_label(Gtk.STOCK_MEDIA_RECORD) - self.apply_button.set_sensitive(False) - self.show_all() - self.play() - - def center_crop(self, filename): - """Crop the specified file to square dimensions.""" - # Load the image into a Pixbuf. - pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename) - - # Get the image dimensions. - height = pixbuf.get_height() - width = pixbuf.get_width() - start_x = 0 - start_y = 0 - - # Calculate a balanced center. - if width > height: - start_x = (width-height)/2 - width = height - else: - start_y = (height-width)/2 - height = width - - # Create a new cropped pixbuf. - new_pixbuf = pixbuf.new_subpixbuf(start_x, start_y, width, height) - - # Overwrite the temporary file with our new cropped image. - new_pixbuf.savev(filename, "png", [], []) - - def on_camera_mugshot_dialog_delete_event(self, widget, data=None): - """Override the dialog delete event to just hide the window.""" - self.hide() - return True - - # Signals used by CameraMugshotDialog: - # image-captured: emitted when the camera is done capturing an image. - # apply: emitted when the apply button has been pressed and there is a new file saved for use. - __gsignals__ = {'image-captured' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, - (GObject.TYPE_PYOBJECT,)), - 'apply' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)) - } - diff --git a/build/lib.linux-x86_64-2.7/mugshot/MugshotWindow.py b/build/lib.linux-x86_64-2.7/mugshot/MugshotWindow.py deleted file mode 100644 index be794d5..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot/MugshotWindow.py +++ /dev/null @@ -1,645 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -from locale import gettext as _ - -import os -# Used for automating chfn -import pexpect -# Used for copying files to ~/.face -import shutil -# Used for which command and checking for running processes. -import subprocess -# DBUS interface is used to update pidgin buddyicon when pidgin is running. -import dbus - -from gi.repository import Gtk, Gdk, GdkPixbuf # pylint: disable=E0611 -import logging -logger = logging.getLogger('mugshot') - -from mugshot_lib import Window -from mugshot.CameraMugshotDialog import CameraMugshotDialog - -username = os.getenv('USER') -if not username: - username = os.getenv('USERNAME') -home = os.path.expanduser('~') -libreoffice_prefs = os.path.join(home, '.config', 'libreoffice', '4', 'user', - 'registrymodifications.xcu') -pidgin_prefs = os.path.join(home, '.purple', 'prefs.xml') -faces_dir = '/usr/share/pixmaps/faces/' - -def which(command): - '''Use the system command which to get the absolute path for the given - command.''' - return subprocess.Popen(['which', command], \ - stdout=subprocess.PIPE).stdout.read().strip() - -def has_running_process(name): - """Check for a running process, return True if any listings are found.""" - command = 'ps -ef | grep " %s" | grep -v "grep" | wc -l' % name - n = subprocess.Popen(command, stdout=subprocess.PIPE, - shell=True).stdout.read().strip() - return int(n) > 0 - -def detach_cb(menu, widget): - '''Detach a widget from its attached widget.''' - menu.detach() - -def get_entry_value(entry_widget): - """Get the value from one of the Mugshot entries.""" - # Get the text from an entry, changing none to '' - value = entry_widget.get_text().strip() - if value.lower() == 'none': - value = '' - return value - -def get_confirmation_dialog(parent, primary_message, secondary_message, - icon_name=None): - """Display a confirmation (yes/no) dialog configured with primary and - secondary messages, as well as a custom icon if requested.""" - dialog = Gtk.MessageDialog(parent, flags=0, type=Gtk.MessageType.QUESTION, - buttons=Gtk.ButtonsType.YES_NO, - message_format=primary_message) - dialog.format_secondary_text(secondary_message) - if icon_name: - image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.DIALOG) - dialog.set_image(image) - dialog.show_all() - response = dialog.run() - dialog.destroy() - return response == Gtk.ResponseType.YES - -def menu_position(self, menu, data=None, something_else=None): - '''Position a menu at the bottom of its attached widget''' - widget = menu.get_attach_widget() - allocation = widget.get_allocation() - window_pos = widget.get_window().get_position() - # Align the left side of the menu with the left side of the button. - x = window_pos[0] + allocation.x - # Align the top of the menu with the bottom of the button. - y = window_pos[1] + allocation.y + allocation.height - return (x, y, True) - -# See mugshot_lib.Window.py for more details about how this class works -class MugshotWindow(Window): - __gtype_name__ = "MugshotWindow" - - def finish_initializing(self, builder): # pylint: disable=E1002 - """Set up the main window""" - super(MugshotWindow, self).finish_initializing(builder) - - self.CameraDialog = CameraMugshotDialog - - # User Image widgets - self.image_button = builder.get_object('image_button') - self.user_image = builder.get_object('user_image') - self.image_menu = builder.get_object('image_menu') - self.image_menu.attach_to_widget(self.image_button, detach_cb) - self.image_from_camera = builder.get_object('image_from_camera') - image_from_browse = builder.get_object('image_from_browse') - image_from_browse.set_visible( os.path.exists(faces_dir) and \ - len(os.listdir(faces_dir)) > 0 ) - - # Entry widgets (chfn) - self.first_name_entry = builder.get_object('first_name') - self.last_name_entry = builder.get_object('last_name') - self.initials_entry = builder.get_object('initials') - self.office_phone_entry = builder.get_object('office_phone') - self.home_phone_entry = builder.get_object('home_phone') - self.email_entry = builder.get_object('email') - self.fax_entry = builder.get_object('fax') - - # Stock photo browser - self.stock_browser = builder.get_object('stock_browser') - self.iconview = builder.get_object('stock_iconview') - - # Populate all of the widgets. - self.init_user_details() - - def init_user_details(self): - """Initialize the user details entries and variables.""" - # Check for .face and set profile image. - logger.debug('Checking for ~/.face profile image') - face = os.path.expanduser('~/.face') - if os.path.isfile(face): - self.set_user_image(face) - else: - self.set_user_image(None) - self.updated_image = None - - # Search /etc/passwd for the current user's details. - logger.debug('Getting user details from /etc/passwd') - for line in open('/etc/passwd', 'r'): - if line.startswith(username + ':'): - logger.debug('Found details: %s' % line.strip()) - details = line.split(':')[4] - name, office, office_phone, home_phone = details.split(',', 3) - break - - # Expand the user's fullname into first, last, and initials. - try: - first_name, last_name = name.split(' ', 1) - initials = first_name[0] + last_name[0] - except: - first_name = name - last_name = '' - initials = first_name[0] - - # If the variables are defined as 'none', use blank for cleanliness. - if home_phone == 'none': home_phone = '' - if office_phone == 'none': office_phone = '' - - # Get dconf settings - logger.debug('Getting initials, email, and fax from dconf') - if self.settings['initials'] != '': - initials = self.settings['initials'] - email = self.settings['email'] - fax = self.settings['fax'] - - # Set the class variables - self.first_name = first_name - self.last_name = last_name - self.initials = initials - self.home_phone = home_phone - self.office_phone = office_phone - - # Populate the GtkEntries. - logger.debug('Populating entries') - self.first_name_entry.set_text(self.first_name) - self.last_name_entry.set_text(self.last_name) - self.initials_entry.set_text(self.initials) - self.office_phone_entry.set_text(self.office_phone) - self.home_phone_entry.set_text(self.home_phone) - self.email_entry.set_text(email) - self.fax_entry.set_text(fax) - - # = Mugshot Window ======================================================= # - def set_user_image(self, filename=None): - """Scale and set the user profile image.""" - logger.debug("Setting user profile image to %s" % str(filename)) - if filename: - pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename) - scaled = pixbuf.scale_simple(128, 128, GdkPixbuf.InterpType.HYPER) - self.user_image.set_from_pixbuf(scaled) - else: - self.user_image.set_from_icon_name('avatar-default', 128) - - def filter_numbers(self, entry, *args): - """Allow only numbers and + in phone entry fields.""" - text = entry.get_text().strip() - entry.set_text(''.join([i for i in text if i in '+0123456789'])) - - def on_apply_button_clicked(self, widget): - """When the window Apply button is clicked, commit any relevant - changes.""" - logger.debug('Applying changes...') - if self.get_chfn_details_updated(): - returns = self.save_chfn_details() - - if self.get_libreoffice_details_updated(): - self.set_libreoffice_data() - - if self.updated_image: - self.save_image() - - self.save_gsettings() - - def save_gsettings(self): - """Save details to dconf (the ones not tracked by /etc/passwd)""" - logger.debug('Saving details to dconf: /apps/mugshot') - self.settings.set_string('initials', - get_entry_value(self.initials_entry)) - self.settings.set_string('email', get_entry_value(self.email_entry)) - self.settings.set_string('fax', get_entry_value(self.fax_entry)) - - def entry_focus_next(self, widget): - """Focus the next available entry when pressing Enter.""" - logger.debug('Entry activated, focusing next widget.') - vbox = widget.get_parent().get_parent().get_parent().get_parent() - vbox.child_focus(Gtk.DirectionType.TAB_FORWARD) - - def on_cancel_button_clicked(self, widget): - """When the window cancel button is clicked, close the program.""" - logger.debug('Cancel clicked, goodbye.') - self.destroy() - - # = Image Button and Menu ================================================ # - def on_image_button_clicked(self, widget): - """When the menu button is clicked, display the photo menu.""" - logger.debug('Show photo menu') - self.image_from_camera.set_visible(os.path.exists('/dev/video0')) - if widget.get_active(): - self.image_menu.popup(None, None, menu_position, - self.image_menu, 3, - Gtk.get_current_event_time()) - - def on_image_menu_hide(self, widget): - """Untoggle the image button when the menu is hidden.""" - self.image_button.set_active(False) - - def on_camera_dialog_apply(self, widget, data=None): - self.updated_image = data - self.set_user_image(data) - - def save_image(self): - """Copy the updated image filename to ~/.face""" - # Check if the image has been updated. - if not self.updated_image: - logger.debug('Photo not updated, not saving changes.') - return False - - face = os.path.expanduser('~/.face') - - # If the .face file already exists, remove it first. - logger.debug('Photo updated, saving changes.') - if os.path.isfile(face): - os.remove(face) - - # Copy the new file to ~/.face - shutil.copyfile(self.updated_image, face) - self.set_pidgin_buddyicon(face) - self.updated_image = None - return True - - def set_pidgin_buddyicon(self, filename=None): - """Sets the pidgin buddyicon to filename (usually ~/.face). - - If pidgin is running, use the dbus interface, otherwise directly modify - the XML file.""" - if not os.path.exists(pidgin_prefs): - logger.debug('Pidgin not installed or never opened, not updating.') - return - logger.debug('Prompting user to update pidgin buddy icon') - update_pidgin = get_confirmation_dialog(self, - _("Update Pidgin Buddy Icon?"), - _("Would you also like to update your Pidgin buddy icon?"), - 'pidgin') - if update_pidgin: - if has_running_process('pidgin'): - self.set_pidgin_buddyicon_dbus(filename) - else: - self.set_pidgin_buddyicon_xml(filename) - else: - logger.debug('Reject: Not updating pidgin buddy icon') - - def set_pidgin_buddyicon_dbus(self, filename=None): - """Set the pidgin buddy icon via dbus.""" - logger.debug('Updating pidgin buddy icon via dbus') - bus = dbus.SessionBus() - obj = bus.get_object("im.pidgin.purple.PurpleService", - "/im/pidgin/purple/PurpleObject") - purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface") - # To make the change instantly visible, set the icon to none first. - purple.PurplePrefsSetPath('/pidgin/accounts/buddyicon', '') - if filename: - purple.PurplePrefsSetPath('/pidgin/accounts/buddyicon', filename) - - def set_pidgin_buddyicon_xml(self, filename=None): - """Set the buddyicon used by pidgin to filename (via the xml file).""" - # This is hacky, but a working implementation for now... - logger.debug('Updating pidgin buddy icon via xml') - prefs_file = pidgin_prefs - tmp_buffer = [] - if os.path.isfile(prefs_file): - for line in open(prefs_file): - if '\n' % filename - else: - new = new + 'value=\'\'/>\n' - tmp_buffer.append(new) - else: - tmp_buffer.append(line) - write_prefs = open(prefs_file, 'w') - for line in tmp_buffer: - write_prefs.write(line) - write_prefs.close() - - # = chfn functions ============================================ # - def get_chfn_details_updated(self): - """Return True if chfn-related details have been modified.""" - logger.debug('Checking if chfn details have been modified.') - if self.first_name != self.first_name_entry.get_text().strip() or \ - self.last_name != self.last_name_entry.get_text().strip() or \ - self.home_phone != self.home_phone_entry.get_text().strip() or \ - self.office_phone != self.office_phone_entry.get_text().strip(): - logger.debug('chfn details have been modified.') - return True - logger.debug('chfn details have NOT been modified.') - return False - - def save_chfn_details(self): - """Commit changes to chfn-related details. For full name, changes must - be performed as root. Other changes are done with the user password. - - Return exit codes for 1) full name changes and 2) home/work phone - changes. - - e.g. [0, 0] (both passed)""" - return_codes = [] - - # Get the user's password - password = self.get_password() - if not password: - return return_codes - - username = os.getenv('USER') - chfn = which('chfn') - - # Get each of the updated values. - first_name = get_entry_value(self.first_name_entry) - last_name = get_entry_value(self.last_name_entry) - full_name = "%s %s" % (first_name, last_name) - full_name = full_name.strip() - office_phone = get_entry_value(self.office_phone_entry) - if office_phone == '': - office_phone = 'none' - home_phone = get_entry_value(self.home_phone_entry) - if home_phone == '': - home_phone = 'none' - - # Full name can only be modified by root. Try using sudo to modify. - logger.debug('Attempting to set fullname with sudo chfn') - child = pexpect.spawn('sudo %s %s' % (chfn, username)) - child.timeout = 5 - try: - child.expect([".*ssword.*", pexpect.EOF]) - child.sendline(password) - child.expect("Full Name.*:") - child.sendline(full_name) - for i in range(5): - child.sendline('') - except pexpect.TIMEOUT: - # Password was incorrect, or sudo rights not granted - logger.debug('Timeout reached, password was incorrect or sudo ' \ - 'rights not granted.') - pass - child.close() - if child.exitstatus == 0: - self.first_name = first_name - self.last_name = last_name - return_codes.append(child.exitstatus) - - logger.debug('Attempting to set user details with chfn') - child = pexpect.spawn('chfn') - child.timeout = 5 - try: - child.expect(['Password: ', pexpect.EOF]) - child.sendline(password) - child.expect('Room Number.*:') - child.sendline('') - child.expect('Work Phone.*:') - child.sendline(office_phone) - child.expect('Home Phone.*:') - child.sendline(home_phone) - child.sendline(home_phone) - except pexpect.TIMEOUT: - logger.debug('Timeout reached, password was likely incorrect.') - child.close(True) - if child.exitstatus == 0: - self.office_phone = office_phone - self.home_phone = home_phone - return_codes.append(child.exitstatus) - return return_codes - - # = LibreOffice ========================================================== # - def get_libreoffice_details_updated(self): - """Return True if LibreOffice settings need to be updated.""" - # Return False if there is no preferences file. - if not os.path.isfile(libreoffice_prefs): - logger.debug('LibreOffice is not installed or has not been opened.' - ' Not updating.') - return False - # Compare the current entries to the existing LibreOffice data. - data = self.get_libreoffice_data() - if data['first_name'] != get_entry_value(self.first_name_entry): - return True - if data['last_name'] != get_entry_value(self.last_name_entry): - return True - if data['initials'] != get_entry_value(self.initials_entry): - return True - if data['email'] != get_entry_value(self.email_entry): - return True - if data['home_phone'] != get_entry_value(self.home_phone_entry): - return True - if data['office_phone'] != get_entry_value(self.office_phone_entry): - return True - if data['fax'] != get_entry_value(self.fax_entry): - return True - logger.debug('LibreOffice details do not need to be updated.') - return False - - def get_libreoffice_data(self): - """Get each of the preferences from the LibreOffice registymodifications - preferences file. - - Return a dict with the details.""" - prefs_file = libreoffice_prefs - data = {'first_name': '', 'last_name': '', 'initials': '', 'email': '', - 'home_phone': '', 'office_phone': '', 'fax': ''} - if os.path.isfile(prefs_file): - logger.debug('Getting settings from %s' % prefs_file) - for line in open(prefs_file): - if "UserProfile/Data" in line: - value = line.split('')[1].split('')[0] - value = value.strip() - # First Name - if 'name="givenname"' in line: - data['first_name'] = value - # Last Name - elif 'name="sn"' in line: - data['last_name'] = value - # Initials - elif 'name="initials"' in line: - data['initials'] = value - # Email - elif 'name="mail"' in line: - data['email'] = value - # Home Phone - elif 'name="homephone"' in line: - data['home_phone'] = value - # Office Phone - elif 'name="telephonenumber"' in line: - data['office_phone'] = value - # Fax Number - elif 'name="facsimiletelephonenumber"' in line: - data['fax'] = value - else: - pass - return data - - def set_libreoffice_data(self): - """Update the LibreOffice registymodifications preferences file.""" - prefs_file = libreoffice_prefs - if os.path.isfile(prefs_file): - logger.debug('Prompting user to update LibreOffice details.') - update_libreoffice = get_confirmation_dialog(self, - _("Update LibreOffice User Details?"), - _("Would you also like to update your user " - "details in LibreOffice?"), - 'libreoffice-startcenter') - if update_libreoffice: - logger.debug('Confirm: Updating details.') - tmp_buffer = [] - for line in open(prefs_file): - new = None - if "UserProfile/Data" in line: - new = line.split('')[0] - # First Name - if 'name="givenname"' in line: - new = new + '%s\n' % \ - get_entry_value(self.first_name_entry) - # Last Name - elif 'name="sn"' in line: - new = new + '%s\n' % \ - get_entry_value(self.last_name_entry) - # Initials - elif 'name="initials"' in line: - new = new + '%s\n' % \ - get_entry_value(self.initials_entry) - # Email - elif 'name="mail"' in line: - new = new + '%s\n' % \ - get_entry_value(self.email_entry) - # Home Phone - elif 'name="homephone"' in line: - new = new + '%s\n' % \ - get_entry_value(self.home_phone_entry) - # Office Phone - elif 'name="telephonenumber"' in line: - new = new + '%s\n' % \ - get_entry_value(self.office_phone_entry) - # Fax Number - elif 'name="facsimiletelephonenumber"' in line: - new = new + '%s\n' % \ - get_entry_value(self.fax_entry) - else: - new = line - tmp_buffer.append(new) - else: - tmp_buffer.append(line) - open_prefs = open(prefs_file, 'w') - for line in tmp_buffer: - open_prefs.write(line) - open_prefs.close() - else: - logger.debug('Reject: Not updating.') - - # = Stock Browser ======================================================== # - def on_image_from_stock_activate(self, widget): - """When the 'Select image from stock' menu item is clicked, load and - display the stock photo browser.""" - self.load_stock_browser() - self.stock_browser.show_all() - - def load_stock_browser(self): - """Load the stock photo browser.""" - # Check if the photos have already been loaded. - model = self.iconview.get_model() - if len(model) != 0: - logger.debug("Stock browser already loaded.") - return - - # If they have not, load each photo from /usr/share/pixmaps/faces. - logger.debug("Loading stock browser photos.") - for filename in os.listdir('/usr/share/pixmaps/faces'): - full_path = os.path.join('/usr/share/pixmaps/faces/', filename) - if os.path.isfile(full_path): - pixbuf = GdkPixbuf.Pixbuf.new_from_file(full_path) - scaled = pixbuf.scale_simple(90, 90, GdkPixbuf.InterpType.HYPER) - model.append([full_path, scaled]) - - def on_stock_iconview_selection_changed(self, widget): - """Enable stock submission only when an item is selected.""" - selected_items = self.iconview.get_selected_items() - self.builder.get_object('stock_ok').set_sensitive( - len(selected_items) > 0) - - def on_stock_browser_delete_event(self, widget, event): - """Hide the stock browser instead of deleting it.""" - widget.hide() - return True - - def on_stock_cancel_clicked(self, widget): - """Hide the stock browser when Cancel is clicked.""" - self.stock_browser.hide() - - def on_stock_ok_clicked(self, widget): - """When the stock browser OK button is clicked, get the currently - selected photo and set it to the user profile image.""" - selected_items = self.iconview.get_selected_items() - if len(selected_items) != 0: - # Get the filename from the stock browser iconview. - path = int(selected_items[0].to_string()) - filename = self.iconview.get_model()[path][0] - logger.debug("Selected %s" % filename) - - # Update variables and widgets, then hide. - self.set_user_image(filename) - self.updated_image = filename - self.stock_browser.hide() - - def on_stock_iconview_item_activated(self, widget, path): - """Allow selecting a stock photo with Enter.""" - self.on_stock_ok_clicked(widget) - - # = 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: - # Update the user image, store the path for committing later. - self.updated_image = chooser.get_filename() - logger.debug("Selected %s" % self.updated_image) - self.set_user_image(self.updated_image) - chooser.hide() - - # = Password Entry ======================================================= # - def get_password(self): - """Display a password dialog for authenticating to sudo and chfn.""" - logger.debug("Prompting user for password") - dialog = self.builder.get_object('password_dialog') - entry = self.builder.get_object('password_entry') - response = dialog.run() - dialog.hide() - if response == Gtk.ResponseType.OK: - logger.debug("Password entered") - pw = entry.get_text() - entry.set_text('') - return pw - logger.debug("Cancelled") - return None - - def on_password_entry_changed(self, widget): - """Enable password submission only when password is not blank.""" - self.builder.get_object('password_ok').set_sensitive( - len(widget.get_text()) > 0) - diff --git a/build/lib.linux-x86_64-2.7/mugshot/__init__.py b/build/lib.linux-x86_64-2.7/mugshot/__init__.py deleted file mode 100644 index 92f9969..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -import optparse - -from locale import gettext as _ - -from gi.repository import Gtk # pylint: disable=E0611 - -from mugshot import MugshotWindow - -from mugshot_lib import set_up_logging, get_version - -def parse_options(): - """Support for command line options""" - parser = optparse.OptionParser(version="%%prog %s" % get_version()) - parser.add_option( - "-v", "--verbose", action="count", dest="verbose", - help=_("Show debug messages (-vv debugs mugshot_lib also)")) - (options, args) = parser.parse_args() - - set_up_logging(options) - -def main(): - 'constructor for your class instances' - parse_options() - - # Run the application. - window = MugshotWindow.MugshotWindow() - window.show() - Gtk.main() diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/Builder.py b/build/lib.linux-x86_64-2.7/mugshot_lib/Builder.py deleted file mode 100644 index 3c3f461..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/Builder.py +++ /dev/null @@ -1,325 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -'''Enhances builder connections, provides object to access glade objects''' - -from gi.repository import GObject, Gtk # pylint: disable=E0611 - -import inspect -import functools -import logging -logger = logging.getLogger('mugshot_lib') - -from xml.etree.cElementTree import ElementTree - -# this module is big so uses some conventional prefixes and postfixes -# *s list, except self.widgets is a dictionary -# *_dict dictionary -# *name string -# ele_* element in a ElementTree - - -# pylint: disable=R0904 -# the many public methods is a feature of Gtk.Builder -class Builder(Gtk.Builder): - ''' extra features - connects glade defined handler to default_handler if necessary - auto connects widget to handler with matching name or alias - auto connects several widgets to a handler via multiple aliases - allow handlers to lookup widget name - logs every connection made, and any on_* not made - ''' - - def __init__(self): - Gtk.Builder.__init__(self) - self.widgets = {} - self.glade_handler_dict = {} - self.connections = [] - self._reverse_widget_dict = {} - -# pylint: disable=R0201 -# this is a method so that a subclass of Builder can redefine it - def default_handler(self, - handler_name, filename, *args, **kwargs): - '''helps the apprentice guru - - glade defined handlers that do not exist come here instead. - An apprentice guru might wonder which signal does what he wants, - now he can define any likely candidates in glade and notice which - ones get triggered when he plays with the project. - this method does not appear in Gtk.Builder''' - logger.debug('''tried to call non-existent function:%s() - expected in %s - args:%s - kwargs:%s''', handler_name, filename, args, kwargs) -# pylint: enable=R0201 - - def get_name(self, widget): - ''' allows a handler to get the name (id) of a widget - - this method does not appear in Gtk.Builder''' - return self._reverse_widget_dict.get(widget) - - def add_from_file(self, filename): - '''parses xml file and stores wanted details''' - Gtk.Builder.add_from_file(self, filename) - - # extract data for the extra interfaces - tree = ElementTree() - tree.parse(filename) - - ele_widgets = tree.getiterator("object") - for ele_widget in ele_widgets: - name = ele_widget.attrib['id'] - widget = self.get_object(name) - - # populate indexes - a dictionary of widgets - self.widgets[name] = widget - - # populate a reversed dictionary - self._reverse_widget_dict[widget] = name - - # populate connections list - ele_signals = ele_widget.findall("signal") - - connections = [ - (name, - ele_signal.attrib['name'], - ele_signal.attrib['handler']) for ele_signal in ele_signals] - - if connections: - self.connections.extend(connections) - - ele_signals = tree.getiterator("signal") - for ele_signal in ele_signals: - self.glade_handler_dict.update( - {ele_signal.attrib["handler"]: None}) - - def connect_signals(self, callback_obj): - '''connect the handlers defined in glade - - reports successful and failed connections - and logs call to missing handlers''' - filename = inspect.getfile(callback_obj.__class__) - callback_handler_dict = dict_from_callback_obj(callback_obj) - connection_dict = {} - connection_dict.update(self.glade_handler_dict) - connection_dict.update(callback_handler_dict) - for item in connection_dict.items(): - if item[1] is None: - # the handler is missing so reroute to default_handler - handler = functools.partial( - self.default_handler, item[0], filename) - - connection_dict[item[0]] = handler - - # replace the run time warning - logger.warn("expected handler '%s' in %s", - item[0], filename) - - # connect glade define handlers - Gtk.Builder.connect_signals(self, connection_dict) - - # let's tell the user how we applied the glade design - for connection in self.connections: - widget_name, signal_name, handler_name = connection - logger.debug("connect builder by design '%s', '%s', '%s'", - widget_name, signal_name, handler_name) - - def get_ui(self, callback_obj=None, by_name=True): - '''Creates the ui object with widgets as attributes - - connects signals by 2 methods - this method does not appear in Gtk.Builder''' - - result = UiFactory(self.widgets) - - # Hook up any signals the user defined in glade - if callback_obj is not None: - # connect glade define handlers - self.connect_signals(callback_obj) - - if by_name: - auto_connect_by_name(callback_obj, self) - - return result - - -# pylint: disable=R0903 -# this class deliberately does not provide any public interfaces -# apart from the glade widgets -class UiFactory(): - ''' provides an object with attributes as glade widgets''' - def __init__(self, widget_dict): - self._widget_dict = widget_dict - for (widget_name, widget) in widget_dict.items(): - setattr(self, widget_name, widget) - - # Mangle any non-usable names (like with spaces or dashes) - # into pythonic ones - cannot_message = """cannot bind ui.%s, name already exists - consider using a pythonic name instead of design name '%s'""" - consider_message = """consider using a pythonic name instead of design name '%s'""" - - for (widget_name, widget) in widget_dict.items(): - pyname = make_pyname(widget_name) - if pyname != widget_name: - if hasattr(self, pyname): - logger.debug(cannot_message, pyname, widget_name) - else: - logger.debug(consider_message, widget_name) - setattr(self, pyname, widget) - - def iterator(): - '''Support 'for o in self' ''' - return iter(widget_dict.values()) - setattr(self, '__iter__', iterator) - - def __getitem__(self, name): - 'access as dictionary where name might be non-pythonic' - return self._widget_dict[name] -# pylint: enable=R0903 - - -def make_pyname(name): - ''' mangles non-pythonic names into pythonic ones''' - pyname = '' - for character in name: - if (character.isalpha() or character == '_' or - (pyname and character.isdigit())): - pyname += character - else: - pyname += '_' - return pyname - - -# Until bug https://bugzilla.gnome.org/show_bug.cgi?id=652127 is fixed, we -# need to reimplement inspect.getmembers. GObject introspection doesn't -# play nice with it. -def getmembers(obj, check): - members = [] - for k in dir(obj): - try: - attr = getattr(obj, k) - except: - continue - if check(attr): - members.append((k, attr)) - members.sort() - return members - - -def dict_from_callback_obj(callback_obj): - '''a dictionary interface to callback_obj''' - methods = getmembers(callback_obj, inspect.ismethod) - - aliased_methods = [x[1] for x in methods if hasattr(x[1], 'aliases')] - - # a method may have several aliases - #~ @alias('on_btn_foo_clicked') - #~ @alias('on_tool_foo_activate') - #~ on_menu_foo_activate(): - #~ pass - alias_groups = [(x.aliases, x) for x in aliased_methods] - - aliases = [] - for item in alias_groups: - for alias in item[0]: - aliases.append((alias, item[1])) - - dict_methods = dict(methods) - dict_aliases = dict(aliases) - - results = {} - results.update(dict_methods) - results.update(dict_aliases) - - return results - - -def auto_connect_by_name(callback_obj, builder): - '''finds handlers like on__ and connects them - - i.e. find widget,signal pair in builder and call - widget.connect(signal, on__)''' - - callback_handler_dict = dict_from_callback_obj(callback_obj) - - for item in builder.widgets.items(): - (widget_name, widget) = item - signal_ids = [] - try: - widget_type = type(widget) - while widget_type: - signal_ids.extend(GObject.signal_list_ids(widget_type)) - widget_type = GObject.type_parent(widget_type) - except RuntimeError: # pylint wants a specific error - pass - signal_names = [GObject.signal_name(sid) for sid in signal_ids] - - # Now, automatically find any the user didn't specify in glade - for sig in signal_names: - # using convention suggested by glade - sig = sig.replace("-", "_") - handler_names = ["on_%s_%s" % (widget_name, sig)] - - # Using the convention that the top level window is not - # specified in the handler name. That is use - # on_destroy() instead of on_windowname_destroy() - if widget is callback_obj: - handler_names.append("on_%s" % sig) - - do_connect(item, sig, handler_names, - callback_handler_dict, builder.connections) - - log_unconnected_functions(callback_handler_dict, builder.connections) - - -def do_connect(item, signal_name, handler_names, - callback_handler_dict, connections): - '''connect this signal to an unused handler''' - widget_name, widget = item - - for handler_name in handler_names: - target = handler_name in callback_handler_dict.keys() - connection = (widget_name, signal_name, handler_name) - duplicate = connection in connections - if target and not duplicate: - widget.connect(signal_name, callback_handler_dict[handler_name]) - connections.append(connection) - - logger.debug("connect builder by name '%s','%s', '%s'", - widget_name, signal_name, handler_name) - - -def log_unconnected_functions(callback_handler_dict, connections): - '''log functions like on_* that we could not connect''' - - connected_functions = [x[2] for x in connections] - - handler_names = callback_handler_dict.keys() - unconnected = [x for x in handler_names if x.startswith('on_')] - - for handler_name in connected_functions: - try: - unconnected.remove(handler_name) - except ValueError: - pass - - for handler_name in unconnected: - logger.debug("Not connected to builder '%s'", handler_name) diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/CameraDialog.py b/build/lib.linux-x86_64-2.7/mugshot_lib/CameraDialog.py deleted file mode 100644 index cf8aae3..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/CameraDialog.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -from gi.repository import Gtk # pylint: disable=E0611 -import logging -logger = logging.getLogger('mugshot_lib') - -from . helpers import get_builder, show_uri, get_help_uri - -class CameraDialog(Gtk.Dialog): - __gtype_name__ = "CameraDialog" - - def __new__(cls): - """Special static method that's automatically called by Python when - constructing a new instance of this class. - - Returns a fully instantiated PreferencesDialog object. - """ - builder = get_builder('CameraMugshotDialog') - new_object = builder.get_object("camera_mugshot_dialog") - new_object.finish_initializing(builder) - return new_object - - def finish_initializing(self, builder): - """Called while initializing this instance in __new__ - - finish_initalizing should be called after parsing the ui definition - and creating a PreferencesDialog object with it in order to - finish initializing the start of the new PerferencesMugshotDialog - instance. - - Put your initialization code in here and leave __init__ undefined. - """ - - # Get a reference to the builder and set up the signals. - self.builder = builder - self.ui = builder.get_ui(self, True) - - # code for other initialization actions should be added here - - def on_btn_close_clicked(self, widget, data=None): - self.destroy() - - def on_btn_help_clicked(self, widget, data=None): - show_uri(self, "ghelp:%s" % get_help_uri('preferences')) - diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/Window.py b/build/lib.linux-x86_64-2.7/mugshot_lib/Window.py deleted file mode 100644 index 6674951..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/Window.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -from gi.repository import Gio, Gtk # pylint: disable=E0611 -import logging -logger = logging.getLogger('mugshot_lib') - -from . helpers import get_builder, show_uri, get_help_uri - -# This class is meant to be subclassed by MugshotWindow. It provides -# common functions and some boilerplate. -class Window(Gtk.Window): - __gtype_name__ = "Window" - - # To construct a new instance of this method, the following notable - # methods are called in this order: - # __new__(cls) - # __init__(self) - # finish_initializing(self, builder) - # __init__(self) - # - # For this reason, it's recommended you leave __init__ empty and put - # your initialization code in finish_initializing - - def __new__(cls): - """Special static method that's automatically called by Python when - constructing a new instance of this class. - - Returns a fully instantiated BaseMugshotWindow object. - """ - builder = get_builder('MugshotWindow') - new_object = builder.get_object("mugshot_window") - new_object.finish_initializing(builder) - return new_object - - def finish_initializing(self, builder): - """Called while initializing this instance in __new__ - - finish_initializing should be called after parsing the UI definition - and creating a MugshotWindow object with it in order to finish - initializing the start of the new MugshotWindow instance. - """ - # Get a reference to the builder and set up the signals. - self.builder = builder - self.ui = builder.get_ui(self, True) - self.CameraDialog = None # class - self.camera_dialog = None # instance - - self.settings = Gio.Settings("apps.mugshot") - self.settings.connect('changed', self.on_preferences_changed) - - def on_help_activate(self, widget, data=None): - show_uri(self, "ghelp:%s" % get_help_uri()) - - def on_menu_camera_activate(self, widget, data=None): - """Display the camera window for mugshot.""" - if self.camera_dialog is not None: - logger.debug('show existing camera_dialog') - self.camera_dialog.show() - elif self.CameraDialog is not None: - logger.debug('create new camera_dialog') - self.camera_dialog = self.CameraDialog() # pylint: disable=E1102 - #self.camera_dialog.connect('destroy', self.on_camera_dialog_destroyed) - self.camera_dialog.connect('apply', self.on_camera_dialog_apply) - self.camera_dialog.show() - - def on_destroy(self, widget, data=None): - """Called when the MugshotWindow is closed.""" - # Clean up code for saving application state should be added here. - Gtk.main_quit() - - def on_preferences_changed(self, settings, key, data=None): - logger.debug('preference changed: %s = %s' % (key, str(settings.get_value(key)))) - diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/__init__.py b/build/lib.linux-x86_64-2.7/mugshot_lib/__init__.py deleted file mode 100644 index bc3d9e7..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -'''facade - makes mugshot_lib package easy to refactor - -while keeping its api constant''' -from . helpers import set_up_logging -from . Window import Window -from . mugshotconfig import get_version - diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/helpers.py b/build/lib.linux-x86_64-2.7/mugshot_lib/helpers.py deleted file mode 100644 index 15ca93f..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/helpers.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -"""Helpers for an Ubuntu application.""" -import logging -import os - -from . mugshotconfig import get_data_file -from . Builder import Builder - -from locale import gettext as _ - -def get_builder(builder_file_name): - """Return a fully-instantiated Gtk.Builder instance from specified ui - file - - :param builder_file_name: The name of the builder file, without extension. - Assumed to be in the 'ui' directory under the data path. - """ - # Look for the ui file that describes the user interface. - ui_filename = get_data_file('ui', '%s.ui' % (builder_file_name,)) - if not os.path.exists(ui_filename): - ui_filename = None - - builder = Builder() - builder.set_translation_domain('mugshot') - builder.add_from_file(ui_filename) - return builder - - -# Owais Lone : To get quick access to icons and stuff. -def get_media_file(media_file_name): - media_filename = get_data_file('media', '%s' % (media_file_name,)) - if not os.path.exists(media_filename): - media_filename = None - - return "file:///"+media_filename - -class NullHandler(logging.Handler): - def emit(self, record): - pass - -def set_up_logging(opts): - # add a handler to prevent basicConfig - root = logging.getLogger() - null_handler = NullHandler() - root.addHandler(null_handler) - - formatter = logging.Formatter("%(levelname)s:%(name)s: %(funcName)s() '%(message)s'") - - logger = logging.getLogger('mugshot') - logger_sh = logging.StreamHandler() - logger_sh.setFormatter(formatter) - logger.addHandler(logger_sh) - - lib_logger = logging.getLogger('mugshot_lib') - lib_logger_sh = logging.StreamHandler() - lib_logger_sh.setFormatter(formatter) - lib_logger.addHandler(lib_logger_sh) - - # Set the logging level to show debug messages. - if opts.verbose: - logger.setLevel(logging.DEBUG) - logger.debug('logging enabled') - if opts.verbose > 1: - lib_logger.setLevel(logging.DEBUG) - -def get_help_uri(page=None): - # help_uri from source tree - default language - here = os.path.dirname(__file__) - help_uri = os.path.abspath(os.path.join(here, '..', 'help', 'C')) - - if not os.path.exists(help_uri): - # installed so use gnome help tree - user's language - help_uri = 'mugshot' - - # unspecified page is the index.page - if page is not None: - help_uri = '%s#%s' % (help_uri, page) - - return help_uri - -def show_uri(parent, link): - from gi.repository import Gtk # pylint: disable=E0611 - screen = parent.get_screen() - Gtk.show_uri(screen, link, Gtk.get_current_event_time()) - -def alias(alternative_function_name): - '''see http://www.drdobbs.com/web-development/184406073#l9''' - def decorator(function): - '''attach alternative_function_name(s) to function''' - if not hasattr(function, 'aliases'): - function.aliases = [] - function.aliases.append(alternative_function_name) - return function - return decorator diff --git a/build/lib.linux-x86_64-2.7/mugshot_lib/mugshotconfig.py b/build/lib.linux-x86_64-2.7/mugshot_lib/mugshotconfig.py deleted file mode 100644 index 7551994..0000000 --- a/build/lib.linux-x86_64-2.7/mugshot_lib/mugshotconfig.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -__all__ = [ - 'project_path_not_found', - 'get_data_file', - 'get_data_path', - ] - -# Where your project will look for your data (for instance, images and ui -# files). By default, this is ../data, relative your trunk layout -__mugshot_data_directory__ = '../data/' -__license__ = 'GPL-3' -__version__ = '0.1' - -import os - -from locale import gettext as _ - -class project_path_not_found(Exception): - """Raised when we can't find the project directory.""" - - -def get_data_file(*path_segments): - """Get the full path to a data file. - - Returns the path to a file underneath the data directory (as defined by - `get_data_path`). Equivalent to os.path.join(get_data_path(), - *path_segments). - """ - return os.path.join(get_data_path(), *path_segments) - - -def get_data_path(): - """Retrieve mugshot data path - - This path is by default /../data/ in trunk - and /usr/share/mugshot in an installed version but this path - is specified at installation time. - """ - - # Get pathname absolute or relative. - path = os.path.join( - os.path.dirname(__file__), __mugshot_data_directory__) - - abs_data_path = os.path.abspath(path) - if not os.path.exists(abs_data_path): - raise project_path_not_found - - return abs_data_path - - -def get_version(): - return __version__ diff --git a/build/scripts-2.7/mugshot b/build/scripts-2.7/mugshot deleted file mode 100755 index 4396fb9..0000000 --- a/build/scripts-2.7/mugshot +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -### DO NOT EDIT THIS FILE ### - -import sys -import os - -import locale -locale.textdomain('mugshot') - -# Add project root directory (enable symlink and trunk execution) -PROJECT_ROOT_DIRECTORY = os.path.abspath( - os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0])))) - -python_path = [] -if os.path.abspath(__file__).startswith('/opt'): - locale.bindtextdomain('mugshot', '/opt/extras.ubuntu.com/mugshot/share/locale') - syspath = sys.path[:] # copy to avoid infinite loop in pending objects - for path in syspath: - opt_path = path.replace('/usr', '/opt/extras.ubuntu.com/mugshot') - python_path.insert(0, opt_path) - sys.path.insert(0, opt_path) - os.putenv("XDG_DATA_DIRS", "%s:%s" % ("/opt/extras.ubuntu.com/mugshot/share/", os.getenv("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/"))) -if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'mugshot')) - and PROJECT_ROOT_DIRECTORY not in sys.path): - python_path.insert(0, PROJECT_ROOT_DIRECTORY) - sys.path.insert(0, PROJECT_ROOT_DIRECTORY) -if python_path: - os.putenv('PYTHONPATH', "%s:%s" % (os.getenv('PYTHONPATH', ''), ':'.join(python_path))) # for subprocesses - -import mugshot -mugshot.main() diff --git a/build/share/applications/mugshot.desktop b/build/share/applications/mugshot.desktop deleted file mode 100644 index d51a0ec..0000000 --- a/build/share/applications/mugshot.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=About Me -Comment=Configure your profile image and contact details -Categories=XFCE;GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-PersonalSettings;DesktopSettings;X-XFCE; -Exec=mugshot -Icon=mugshot -Terminal=false -Type=Application diff --git a/debian/changelog b/debian/changelog index 2991d2b..069b5da 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,41 +1,3 @@ -mugshot (13.07ubuntu1) UNRELEASED; urgency=low - - * Fix setup.py, update debian/control - * Add translations - * Update messages - * Added camera error logging for failed init - * Do not show stock browser if no faces directory. Show error message - if camera fails to init. - * Small fixes and lots of comments - * Remove temp file when exiting, show camera option only if camera is - installed - * Introduction of working camera code. - * Initial camera, inspired by Rick Spencer's quidgets. - * Added mugshot.svg by Simon Steinbeiß - * Use old username to always work. - * Creating ubuntu package - * More debug, fix for libreoffice confirmation - * Update desktop file and version number - * Remove about dialog, connect the help button. - * Improved usability and additional cleanup. - * Add prompts for updating Pidgin/LibreOffice - * Discard preferences dialog - * Add COPYING - * Store additional entries in dconf - * Add number filter and libreoffice settings. - * Set pidgin profile image when changing image. - * Improve default widgets, further cleanup - * Initial code cleanup and bug fixes. - * Initial commit with functionality. - - -- Sean Davis Wed, 17 Jul 2013 12:53:22 -0400 - -mugshot (13.07) raring; urgency=low - - * Fedora fixes for LibreOffice and chfn - - -- Sean Davis Wed, 17 Jul 2013 12:53:22 -0400 - mugshot (0.1) raring; urgency=low * Initial release. diff --git a/debian/control b/debian/control index e77b3ef..0cdb3f0 100644 --- a/debian/control +++ b/debian/control @@ -23,5 +23,10 @@ Depends: ${misc:Depends}, yelp Suggests: gstreamer1.0-plugins-good -Description: UNKNOWN - UNKNOWN +Description: a lightweight user-configuration application + Mugshot allows you to easily update personal user details. This includes: + . + Linux profile image: ~/.face + User details stored in /etc/passwd (used by finger) + Pidgin buddy icon + LibreOffice user details diff --git a/tests/test_example.py b/tests/test_example.py deleted file mode 100644 index d4efca3..0000000 --- a/tests/test_example.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -import sys -import os.path -import unittest -sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), ".."))) - -#from mugshot import AboutMugshotDialog - -class TestExample(unittest.TestCase): - def setUp(self): - pass - # Keeping the below items for reference later. - #self.AboutMugshotDialog_members = [ - #'AboutDialog', 'AboutMugshotDialog', 'gettext', 'logger', 'logging'] - - #def test_AboutMugshotDialog_members(self): - # all_members = dir(AboutMugshotDialog) - # public_members = [x for x in all_members if not x.startswith('_')] - # public_members.sort() - # self.assertEqual(self.AboutMugshotDialog_members, public_members) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_lint.py b/tests/test_lint.py deleted file mode 100644 index 1d4859b..0000000 --- a/tests/test_lint.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/python -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- -### BEGIN LICENSE -# Copyright (C) 2013 Sean Davis -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -### END LICENSE - -import unittest -import subprocess - -class TestPylint(unittest.TestCase): - def test_project_errors_only(self): - '''run pylint in error only mode - - your code may well work even with pylint errors - but have some unusual code''' - return_code = subprocess.call(["pylint", '-E', 'mugshot']) - # not needed because nosetests displays pylint console output - #self.assertEqual(return_code, 0) - - # un-comment the following for loads of diagnostics - #~ def test_project_full_report(self): - #~ '''Only for the brave -#~ - #~ you will have to make judgement calls about your code standards - #~ that differ from the norm''' - #~ return_code = subprocess.call(["pylint", 'mugshot']) - -if __name__ == '__main__': - 'you will get better results with nosetests' - unittest.main()