Changeset f8809f6ead608ebf57654a28ca9e0bc748cb3ee6

Show
Ignore:
Timestamp:
11/09/09 10:59:45 (4 years ago)
Author:
Armin Burgmeier <armin@…>
git-author:
Armin Burgmeier <armin@arbur.net> / 2009-11-08T17:03:25Z+0100
Parents:
877d3231c6feab2ff51abd8a53b79bf1ea6c7ad6
Children:
74e640926423470402269ebe48f3082b89e6cba9
git-committer:
Armin Burgmeier <armin@arbur.net> / 2009-11-09T10:59:45Z+0100
Message:

Split BrowserCommands?

2009-11-08 Armin Burgmeier <armin@…>

  • code/commands/subscription-commands.hpp:
  • code/commands/subscription-commands.cpp: New class handling session subscriptions.
  • code/commands/synchronization-commands.hpp:
  • code/commands/synchronization-commands.cpp: New class handling session synchronization.
  • code/commands/user-join-commands.hpp:
  • code/commands/user-join-commands.cpp: New class handling user join.
  • code/commands/browser-commands.hpp:
  • code/commands/browser-commands.cpp: Removed the functionality that has been moved to the classes mentioned above.
  • code/commands/Makfile.am: Add the new files to the build.
  • code/window.hpp:
  • code/window.cpp: Instantiante the new classes.
Files:
6 added
6 modified

Legend:

