OSG_Mugshot_fork/mugshot/MugshotWindow.py

271 lines
10 KiB
Python
Raw Normal View History

2013-07-12 17:56:24 +00:00
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
2013-07-13 15:09:49 +00:00
# Copyright (C) 2013 Sean Davis <smd.seandavis@gmail.com>
# 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 <http://www.gnu.org/licenses/>.
2013-07-12 17:56:24 +00:00
### END LICENSE
from locale import gettext as _
2013-07-13 15:09:49 +00:00
import os
import pexpect
import shutil
import subprocess
from gi.repository import Gtk, Gdk, GdkPixbuf # pylint: disable=E0611
2013-07-12 17:56:24 +00:00
import logging
logger = logging.getLogger('mugshot')
from mugshot_lib import Window
from mugshot.AboutMugshotDialog import AboutMugshotDialog
from mugshot.PreferencesMugshotDialog import PreferencesMugshotDialog
2013-07-13 15:09:49 +00:00
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 detach_cb(menu, widget):
'''Detach a widget from its attached widget.'''
menu.detach()
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()
x = window_pos[0] + allocation.x
y = window_pos[1] + allocation.y + allocation.height
return (x, y, True)
2013-07-12 17:56:24 +00:00
# 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.AboutDialog = AboutMugshotDialog
self.PreferencesDialog = PreferencesMugshotDialog
2013-07-13 15:09:49 +00:00
self.updated_image = None
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.user_image = builder.get_object('user_image')
self.image_button = builder.get_object('image_button')
self.image_menu = builder.get_object('image_menu')
self.image_menu.attach_to_widget(self.image_button, detach_cb)
self.iconview = builder.get_object('stock_iconview')
self.stock_browser = builder.get_object('stock_browser')
face = os.path.expanduser('~/.face')
if os.path.isfile(face):
self.set_user_image(face)
else:
self.set_user_image(None)
2013-07-12 17:56:24 +00:00
# Code for other initialization actions should be added here.
2013-07-13 15:09:49 +00:00
self.first_name, self.last_name, self.initials, self.office_phone, \
self.home_phone = self.get_user_details()
if self.home_phone == 'none': self.home_phone = ''
if self.office_phone == 'none': self.office_phone = ''
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)
def on_image_from_browse_activate(self, widget):
chooser = Gtk.FileChooserDialog(_("Select an image"), self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))
image_filter = Gtk.FileFilter()
image_filter.set_name('Images')
image_filter.add_mime_type('image/*')
chooser.add_filter(image_filter)
response = chooser.run()
if response == Gtk.ResponseType.OK:
self.updated_image = chooser.get_filename()
self.set_user_image(self.updated_image)
chooser.hide()
def on_stock_browser_delete_event(self, widget, event):
widget.hide()
return True
def on_image_from_stock_activate(self, widget):
self.load_stock_browser()
self.stock_browser.show_all()
def on_image_button_clicked(self, widget):
"""When the menu button is clicked, display the appmenu."""
if widget.get_active():
self.image_menu.popup(None, None, menu_position,
self.image_menu, 3,
Gtk.get_current_event_time())
def on_cancel_button_clicked(self, widget):
self.destroy()
def on_image_menu_hide(self, widget):
self.image_button.set_active(False)
def get_finger_details_updated(self):
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():
return True
return False
def on_apply_button_clicked(self, widget):
if self.get_finger_details_updated():
self.save_finger()
if self.updated_image:
self.save_image()
def set_user_image(self, filename=None):
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 load_stock_browser(self):
model = self.iconview.get_model()
if len(model) != 0:
return
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_cancel_clicked(self, widget):
self.stock_browser.hide()
def on_stock_ok_clicked(self, widget):
selected_items = self.iconview.get_selected_items()
if len(selected_items) != 0:
path = int(selected_items[0].to_string())
filename = self.iconview.get_model()[path][0]
self.set_user_image(filename)
self.updated_image = filename
self.stock_browser.hide()
def get_user_details(self):
# Get user finger details from /etc/passwd
username = os.getenv('USER')
for line in open('/etc/passwd', 'r'):
if line.startswith(username + ':'):
details = line.split(':')[4]
name, office, office_phone, home_phone = details.split(',', 3)
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]
return first_name, last_name, initials, office_phone, home_phone
def get_password(self):
# Show a password dialog to get 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:
pw = entry.get_text()
entry.set_text('')
return pw
return None
def get_entry_value(self, entry_widget):
# Get the text from an entry, changing none to ''
value = entry_widget.get_text().strip()
if value.lower() == 'none':
value = ''
return value
def save_finger(self):
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 = self.get_entry_value(self.first_name_entry)
last_name = self.get_entry_value(self.last_name_entry)
full_name = "%s %s" % (first_name, last_name)
full_name = full_name.strip()
office_phone = self.get_entry_value(self.office_phone_entry)
if office_phone == '':
office_phone = 'none'
home_phone = self.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.
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
pass
child.close()
return_codes.append(child.exitstatus)
child = pexpect.spawn('chfn')
child.expect('Password: ')
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)
child.close(True)
return_codes.append(child.exitstatus)
return return_codes
def save_image(self):
# Copy the updated image to .face
if not self.updated_image:
return False
face = os.path.expanduser('~/.face')
if os.path.isfile(face):
os.remove(face)
shutil.copyfile(self.updated_image, face)
self.updated_image = None
return True
2013-07-12 17:56:24 +00:00