diff options
Diffstat (limited to 'vnc.py')
-rw-r--r-- | vnc.py | 307 |
1 files changed, 307 insertions, 0 deletions
@@ -0,0 +1,307 @@ +# Copyright (c) 2011, Fran Rogers +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import simplejson +import logging +from gettext import gettext as _ + +import gobject +import gtk +import gtkvnc +import hippo + +from sugar.graphics.entry import CanvasEntry +from sugar.graphics.icon import Icon +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.toolbarbox import ToolbarBox +from sugar.graphics.toolbarbox import ToolbarButton +from sugar.activity.widgets import ActivityToolbarButton +from sugar.activity.widgets import StopButton +from sugar.activity import activity +from sugar.graphics import style + +_BACKGROUND_COLOR = style.COLOR_WHITE + +MASKED_ENVIRONMENT = [ + 'DBUS_SESSION_BUS_ADDRESS', + 'PPID'] + +log = logging.getLogger('VNC') +log.setLevel(logging.DEBUG) +logging.basicConfig() + + +class VNCActivity(activity.Activity): + + def __init__(self, handle): + activity.Activity.__init__(self, handle) + + self.max_participants = 1 + + self.host = None + self.password = None + + toolbar_box = ToolbarBox() + + activity_button = ActivityToolbarButton(self) + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.page.keep.props.accelerator = '<Ctrl><Shift>S' + activity_button.show() + + view_toolbar = self._create_view_toolbar() + view_toolbar_button = ToolbarButton( + page=view_toolbar, + icon_name='toolbar-view') + view_toolbar.show() + toolbar_box.toolbar.insert(view_toolbar_button, -1) + view_toolbar_button.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + stop_button = StopButton(self) + stop_button.props.accelerator = '<Ctrl><Shift>Q' + toolbar_box.toolbar.insert(stop_button, -1) + stop_button.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show() + + if self.host == None: + self.show_connect_dialog() + + def _create_view_toolbar(self): + view_toolbar = gtk.Toolbar() + fullscreen_button = ToolButton('view-fullscreen') + fullscreen_button.set_tooltip(_("Fullscreen")) + fullscreen_button.props.accelerator = '<Alt>Return' + fullscreen_button.connect('clicked', self.__fullscreen_cb) + view_toolbar.insert(fullscreen_button, -1) + fullscreen_button.show() + return view_toolbar + + def __fullscreen_cb(self, button): + self.fullscreen() + + def __connect_clicked_cb(self, widget): + self.vnc_connect(widget.get_host()) + + def __password_cb(self, widget): + self.password = self._password_dialog.get_password() + self._vnc.set_credential(gtkvnc.CREDENTIAL_PASSWORD, self.password) + self.set_canvas(self._vnc) + + def __vnc_connected_cb(self, widget): + pass # TODO + + def __vnc_initialized_cb(self, widget): + pass # TODO + + def __vnc_disconnected_cb(self, widget): + pass # TODO + + def __vnc_auth_credential(self, widget, creds): + if creds == [gtkvnc.CREDENTIAL_PASSWORD]: + if self.password != None: + self._vnc.set_credential(gtkvnc.CREDENTIAL_PASSWORD, + self.password) + else: + self._password_dialog = VNCActivityPasswordDialog() + self._password_dialog.connect('activated', self.__password_cb) + self._password_dialog.show() + self.set_canvas(self._password_dialog) + + def __vnc_auth_failure(self, widget): + pass # TODO + + def __vnc_auth_unsupported(self, widget): + pass # TODO + + def vnc_connect(self, host, password=None): + self.host = host + self.password = password + + if ':' in host: + colon = host.rindex(':') + hostname = host[:colon] + display = 0 + try: + display = int(host[colon+1:]) + except: + return # TODO + else: + hostname = host + display = 0 + + self._vnc = gtkvnc.Display() + self._vnc.connect('vnc-connected', self.__vnc_connected_cb) + self._vnc.connect('vnc-initialized', self.__vnc_initialized_cb) + self._vnc.connect('vnc-disconnected', self.__vnc_disconnected_cb) + self._vnc.connect('vnc-auth-credential', self.__vnc_auth_credential) + self._vnc.connect('vnc-auth-failure', self.__vnc_auth_failure) + self._vnc.connect('vnc-auth-unsupported', self.__vnc_auth_unsupported) + self._vnc.show() + self.set_canvas(self._vnc) + + self._vnc.open_host(hostname, str(5900 + display)) + + def show_connect_dialog(self): + self._vnc = None + self._connect_dialog = VNCActivityConnectDialog() + self._connect_dialog.connect('activated', self.__connect_clicked_cb) + self._connect_dialog.show() + self.set_canvas(self._connect_dialog) + + def read_file(self, file_path): + if self.metadata['mime_type'] != 'text/plain': + return + + fd = open(file_path, 'r') + text = fd.read() + data = simplejson.loads(text) + fd.close() + + data_file = file_path + + if data['host'] != None: + if data['password'] != None: + self.vnc_connect(data['host'], data['password']) + else: + self.vnc_connect(data['host']) + + def write_file(self, file_path): + if not self.metadata['mime_type']: + self.metadata['mime_type'] = 'text/plain' + + data = {} + data['host'] = self.host + data['password'] = self.password + + fd = open(file_path, 'w') + text = simplejson.dumps(data) + fd.write(text) + fd.close() + + +class VNCActivityConnectDialog(hippo.Canvas): + __gsignals__ = { + 'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (),) + } + + def __init__(self): + hippo.Canvas.__init__(self) + self.connect('key-press-event', self.__key_press_cb) + + root_box = hippo.CanvasBox(padding=style.zoom(30), + background_color=_BACKGROUND_COLOR.get_int()) + + opts_box = hippo.CanvasBox(xalign=hippo.ALIGNMENT_CENTER, + background_color=_BACKGROUND_COLOR.get_int(), + spacing=style.DEFAULT_SPACING, + orientation=hippo.ORIENTATION_HORIZONTAL,) + label = hippo.CanvasText(text=_("Host:")) + opts_box.append(label) + host_canvas_entry = CanvasEntry(box_width=style.zoom(300)) + host_canvas_entry.set_background(_BACKGROUND_COLOR.get_html()) + self._host_entry = host_canvas_entry.props.widget + self._host_entry.set_max_length(45) + self._host_entry.connect('key-press-event', self.__key_press_cb) + opts_box.append(host_canvas_entry) + root_box.append(opts_box, hippo.PACK_EXPAND) + + button_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) + button_box.append(hippo.CanvasBox(), hippo.PACK_EXPAND) + self._connect_button = hippo.CanvasButton(text=_('Connect')) + self._connect_button.props.widget.set_image(Icon(icon_name='go-right')) + self._connect_button.connect('activated', self._connect_activated_cb) + button_box.append(self._connect_button) + root_box.append(button_box) + + self.set_root(root_box) + + def get_host(self): + return self._host_entry.get_text() + + def set_host(self, host): + self._host_entry.set_text(host) + + def __key_press_cb(self, widget, event): + if gtk.gdk.keyval_name(event.keyval) == "Return": + self.activate() + return True + + def _connect_activated_cb(self, item): + self.activate() + + def activate(self): + self.emit('activated') + + +class VNCActivityPasswordDialog(hippo.Canvas): + __gsignals__ = { + 'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (),) + } + + def __init__(self): + hippo.Canvas.__init__(self) + self.connect('key-press-event', self.__key_press_cb) + + root_box = hippo.CanvasBox(padding=style.zoom(30), + background_color=_BACKGROUND_COLOR.get_int()) + + opts_box = hippo.CanvasBox(xalign=hippo.ALIGNMENT_CENTER, + background_color=_BACKGROUND_COLOR.get_int(), + spacing=style.DEFAULT_SPACING, + orientation=hippo.ORIENTATION_HORIZONTAL,) + label = hippo.CanvasText(text=_("Password:")) + opts_box.append(label) + host_canvas_entry = CanvasEntry(box_width=style.zoom(300)) + host_canvas_entry.set_background(_BACKGROUND_COLOR.get_html()) + self._host_entry = host_canvas_entry.props.widget + self._host_entry.set_max_length(45) + self._host_entry.connect('key-press-event', self.__key_press_cb) + opts_box.append(host_canvas_entry) + root_box.append(opts_box, hippo.PACK_EXPAND) + + button_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) + button_box.append(hippo.CanvasBox(), hippo.PACK_EXPAND) + self._connect_button = hippo.CanvasButton(text=_('Continue')) + self._connect_button.props.widget.set_image(Icon(icon_name='go-right')) + self._connect_button.connect('activated', self._connect_activated_cb) + button_box.append(self._connect_button) + root_box.append(button_box) + + self.set_root(root_box) + + def get_password(self): + return self._host_entry.get_text() + + def set_password(self, host): + self._host_entry.set_text(host) + + def __key_press_cb(self, widget, event): + if gtk.gdk.keyval_name(event.keyval) == "Return": + self.activate() + return True + + def _connect_activated_cb(self, item): + self.activate() + + def activate(self): + self.emit('activated') |