Пример #1
0
static void
inf_adopted_session_create_algorithm(InfAdoptedSession* session)
{
  InfAdoptedSessionPrivate* priv;
  priv = INF_ADOPTED_SESSION_PRIVATE(session);

  g_assert(priv->algorithm == NULL);

  g_assert(
    inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING
  );

  priv->algorithm = inf_adopted_algorithm_new_full(
    inf_session_get_user_table(INF_SESSION(session)),
    inf_session_get_buffer(INF_SESSION(session)),
    priv->max_total_log_size
  );

  g_signal_connect(
    G_OBJECT(priv->algorithm),
    "execute-request",
    G_CALLBACK(inf_adopted_session_execute_request_cb),
    session
  );

  g_object_notify(G_OBJECT(session), "algorithm");
}
Пример #2
0
/* Breadcasts a request N times - makes only sense for undo and redo requests,
 * so that's the only thing we offer API for. */
static void
inf_adopted_session_broadcast_n_requests(InfAdoptedSession* session,
                                         InfAdoptedRequest* request,
                                         guint n)
{
  InfAdoptedSessionPrivate* priv;
  InfAdoptedSessionClass* session_class;
  InfUserTable* user_table;
  guint user_id;
  InfUser* user;
  InfAdoptedSessionLocalUser* local;
  xmlNodePtr xml;

  priv = INF_ADOPTED_SESSION_PRIVATE(session);
  session_class = INF_ADOPTED_SESSION_GET_CLASS(session);
  g_assert(session_class->request_to_xml != NULL);

  user_table = inf_session_get_user_table(INF_SESSION(session));
  user_id = inf_adopted_request_get_user_id(request);
  user = inf_user_table_lookup_user_by_id(user_table, user_id);
  g_assert(user != NULL);

  local = inf_adopted_session_lookup_local_user(
    session,
    INF_ADOPTED_USER(user)
  );
  g_assert(local != NULL);

  xml = xmlNewNode(NULL, (const xmlChar*)"request");

  session_class->request_to_xml(
    session,
    xml,
    request,
    local->last_send_vector,
    FALSE
  );

  if(n > 1) inf_xml_util_set_attribute_uint(xml, "num", n);
  inf_session_send_to_subscriptions(INF_SESSION(session), xml);

  inf_adopted_state_vector_free(local->last_send_vector);
  local->last_send_vector = inf_adopted_state_vector_copy(
    inf_adopted_request_get_vector(request)
  );

  /* Add this request to last send vector if it increases vector time
   * (-> affects buffer). */
  if(inf_adopted_request_affects_buffer(request) == TRUE)
    inf_adopted_state_vector_add(local->last_send_vector, user_id, n);

  inf_adopted_session_stop_noop_timer(session, local);
}
Пример #3
0
/* Note plugin implementation */
static InfSession*
infinoted_plugin_note_text_session_new(InfIo* io,
                                       InfCommunicationManager* manager,
                                       InfSessionStatus status,
                                       InfCommunicationGroup* sync_group,
                                       InfXmlConnection* sync_connection,
                                       const gchar* path,
                                       gpointer user_data)
{
  InfTextSession* session;
  InfTextBuffer* buffer;

  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  session = inf_text_session_new(
    manager,
    buffer,
    io,
    status,
    sync_group,
    sync_connection
  );

  g_object_unref(buffer);

  return INF_SESSION(session);
}
Пример #4
0
static InfAdoptedUser*
inf_adopted_session_user_from_request_xml(InfAdoptedSession* session,
                                          xmlNodePtr xml,
                                          GError** error)
{
  InfUserTable* user_table;
  InfUser* user;
  guint user_id;

  user_table = inf_session_get_user_table(INF_SESSION(session));

  if(!inf_xml_util_get_attribute_uint_required(xml, "user", &user_id, error))
    return FALSE;

  /* User ID 0 means no user */
  if(user_id == 0) return NULL;

  user = inf_user_table_lookup_user_by_id(user_table, user_id);

  if(user == NULL)
  {
    g_set_error(
      error,
      inf_adopted_session_error_quark,
      INF_ADOPTED_SESSION_ERROR_NO_SUCH_USER,
      _("No such user with user ID '%u'"),
      user_id
    );

    return NULL;
  }

  g_assert(INF_ADOPTED_IS_USER(user));
  return INF_ADOPTED_USER(user);
}
/* Note plugin implementation */
static InfSession*
infinoted_plugin_note_chat_session_new(InfIo* io,
                                       InfCommunicationManager* manager,
                                       InfSessionStatus status,
                                       InfCommunicationGroup* sync_group,
                                       InfXmlConnection* sync_connection,
                                       const gchar* path,
                                       gpointer user_data)
{
  InfChatBuffer* buffer;
  InfChatSession* session;

  buffer = inf_chat_buffer_new(256);

  session = inf_chat_session_new(
    manager,
    buffer,
    status,
    INF_COMMUNICATION_GROUP(sync_group),
    sync_connection
  );

  g_object_unref(buffer);
  return INF_SESSION(session);
}
Пример #6
0
static InfSession*
inf_test_gtk_browser_session_new(InfIo* io,
                                 InfConnectionManager* manager,
                                 InfConnectionManagerGroup* sync_group,
                                 InfXmlConnection* sync_connection,
                                 gpointer user_data)
{
  InfTextGtkBuffer* buffer;
  InfUserTable* user_table;
  GtkTextBuffer* textbuffer;
  InfTextSession* session;

  textbuffer = gtk_text_buffer_new(NULL);
  user_table = inf_user_table_new();
  buffer = inf_text_gtk_buffer_new(textbuffer, user_table);

  session = inf_text_session_new_with_user_table(
    manager,
    INF_TEXT_BUFFER(buffer),
    io,
    user_table,
    sync_group,
    sync_connection
  );

  return INF_SESSION(session);
}
Пример #7
0
static void
inf_adopted_session_dispose(GObject* object)
{
  InfAdoptedSession* session;
  InfAdoptedSessionPrivate* priv;
  InfUserTable* user_table;

  session = INF_ADOPTED_SESSION(object);
  priv = INF_ADOPTED_SESSION_PRIVATE(session);

  user_table = inf_session_get_user_table(INF_SESSION(session));

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(user_table),
    G_CALLBACK(inf_adopted_session_add_local_user_cb),
    session
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(user_table),
    G_CALLBACK(inf_adopted_session_remove_local_user_cb),
    session
  );

  if(priv->noop_timeout != NULL)
  {
    inf_io_remove_timeout(priv->io, priv->noop_timeout);
    priv->noop_timeout = NULL;
  }

  /* This calls the close vfunc if the session is running, in which we
   * free the local users. */
  G_OBJECT_CLASS(parent_class)->dispose(object);

  g_assert(priv->local_users == NULL);

  if(priv->algorithm != NULL)
  {
    inf_signal_handlers_disconnect_by_func(
      G_OBJECT(priv->algorithm),
      G_CALLBACK(inf_adopted_session_execute_request_cb),
      session
    );

    g_object_unref(G_OBJECT(priv->algorithm));
    priv->algorithm = NULL;
  }

  if(priv->io != NULL)
  {
    g_object_unref(G_OBJECT(priv->io));
    priv->io = NULL;
  }
}
Пример #8
0
void Gobby::ChatSessionView::set_active_user(InfUser* user)
{
	g_assert(
		user == NULL ||
		inf_user_table_lookup_user_by_id(
			inf_session_get_user_table(INF_SESSION(m_session)),
			inf_user_get_id(INF_USER(user)))
		== INF_USER(user));

	inf_gtk_chat_set_active_user(m_chat, user);
	active_user_changed(user);
}
Пример #9
0
Gobby::ChatSessionView::ChatSessionView(InfChatSession* session,
                                        const Glib::ustring& title,
                                        const Glib::ustring& path,
                                        const Glib::ustring& hostname,
                                        Preferences& preferences):
	SessionView(INF_SESSION(session), title, path, hostname),
	m_preferences(preferences), m_chat(INF_GTK_CHAT(inf_gtk_chat_new()))
{
	inf_gtk_chat_set_session(m_chat, session);
	gtk_widget_show(GTK_WIDGET(m_chat));

	gtk_box_pack_start(GTK_BOX(gobj()), GTK_WIDGET(m_chat),
	                   TRUE, TRUE, 0);
}
Пример #10
0
Gobby::TextTabLabel::~TextTabLabel()
{
	TextSessionView& text_view = dynamic_cast<TextSessionView&>(m_view);

	g_signal_handler_disconnect(text_view.get_text_buffer(),
	                            m_modified_changed_handle);
	InfTextBuffer* buffer = 
		INF_TEXT_BUFFER(
			inf_session_get_buffer(
				INF_SESSION(m_view.get_session())));

	g_signal_handler_disconnect(buffer, m_erase_text_handle);
	g_signal_handler_disconnect(buffer, m_insert_text_handle);
}
Пример #11
0
static void
infc_session_proxy_set_property(GObject* object,
                                guint prop_id,
                                const GValue* value,
                                GParamSpec* pspec)
{
  InfcSessionProxy* proxy;
  InfcSessionProxyPrivate* priv;

  proxy = INFC_SESSION_PROXY(object);
  priv = INFC_SESSION_PROXY_PRIVATE(proxy);

  switch(prop_id)
  {
  case PROP_SESSION:
    g_assert(priv->session == NULL); /* construct only */
    priv->session = INF_SESSION(g_value_dup_object(value));

    g_signal_connect(
      G_OBJECT(priv->session),
      "close",
      G_CALLBACK(infc_session_proxy_session_close_cb),
      proxy
    );

    g_signal_connect(
      G_OBJECT(priv->session),
      "synchronization-complete",
      G_CALLBACK(infc_session_proxy_session_synchronization_complete_cb),
      proxy
    );

    g_signal_connect(
      G_OBJECT(priv->session),
      "synchronization-failed",
      G_CALLBACK(infc_session_proxy_session_synchronization_failed_cb),
      proxy
    );

    break;
  case PROP_SUBSCRIPTION_GROUP:
  case PROP_CONNECTION:
    /* these are read-only because they can only be changed both at once,
     * refer to infc_session_proxy_set_connection(). */
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    break;
  }
}
Пример #12
0
	bool on_activation_timeout()
	{
		// The user activated this document, but did not something for
		// a while, so explicitely set the user active
		g_assert(m_active);
		g_assert(m_active_user != NULL);
		g_assert(inf_user_get_status(m_active_user) ==
		         INF_USER_INACTIVE);

		inf_session_set_user_status(
			INF_SESSION(m_view.get_session()), m_active_user,
			INF_USER_ACTIVE);

		return false;
	}
