Beispiel #1
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
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");
}
Gobby::UserJoinCommands::UserJoinInfo::UserJoinInfo(UserJoinCommands& cmds,
                                                    InfBrowser* browser,
                                                    const InfBrowserIter* it,
                                                    InfSessionProxy* proxy,
                                                    Folder& folder,
                                                    SessionView& view):
	m_node(browser, it), m_commands(cmds), m_proxy(proxy),
	m_folder(folder), m_view(view), m_request(NULL),
	m_synchronization_complete_handler(0), m_retry_index(1)
{
	g_object_ref(m_proxy);

	InfSession* session;
	g_object_get(G_OBJECT(proxy), "session", &session, NULL);

	if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING)
	{
		// If not yet synchronized, wait for synchronization until
		// attempting userjoin
		m_synchronization_complete_handler = g_signal_connect_after(
			G_OBJECT(session), "synchronization-complete",
			G_CALLBACK(on_synchronization_complete_static), this);
	}
	else
	{
		// Delay this call to make sure we don't call finish()
		// right inside the constructor.
		Glib::signal_idle().connect(
			sigc::bind_return(sigc::mem_fun(
				*this, &UserJoinInfo::attempt_user_join),
				false));
	}

	g_object_unref(session);
}
static void
inf_test_mass_join_subscribe_finished_cb(InfRequest* request,
        const InfRequestResult* result,
        const GError* error,
        gpointer user_data)
{
    InfTestMassJoiner* joiner;
    const InfBrowserIter* iter;
    InfSession* session;

    joiner = (InfTestMassJoiner*)user_data;
    inf_request_result_get_subscribe_session(result, NULL, &iter, NULL);

    joiner->session = INFC_SESSION_PROXY(
                          inf_browser_get_session(
                              INF_BROWSER(joiner->browser),
                              iter
                          )
                      );

    g_assert(joiner->session != NULL);

    g_object_get(G_OBJECT(joiner->session), "session", &session, NULL);
    switch(inf_session_get_status(session))
    {
    case INF_SESSION_PRESYNC:
    case INF_SESSION_SYNCHRONIZING:
        g_signal_connect_after(
            G_OBJECT(session),
            "synchronization-failed",
            G_CALLBACK(inf_test_mass_join_session_synchronization_failed_cb),
            joiner
        );

        g_signal_connect_after(
            G_OBJECT(session),
            "synchronization-complete",
            G_CALLBACK(inf_test_mass_join_session_synchronization_complete_cb),
            joiner
        );

        break;
    case INF_SESSION_RUNNING:
        inf_test_mass_join_join_user(joiner);
        break;
    case INF_SESSION_CLOSED:
        fprintf(
            stderr,
            "Joiner %s: Session closed after subscription\n",
            joiner->username
        );

        inf_xml_connection_close(infc_browser_get_connection(joiner->browser));
        break;
    }

    g_object_unref(session);
}
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);
}
void
Gobby::SynchronizationCommands::on_document_added(SessionView& view)
{
	InfSession* session = view.get_session();
	if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING)
	{
		InfXmlConnection* connection;
		g_object_get(G_OBJECT(session),
		             "sync-connection", &connection, NULL);
		gdouble percentage = inf_session_get_synchronization_progress(
			session, connection);
		g_object_unref(connection);

		g_assert(m_sync_map.find(session) == m_sync_map.end());
		m_sync_map[session] = new SyncInfo(*this, view);
		set_progress_text(view, percentage);
	}
}
Beispiel #7
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());
}
Beispiel #8
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();
		}
	}
}
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);
}
Beispiel #10
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;
		}
	}
}
Beispiel #11
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();
	}
}
Beispiel #12
0
Gobby::UserJoin::UserJoin(InfBrowser* browser, const InfBrowserIter* iter,
                          InfSessionProxy* proxy,
                          std::auto_ptr<ParameterProvider> param_provider):
	m_node(browser, iter), m_proxy(proxy),
	m_param_provider(param_provider),
	m_synchronization_complete_handler(0), m_request(NULL),
	m_retry_index(1), m_user(NULL), m_error(NULL)
{
	g_object_ref(m_proxy);

	InfSession* session;
	g_object_get(G_OBJECT(proxy), "session", &session, NULL);

	if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING)
	{
		// If not yet synchronized, wait for synchronization until
		// attempting userjoin
		m_synchronization_complete_handler = g_signal_connect_after(
			G_OBJECT(session), "synchronization-complete",
			G_CALLBACK(on_synchronization_complete_static), this);
	}
	else
	{
		// Delay this call to make sure we don't emit the
		// finished signal right inside the constructor.
		// TODO: This might not be a problem, since the caller
		// can just check for completion with the get_user()
		// and get_error() methods.
		Glib::signal_idle().connect(
			sigc::bind_return(sigc::mem_fun(
				*this, &UserJoin::attempt_user_join),
				false));
	}

	g_object_unref(session);
}
Beispiel #13
0
static gboolean
infc_session_proxy_net_object_received(InfNetObject* net_object,
                                       InfXmlConnection* connection,
                                       xmlNodePtr node,
                                       GError** error)
{
  InfcSessionProxy* proxy;
  InfcSessionProxyPrivate* priv;
  InfcSessionProxyClass* proxy_class;
  InfSessionSyncStatus status;
  GError* local_error;

  InfcRequest* request;
  GError* seq_error;

  proxy = INFC_SESSION_PROXY(net_object);
  priv = INFC_SESSION_PROXY_PRIVATE(proxy);
  proxy_class = INFC_SESSION_PROXY_GET_CLASS(proxy);
  status = inf_session_get_synchronization_status(priv->session, connection);
  local_error = NULL;

  g_assert(status != INF_SESSION_SYNC_NONE || priv->connection == connection);
  g_assert(inf_session_get_status(priv->session) != INF_SESSION_CLOSED);

  if(status != INF_SESSION_SYNC_NONE)
  {
    /* Direct delegate during synchronization */
    return inf_net_object_received(
      INF_NET_OBJECT(priv->session),
      connection,
      node,
      error
    );
  }
  else
  {
    if(strcmp((const char*)node->name, "user-join") == 0)
    {
      infc_session_proxy_handle_user_join(
        proxy,
        connection,
        node,
        &local_error
      );
    }
    else if(strcmp((const char*)node->name, "user-rejoin") == 0)
    {
      infc_session_proxy_handle_user_rejoin(
        proxy,
        connection,
        node,
        &local_error
      );
    }
    else if(strcmp((const char*)node->name, "request-failed") == 0)
    {
      infc_session_proxy_handle_request_failed(
        proxy,
        connection,
        node,
        &local_error
      );
    }
    else if(strcmp((const char*)node->name, "session-close") == 0)
    {
      infc_session_proxy_handle_session_close(
        proxy,
        connection,
        node,
        &local_error
      );
    }
    else
    {
      return inf_net_object_received(
        INF_NET_OBJECT(priv->session),
        connection,
        node,
        error
      );
    }
  }

  if(local_error != NULL)
  {
    /* If the request had a (valid) seq set, we cancel the corresponding
     * request because the reply could not be processed. */
    request = infc_request_manager_get_request_by_xml(
      priv->request_manager,
      NULL,
      node,
      NULL
    );

    if(request != NULL)
    {
      /* If the request had a seq set, we cancel the corresponding request
       * because the reply could not be processed. */
      seq_error = NULL;
      g_set_error(
        &seq_error,
        inf_request_error_quark(),
        INF_REQUEST_ERROR_REPLY_UNPROCESSED,
        _("Server reply could not be processed: %s"),
        local_error->message
      );

      infc_request_manager_fail_request(
        priv->request_manager,
        request,
        seq_error
      );

      g_error_free(seq_error);
    }

    g_propagate_error(error, local_error);
  }

  /* Don't forward any of the handled messages */
  return FALSE;
}
Beispiel #14
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);
	}
}