Example #1
0
void Gobby::TitleBar::on_document_changed(SessionView* view)
{
	if(m_current_view != NULL)
	{
		InfSession* session = m_current_view->get_session();
		InfBuffer* buffer = inf_session_get_buffer(session);

		g_signal_handler_disconnect(G_OBJECT(session),
		                            m_notify_status_handler);
		g_signal_handler_disconnect(G_OBJECT(buffer),
		                            m_modified_changed_handler);
	}

	m_current_view = view;

	if(view != NULL)
	{
		InfSession* session = view->get_session();
		InfBuffer* buffer = inf_session_get_buffer(session);

		m_notify_status_handler = g_signal_connect(
			G_OBJECT(session), "notify::status",
			G_CALLBACK(on_notify_status_static), this);
		m_modified_changed_handler = g_signal_connect(
			G_OBJECT(buffer), "notify::modified",
			G_CALLBACK(on_notify_modified_static), this);
	}

	update_title();
}
static void
infinoted_plugin_autosave_session_added(const InfBrowserIter* iter,
                                        InfSessionProxy* proxy,
                                        gpointer plugin_info,
                                        gpointer session_info)
{
  InfinotedPluginAutosaveSessionInfo* info;
  InfSession* session;
  InfBuffer* buffer;

  info = (InfinotedPluginAutosaveSessionInfo*)session_info;
  info->plugin = (InfinotedPluginAutosave*)plugin_info;
  info->iter = *iter;
  info->proxy = proxy;
  info->timeout = NULL;
  g_object_ref(proxy);

  g_object_get(G_OBJECT(proxy), "session", &session, NULL);
  buffer = inf_session_get_buffer(session);

  g_signal_connect(
    G_OBJECT(buffer),
    "notify::modified",
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  if(inf_buffer_get_modified(buffer) == TRUE)
    infinoted_plugin_autosave_start(info);

  g_object_unref(session);
}
Example #3
0
void Gobby::TitleBar::update_title()
{
	// TODO: Show path, as gedit does. This requires change notification
	// for document info storage.
	if(m_current_view != NULL)
	{
		InfSession* session = m_current_view->get_session();
		InfBuffer* buffer = inf_session_get_buffer(session);

		InfSessionStatus status = inf_session_get_status(session);
		if(status == INF_SESSION_SYNCHRONIZING ||
		   !inf_buffer_get_modified(buffer))
		{
			m_window.set_title(
				m_current_view->get_title() + " - Gobby");
		}
		else
		{
			m_window.set_title(
				"*" + m_current_view->get_title() +
				" - Gobby");
		}
	}
	else
	{
		m_window.set_title("Gobby");
	}
}
static void
infinoted_plugin_autosave_buffer_notify_modified_cb(GObject* object,
                                                    GParamSpec* pspec,
                                                    gpointer user_data)
{
  InfinotedPluginAutosaveSessionInfo* info;
  InfSession* session;
  InfBuffer* buffer;

  info = (InfinotedPluginAutosaveSessionInfo*)user_data;
  g_object_get(G_OBJECT(info->proxy), "session", &session, NULL);
  buffer = inf_session_get_buffer(session);

  if(inf_buffer_get_modified(buffer) == TRUE)
  {
    if(info->timeout == NULL)
      infinoted_plugin_autosave_start(info);
  }
  else
  {
    if(info->timeout != NULL)
      infinoted_plugin_autosave_stop(info);
  }

  g_object_unref(session);
}
static void
infinoted_plugin_autosave_session_removed(const InfBrowserIter* iter,
                                          InfSessionProxy* proxy,
                                          gpointer plugin_info,
                                          gpointer session_info)
{
  InfinotedPluginAutosaveSessionInfo* info;
  InfSession* session;
  InfBuffer* buffer;

  info = (InfinotedPluginAutosaveSessionInfo*)session_info;

  /* Cancel autosave timeout even if session is modified. If the directory
   * removed the session, then it has already saved it anyway. */
  if(info->timeout != NULL)
    infinoted_plugin_autosave_stop(info);

  g_object_get(G_OBJECT(info->proxy), "session", &session, NULL);
  buffer = inf_session_get_buffer(session);

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  g_object_unref(session);
  g_object_unref(info->proxy);
}
Example #6
0
static void
infinoted_autosave_add_session(InfinotedAutosave* autosave,
                               InfdDirectoryIter* iter)
{
  InfinotedAutosaveSession* session;
  InfdSessionProxy* proxy;
  InfBuffer* buffer;

  g_assert(infinoted_autosave_find_session(autosave, iter) == NULL);

  session = g_slice_new(InfinotedAutosaveSession);
  session->autosave = autosave;
  session->iter = *iter;

  proxy = infd_directory_iter_peek_session(autosave->directory, iter);
  g_assert(proxy != NULL);
  session->proxy = proxy;
  session->timeout_handle = NULL;

  autosave->sessions = g_slist_prepend(autosave->sessions, session);

  buffer = inf_session_get_buffer(infd_session_proxy_get_session(proxy));

  g_signal_connect(
    G_OBJECT(buffer),
    "notify::modified",
    G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb),
    session
  );

  if(inf_buffer_get_modified(buffer) == TRUE)
  {
    infinoted_autosave_session_start(autosave, session);
  }
}
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");
}
static void
infinoted_directory_sync_remove_session(InfinotedDirectorySync* dsync,
                                        InfinotedDirectorySyncSession* sess)
{
  InfTextBuffer* buffer;

  if(sess->timeout != NULL)
  {
    infinoted_directory_sync_session_save(dsync, sess);
    infinoted_directory_sync_session_stop(dsync, sess);
  }

  buffer = INF_TEXT_BUFFER(
    inf_session_get_buffer(infd_session_proxy_get_session(sess->proxy))
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_directory_sync_buffer_text_inserted_cb),
    sess
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_directory_sync_buffer_text_erased_cb),
    sess
  );

  dsync->sessions = g_slist_remove(dsync->sessions, sess);

  g_free(sess->path);
  g_slice_free(InfinotedDirectorySyncSession, sess);
}
Example #9
0
	virtual void deactivate()
	{
		DocInfo::deactivate();

		InfTextGtkBuffer* buffer = INF_TEXT_GTK_BUFFER(
			inf_session_get_buffer(m_view.get_session()));

		inf_text_gtk_buffer_set_wake_on_cursor_movement(
			buffer, FALSE);
	}