Unmodified
Added
Removed
  • ChangeLog

    r877d323 rf8809f6  
     12009-11-08  Armin Burgmeier  <armin@arbur.net> 
     2 
     3        * code/commands/subscription-commands.hpp: 
     4        * code/commands/subscription-commands.cpp: New class handling session 
     5        subscriptions. 
     6 
     7        * code/commands/synchronization-commands.hpp: 
     8        * code/commands/synchronization-commands.cpp: New class handling 
     9        session synchronization. 
     10 
     11        * code/commands/user-join-commands.hpp: 
     12        * code/commands/user-join-commands.cpp: New class handling user join. 
     13 
     14        * code/commands/browser-commands.hpp: 
     15        * code/commands/browser-commands.cpp: Removed the functionality that 
     16        has been moved to the classes mentioned above. 
     17 
     18        * code/commands/Makfile.am: Add the new files to the build. 
     19 
     20        * code/window.hpp: 
     21        * code/window.cpp: Instantiante the new classes. 
     22 
    1232009-11-08  Armin Burgmeier  <armin@arbur.net> 
    224 
  • code/commands/Makefile.am

    r1a96a2b rf8809f6  
    1111        folder-commands.cpp \ 
    1212        help-commands.cpp \ 
     13        subscription-commands.cpp \ 
     14        synchronization-commands.cpp \ 
     15        user-join-commands.cpp \ 
    1316        view-commands.cpp 
    1417 
     
    2124        folder-commands.hpp \ 
    2225        help-commands.hpp \ 
     26        subscription-commands.hpp \ 
     27        synchronization-commands.hpp \ 
     28        user-join-commands.hpp \ 
    2329        view-commands.hpp 
    2430 
  • code/commands/browser-commands.cpp

    r877d323 rf8809f6  
    1717 */ 
    1818 
    19 // TODO: Split this file into multiple smaller files, 
    20 // perhaps browser-commands.cpp (basically on_activate) 
    21 // synchronization-commands.cpp (basically on_subscribe_session) 
    22 // user-join-commands.cpp (basically join_user) 
    23  
    2419#include "commands/browser-commands.hpp" 
    2520#include "util/i18n.hpp" 
    2621 
    27 #include <libinftext/inf-text-user.h> 
    28 #include <libinfinity/common/inf-error.h> 
     22class Gobby::BrowserCommands::RequestInfo 
     23{ 
     24public: 
     25        RequestInfo(BrowserCommands& commands, InfcBrowser* browser, 
     26                    InfcNodeRequest* request, StatusBar& status_bar); 
     27        ~RequestInfo(); 
    2928 
    30 namespace 
    31 { 
    32         const char* GOBBY_BROWSER_COMMANDS_SESSION_PROXY = 
    33                 "GOBBY_BROWSER_COMMANDS_SESSION_PROXY"; 
    34         const char* GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY = 
    35                 "GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY"; 
    36  
    37         enum ErrorType { 
    38                 SYNC_ERROR, 
    39                 USER_JOIN_ERROR 
    40         }; 
    41  
    42         void set_error_text(Gobby::SessionView& view, 
    43                             const Glib::ustring& initial_text, 
    44                             ErrorType type) 
     29private: 
     30        static void on_failed_static(InfcNodeRequest* request, 
     31                                     const GError* error, gpointer user_data) 
    4532        { 
    46                 using namespace Gobby; 
    47                 Glib::ustring type_text; 
    48  
    49                 switch(type) 
    50                 { 
    51                 case SYNC_ERROR: 
    52                         // Document cannot be used if an error happened 
    53                         // during synchronization. 
    54                         type_text = _("This document cannot be used."); 
    55                         break; 
    56                 case USER_JOIN_ERROR: 
    57                         type_text = _("You can still watch others editing " 
    58                                       "the document, but you cannot edit " 
    59                                       "it yourself."); 
    60                         break; 
    61                 } 
    62  
    63                 const Glib::ustring info_text = 
    64                         _("If you have an idea what could have caused the " 
    65                           "problem, then you may attempt to solve it and " 
    66                           "try again (after having closed this document). " 
    67                           "Otherwise it is most likely a bug in the " 
    68                           "software. In that case, please file a bug report " 
    69                           "at http://gobby.0x539.de/trac/newticket and " 
    70                           "provide as much information as you can, including " 
    71                           "what you did when the problem occurred and how to " 
    72                           "reproduce the problem (if possible) so that we " 
    73                           "can fix the problem in a later version. " 
    74                           "Thank you."); 
    75  
    76                 view.set_info( 
    77                         initial_text + "\n\n" + type_text + "\n\n" + 
    78                         info_text, true); 
     33                static_cast<BrowserCommands*>(user_data)-> 
     34                        on_failed(request, error); 
    7935        } 
    8036 
    81         void retr_local_user_func(InfUser* user, gpointer user_data) 
     37        static void on_finished_static(InfcNodeRequest* request, 
     38                                       InfcBrowserIter* iter, 
     39                                       gpointer user_data) 
    8240        { 
    83                 (*static_cast<InfUser**>(user_data)) = user; 
     41                static_cast<BrowserCommands*>(user_data)-> 
     42                        on_finished(request); 
    8443        } 
     44 
     45        InfcNodeRequest* m_request; 
     46 
     47        StatusBar& m_status_bar; 
     48        StatusBar::MessageHandle m_handle; 
     49 
     50        gulong m_failed_handler; 
     51        gulong m_finished_handler; 
     52}; 
     53 
     54Gobby::BrowserCommands::RequestInfo::RequestInfo(BrowserCommands& commands, 
     55                                                 InfcBrowser* browser, 
     56                                                 InfcNodeRequest* request, 
     57                                                 StatusBar& status_bar): 
     58        m_request(request), m_status_bar(status_bar) 
     59{ 
     60        g_object_ref(request); 
     61 
     62        InfcBrowserIter iter; 
     63        gboolean have_iter = 
     64                infc_browser_iter_from_node_request(browser, request, &iter); 
     65        g_assert(have_iter); 
     66 
     67        m_handle = m_status_bar.add_info_message( 
     68                Glib::ustring::compose(_("Subscribing to %1..."), 
     69                        Glib::ustring( 
     70                                infc_browser_iter_get_name(browser, &iter)))); 
     71 
     72        m_failed_handler = g_signal_connect(request, "failed", 
     73                         G_CALLBACK(on_failed_static), &commands); 
     74        m_finished_handler = g_signal_connect(request, "finished", 
     75                         G_CALLBACK(on_finished_static), &commands); 
    8576} 
    8677 
    87 struct Gobby::BrowserCommands::BrowserNode 
     78Gobby::BrowserCommands::RequestInfo::~RequestInfo() 
    8879{ 
    89         BrowserNode(BrowserCommands& commands, InfcBrowser* browser): 
    90                 m_browser(browser) 
    91         { 
    92                 g_object_ref(m_browser); 
     80        m_status_bar.remove_message(m_handle); 
    9381 
    94                 m_subscribe_session_handler = g_signal_connect( 
    95                         G_OBJECT(browser), "subscribe-session", 
    96                         G_CALLBACK(&on_subscribe_session_static), &commands); 
    97         } 
     82        g_signal_handler_disconnect(m_request, m_failed_handler); 
     83        g_signal_handler_disconnect(m_request, m_finished_handler); 
    9884 
    99         ~BrowserNode() 
    100         { 
    101                 g_signal_handler_disconnect(G_OBJECT(m_browser), 
    102                                             m_subscribe_session_handler); 
    103  
    104                 g_object_unref(m_browser); 
    105         } 
    106  
    107         InfcBrowser* m_browser; 
    108         gulong m_subscribe_session_handler; 
    109 }; 
    110  
    111 // These need default and copy constructors to satisfy the map properties. 
    112 // However, we only do copy them as long as they are unset. 
    113 Gobby::BrowserCommands::RequestNode::RequestNode(): 
    114         commands(NULL) {} 
    115  
    116 Gobby::BrowserCommands::RequestNode::RequestNode(const RequestNode& node): 
    117         commands(node.commands) 
    118 { 
    119         g_assert(commands == NULL); 
     85        g_object_unref(m_request); 
    12086} 
    12187 
    122 Gobby::BrowserCommands::RequestNode::~RequestNode() 
     88Gobby::BrowserCommands::BrowserCommands(Browser& browser, 
     89                                        Folder& folder, 
     90                                        StatusBar& status_bar): 
     91        m_browser(browser), m_folder(folder), m_status_bar(status_bar) 
    12392{ 
    124         if(commands != NULL) 
    125         { 
    126                 commands->m_status_bar.remove_message(handle); 
    127         } 
    128 } 
    129  
    130 Gobby::BrowserCommands::SessionNode::SessionNode(): 
    131         proxy(NULL) {} 
    132  
    133 Gobby::BrowserCommands::SessionNode::SessionNode(const SessionNode& node): 
    134         proxy(node.proxy), status(node.status) 
    135 { 
    136         g_assert(proxy == NULL); 
    137 } 
    138  
    139 Gobby::BrowserCommands::SessionNode::~SessionNode() 
    140 { 
    141         if(proxy != NULL) 
    142         { 
    143                 InfSession* session = infc_session_proxy_get_session(proxy); 
    144                 g_signal_handler_disconnect(proxy, notify_connection_id); 
    145                 g_signal_handler_disconnect(session, failed_id); 
    146                 g_signal_handler_disconnect(session, complete_before_id); 
    147                 g_signal_handler_disconnect(session, complete_after_id); 
    148                 g_signal_handler_disconnect(session, progress_id); 
    149                 g_signal_handler_disconnect(session, close_id); 
    150  
    151                 g_object_unref(proxy); 
    152         } 
    153 } 
    154  
    155 Gobby::BrowserCommands::BrowserCommands(Browser& browser, Folder& folder, 
    156                                         DocumentInfoStorage& info_storage, 
    157                                         StatusBar& status_bar, 
    158                                         const Preferences& preferences): 
    159         m_browser(browser), m_folder(folder), m_info_storage(info_storage), 
    160         m_status_bar(status_bar), m_preferences(preferences) 
    161 { 
    162         InfGtkBrowserModel* model = INF_GTK_BROWSER_MODEL(browser.get_store()); 
    163         m_set_browser_handler = 
    164                 g_signal_connect(G_OBJECT(model), "set-browser", 
    165                                  G_CALLBACK(&on_set_browser_static), this); 
    166  
    16793        m_browser.signal_activate().connect( 
    16894                sigc::mem_fun(*this, &BrowserCommands::on_activate)); 
     
    17197Gobby::BrowserCommands::~BrowserCommands() 
    17298{ 
    173         for(BrowserMap::iterator iter = m_browser_map.begin(); 
    174             iter != m_browser_map.end(); ++ iter) 
     99        for(RequestMap::iterator iter = m_request_map.begin(); 
     100            iter != m_request_map.end(); ++ iter) 
    175101        { 
    176102                delete iter->second; 
    177         } 
    178  
    179         g_signal_handler_disconnect( 
    180                 INF_GTK_BROWSER_MODEL(m_browser.get_store()), 
    181                 m_set_browser_handler); 
    182 } 
    183  
    184 void Gobby::BrowserCommands::on_set_browser(InfGtkBrowserModel* model, 
    185                                             GtkTreeIter* iter, 
    186                                             InfcBrowser* browser) 
    187 { 
    188         if(browser != NULL) 
    189         { 
    190                 g_assert(m_browser_map.find(browser) == m_browser_map.end()); 
    191                 m_browser_map[browser ] = new BrowserNode(*this, browser); 
    192         } 
    193         else 
    194         { 
    195                 InfcBrowser* old_browser; 
    196                 gtk_tree_model_get( 
    197                         GTK_TREE_MODEL(model), iter, 
    198                         INF_GTK_BROWSER_MODEL_COL_BROWSER, &old_browser, -1); 
    199  
    200                 if(old_browser != NULL) 
    201                 { 
    202                         BrowserMap::iterator iter = 
    203                                 m_browser_map.find(old_browser); 
    204                         g_assert(iter != m_browser_map.end()); 
    205                         delete iter->second; 
    206                         m_browser_map.erase(iter); 
    207                         g_object_unref(old_browser); 
    208                 } 
    209103        } 
    210104} 
     
    218112        { 
    219113                InfSession* session = infc_session_proxy_get_session(proxy); 
    220                 //InfTextSession* text_session = INF_TEXT_SESSION(session); 
    221114                SessionView* view = m_folder.lookup_document(session); 
    222                 //DocWindow* window = m_folder.lookup_document(text_session); 
    223115 
    224116                if(view != NULL) 
     
    245137                                                                      iter); 
    246138 
    247                         RequestNode& node = m_request_map[request]; 
    248                         node.commands = this; 
    249                         node.browser = browser; 
    250                         node.handle = m_status_bar.add_info_message( 
    251                                 Glib::ustring::compose( 
    252                                         _("Subscribing to %1..."), 
    253                                         Glib::ustring( 
    254                                                 infc_browser_iter_get_name( 
    255                                                         browser, iter)))); 
    256  
    257                         g_signal_connect( 
    258                                 request, "finished", 
    259                                 G_CALLBACK(&on_finished_static), this); 
    260  
    261                         g_signal_connect( 
    262                                 request, "failed", 
    263                                 G_CALLBACK(&on_failed_static), this); 
    264                 } 
    265                 else 
    266                 { 
    267                         m_status_bar.add_info_message( 
    268                                 _("Subscription already in progress")); 
     139                        g_assert(m_request_map.find(request) == 
     140                                 m_request_map.end()); 
     141                        m_request_map[request] = 
     142                                new RequestInfo(*this, browser, request, 
     143                                                m_status_bar); 
    269144                } 
    270145        } 
     
    275150        RequestMap::iterator iter = m_request_map.find(request); 
    276151        g_assert(iter != m_request_map.end()); 
    277  
    278         // The synchronization is watched in on_subscribe_session which is 
    279         // emitted along with this signal. 
     152        delete iter->second; 
    280153        m_request_map.erase(iter); 
    281 } 
    282  
    283 void Gobby::BrowserCommands::on_subscribe_session(InfcBrowser* browser, 
    284                                                   InfcBrowserIter* iter, 
    285                                                   InfcSessionProxy* proxy) 
    286 { 
    287         InfSession* session = infc_session_proxy_get_session(proxy); 
    288         gchar* path = infc_browser_iter_get_path(browser, iter); 
    289         gchar* hostname; 
    290         g_object_get(G_OBJECT(infc_browser_get_connection(browser)), 
    291                      "remote-hostname", &hostname, NULL); 
    292  
    293         TextSessionView& view = m_folder.add_text_session( 
    294                 INF_TEXT_SESSION(session), 
    295                 infc_browser_iter_get_name(browser, iter), 
    296                 path, hostname, 
    297                 m_info_storage.get_key(browser, iter)); 
    298  
    299         g_free(hostname); 
    300         g_free(path); 
    301  
    302         // For now we always highlight the newly created session... 
    303         // TODO: If the user issued other browserview events in the meanwhile, 
    304         // then don't select the item, and if the user did issue other folder 
    305         // events, then don't switch to the document in the folder. 
    306         m_folder.switch_to_document(view); 
    307         gtk_widget_grab_focus(GTK_WIDGET(view.get_text_view())); 
    308         m_browser.set_selected(browser, iter); 
    309  
    310         SessionNode& node = m_session_map[session]; 
    311         node.proxy = proxy; 
    312  
    313         /* We cache this for the synchronization-complete signal handler, 
    314          * since the session already changed to RUNNING before the signal 
    315          * handler is run: */ 
    316         node.status = inf_session_get_status(session); 
    317         g_object_ref(proxy); 
    318  
    319         node.notify_connection_id = g_signal_connect( 
    320                 proxy, "notify::connection", 
    321                 G_CALLBACK(on_notify_connection_static), this); 
    322         node.failed_id = g_signal_connect( 
    323                 session, "synchronization-failed", 
    324                 G_CALLBACK(on_synchronization_failed_static), this); 
    325  
    326         // Connect _after here so that we can access the  
    327         // AdoptedAlgorithm the default handler created to perform 
    328         // the user join. 
    329         node.complete_before_id = g_signal_connect( 
    330                 session, "synchronization-complete", 
    331                 G_CALLBACK(on_synchronization_complete_before_static), this); 
    332         node.complete_after_id = g_signal_connect_after( 
    333                 session, "synchronization-complete", 
    334                 G_CALLBACK(on_synchronization_complete_after_static), this); 
    335         node.progress_id = g_signal_connect( 
    336                 session, "synchronization-progress", 
    337                 G_CALLBACK(on_synchronization_progress_static), this); 
    338         node.close_id = g_signal_connect( 
    339                 session, "close", G_CALLBACK(on_close_static), this); 
    340  
    341         if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING) 
    342         { 
    343                 InfXmlConnection* connection; 
    344                 g_object_get(G_OBJECT(session), 
    345                              "sync-connection", &connection, NULL); 
    346  
    347                 gdouble percentage = 
    348                         inf_session_get_synchronization_progress(session, 
    349                                                                  connection); 
    350                 g_object_unref(connection); 
    351  
    352                 view.set_info( 
    353                         Glib::ustring::compose( 
    354                                 _("Synchronization in progress... %1%%"), 
    355                                 static_cast<unsigned int>(percentage * 100)), 
    356                         false); 
    357         } 
    358         else 
    359         { 
    360                 // Already in running state, do user join 
    361                 join_user(proxy, m_preferences.user.name); 
    362         } 
    363154} 
    364155 
     
    368159        RequestMap::iterator iter = m_request_map.find(request); 
    369160        g_assert(iter != m_request_map.end()); 
    370  
     161        delete iter->second; 
    371162        m_request_map.erase(iter); 
    372163 
     
    375166                error->message); 
    376167} 
    377  
    378 void Gobby::BrowserCommands::on_synchronization_failed(InfSession* session, 
    379                                                        InfXmlConnection* conn, 
    380                                                        const GError* error) 
    381 { 
    382         SessionMap::iterator iter = m_session_map.find(session); 
    383         g_assert(iter != m_session_map.end()); 
    384  
    385         if(iter->second.status == INF_SESSION_SYNCHRONIZING) 
    386         { 
    387                 SessionView* view = m_folder.lookup_document(session); 
    388                 g_assert(view != NULL); 
    389  
    390                 set_error_text( 
    391                         *view, 
    392                         Glib::ustring::compose("Synchronization failed: %1", 
    393                                                error->message), SYNC_ERROR); 
    394  
    395                 // The document will be of no use anyway, so consider it not 
    396                 // being modified. 
    397                 InfBuffer* buffer = inf_session_get_buffer(session); 
    398                 inf_buffer_set_modified(buffer, FALSE); 
    399  
    400                 // Don't wait until the session is closed because of this, 
    401                 // since this would also cause a connection notify, 
    402                 // overwriting the error message with a useless one. 
    403                 m_session_map.erase(iter); 
    404         } 
    405 } 
    406  
    407 void Gobby::BrowserCommands:: 
    408         on_synchronization_complete_before(InfSession* session, 
    409                                            InfXmlConnection* connection) 
    410 { 
    411         SessionMap::iterator iter = m_session_map.find(session); 
    412         g_assert(iter != m_session_map.end()); 
    413  
    414         if(iter->second.status == INF_SESSION_SYNCHRONIZING) 
    415         { 
    416                 // Unset modified flag after synchronization. 
    417                 SessionView* view = m_folder.lookup_document(session); 
    418                 g_assert(view != NULL); 
    419  
    420                 InfBuffer* buffer = inf_session_get_buffer(session); 
    421                 inf_buffer_set_modified(buffer, FALSE); 
    422  
    423                 // TODO: Actually we should always set the modified flag, 
    424                 // except the document is either empty, or known in the 
    425                 // document info storage and the version on disk is the same 
    426                 // as the one we got synchronized. We could store a hash and 
    427                 // modification time in the documentinfo storage for this. 
    428                 // We should do this is another source file, such as 
    429                 // synchronization-commands.cpp. 
    430         } 
    431 } 
    432  
    433 void Gobby::BrowserCommands:: 
    434         on_synchronization_complete_after(InfSession* session, 
    435                                           InfXmlConnection* connection) 
    436 { 
    437         SessionMap::iterator iter = m_session_map.find(session); 
    438         g_assert(iter != m_session_map.end()); 
    439  
    440         if(iter->second.status == INF_SESSION_SYNCHRONIZING) 
    441         { 
    442                 iter->second.status = INF_SESSION_RUNNING; 
    443                 join_user(iter->second.proxy, m_preferences.user.name); 
    444         } 
    445 } 
    446  
    447 void Gobby::BrowserCommands::on_synchronization_progress(InfSession* session, 
    448                                                          InfXmlConnection* c, 
    449                                                          gdouble percentage) 
    450 { 
    451         SessionMap::iterator iter = m_session_map.find(session); 
    452         g_assert(iter != m_session_map.end()); 
    453  
    454         if(iter->second.status == INF_SESSION_SYNCHRONIZING) 
    455         { 
    456                 SessionView* view = m_folder.lookup_document(session); 
    457  
    458                 g_assert(view != NULL); 
    459                 view->set_info( 
    460                         Glib::ustring::compose( 
    461                                 _("Synchronization in progress... %1%%"), 
    462                                 static_cast<unsigned int>(percentage * 100)), 
    463                         false); 
    464         } 
    465 } 
    466  
    467 void Gobby::BrowserCommands::on_close(InfSession* session) 
    468 { 
    469         SessionMap::iterator iter = m_session_map.find(session); 
    470         g_assert(iter != m_session_map.end()); 
    471         m_session_map.erase(iter); 
    472 } 
    473  
    474 void Gobby::BrowserCommands::on_notify_connection(InfcSessionProxy* proxy) 
    475 { 
    476         InfSession* session = infc_session_proxy_get_session(proxy); 
    477         SessionMap::iterator iter = m_session_map.find(session); 
    478         g_assert(iter != m_session_map.end()); 
    479  
    480         if(infc_session_proxy_get_connection(proxy) == NULL) 
    481         { 
    482                 SessionView* view = m_folder.lookup_document(session); 
    483                 g_assert(view != NULL); 
    484  
    485                 view->set_info(_( 
    486                         "The connection to the publisher of this document " 
    487                         "has been lost. Further changes to the document " 
    488                         "could not be synchronized to others anymore, " 
    489                         "therefore the document cannot be edited anymore.\n\n" 
    490                         "Please note also that it is possible that not all " 
    491                         "of your latest changes have reached the " 
    492                         "publisher before the connection was lost."), true); 
    493  
    494                 TextSessionView* text_view = 
    495                         dynamic_cast<TextSessionView*>(view); 
    496                 if(text_view) 
    497                         text_view->set_active_user(NULL); 
    498         } 
    499 } 
    500  
    501 void Gobby::BrowserCommands::join_user(InfcSessionProxy* proxy, 
    502                                        const Glib::ustring& name) 
    503 { 
    504         // Check if there is already a local user 
    505         InfSession* session = infc_session_proxy_get_session(proxy); 
    506         InfUserTable* user_table = inf_session_get_user_table(session); 
    507  
    508         InfUser* user = NULL; 
    509         inf_user_table_foreach_local_user(user_table, &retr_local_user_func, 
    510                                           &user); 
    511  
    512         if(user == NULL) 
    513         { 
    514                 // TODO: Make this work also for non-text views... should 
    515                 // probably go into user-join-commands.cpp 
    516                 SessionView* view = m_folder.lookup_document(session); 
    517                 TextSessionView* text_view = 
    518                         dynamic_cast<TextSessionView*>(view); 
    519                 g_assert(text_view != NULL); 
    520  
    521                 // TODO: Automatically join with a different name if there is 
    522                 // already a user with the preferred name? 
    523                 GParameter params[5] = { 
    524                         { "name", { 0 } }, 
    525                         { "hue", { 0 } }, 
    526                         { "vector", { 0 } }, 
    527                         { "caret-position", { 0 } }, 
    528                         { "status", { 0 } } 
    529                 }; 
    530  
    531                 g_value_init(&params[0].value, G_TYPE_STRING); 
    532                 g_value_init(&params[1].value, G_TYPE_DOUBLE); 
    533                 g_value_init(&params[2].value, INF_ADOPTED_TYPE_STATE_VECTOR); 
    534                 g_value_init(&params[3].value, G_TYPE_UINT); 
    535                 g_value_init(&params[4].value, INF_TYPE_USER_STATUS); 
    536  
    537                 g_value_set_static_string(&params[0].value, name.c_str()); 
    538                 g_value_set_double( 
    539                         &params[1].value, m_preferences.user.hue); 
    540                 g_value_take_boxed( 
    541                         &params[2].value,inf_adopted_state_vector_copy( 
    542                                 inf_adopted_algorithm_get_current( 
    543                                         inf_adopted_session_get_algorithm( 
    544                                                 INF_ADOPTED_SESSION( 
    545                                                         session))))); 
    546  
    547                 GtkTextBuffer* buffer = 
    548                         GTK_TEXT_BUFFER(text_view->get_text_buffer()); 
    549                 GtkTextMark* mark = gtk_text_buffer_get_insert(buffer); 
    550                 GtkTextIter caret_iter; 
    551                 gtk_text_buffer_get_iter_at_mark(buffer, &caret_iter, mark); 
    552                 g_value_set_uint(&params[3].value, 
    553                                  gtk_text_iter_get_offset(&caret_iter)); 
    554  
    555                 if(m_folder.get_current_document() == view) 
    556                         g_value_set_enum(&params[4].value, INF_USER_ACTIVE); 
    557                 else 
    558                         g_value_set_enum(&params[4].value, INF_USER_INACTIVE); 
    559  
    560                 GError* error = NULL; 
    561                 InfcUserRequest* request = infc_session_proxy_join_user( 
    562                         proxy, params, 5, &error); 
    563  
    564                 g_value_unset(&params[0].value); 
    565                 g_value_unset(&params[1].value); 
    566                 g_value_unset(&params[2].value); 
    567                 g_value_unset(&params[3].value); 
    568                 g_value_unset(&params[4].value); 
    569  
    570                 if(request == NULL) 
    571                 { 
    572                         set_error_text( 
    573                                 *view, 
    574                                 Glib::ustring::compose("User Join failed: %1", 
    575                                                        error->message), 
    576                                 USER_JOIN_ERROR); 
    577                 } 
    578                 else 
    579                 { 
    580                         view->set_info( 
    581                                 _("User Join in progress..."), false); 
    582  
    583                         g_signal_connect( 
    584                                 request, "failed", 
    585                                 G_CALLBACK(on_user_join_failed_static), this); 
    586                         g_signal_connect( 
    587                                 request, "finished", 
    588                                 G_CALLBACK(on_user_join_finished_static), 
    589                                 this); 
    590  
    591                         g_object_set_data( 
    592                                 G_OBJECT(request), 
    593                                 GOBBY_BROWSER_COMMANDS_SESSION_PROXY, 
    594                                 proxy); 
    595                 } 
    596         } 
    597         else 
    598         { 
    599                 user_joined(proxy, user); 
    600         } 
    601 } 
    602  
    603 void Gobby::BrowserCommands::on_user_join_failed(InfcUserRequest* request, 
    604                                                  const GError* error) 
    605 { 
    606         gpointer proxy_ptr = 
    607                 g_object_get_data(G_OBJECT(request), 
    608                                   GOBBY_BROWSER_COMMANDS_SESSION_PROXY); 
    609  
    610         InfcSessionProxy* proxy = static_cast<InfcSessionProxy*>(proxy_ptr); 
    611         SessionView* view = m_folder.lookup_document( 
    612                 infc_session_proxy_get_session(proxy)); 
    613         g_assert(view != NULL); 
    614  
    615         if(error->domain == inf_user_error_quark() && 
    616            error->code == INF_USER_ERROR_NAME_IN_USE) 
    617         { 
    618                 gpointer retry_ptr = g_object_get_data( 
    619                         G_OBJECT(proxy), 
    620                         GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY); 
    621  
    622                 guint retry; 
    623                 if(retry_ptr) 
    624                         retry = GPOINTER_TO_UINT(retry_ptr); 
    625                 else 
    626                         retry = 2; 
    627  
    628                 // TODO: Introduce an "alternative name" preference 
    629                 join_user(proxy, Glib::ustring::compose( 
    630                         "%1 %2", m_preferences.user.name, retry)); 
    631  
    632                 g_object_set_data( 
    633                         G_OBJECT(proxy), 
    634                         GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY, 
    635                         GUINT_TO_POINTER(retry + 1)); 
    636         } 
    637         else 
    638         { 
    639                 // Remove the user join retry counter as we don't need it 
    640                 // anymore if the user join failed anyway 
    641                 g_object_set_data(G_OBJECT(proxy), 
    642                                   GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY, 
    643                                   NULL); 
    644  
    645                 set_error_text( 
    646                         *view, 
    647                         Glib::ustring::compose("User Join failed: %1", 
    648                                                error->message), 
    649                         USER_JOIN_ERROR); 
    650         } 
    651 } 
    652  
    653 void Gobby::BrowserCommands::on_user_join_finished(InfcUserRequest* request, 
    654                                                    InfUser* user) 
    655 { 
    656         g_assert(INF_TEXT_IS_USER(user)); 
    657  
    658         gpointer proxy_ptr = 
    659                 g_object_get_data(G_OBJECT(request), 
    660                                   GOBBY_BROWSER_COMMANDS_SESSION_PROXY); 
    661  
    662         InfcSessionProxy* proxy = static_cast<InfcSessionProxy*>(proxy_ptr); 
    663          
    664         // Clear user join retry counter from proxy now that 
    665         // the user join finished. 
    666         g_object_set_data(G_OBJECT(proxy), 
    667                           GOBBY_BROWSER_COMMANDS_USER_JOIN_RETRY, NULL); 
    668  
    669         user_joined(proxy, user); 
    670 } 
    671  
    672 void Gobby::BrowserCommands::user_joined(InfcSessionProxy* proxy, 
    673                                          InfUser* user) 
    674 { 
    675         SessionView* view = m_folder.lookup_document( 
    676                 infc_session_proxy_get_session(proxy)); 
    677         g_assert(view != NULL); 
    678  
    679         // TODO: Notify the user that he is using an alternative name if 
    680         // inf_user_get_name(user) does not match m_preferences.user.name. 
    681  
    682         view->unset_info(); 
    683         TextSessionView* text_view = dynamic_cast<TextSessionView*>(view); 
    684         if(text_view) 
    685                 text_view->set_active_user(INF_TEXT_USER(user)); 
    686 } 
  • code/commands/browser-commands.hpp

    r6b79c69 rf8809f6  
    2020#define _GOBBY_BROWSER_COMMANDS_HPP_ 
    2121 
    22 #include "core/documentinfostorage.hpp" 
    2322#include "core/browser.hpp" 
    24 #include "core/folder.hpp" 
    2523#include "core/statusbar.hpp" 
    2624 
    27 #include <libinfinity/client/infc-browser.h> 
    28 #include <libinfinity/client/infc-request.h> 
    29 #include <libinfinity/client/infc-node-request.h> 
     25#include <sigc++/trackable.h> 
    3026 
    3127namespace Gobby 
     
    3632public: 
    3733        BrowserCommands(Browser& browser, Folder& folder, 
    38                         DocumentInfoStorage& info_storage, 
    39                         StatusBar& status_bar, 
    40                         const Preferences& preferences); 
     34                        StatusBar& status_bar); 
    4135        ~BrowserCommands(); 
    4236 
    4337protected: 
    44         static void on_set_browser_static(InfGtkBrowserModel* model, 
    45                                           GtkTreePath* path, 
    46                                           GtkTreeIter* iter, 
    47                                           InfcBrowser* browser, 
    48                                           gpointer user_data) 
    49         { 
    50                 static_cast<BrowserCommands*>(user_data)->on_set_browser( 
    51                         model, iter, browser); 
    52         } 
    53  
    54         static void on_subscribe_session_static(InfcBrowser* browser, 
    55                                                 InfcBrowserIter* iter, 
    56                                                 InfcSessionProxy* proxy, 
    57                                                 gpointer user_data) 
    58         { 
    59                 static_cast<BrowserCommands*>(user_data)-> 
    60                         on_subscribe_session(browser, iter, proxy); 
    61         } 
    62  
    63         static void on_finished_static(InfcNodeRequest* request, 
    64                                        const InfcBrowserIter* iter, 
    65                                        gpointer user_data) 
    66         { 
    67                 static_cast<BrowserCommands*>(user_data)->on_finished( 
    68                         request); 
    69         } 
    70  
    71         static void on_failed_static(InfcRequest* request, 
    72                                      const GError* error, 
    73                                      gpointer user_data) 
    74         { 
    75                 static_cast<BrowserCommands*>(user_data)->on_failed( 
    76                         INFC_NODE_REQUEST(request), error); 
    77         } 
    78  
    79         static void on_synchronization_failed_static(InfSession* session, 
    80                                                      InfXmlConnection* conn, 
    81                                                      const GError* error, 
    82                                                      gpointer user_data) 
    83         { 
    84                 static_cast<BrowserCommands*>(user_data)-> 
    85                         on_synchronization_failed(session, conn, error); 
    86         } 
    87  
    88         static void 
    89         on_synchronization_complete_before_static(InfSession* session, 
    90                                                   InfXmlConnection* conn, 
    91                                                   gpointer user_data) 
    92         { 
    93                 static_cast<BrowserCommands*>(user_data)-> 
    94                         on_synchronization_complete_before(session, conn); 
    95         } 
    96  
    97         static void 
    98         on_synchronization_complete_after_static(InfSession* session, 
    99                                                  InfXmlConnection* conn, 
    100                                                  gpointer user_data) 
    101         { 
    102                 static_cast<BrowserCommands*>(user_data)-> 
    103                         on_synchronization_complete_after(session, conn); 
    104         } 
    105  
    106         static void on_synchronization_progress_static(InfSession* session, 
    107                                                        InfXmlConnection* conn, 
    108                                                        gdouble percentage, 
    109                                                        gpointer user_data) 
    110         { 
    111                 static_cast<BrowserCommands*>(user_data)-> 
    112                         on_synchronization_progress( 
    113                                 session, conn, percentage); 
    114         } 
    115  
    116         static void on_notify_connection_static(GObject* object, 
    117                                                 GParamSpec* pspec, 
    118                                                 gpointer user_data) 
    119         { 
    120                 static_cast<BrowserCommands*>(user_data)-> 
    121                         on_notify_connection(INFC_SESSION_PROXY(object)); 
    122         } 
    123  
    124         static void on_close_static(InfSession* session, 
    125                                     gpointer user_data) 
    126         { 
    127                 static_cast<BrowserCommands*>(user_data)->on_close(session); 
    128         } 
    129  
    130         static void on_user_join_failed_static(InfcUserRequest* request, 
    131                                                const GError* error, 
    132                                                gpointer user_data) 
    133         { 
    134                 static_cast<BrowserCommands*>(user_data)-> 
    135                         on_user_join_failed(request, error); 
    136         } 
    137  
    138         static void on_user_join_finished_static(InfcUserRequest* request, 
    139                                                  InfUser* user, 
    140                                                  gpointer user_data) 
    141         { 
    142                 static_cast<BrowserCommands*>(user_data)-> 
    143                         on_user_join_finished(request, user); 
    144         } 
    145  
    146         void on_set_browser(InfGtkBrowserModel* model, GtkTreeIter* iter, 
    147                             InfcBrowser* browser); 
    148  
    14938        void on_activate(InfcBrowser* browser, InfcBrowserIter* iter); 
    15039        void on_finished(InfcNodeRequest* request); 
    15140        void on_failed(InfcNodeRequest* request, const GError* error); 
    15241 
    153         void on_subscribe_session(InfcBrowser* browser, InfcBrowserIter* iter, 
    154                                   InfcSessionProxy* proxy); 
    155  
    156         void on_synchronization_failed(InfSession* session, 
    157                                        InfXmlConnection* connection, 
    158                                        const GError* error); 
    159         void on_synchronization_complete_before(InfSession* session, 
    160                                                 InfXmlConnection* connection); 
    161         void on_synchronization_complete_after(InfSession* session, 
    162                                                InfXmlConnection* connection); 
    163         void on_synchronization_progress(InfSession* session, 
    164                                          InfXmlConnection* connection, 
    165                                          gdouble percentage); 
    166         void on_close(InfSession* session); 
    167         void on_notify_connection(InfcSessionProxy* proxy); 
    168  
    169         void join_user(InfcSessionProxy* proxy, const Glib::ustring& name); 
    170  
    171         void on_user_join_failed(InfcUserRequest* request, 
    172                                  const GError* error); 
    173         void on_user_join_finished(InfcUserRequest* request, InfUser* user); 
    174         void user_joined(InfcSessionProxy* proxy, InfUser* user); 
    175  
    17642        Browser& m_browser; 
    17743        Folder& m_folder; 
    178         DocumentInfoStorage& m_info_storage; 
    17944        StatusBar& m_status_bar; 
    180         const Preferences& m_preferences; 
    18145 
    182         gulong m_set_browser_handler; 
    183  
    184         struct RequestNode { 
    185                 BrowserCommands* commands; 
    186                 InfcBrowser* browser; 
    187                 StatusBar::MessageHandle handle; 
    188  
    189                 RequestNode(); 
    190                 RequestNode(const RequestNode& node); 
    191                 ~RequestNode(); 
    192         }; 
    193  
    194         struct SessionNode { 
    195                 InfcSessionProxy* proxy; 
    196                 InfSessionStatus status; 
    197  
    198                 gulong notify_connection_id; 
    199                 gulong failed_id; 
    200                 gulong complete_before_id; 
    201                 gulong complete_after_id; 
    202                 gulong progress_id; 
    203                 gulong close_id; 
    204  
    205                 SessionNode(); 
    206                 SessionNode(const SessionNode& node); 
    207                 ~SessionNode(); 
    208         }; 
    209  
    210         struct BrowserNode; 
    211  
    212         typedef std::map<InfcBrowser*, BrowserNode*> BrowserMap; 
    213         BrowserMap m_browser_map; 
    214  
    215         typedef std::map<InfcNodeRequest*, RequestNode> RequestMap; 
     46        class RequestInfo; 
     47        typedef std::map<InfcNodeRequest*, RequestInfo*> RequestMap; 
    21648        RequestMap m_request_map; 
    217  
    218         typedef std::map<InfSession*, SessionNode> SessionMap; 
    219         SessionMap m_session_map; 
    22049}; 
    22150 
    22251} 
    223          
     52 
    22453#endif // _GOBBY_BROWSER_COMMANDS_HPP_ 
  • code/window.cpp

    r877d323 rf8809f6  
    5353        m_commands_autosave(m_text_folder, m_operations, m_info_storage, 
    5454                            m_preferences), 
    55         m_commands_browser(m_browser, m_text_folder, m_info_storage, 
    56                            m_statusbar, m_preferences), 
     55        m_commands_browser(m_browser, m_text_folder, m_statusbar), 
     56        m_commands_subscription(m_browser, m_text_folder, m_info_storage), 
     57        m_commands_synchronization(m_commands_subscription), 
     58        m_commands_user_join(m_commands_subscription, m_preferences), 
    5759        m_commands_browser_context(*this, m_browser, m_file_chooser, 
    5860                                   m_operations, m_preferences), 
  • code/window.hpp

    r877d323 rf8809f6  
    2424#include "commands/autosave-commands.hpp" 
    2525#include "commands/browser-commands.hpp" 
     26#include "commands/subscription-commands.hpp" 
     27#include "commands/synchronization-commands.hpp" 
     28#include "commands/user-join-commands.hpp" 
    2629#include "commands/browser-context-commands.hpp" 
    2730#include "commands/folder-commands.hpp" 
     
    148151        AutosaveCommands m_commands_autosave; 
    149152        BrowserCommands m_commands_browser; 
     153        SubscriptionCommands m_commands_subscription; 
     154        SynchronizationCommands m_commands_synchronization; 
     155        UserJoinCommands m_commands_user_join; 
     156 
    150157        BrowserContextCommands m_commands_browser_context; 
    151158        FolderCommands m_commands_folder;