Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/vnc.py
diff options
context:
space:
mode:
Diffstat (limited to 'vnc.py')
-rw-r--r--vnc.py307
1 files changed, 307 insertions, 0 deletions
diff --git a/vnc.py b/vnc.py
new file mode 100644
index 0000000..085777a
--- /dev/null
+++ b/vnc.py
@@ -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')