Пример #13
0
static InfSession*
infinoted_plugin_note_text_session_read(InfdStorage* storage,
                                        InfIo* io,
                                        InfCommunicationManager* manager,
                                        const gchar* path,
                                        gpointer user_data,
                                        GError** error)
{
  InfUserTable* user_table;
  InfTextBuffer* buffer;
  gboolean result;
  InfTextSession* session;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));

  user_table = inf_user_table_new();
  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  result = inf_text_filesystem_format_read(
    INFD_FILESYSTEM_STORAGE(storage),
    path,
    user_table,
    buffer,
    error
  );

  if(result == FALSE)
  {
    g_object_unref(user_table);
    g_object_unref(buffer);
    return NULL;
  }

  session = inf_text_session_new_with_user_table(
    manager,
    buffer,
    io,
    user_table,
    INF_SESSION_RUNNING,
    NULL,
    NULL
  );

  g_object_unref(user_table);
  g_object_unref(buffer);

  return INF_SESSION(session);
}
Пример #14
0
void Gobby::TextTabLabel::update_modified()
{
	InfSession* session = INF_SESSION(m_view.get_session());
	bool modified =
		inf_buffer_get_modified(inf_session_get_buffer(session));

	InfSessionStatus status = inf_session_get_status(session);
	if(status == INF_SESSION_SYNCHRONIZING ||
	   status == INF_SESSION_PRESYNC)
	{
		modified = false;
	}

	if(modified)
		m_title.set_text("*" + m_view.get_title());
	else
		m_title.set_text(m_view.get_title());
}
Пример #15
0
void Gobby::ViewCommands::on_hide_user_colors()
{
	SessionView* view = m_text_folder.get_current_document();
	TextSessionView* text_view = dynamic_cast<TextSessionView*>(view);
	g_assert(text_view != NULL);

	InfSession* session = INF_SESSION(text_view->get_session());
	GtkTextBuffer* textbuffer =
		GTK_TEXT_BUFFER(text_view->get_text_buffer());
	InfBuffer* buffer = inf_session_get_buffer(session);
	InfTextGtkBuffer* infbuffer = INF_TEXT_GTK_BUFFER(buffer);

	GtkTextIter start, end;
	gtk_text_buffer_get_start_iter(textbuffer, &start);
	gtk_text_buffer_get_end_iter(textbuffer, &end);

	inf_text_gtk_buffer_show_user_colors(infbuffer, FALSE, &start, &end);
}
Пример #16
0
void Gobby::TextTabLabel::on_changed(InfTextUser* author)
{
	if(!m_changed)
	{
		InfSession* session = INF_SESSION(m_view.get_session());
		if(inf_session_get_status(session) == INF_SESSION_RUNNING)
			set_changed();
	}

	if(m_folder.get_current_document() != &m_view)
	{
		// TODO: remove dot if all the user's
		// new contributions where undone
		if(std::find(m_changed_by.begin(), m_changed_by.end(), author)
		   == m_changed_by.end())
		{
			m_changed_by.push_back(UserWatcher(this, author));
			update_dots();
		}
	}
}
Пример #17
0
static InfSession*
infd_note_plugin_text_session_new(InfIo* io,
                                  InfCommunicationManager* manager,
                                  InfSessionStatus status,
                                  InfCommunicationHostedGroup* sync_group,
                                  InfXmlConnection* sync_connection,
                                  gpointer user_data)
{
  InfTextSession* session;

  session = inf_text_session_new(
    manager,
    INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")),
    io,
    status,
    INF_COMMUNICATION_GROUP(sync_group),
    sync_connection
  );

  return INF_SESSION(session);
}
Пример #18
0
static void
inf_adopted_session_local_user_added(InfAdoptedSession* session,
                                     InfAdoptedUser* user)
{
  InfAdoptedSessionPrivate* priv;
  InfSessionStatus status;
  InfAdoptedSessionLocalUser* local;
  InfAdoptedStateVector* current_state;

  priv = INF_ADOPTED_SESSION_PRIVATE(session);
  status = inf_session_get_status(INF_SESSION(session));

  /* Cannot be local while synchronizing */
  g_assert(status == INF_SESSION_RUNNING);

  local = g_slice_new(InfAdoptedSessionLocalUser);
  local->user = user;

  local->last_send_vector = inf_adopted_state_vector_copy(
    inf_adopted_user_get_vector(user)
  );

  /* Set current vector for local user, this is kept up-to-date by
   * InfAdoptedAlgorithm. TODO: Also do this in InfAdoptedAlgorithm? */
  inf_adopted_user_set_vector(
    user,
    inf_adopted_state_vector_copy(
      inf_adopted_algorithm_get_current(priv->algorithm)
    )
  );

  local->noop_time = 0;

  priv->local_users = g_slist_prepend(priv->local_users, local);

  /* Start noop timer if user is not up to date */
  current_state = inf_adopted_algorithm_get_current(priv->algorithm);
  if(inf_adopted_state_vector_compare(current_state, local->last_send_vector))
    inf_adopted_session_start_noop_timer(session, local);
}
Пример #19
0
void Gobby::TabLabel::update_icon()
{
	InfSession* session = INF_SESSION(m_view.get_session());

	if(inf_session_get_subscription_group(session) == NULL)
	{
		m_icon.set_from_icon_name("network-offline",
		                          Gtk::ICON_SIZE_MENU);
	}
	else
	{
		switch(inf_session_get_status(session))
		{
		case INF_SESSION_PRESYNC:
		case INF_SESSION_SYNCHRONIZING:
			// TODO: Switch to process-working, if/when m_icon can
			// show animations.
			m_icon.set_from_icon_name("system-run",
			                          Gtk::ICON_SIZE_MENU);
			break;
		case INF_SESSION_RUNNING:
			if(m_view.get_active_user() != NULL)
			{
				m_icon.set_from_icon_name(m_active_icon_name,
				                          Gtk::ICON_SIZE_MENU);
			}
			else
			{
				m_icon.set_from_icon_name("text-x-generic",
				                          Gtk::ICON_SIZE_MENU);
			}

			break;
		case INF_SESSION_CLOSED:
			m_icon.set_from_icon_name("network-offline",
			                          Gtk::ICON_SIZE_MENU);
			break;
		}
	}
}
static InfSession*
infinoted_plugin_note_chat_session_read(InfdStorage* storage,
                                        InfIo* io,
                                        InfCommunicationManager* manager,
                                        const gchar* path,
                                        gpointer user_data,
                                        GError** error)
{
  InfChatBuffer* buffer;
  gboolean result;
  InfChatSession* session;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));

  buffer = inf_chat_buffer_new(256);

  result = infd_chat_filesystem_format_read(
    INFD_FILESYSTEM_STORAGE(storage),
    path,
    buffer,
    error
  );

  if(result == FALSE)
  {
    g_object_unref(buffer);
    return NULL;
  }

  session = inf_chat_session_new(
    manager,
    buffer,
    INF_SESSION_RUNNING,
    NULL,
    NULL
  );

  g_object_unref(buffer);
  return INF_SESSION(session);
}
Пример #21
0
void Gobby::TabLabel::update_color()
{
	InfSession* session = INF_SESSION(m_view.get_session());

	if(m_changed)
	{
		// Document has changed: awareness -> red
		m_title.override_color(Gdk::RGBA("#c00000"));
	}
	else if(inf_session_get_subscription_group(session) == NULL ||
	        inf_session_get_status(session) != INF_SESSION_RUNNING)
	{
		// Document disconnected or not yet running
		// (most probably synchronizing): not (yet) available -> grey
		m_title.override_color(Gdk::RGBA("#606060"));
	}
	else
	{
		// Otherwise default
		m_title.unset_color();
	}
}
Пример #22
0
Gobby::TextTabLabel::TextTabLabel(Folder& folder, TextSessionView& view):
	TabLabel(folder, view, Gtk::Stock::EDIT), m_dot_char(0)
{
	update_modified();
	update_dots();

	m_modified_changed_handle = g_signal_connect_after(
		G_OBJECT(view.get_text_buffer()), "modified-changed",
		G_CALLBACK(on_modified_changed_static), this);

	InfTextBuffer* buffer = 
		INF_TEXT_BUFFER(
			inf_session_get_buffer(
				INF_SESSION(view.get_session())));
	m_insert_text_handle = g_signal_connect_after(
		G_OBJECT(buffer), "text-inserted",
		G_CALLBACK(on_text_inserted_static), this);
	m_erase_text_handle = g_signal_connect_after(
		G_OBJECT(buffer), "text-erased",
		G_CALLBACK(on_text_erased_static), this);

	m_extra.pack_start(m_dots, Gtk::PACK_SHRINK);
}
Пример #23
0
	void deactivate_user()
	{
		g_assert(m_active_user != NULL);

		switch(inf_user_get_status(m_active_user))
		{
		case INF_USER_INACTIVE:
			g_assert(m_timeout_connection.connected());
			m_timeout_connection.disconnect();
			break;
		case INF_USER_ACTIVE:
			/* Flush pending requests, so user is not set active
			 * again later. TODO: Maybe this should become a
			 * virtual function in InfSession actually. */
			flush();

			inf_session_set_user_status(
				INF_SESSION(m_view.get_session()),
				m_active_user, INF_USER_INACTIVE);
			break;
		case INF_USER_UNAVAILABLE:
			// It can happen that the user is already unavailable
			// here, for example when we have lost the connection
			// to the server, so this is not an error.

			// If the user was active before we lost the
			// connection then cancel the activation timeout
			if(m_timeout_connection.connected())
				m_timeout_connection.disconnect();

			// TODO: Shouldn't local users stay available on
			// connection loss? We probably need to fix this
			// in infinote.
			break;
		}
	}