static gboolean
infinoted_plugin_note_chat_session_write(InfdStorage* storage,
                                         InfSession* session,
                                         const gchar* path,
                                         gpointer user_data,
                                         GError** error)
{
  return infd_chat_filesystem_format_write(
    INFD_FILESYSTEM_STORAGE(storage),
    path,
    INF_CHAT_BUFFER(inf_session_get_buffer(session)),
    error
  );
}
Example #11
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);
}
Example #12
0
void Gobby::TitleBar::on_document_changed(SessionView* view)
{
	if(m_current_view != NULL)
	{
		InfSession* session = m_current_view->get_session();
		InfBuffer* buffer = inf_session_get_buffer(session);

		g_signal_handler_disconnect(G_OBJECT(session),
		                            m_notify_status_handler);
		g_signal_handler_disconnect(G_OBJECT(buffer),
		                            m_notify_modified_handler);
		
		m_rename_handler.disconnect();
	}

	m_current_view = view;

	if(view != NULL)
	{
		InfSession* session = view->get_session();
		InfBuffer* buffer = inf_session_get_buffer(session);

		m_notify_status_handler = g_signal_connect(
			G_OBJECT(session), "notify::status",
			G_CALLBACK(on_notify_status_static), this);
		m_notify_modified_handler = g_signal_connect(
			G_OBJECT(buffer), "notify::modified",
			G_CALLBACK(on_notify_modified_static), this);
		
		// We are subscribing to the view's signal to avoid a race condition,
		// since we can't otherwise guarantee that the view's new name has already been set
		m_rename_handler = m_current_view->signal_session_name_changed().connect(
			sigc::mem_fun(*this, &TitleBar::on_session_name_changed));
	}

	update_title();
}
Example #13
0
static void
inf_chat_test_subscribe_finished_cb(InfcNodeRequest* request,
                                    const InfcBrowserIter* iter,
                                    gpointer user_data)
{
  InfTestChat* test;
  InfSession* session;
  test = (InfTestChat*)user_data;

  printf("Subscription successful, waiting for synchronization...\n");

  session = infc_session_proxy_get_session(
    infc_browser_get_chat_session(test->browser));

  test->buffer = INF_CHAT_BUFFER(inf_session_get_buffer(session));

  /* TODO: Show backlog after during/after synchronization */

  g_signal_connect_after(
    G_OBJECT(session),
    "receive-message",
    G_CALLBACK(inf_chat_test_buffer_receive_message_cb),
    test
  );

  g_signal_connect_after(
    G_OBJECT(session),
    "synchronization-complete",
    G_CALLBACK(inf_chat_test_session_synchronization_complete_cb),
    test
  );

  g_signal_connect_after(
    G_OBJECT(session),
    "synchronization-failed",
    G_CALLBACK(inf_chat_test_session_synchronization_failed_cb),
    test
  );

  /* This can happen when the server disables the chat without being
   * shutdown. */
  g_signal_connect_after(
    G_OBJECT(session),
    "close",
    G_CALLBACK(inf_chat_test_session_close_cb),
    test
  );
}
static void
infinoted_plugin_linekeeper_session_added(const InfBrowserIter* iter,
                                          InfSessionProxy* proxy,
                                          gpointer plugin_info,
                                          gpointer session_info)
{
  InfinotedPluginLinekeeperSessionInfo* info;
  InfSession* session;
  InfUserTable* user_table;

  info = (InfinotedPluginLinekeeperSessionInfo*)session_info;

  info->plugin = (InfinotedPluginLinekeeper*)plugin_info;
  info->proxy = proxy;
  info->request = NULL;
  info->user = NULL;
  info->dispatch = NULL;
  g_object_ref(proxy);

  g_object_get(G_OBJECT(proxy), "session", &session, NULL);
  g_assert(inf_session_get_status(session) == INF_SESSION_RUNNING);
  info->buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session));
  g_object_ref(info->buffer);

  user_table = inf_session_get_user_table(session);

  g_signal_connect(
    G_OBJECT(user_table),
    "add-available-user",
    G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb),
    info
  );

  g_signal_connect(
    G_OBJECT(user_table),
    "remove-available-user",
    G_CALLBACK(infinoted_plugin_linekeeper_remove_available_user_cb),
    info
  );

  /* Only join a user when there are other nonlocal users available, so that
   * we don't keep the session from going idle. */
  if(infinoted_plugin_linekeeper_has_available_users(info) == TRUE)
    infinoted_plugin_linekeeper_join_user(info);

  g_object_unref(session);
}
static void
infinoted_plugin_document_stream_start(
  InfinotedPluginDocumentStreamStream* stream)
{
  InfSession* session;
  InfBuffer* buffer;

  g_object_get(G_OBJECT(stream->proxy), "session", &session, NULL);

  buffer = inf_session_get_buffer(session);
  stream->buffer = buffer;
  g_object_ref(buffer);

  if(INF_TEXT_IS_SESSION(session))
  {
    infinoted_plugin_document_stream_sync_text(stream);

    g_signal_connect(
      G_OBJECT(buffer),
      "text-inserted",
      G_CALLBACK(infinoted_plugin_document_stream_text_inserted_cb),
      stream
    );

    g_signal_connect(
      G_OBJECT(buffer),
      "text-erased",
      G_CALLBACK(infinoted_plugin_document_stream_text_erased_cb),
      stream
    );
  }
  else if(INF_IS_CHAT_SESSION(session))
  {
    infinoted_plugin_document_stream_sync_chat(stream);
    
    g_signal_connect_after(
      G_OBJECT(buffer),
      "add-message",
      G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb),
      stream
    );
  }

  g_object_unref(session);
}
Example #16
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);
}
Example #17
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());
}
void
Gobby::SynchronizationCommands::
	on_synchronization_complete(InfSession* session,
                                    InfXmlConnection* c)
{
	SyncMap::iterator iter = m_sync_map.find(session);
	g_assert(iter != m_sync_map.end());

	// TODO: Actually we should always set the modified flag, except the
	// document is either empty, or known in the document info storage
	// and the version on disk is the same as the one we got
	// synchronized. We could store a hash and modification time in the
	// documentinfo storage for this.
	InfBuffer* buffer = inf_session_get_buffer(session);
	inf_buffer_set_modified(buffer, FALSE);

	delete iter->second;
	m_sync_map.erase(iter);
}
void
Gobby::SynchronizationCommands::
	on_synchronization_failed(InfSession* session,
                                  InfXmlConnection* c,
                                  const GError* error)
{
	SyncMap::iterator iter = m_sync_map.find(session);
	g_assert(iter != m_sync_map.end());

	set_error_text(iter->second->get_session_view(), error->message);

	// The document will be of no use anyway, so consider it as not
	// being modified.
	InfBuffer* buffer = inf_session_get_buffer(session);
	inf_buffer_set_modified(buffer, FALSE);

	delete iter->second;
	m_sync_map.erase(iter);
}
Example #20
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);
}
Example #21
0
static void
infinoted_autosave_buffer_notify_modified_cb(GObject* object,
                                             GParamSpec* pspec,
                                             gpointer user_data)
{
  InfinotedAutosaveSession* session;
  InfBuffer* buffer;

  session = (InfinotedAutosaveSession*)user_data;
  buffer = inf_session_get_buffer(
    infd_session_proxy_get_session(session->proxy)
  );

  if(inf_buffer_get_modified(buffer) == TRUE)
  {
    if(session->timeout_handle == NULL)
      infinoted_autosave_session_start(session->autosave, session);
  }
  else
  {
    if(session->timeout_handle != NULL)
      infinoted_autosave_session_stop(session->autosave, session);
  }
}
Example #22
0
static void
on_subscribe_session(InfcBrowser* browser,
                     InfcBrowserIter* iter,
                     InfcSessionProxy* proxy,
                     gpointer user_data)
{
  GtkWidget* window;
  GtkWidget* scroll;
  GtkWidget* textview;
  GtkWidget* vbox;
  GtkWidget* hbox;
  GtkWidget* undo_button;
  GtkWidget* redo_button;
  InfSession* session;
  InfTextGtkBuffer* buffer;
  GtkTextBuffer* textbuffer;
  InfTestGtkBrowserWindow* test;

  session = infc_session_proxy_get_session(proxy);
  buffer = INF_TEXT_GTK_BUFFER(inf_session_get_buffer(session));
  textbuffer = inf_text_gtk_buffer_get_text_buffer(buffer);

  textview = gtk_text_view_new_with_buffer(textbuffer);
  gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE);
  gtk_widget_show(textview);

  scroll = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(
    GTK_SCROLLED_WINDOW(scroll),
    GTK_SHADOW_IN
  );

  gtk_scrolled_window_set_policy(
    GTK_SCROLLED_WINDOW(scroll),
    GTK_POLICY_AUTOMATIC,
    GTK_POLICY_AUTOMATIC
  );

  gtk_container_add(GTK_CONTAINER(scroll), textview);
  gtk_widget_show(scroll);

  undo_button = gtk_button_new_from_stock(GTK_STOCK_UNDO);
  redo_button = gtk_button_new_from_stock(GTK_STOCK_REDO);
  gtk_widget_set_sensitive(undo_button, FALSE);
  gtk_widget_set_sensitive(redo_button, FALSE);
  gtk_widget_show(undo_button);
  gtk_widget_show(redo_button);

  hbox = gtk_hbutton_box_new();
  gtk_box_pack_start(GTK_BOX(hbox), undo_button, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), redo_button, FALSE, FALSE, 0);
  gtk_widget_show(hbox);

  vbox = gtk_vbox_new(FALSE, 6);
  gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show(vbox);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title(
    GTK_WINDOW(window),
    infc_browser_iter_get_name(browser, iter)
  );

  gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
  gtk_window_set_icon_name(GTK_WINDOW(window), "infinote");
  gtk_container_set_border_width(GTK_CONTAINER(window), 6);
  gtk_container_add(GTK_CONTAINER(window), vbox);
  gtk_widget_show(window);

  test = g_slice_new(InfTestGtkBrowserWindow);
  test->textview = textview;
  test->undo_button = undo_button;
  test->redo_button = redo_button;
  test->buffer = buffer;
  test->proxy = proxy;
  test->user = NULL;

  g_signal_connect_after(
    G_OBJECT(session),
    "synchronization-failed",
    G_CALLBACK(on_synchronization_failed),
    test
  );

  g_signal_connect_after(
    G_OBJECT(session),
    "synchronization-complete",
    G_CALLBACK(on_synchronization_complete),
    test
  );

  g_signal_connect(
    G_OBJECT(window),
    "destroy",
    G_CALLBACK(on_text_window_destroy),
    test
  );

  g_signal_connect(
    G_OBJECT(undo_button),
    "clicked",
    G_CALLBACK(on_undo_button_clicked),
    test
  );

  g_signal_connect(
    G_OBJECT(redo_button),
    "clicked",
    G_CALLBACK(on_redo_button_clicked),
    test
  );
}
static gboolean
infinoted_directory_sync_add_session(InfinotedDirectorySync* dsync,
                                     InfdDirectoryIter* iter,
                                     GError** error)
{
  InfinotedDirectorySyncSession* session;
  InfdSessionProxy* proxy;
  InfBuffer* buffer;
  gchar* iter_path;
#ifdef G_OS_WIN32
  gchar* pos;
#endif
  gchar* full_path;
  gchar* converted;

  g_assert(infinoted_directory_sync_find_session(dsync, iter) == NULL);

  proxy = infd_directory_iter_peek_session(dsync->directory, iter);
  g_assert(proxy != NULL);

  /* Ignore if this is not a text session */
  if(!INF_TEXT_IS_SESSION(infd_session_proxy_get_session(proxy)))
    return TRUE;

  iter_path = infd_directory_iter_get_path(dsync->directory, iter);
#ifdef G_OS_WIN32
  for(pos = iter_path; *pos != '\0'; ++pos)
  {
    if(*pos == '\\')
    {
      g_set_error(
        error,
        infinoted_directory_sync_error_quark(),
        INFINOTED_DIRECTORY_SYNC_ERROR_INVALID_PATH,
        _("Node \"%s\" contains invalid characters"),
        iter_path
      );

      g_free(iter_path);
      return FALSE;
    }
    else if(*pos == '/')
    {
      *pos = '\\';
    }
  }
#endif

  full_path = g_build_filename(dsync->sync_directory, iter_path+1, NULL);
  g_free(iter_path);

  converted = g_filename_from_utf8(full_path, -1, NULL, NULL, error);
  g_free(full_path);
  if(!converted) return FALSE;

  session = g_slice_new(InfinotedDirectorySyncSession);
  session->dsync = dsync;
  session->iter = *iter;

  session->proxy = proxy;
  session->timeout = NULL;
  session->path = converted;

  dsync->sessions = g_slist_prepend(dsync->sessions, session);

  buffer = inf_session_get_buffer(infd_session_proxy_get_session(proxy));

  g_signal_connect(
    G_OBJECT(buffer),
    "text-inserted",
    G_CALLBACK(infinoted_directory_sync_buffer_text_inserted_cb),
    session
  );

  g_signal_connect(
    G_OBJECT(buffer),
    "text-erased",
    G_CALLBACK(infinoted_directory_sync_buffer_text_erased_cb),
    session
  );

  infinoted_directory_sync_session_save(dsync, session);
  return TRUE;
}
static void
infinoted_directory_sync_session_save(InfinotedDirectorySync* dsync,
                                      InfinotedDirectorySyncSession* session)
{
  InfdDirectoryIter* iter;
  GError* error;
  InfBuffer* buffer;
  InfTextChunk* chunk;
  gchar* content;
  gsize bytes;

  iter = &session->iter;
  error = NULL;

  if(session->timeout != NULL)
  {
    inf_io_remove_timeout(
      infd_directory_get_io(dsync->directory),
      session->timeout
    );

    session->timeout = NULL;
  }

  buffer = inf_session_get_buffer(
    infd_session_proxy_get_session(session->proxy)
  );

  error = NULL;
  if(!infinoted_util_create_dirname(session->path, &error))
  {
    g_warning(_("Failed to create directory for path \"%s\": %s\n\n"),
              session->path, error->message);
    g_error_free(error);
  }
  else
  {
    /* TODO: Use the iterator API here, which should be less expensive */
    chunk = inf_text_buffer_get_slice(
      INF_TEXT_BUFFER(buffer),
      0,
      inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer))
    );

    content = inf_text_chunk_get_text(chunk, &bytes);
    inf_text_chunk_free(chunk);

    if(!g_file_set_contents(session->path, content, bytes, &error))
    {
      g_warning(
        _("Failed to write session for path \"%s\": %s\n\n"
          "Will retry in %u seconds."),
        session->path, error->message, dsync->sync_interval
      );

      g_error_free(error);

      infinoted_directory_sync_session_start(session->dsync, session);
    }

    g_free(content);
  }
}
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;
}
Example #26
0
static void
infinoted_autosave_session_save(InfinotedAutosave* autosave,
                                InfinotedAutosaveSession* session)
{
  InfdDirectory* directory;
  InfdDirectoryIter* iter;
  GError* error;
  gchar* path;
  InfBuffer* buffer;

  directory = autosave->directory;
  iter = &session->iter;
  error = NULL;

  if(session->timeout_handle != NULL)
  {
    inf_io_remove_timeout(
      infd_directory_get_io(directory),
      session->timeout_handle
    );

    session->timeout_handle = NULL;
  }

  buffer = inf_session_get_buffer(
    infd_session_proxy_get_session(session->proxy)
  );

  g_signal_handlers_block_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb),
    session
  );

  if(infd_directory_iter_save_session(directory, iter, &error) == FALSE)
  {
    path = infd_directory_iter_get_path(directory, iter);
    g_warning(
      _("Failed to auto-save session \"%s\": %s\n\n"
        "Will retry in %u seconds."),
      path,
      error->message,
      session->autosave->autosave_interval
    );

    g_free(path);
    g_error_free(error);

    infinoted_autosave_session_start(session->autosave, session);
  }
  else
  {
    /* TODO: Remove this as soon as directory itself unsets modified flag
     * on session_write */
    inf_buffer_set_modified(INF_BUFFER(buffer), FALSE);
  }

  g_signal_handlers_unblock_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_autosave_buffer_notify_modified_cb),
    session
  );
}
static gboolean
infd_note_plugin_text_session_write(InfdStorage* storage,
                                    InfSession* session,
                                    const gchar* path,
                                    gpointer user_data,
                                    GError** error)
{
  InfUserTable* table;
  InfTextBuffer* buffer;
  InfTextBufferIter* iter;
  xmlNodePtr root;
  xmlNodePtr buffer_node;
  xmlNodePtr segment_node;

  guint author;
  gchar* content;
  gsize bytes;

  FILE* stream;
  xmlDocPtr doc;
  xmlErrorPtr xmlerror;

  g_assert(INFD_IS_FILESYSTEM_STORAGE(storage));
  g_assert(INF_TEXT_IS_SESSION(session));

  /* Open stream before exporting buffer to XML so possible errors are
   * catched earlier. */
  stream = infd_filesystem_storage_open(
    INFD_FILESYSTEM_STORAGE(storage),
    "InfText",
    path,
    "w",
    error
  );

  if(stream == NULL)
    return FALSE;

  root = xmlNewNode(NULL, (const xmlChar*)"inf-text-session");
  buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session));
  table = inf_session_get_user_table(session);

  inf_user_table_foreach_user(
    table,
    infd_note_plugin_text_session_write_foreach_user_func,
    root
  );

  buffer_node = xmlNewChild(root, NULL, (const xmlChar*)"buffer", NULL);
  iter = inf_text_buffer_create_iter(buffer);
  if(iter != NULL)
  {
    do
    {
      author = inf_text_buffer_iter_get_author(buffer, iter);
      content = inf_text_buffer_iter_get_text(buffer, iter);
      bytes = inf_text_buffer_iter_get_bytes(buffer, iter);

      segment_node = xmlNewChild(
        buffer_node,
        NULL,
        (const xmlChar*)"segment",
        NULL
      );

      inf_xml_util_set_attribute_uint(segment_node, "author", author);
      inf_xml_util_add_child_text(segment_node, content, bytes);
      g_free(content);
    } while(inf_text_buffer_iter_next(buffer, iter));

    inf_text_buffer_destroy_iter(buffer, iter);
  }

  doc = xmlNewDoc((const xmlChar*)"1.0");
  xmlDocSetRootElement(doc, root);

  if(xmlDocFormatDump(stream, doc, 1) == -1)
  {
    xmlerror = xmlGetLastError();
    fclose(stream);
    xmlFreeDoc(doc);

    g_set_error(
      error,
      g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"),
      xmlerror->code,
      "%s",
      xmlerror->message
    );

    return FALSE;
  }

  fclose(stream);
  xmlFreeDoc(doc);
  return TRUE;
}
Example #28
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;
}
static void
infinoted_plugin_autosave_save(InfinotedPluginAutosaveSessionInfo* info)
{
  InfdDirectory* directory;
  InfBrowserIter* iter;
  GError* error;
  gchar* path;
  InfSession* session;
  InfBuffer* buffer;
  gchar* root_directory;
  gchar* argv[4];

  directory = infinoted_plugin_manager_get_directory(info->plugin->manager);
  iter = &info->iter;
  error = NULL;

  if(info->timeout != NULL)
  {
    inf_io_remove_timeout(infd_directory_get_io(directory), info->timeout);
    info->timeout = NULL;
  }

  g_object_get(G_OBJECT(info->proxy), "session", &session, NULL);
  buffer = inf_session_get_buffer(session);

  inf_signal_handlers_block_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  if(infd_directory_iter_save_session(directory, iter, &error) == FALSE)
  {
    path = inf_browser_get_path(INF_BROWSER(directory), iter);

    infinoted_log_warning(
      infinoted_plugin_manager_get_log(info->plugin->manager),
      _("Failed to auto-save session \"%s\": %s\n\n"
        "Will retry in %u seconds."),
      path,
      error->message,
      info->plugin->interval
    );

    g_free(path);
    g_error_free(error);
    error = NULL;

    infinoted_plugin_autosave_start(info);
  }
  else
  {
    /* TODO: Remove this as soon as directory itself unsets modified flag
     * on session_write */
    inf_buffer_set_modified(INF_BUFFER(buffer), FALSE);

    if(info->plugin->hook != NULL)
    {
      path = inf_browser_get_path(INF_BROWSER(directory), iter);

      g_object_get(
        G_OBJECT(infd_directory_get_storage(directory)),
        "root-directory",
        &root_directory,
        NULL
      );

      argv[0] = info->plugin->hook;
      argv[1] = root_directory;
      argv[2] = path;
      argv[3] = NULL;

      if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
                        NULL, NULL, NULL, &error))
      {
        infinoted_log_warning(
          infinoted_plugin_manager_get_log(info->plugin->manager),
          _("Could not execute autosave hook: \"%s\""),
          error->message
        );

        g_error_free(error);
        error = NULL;
      }

      g_free(path);
      g_free(root_directory);
    }
  }
  
  inf_signal_handlers_unblock_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  g_object_unref(session);
}