[gnome-games/sudoku-tube] Popup dialog after the tube offer is out



commit fad7e04231c3a1d6389bf469b5ccf5370e882f56
Author: Zhang Sen <zh jesse gmail com>
Date:   Wed Aug 5 10:11:59 2009 +0800

    Popup dialog after the tube offer is out
    
    And let the user be able to cancel the offer;
    And tell the user if the offer is failed

 gnome-sudoku/src/lib/main.py         |   49 ++++++++++++++++--
 gnome-sudoku/src/lib/tp_tube.py      |   88 +++++++++++++++++++++++----------
 gnome-sudoku/src/lib/tube_handler.py |    6 +--
 3 files changed, 105 insertions(+), 38 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index a86393b..4ad61fe 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -72,8 +72,7 @@ class UI (gconf_wrapper.GConfWrapper):
         self.setup_gui()
 
         self.tube_handler = tube_handler.TubeHandler(self._tube_service,
-                tube_received_cb=self._tube_received_cb,
-                tube_closed_cb=self._tube_closed_cb)
+                tube_received_cb=self._tube_received_cb)
 
         self.timer = timer.ActiveTimer(self.w)
         self.won = False
@@ -412,16 +411,50 @@ class UI (gconf_wrapper.GConfWrapper):
             conn, handle, contact = choice
             logger.info("selected: %s\n  connection: %s\n  handle: %d" % (
                     contact.alias, conn.service_name, handle))
