void Gobby::UserJoinCommands::UserJoinInfo:: add_text_user_properties(std::vector<GParameter>& params, TextSessionView& view) { InfTextSession* session = view.get_session(); GParameter hue_param = { "hue", { 0 } }; g_value_init(&hue_param.value, G_TYPE_DOUBLE); g_value_set_double(&hue_param.value, m_commands.m_preferences.user.hue); params.push_back(hue_param); GParameter vector_param = { "vector", { 0 } }; g_value_init(&vector_param.value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_take_boxed(&vector_param.value, inf_adopted_state_vector_copy( inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm( INF_ADOPTED_SESSION(session))))); params.push_back(vector_param); GParameter caret_param = { "caret-position", { 0 } }; g_value_init(&caret_param.value, G_TYPE_UINT); GtkTextBuffer* buffer = GTK_TEXT_BUFFER(view.get_text_buffer()); GtkTextMark* mark = gtk_text_buffer_get_insert(buffer); GtkTextIter caret_iter; gtk_text_buffer_get_iter_at_mark(buffer, &caret_iter, mark); g_value_set_uint(&caret_param.value, gtk_text_iter_get_offset(&caret_iter)); params.push_back(caret_param); }
void Gobby::EditCommands::on_active_user_changed(InfUser* active_user) { g_assert(m_current_view != NULL); if(active_user != NULL) { InfTextSession* session = m_current_view->get_session(); InfAdoptedAlgorithm* algorithm = inf_adopted_session_get_algorithm( INF_ADOPTED_SESSION(session)); GtkTextBuffer* buffer = GTK_TEXT_BUFFER( m_current_view->get_text_buffer()); m_header.action_edit_undo->set_sensitive( inf_adopted_algorithm_can_undo( algorithm, INF_ADOPTED_USER(active_user))); m_header.action_edit_redo->set_sensitive( inf_adopted_algorithm_can_redo( algorithm, INF_ADOPTED_USER(active_user))); m_header.action_edit_cut->set_sensitive( gtk_text_buffer_get_has_selection(buffer)); m_header.action_edit_paste->set_sensitive(true); } else { m_header.action_edit_undo->set_sensitive(false); m_header.action_edit_redo->set_sensitive(false); m_header.action_edit_cut->set_sensitive(false); m_header.action_edit_paste->set_sensitive(false); } }
static void on_synchronization_complete(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfTestGtkBrowserWindow* test; InfAdoptedAlgorithm* algorithm; test = (InfTestGtkBrowserWindow*)user_data; session = infc_session_proxy_get_session(test->proxy); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_signal_connect( G_OBJECT(algorithm), "can-undo-changed", G_CALLBACK(on_can_undo_changed), test ); g_signal_connect( G_OBJECT(algorithm), "can-redo-changed", G_CALLBACK(on_can_redo_changed), test ); request_join(test, g_get_user_name()); }
static void on_join_finished(InfcUserRequest* request, InfUser* user, gpointer user_data) { InfTestGtkBrowserWindow* test; InfAdoptedSession* session; InfAdoptedAlgorithm* algorithm; gboolean undo; gboolean redo; test = (InfTestGtkBrowserWindow*)user_data; inf_text_gtk_buffer_set_active_user(test->buffer, INF_TEXT_USER(user)); gtk_text_view_set_editable(GTK_TEXT_VIEW(test->textview), TRUE); test->user = user; session = INF_ADOPTED_SESSION(infc_session_proxy_get_session(test->proxy)); algorithm = inf_adopted_session_get_algorithm(session); undo = inf_adopted_algorithm_can_undo(algorithm, INF_ADOPTED_USER(user)); redo = inf_adopted_algorithm_can_redo(algorithm, INF_ADOPTED_USER(user)); gtk_widget_set_sensitive(test->undo_button, undo); gtk_widget_set_sensitive(test->redo_button, redo); }
static void inf_test_mass_join_join_user(InfTestMassJoiner* joiner) { InfSession* session; InfAdoptedStateVector* v; GParameter params[3] = { { "name", { 0 } }, { "vector", { 0 } }, { "caret-position", { 0 } } }; g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_init(¶ms[1].value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_init(¶ms[2].value, G_TYPE_UINT); g_value_set_static_string(¶ms[0].value, joiner->username); g_object_get(G_OBJECT(joiner->session), "session", &session, NULL); v = inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)) ); g_object_unref(session); g_value_set_boxed(¶ms[1].value, v); g_value_set_uint(¶ms[2].value, 0u); inf_session_proxy_join_user( INF_SESSION_PROXY(joiner->session), 3, params, inf_test_mass_join_user_join_finished_cb, joiner ); g_value_unset(¶ms[2].value); g_value_unset(¶ms[1].value); g_value_unset(¶ms[0].value); }
void Gobby::EditCommands::on_sync_complete() { g_assert(m_current_view != NULL); InfTextSession* session = m_current_view->get_session(); InfAdoptedAlgorithm* algorithm = inf_adopted_session_get_algorithm( INF_ADOPTED_SESSION(session)); m_can_undo_changed_handler = g_signal_connect( G_OBJECT(algorithm), "can-undo-changed", G_CALLBACK(&on_can_undo_changed_static), this); m_can_redo_changed_handler = g_signal_connect( G_OBJECT(algorithm), "can-redo-changed", G_CALLBACK(&on_can_redo_changed_static), this); if(m_synchronization_complete_handler != 0) { g_signal_handler_disconnect( G_OBJECT(session), m_synchronization_complete_handler); m_synchronization_complete_handler = 0; } }
void Gobby::EditCommands::on_document_changed(SessionView* view) { if(m_current_view != NULL) { InfTextSession* session = m_current_view->get_session(); InfAdoptedAlgorithm* algorithm = inf_adopted_session_get_algorithm( INF_ADOPTED_SESSION(session)); GtkTextBuffer* buffer = GTK_TEXT_BUFFER( m_current_view->get_text_buffer()); if(m_synchronization_complete_handler != 0) { g_signal_handler_disconnect( G_OBJECT(session), m_synchronization_complete_handler); } else { g_signal_handler_disconnect( G_OBJECT(algorithm), m_can_undo_changed_handler); g_signal_handler_disconnect( G_OBJECT(algorithm), m_can_redo_changed_handler); } g_signal_handler_disconnect(G_OBJECT(buffer), m_mark_set_handler); g_signal_handler_disconnect(G_OBJECT(buffer), m_changed_handler); m_active_user_changed_connection.disconnect(); } m_current_view = dynamic_cast<TextSessionView*>(view); if(m_current_view != NULL) { InfTextSession* session = m_current_view->get_session(); InfUser* active_user = m_current_view->get_active_user(); GtkTextBuffer* buffer = GTK_TEXT_BUFFER(m_current_view->get_text_buffer()); m_active_user_changed_connection = m_current_view->signal_active_user_changed().connect( sigc::mem_fun( *this, &EditCommands:: on_active_user_changed)); m_mark_set_handler = g_signal_connect_after( G_OBJECT(buffer), "mark-set", G_CALLBACK(&on_mark_set_static), this); // The selection might change without mark-set being emitted // when the document changes, for example when all // currently selected text is deleted. m_changed_handler = g_signal_connect_after( G_OBJECT(buffer), "changed", G_CALLBACK(&on_changed_static), this); if(inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING) { // This connects to can-undo-changed and // can-redo-changed of the algorithm. Set // m_synchronization_complete_handler to zero so that // the function does not try to disconnect from it. m_synchronization_complete_handler = 0; on_sync_complete(); } else { // The InfAdoptedSession is created after // synchronization, so we wait until that finished. m_synchronization_complete_handler = g_signal_connect_after( G_OBJECT(session), "synchronization_complete", G_CALLBACK(&on_sync_complete_static), this); m_can_undo_changed_handler = 0; m_can_redo_changed_handler = 0; } // Set initial sensitivity for active user: on_active_user_changed(active_user); // Set initial sensitivity for cut/copy/paste: on_mark_set(); // Set initial sensitivity for find/replace/goto: m_header.action_edit_find->set_sensitive(true); if(m_find_dialog.get()) { on_find_text_changed(); } else { m_header.action_edit_find_next->set_sensitive(false); m_header.action_edit_find_prev->set_sensitive(false); } m_header.action_edit_find_replace->set_sensitive(true); m_header.action_edit_goto_line->set_sensitive(true); } else { m_header.action_edit_undo->set_sensitive(false); m_header.action_edit_redo->set_sensitive(false); m_header.action_edit_cut->set_sensitive(false); m_header.action_edit_copy->set_sensitive(false); m_header.action_edit_paste->set_sensitive(false); m_header.action_edit_find->set_sensitive(false); m_header.action_edit_find_next->set_sensitive(false); m_header.action_edit_find_prev->set_sensitive(false); m_header.action_edit_find_replace->set_sensitive(false); m_header.action_edit_goto_line->set_sensitive(false); } }
static gboolean perform_test(guint max_total_log_size, InfTextChunk* initial, GSList* users, GSList* requests, GError** error) { InfTextBuffer* buffer; InfCommunicationManager* manager; InfIo* io; InfTextSession* session; InfAdoptedAlgorithm* algorithm; InfUserTable* user_table; InfTextUser* user; gchar* user_name; GSList* item; xmlNodePtr request; gboolean result; GError* local_error; guint verify_user_id; InfAdoptedUser* verify_user; guint verify_log_size; gint verify_can_undo; gint verify_can_redo; InfAdoptedRequestLog* log; guint log_size; buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_chunk(buffer, 0, initial, NULL); manager = inf_communication_manager_new(); io = INF_IO(inf_standalone_io_new()); user_table = inf_user_table_new(); local_error = NULL; for(item = users; item != NULL; item = g_slist_next(item)) { user_name = g_strdup_printf("User_%u", GPOINTER_TO_UINT(item->data)); user = INF_TEXT_USER( g_object_new( INF_TEXT_TYPE_USER, "id", GPOINTER_TO_UINT(item->data), "name", user_name, "status", INF_USER_ACTIVE, "flags", 0, NULL ) ); g_free(user_name); inf_user_table_add_user(user_table, INF_USER(user)); g_object_unref(user); } session = INF_TEXT_SESSION( g_object_new( INF_TEXT_TYPE_SESSION, "communication-manager", manager, "buffer", buffer, "io", io, "user_table", user_table, "max-total-log-size", max_total_log_size, NULL ) ); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_object_unref(io); g_object_unref(manager); g_object_unref(user_table); g_object_unref(buffer); for(item = requests; item != NULL; item = item->next) { request = (xmlNodePtr)item->data; if(strcmp((const char*)request->name, "request") == 0) { /* Request */ result = inf_communication_object_received( INF_COMMUNICATION_OBJECT(session), NULL, request, &local_error ); if(local_error != NULL) goto fail; } else { /* TODO: Make an extra function out of this: */ /* Verify */ result = inf_xml_util_get_attribute_uint_required( request, "user", &verify_user_id, &local_error ); if(result == FALSE) goto fail; verify_user = INF_ADOPTED_USER( inf_user_table_lookup_user_by_id(user_table, verify_user_id) ); if(verify_user == NULL) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_USER_UNAVAILABLE, "User ID '%u' not available", verify_user_id ); goto fail; } result = inf_xml_util_get_attribute_uint( request, "log-size", &verify_log_size, &local_error ); if(local_error) goto fail; if(result) { log = inf_adopted_user_get_request_log(INF_ADOPTED_USER(verify_user)); log_size = inf_adopted_request_log_get_end(log) - inf_adopted_request_log_get_begin(log); if(verify_log_size != log_size) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "Log size does not match; got %u, but expected %u", log_size, verify_log_size ); goto fail; } } result = inf_xml_util_get_attribute_int( request, "can-undo", &verify_can_undo, &local_error ); if(local_error) goto fail; if(result) { result = inf_adopted_algorithm_can_undo(algorithm, verify_user); if(result != verify_can_undo) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "can-undo does not match; got %d, but expected %d", (guint)result, verify_can_undo ); goto fail; } } result = inf_xml_util_get_attribute_int( request, "can-redo", &verify_can_redo, &local_error ); if(local_error) goto fail; if(result) { result = inf_adopted_algorithm_can_redo(algorithm, verify_user); if(result != verify_can_redo) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "can-redo does not match; got %d, but expected %d", (guint)result, verify_can_redo ); goto fail; } } } } g_object_unref(session); return TRUE; fail: g_object_unref(session); if(local_error) g_propagate_error(error, local_error); return FALSE; }
static gboolean infinoted_plugin_transformation_protection_check_request_cb(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedUser* user, gpointer user_data) { InfinotedPluginTransformationProtectionSessionInfo* info; guint vdiff; InfXmlConnection* connection; gchar* request_str; gchar* current_str; gchar* remote_id; gchar* path; info = (InfinotedPluginTransformationProtectionSessionInfo*)user_data; vdiff = inf_adopted_state_vector_vdiff( inf_adopted_request_get_vector(request), inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(session) ) ); if(vdiff > info->plugin->max_vdiff) { connection = inf_user_get_connection(INF_USER(user)); /* Local requests do not need to be transformed, so always have a * zero vdiff. */ g_assert(connection != NULL); /* Kill the connection */ infd_session_proxy_unsubscribe( INFD_SESSION_PROXY(info->proxy), connection ); /* Write a log message */ path = inf_browser_get_path( INF_BROWSER( infinoted_plugin_manager_get_directory(info->plugin->manager) ), &info->iter ); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); current_str = inf_adopted_state_vector_to_string( inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(session) ) ); g_object_get(G_OBJECT(connection), "remote-id", &remote_id, NULL); infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("In document \"%s\": Attempt to transform request \"%s\" to current state \"%s\" " "(vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the " "connection has been unsubscribed."), path, request_str, current_str, vdiff, inf_user_get_name(INF_USER(user)), inf_user_get_id(INF_USER(user)), remote_id, info->plugin->max_vdiff ); g_free(path); g_free(request_str); g_free(current_str); g_free(remote_id); /* Prevent the request from being transformed */ return TRUE; } return FALSE; }
static void request_join(InfTestGtkBrowserWindow* test, const gchar* user_name) { InfcUserRequest* request; InfAdoptedStateVector* v; GError* error; GtkTextBuffer* buffer; GtkTextMark* mark; GtkTextIter iter; GParameter params[3] = { { "name", { 0 } }, { "vector", { 0 } }, { "caret-position", { 0 } } }; g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_init(¶ms[1].value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_init(¶ms[2].value, G_TYPE_UINT); g_value_set_static_string(¶ms[0].value, user_name); /* Use current state vector. Infinote should already do this. */ v = inf_adopted_state_vector_copy( inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm( INF_ADOPTED_SESSION(infc_session_proxy_get_session(test->proxy)) ) ) ); g_value_take_boxed(¶ms[1].value, v); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(test->textview)); mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark); g_value_set_uint(¶ms[2].value, gtk_text_iter_get_offset(&iter)); error = NULL; request = infc_session_proxy_join_user(test->proxy, params, 3, &error); /* TODO: Free GValues? */ if(request == NULL) { set_error(test, "Failed to request user join", error->message); } else { g_signal_connect_after( G_OBJECT(request), "failed", G_CALLBACK(on_join_failed), test ); g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(on_join_finished), test ); } }