Пример #24
0
static GObject*
inf_adopted_session_constructor(GType type,
                                guint n_construct_properties,
                                GObjectConstructParam* construct_properties)
{
  GObject* object;
  InfAdoptedSession* session;
  InfAdoptedSessionPrivate* priv;
  InfSessionStatus status;
  InfUserTable* user_table;

  object = G_OBJECT_CLASS(parent_class)->constructor(
    type,
    n_construct_properties,
    construct_properties
  );

  session = INF_ADOPTED_SESSION(object);
  priv = INF_ADOPTED_SESSION_PRIVATE(session);

  g_assert(priv->io != NULL);
  g_object_get(G_OBJECT(session), "status", &status, NULL);

  user_table = inf_session_get_user_table(INF_SESSION(session));

  g_signal_connect(
    G_OBJECT(user_table),
    "add-local-user",
    G_CALLBACK(inf_adopted_session_add_local_user_cb),
    session
  );

  g_signal_connect(
    G_OBJECT(user_table),
    "remove-local-user",
    G_CALLBACK(inf_adopted_session_remove_local_user_cb),
    session
  );

  switch(status)
  {
  case INF_SESSION_PRESYNC:
  case INF_SESSION_SYNCHRONIZING:
    /* algorithm is created during initial synchronization when parameters
     * like initial vector time, max total log size etc. are known. */
    break;
  case INF_SESSION_RUNNING:
    g_assert(inf_session_get_buffer(INF_SESSION(session)) != NULL);
    inf_adopted_session_create_algorithm(session);

    break;
  case INF_SESSION_CLOSED:
    /* Session should not be initially closed */
  default:
    g_assert_not_reached();
    break;
  }

  /* Add initial local users. Note that this requires the algorithm to exist, 
   * though in synchronizing state no local users can exist. */
  inf_user_table_foreach_local_user(
    user_table,
    inf_adopted_session_constructor_foreach_local_user_func,
    session
  );

  return object;
}
Пример #25
0
static InfSession*
infd_note_plugin_text_session_read(InfdStorage* storage,
                                   InfIo* io,
                                   InfCommunicationManager* manager,
                                   const gchar* path,
                                   gpointer user_data,
                                   GError** error)
{
  InfUserTable* user_table;
  InfTextBuffer* buffer;
  InfTextSession* session;

  FILE* stream;
  xmlDocPtr doc;
  xmlErrorPtr xmlerror;
  xmlNodePtr root;
  xmlNodePtr child;
  gboolean result;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));

  user_table = inf_user_table_new();
  buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8"));

  /* TODO: Use a SAX parser for better performance */
  stream = infd_filesystem_storage_open(
    INFD_FILESYSTEM_STORAGE(storage),
    "InfText",
    path,
    "r",
    error
  );

  if(stream == NULL) return FALSE;

  doc = xmlReadIO(
    infd_note_plugin_text_session_read_read_func,
    infd_note_plugin_text_sesison_read_close_func,
    stream,
    path, /* TODO: Get some "infinote-filesystem-storage://" URL? */
    "UTF-8",
    XML_PARSE_NOWARNING | XML_PARSE_NOERROR
  );

  if(doc == NULL)
  {
    xmlerror = xmlGetLastError();

    g_set_error(
      error,
      g_quark_from_static_string("LIBXML2_PARSER_ERROR"),
      xmlerror->code,
      "Error parsing XML in file '%s': [%d]: %s",
      path,
      xmlerror->line,
      xmlerror->message
    );

    result = FALSE;
  }
  else
  {
    root = xmlDocGetRootElement(doc);
    if(strcmp((const char*)root->name, "inf-text-session") != 0)
    {
      g_set_error(
        error,
        g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"),
        INFD_NOTE_PLUGIN_TEXT_ERROR_NOT_A_TEXT_SESSION,
        "Error processing file '%s': %s",
        path,
        "The document is not a text session"
      );

      result = FALSE;
    }
    else
    {
      for(child = root->children; child != NULL; child = child->next)
      {
        if(child->type != XML_ELEMENT_NODE)
          continue;

        if(strcmp((const char*)child->name, "user") == 0)
        {
          if(!infd_note_plugin_text_read_user(user_table, child, error))
          {
            g_prefix_error(error, "Error processing file '%s': ", path);
            result = FALSE;
            break;
          }
        }
        else if(strcmp((const char*)child->name, "buffer") == 0)
        {
          if(!infd_note_plugin_text_read_buffer(buffer, user_table,
                                                child, error))
          {
            g_prefix_error(error, "Error processing file '%s': ", path);
            result = FALSE;
            break;
          }
        }
        else
        {
          infd_note_plugin_text_session_unexpected_node(child, error);
          g_prefix_error(error, "Error processing file '%s': ", path);
          result = FALSE;
          break;
        }
      }

      if(child == NULL)
        result = TRUE;
    }

    xmlFreeDoc(doc);
  }

  if(result == FALSE)
    return NULL;

  session = inf_text_session_new_with_user_table(
    manager,
    buffer,
    io,
    user_table,
    INF_SESSION_RUNNING,
    NULL,
    NULL
  );

  return INF_SESSION(session);
}
Пример #26
0
int main(int argc, char* argv[])
{
  InfAdoptedSessionReplay* replay;
  InfAdoptedSession* session;
  GError* error;
  int i;
  int ret;

  InfBuffer* buffer;
  GSList* item;
  gint counter;

  if(argc < 2)
  {
    fprintf(stderr, "Usage: %s <record-file> [index]\n", argv[0]);
    return -1;
  }

  counter = 0;
  if(argc > 2) counter = atoi(argv[2]);

  error = NULL;
  if(!inf_init(&error))
  {
    fprintf(stderr, "%s\n", error->message);
    g_error_free(error);
    return -1;
  }

  ret = 0;
  for(i = 1; i < 2; ++ i)
  {
    replay = inf_adopted_session_replay_new();
    inf_adopted_session_replay_set_record(
      replay,
      argv[i],
      &INF_TEST_TEXT_RECOVER_TEXT_PLUGIN,
      &error
    );

    if(error != NULL)
    {
      fprintf(stderr, "%s\n", error->message);
      g_error_free(error);
      error = NULL;

      ret = -1;
    }
    else
    {
      session = inf_adopted_session_replay_get_session(replay);
      buffer = inf_session_get_buffer(INF_SESSION(session));

      g_signal_connect(
        buffer,
        "text-erased",
        G_CALLBACK(inf_test_text_recover_text_erased_cb),
        &counter
      );

      if(!inf_adopted_session_replay_play_to_end(replay, &error))
      {
        fprintf(stderr, "%s\n", error->message);
        g_error_free(error);
        error = NULL;

        ret = -1;
      }
      else if(counter == 0)
      {
        inf_test_util_print_buffer(INF_TEXT_BUFFER(buffer));
      }
    }

    g_object_unref(replay);
  }

  return ret;
}
Пример #27
0
void Gobby::OperationOpen::read_finish()
{
	// If the last character is a newline character, remove it.
	GtkTextIter end_iter, test_iter;
	gtk_text_buffer_get_end_iter(m_content, &end_iter);
	test_iter = end_iter;
	if(gtk_text_iter_backward_char(&test_iter))
	{
		if(gtk_text_iter_get_char(&test_iter) == '\n')
		{
			gtk_text_buffer_delete(
				m_content, &test_iter, &end_iter);
		}
	}

	gtk_text_buffer_set_modified(m_content, FALSE);

	GtkTextIter insert_iter;
	GtkTextMark* insert = gtk_text_buffer_get_insert(m_content);
	gtk_text_buffer_get_iter_at_mark(m_content, &insert_iter, insert);

	InfUser* user = INF_USER(g_object_new(
		INF_TEXT_TYPE_USER,
		"id", 1,
		"flags", INF_USER_LOCAL,
		"name", m_preferences.user.name.get().c_str(),
		/* The user is made active when the user
		 * switches to the document. */
		"status", INF_USER_INACTIVE,
		"hue", m_preferences.user.hue.get(),
		"caret-position", gtk_text_iter_get_offset(&insert_iter),
		static_cast<void*>(NULL)));

	InfUserTable* user_table = inf_user_table_new();
	inf_user_table_add_user(user_table, user);
	g_object_unref(user);

	InfTextGtkBuffer* text_gtk_buffer =
		inf_text_gtk_buffer_new(m_content, user_table);
	g_object_unref(user_table);

	ConnectionManager& connection_manager =
		get_browser().get_connection_manager();
	InfCommunicationManager* communication_manager =
		connection_manager.get_communication_manager();

	InfBrowser* browser = m_parent.get_browser();

	InfIo* io;
	g_object_get(G_OBJECT(browser), "io", &io, NULL);

	InfTextSession* session = inf_text_session_new_with_user_table(
		communication_manager, INF_TEXT_BUFFER(text_gtk_buffer), io,
		user_table, INF_SESSION_RUNNING, NULL, NULL);

	g_object_unref(io);
	g_object_unref(text_gtk_buffer);

	InfRequest* request = inf_browser_add_note(
		m_parent.get_browser(), m_parent.get_browser_iter(),
		m_name.c_str(), "InfText", NULL,
		INF_SESSION(session), TRUE,
		on_request_finished_static, this);
	g_object_unref(session);

	if(request != NULL)
	{
		m_request = request;
		g_object_ref(m_request);

		// TODO: We can remove the node watch here, but need to have
		// the browser available in on_request_finished then. Maybe
		// just disconnect the signal, or bind it.
	}
}
Пример #28
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);
	}
}