-            tp_tube.offer_tube(conn, handle, self._tube_service,
-                    tube_offered_cb=self._tube_offered_cb,
-                    tube_closed_cb=self._tube_closed_cb)
+            self._tube_offer = tp_tube.TubeOffer(conn, handle,
+                    self._tube_service)
+
+            _connecting_label = gtk.Label(_("Connecting..."))
+            self._wait_dialog = gtk.Dialog("Sending request...",
+                    self.w,
+                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+                    (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
+            _connecting_label.show()
+            self._wait_dialog.vbox.pack_start(_connecting_label)
+            self._wait_dialog.connect("response", self._wait_dialog_response_cb)
+
+            self._tube_offer.connect("offer-succeeded", self._tube_offered_cb)
+            self._tube_offer.connect("offer-failed", self._offer_fail_cb)
+
+            self._tube_offer.execute()
+            self._wait_dialog.run()
         else:
             logger.info("None selected")
 
+    def _wait_dialog_response_cb(self, dialog, response_id):
+        if response_id in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT):
+            self._tube_offer.cancel()
+        # else don't need to do anything
+        self._wait_dialog.destroy()
+
+    def _offer_fail_cb(self, offer):
+        # clear label and button
+        vbox = self._wait_dialog.vbox
+        vbox.remove(vbox.get_children()[0])
+        action = self._wait_dialog.action_area
+        action.remove(action.get_children()[0])
+
+        fail_label = gtk.Label(_("failed"))
+        fail_label.show()
+        self._wait_dialog.vbox.pack_start(fail_label)
+        self._wait_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
+
     def _tube_received_cb(self, bus, tube):
         """Called when we receive a tube"""
         self._bus = bus
         self._tube = tube
+        self._tube[tp_tube.CHANNEL_INTERFACE].connect_to_signal(
+                'Closed', self._tube_closed_cb)
         virgin_puzzle = bus.get_object(object_path=self._virgin_puzzle_obj_path)
         virgin_puzzle.get_puzzle(
                 dbus_interface="org.gnome.Sudoku.view",
@@ -440,10 +473,13 @@ class UI (gconf_wrapper.GConfWrapper):
     def _error_cb(self, exception):
         print 'error', exception
 
-    def _tube_offered_cb(self, bus, tube):
+    def _tube_offered_cb(self, offer, bus, tube):
         """Called when the peer accepts our tube"""
+        self._wait_dialog.destroy()
         self._close_current_game()
         self._tube = tube
+        self._tube[tp_tube.CHANNEL_INTERFACE].connect_to_signal(
+                'Closed', self._tube_closed_cb)
         # use this flag to ensure we are in a new game, and self._puzzle is a
         # string. FIXME
         self._auto_open_game(check_saved=False)
@@ -507,6 +543,7 @@ class UI (gconf_wrapper.GConfWrapper):
     def do_stop (self):
         self.stop_dancer()
         self._main_model = None
+        self._notes_model = None
         self._main_grid_vew.reset()
         self._tracker_ui.reset()
         self._history_manager.clear()
diff --git a/gnome-sudoku/src/lib/tp_tube.py b/gnome-sudoku/src/lib/tp_tube.py
index 557008a..aeaf6c9 100644
--- a/gnome-sudoku/src/lib/tp_tube.py
+++ b/gnome-sudoku/src/lib/tp_tube.py
@@ -3,6 +3,7 @@
 import logging
 
 import dbus
+import gobject
 from telepathy.client.channel import Channel
 from telepathy.interfaces import (
         CHANNEL_INTERFACE,
@@ -19,39 +20,72 @@ import telepathy.errors
 logger = logging.getLogger("main.tp_tube")
 
 
-def offer_tube(conn, handle, tube_service, tube_offered_cb, tube_closed_cb):
-    def tube_state_changed_cb(state):
+class TubeOffer(gobject.GObject):
+
+    __gsignals__ = {
+            "offer-succeeded": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
+                (object, object)),
+            "offer-failed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+            }
+
+    def __init__(self, conn, handle, tube_service):
+        logger.debug("create an offer")
+        gobject.GObject.__init__(self)
+        self._tube_state = None
+        self._address = None
+        self._chan = None
+        self._closed_signal = None
+
+        self._conn = conn
+        self._handle = handle
+        self._tube_service = tube_service
+
+    def _tube_state_changed_cb(self, state):
+        self._tube_state = state
         if state == TUBE_CHANNEL_STATE_OPEN:
             logger.info("Tube state changed ->open")
-            tube_conn = dbus.connection.Connection(address)
-            tube_offered_cb(bus=tube_conn, tube=chan)
+            tube_conn = dbus.connection.Connection(self._address)
+            self.emit("offer-succeeded", tube_conn, self._chan)
         elif state == TUBE_CHANNEL_STATE_REMOTE_PENDING:
             logger.info("Tube state changed ->remote-pending")
         else:
             logger.info("Tube state changed ->%s" % state)
 
-    logger.debug("creating tube channel")
-    request = {
-        CHANNEL_INTERFACE + ".ChannelType": CHANNEL_TYPE_DBUS_TUBE,
-        CHANNEL_INTERFACE + ".TargetHandleType": HANDLE_TYPE_CONTACT,
-        CHANNEL_INTERFACE + ".TargetHandle": handle,
-        CHANNEL_TYPE_DBUS_TUBE + ".ServiceName": tube_service}
-    try:
-        path, props = conn[CONNECTION_INTERFACE_REQUESTS].CreateChannel(request)
-    except dbus.exceptions.DBusException as excep:
-        error_busname = telepathy.errors.NotImplemented().get_dbus_name()
-        if excep.get_dbus_name() == error_busname:
-            logger.error("REQUESTS interface not implemented on %s" %
-                    conn.service_name)
-            return
-        else:
-            raise
+    def _tube_closed_cb(self):
+        logger.info("Tube closed")
+        if self._tube_state == TUBE_CHANNEL_STATE_REMOTE_PENDING:
+            # if tube is already open, it's not _offer_ failed (it's other
+            # problems)
+            self.emit("offer-failed")
+
+    def cancel(self):
+        if self._chan:
+            self._closed_signal.remove()
+            self._chan[CHANNEL_INTERFACE].Close()
+
+    def execute(self):
+        request = {
+            CHANNEL_INTERFACE + ".ChannelType": CHANNEL_TYPE_DBUS_TUBE,
+            CHANNEL_INTERFACE + ".TargetHandleType": HANDLE_TYPE_CONTACT,
+            CHANNEL_INTERFACE + ".TargetHandle": self._handle,
+            CHANNEL_TYPE_DBUS_TUBE + ".ServiceName": self._tube_service}
+        try:
+            path, props = self._conn[CONNECTION_INTERFACE_REQUESTS].CreateChannel(request)
+        except dbus.exceptions.DBusException as excep:
+            error_busname = telepathy.errors.NotImplemented().get_dbus_name()
+            if excep.get_dbus_name() == error_busname:
+                logger.error("REQUESTS interface not implemented on %s" %
+                        self._conn.service_name)
+                return
+            else:
+                raise
 
-    chan = Channel(conn.service_name, path)
-    chan[CHANNEL_INTERFACE_TUBE].connect_to_signal('TubeChannelStateChanged',
-            tube_state_changed_cb)
-    chan[CHANNEL_INTERFACE].connect_to_signal('Closed', tube_closed_cb)
+        self._chan = Channel(self._conn.service_name, path)
+        self._chan[CHANNEL_INTERFACE_TUBE].connect_to_signal(
+                'TubeChannelStateChanged', self._tube_state_changed_cb)
+        self._closed_signal = self._chan[CHANNEL_INTERFACE].connect_to_signal(
+                'Closed', self._tube_closed_cb)
 
-    logger.debug("offering tube")
-    address = chan[CHANNEL_TYPE_DBUS_TUBE].Offer({},
-            SOCKET_ACCESS_CONTROL_CREDENTIALS)
+        logger.debug("offering tube")
+        self._address = self._chan[CHANNEL_TYPE_DBUS_TUBE].Offer({},
+                SOCKET_ACCESS_CONTROL_CREDENTIALS)
diff --git a/gnome-sudoku/src/lib/tube_handler.py b/gnome-sudoku/src/lib/tube_handler.py
index e39996d..e39b5eb 100644
--- a/gnome-sudoku/src/lib/tube_handler.py
+++ b/gnome-sudoku/src/lib/tube_handler.py
@@ -12,7 +12,6 @@ from telepathy.constants import (
         TUBE_STATE_OPEN,
         SOCKET_ACCESS_CONTROL_CREDENTIALS)
 from telepathy.interfaces import (
-        CHANNEL_INTERFACE,
         CHANNEL_INTERFACE_TUBE,
         CHANNEL_TYPE_DBUS_TUBE)
 
@@ -32,10 +31,9 @@ def _build_object_path(bus_name):
 class TubeHandler(dbus.service.Object):
     """Listen to coming tube and emit a signal for it"""
 
-    def __init__(self, service_name, tube_received_cb, tube_closed_cb):
+    def __init__(self, service_name, tube_received_cb):
         logger.info("creating TubeHandler")
         self._tube_received_cb = tube_received_cb
-        self._tube_closed_cb = tube_closed_cb
 
         bus_name = _build_bus_name(service_name)
         obj_path = _build_object_path(bus_name)
@@ -59,8 +57,6 @@ class TubeHandler(dbus.service.Object):
                 SOCKET_ACCESS_CONTROL_CREDENTIALS)
         self._tube_chan[CHANNEL_INTERFACE_TUBE].connect_to_signal(
                 'TubeChannelStateChanged', self._tube_state_changed_cb)
-        self._tube_chan[CHANNEL_INTERFACE].connect_to_signal(
-                'Closed', self._tube_closed_cb)
 
     def _tube_state_changed_cb(self, state):
         if state == TUBE_STATE_OPEN:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]