Beispiel #1
0
	void on_user_notify_status(InfUser* user)
	{
		// User cannot be activated when we are not active
		g_assert(m_active ||
		         inf_user_get_status(user) != INF_USER_ACTIVE);

		if(inf_user_get_status(user) == INF_USER_ACTIVE && m_active)
		{
			// The user did something (therefore becoming active),
			// so we do not need to explictely activate the user.
			g_assert(m_timeout_connection.connected());
			m_timeout_connection.disconnect();
		}
	}
static void
inf_text_gtk_viewport_user_removed(InfTextGtkViewport* viewport,
                                   InfTextUser* user)
{
  InfTextGtkViewportPrivate* priv;
  InfTextGtkViewportUser* viewport_user;

  priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport);

  if(user == priv->active_user)
  {
    priv->active_user = NULL;
    g_object_notify(G_OBJECT(viewport), "active-user");
  }
  else
  {
    inf_signal_handlers_disconnect_by_func(
      user,
      G_CALLBACK(inf_text_gtk_viewport_user_notify_status_cb),
      viewport
    );

    if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE)
    {
      viewport_user = inf_text_gtk_viewport_find_user(viewport, user);
      g_assert(viewport_user != NULL);

      inf_text_gtk_viewport_remove_user(viewport_user);
    }
  }
}
static void
inf_text_gtk_viewport_user_notify_status_cb(GObject* object,
                                            GParamSpec* pspec,
                                            gpointer user_data)
{
  InfTextGtkViewport* viewport;
  InfTextGtkViewportPrivate* priv;
  InfTextUser* user;
  InfTextGtkViewportUser* viewport_user;

  viewport = INF_TEXT_GTK_VIEWPORT(user_data);
  priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport);
  user = INF_TEXT_USER(object);

  g_assert(user != priv->active_user);
  viewport_user = inf_text_gtk_viewport_find_user(viewport, user);

  if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE)
  {
    if(!viewport_user)
      inf_text_gtk_viewport_add_user(viewport, user);
  }
  else
  {
    if(viewport_user)
      inf_text_gtk_viewport_remove_user(viewport_user);
  }
}
Beispiel #4
0
	void activate_user()
	{
		g_assert(!m_timeout_connection.connected());
		g_assert(m_active_user != NULL);
		g_assert(inf_user_get_status(m_active_user) ==
		         INF_USER_INACTIVE);

		m_timeout_connection = Glib::signal_timeout().connect(
			sigc::mem_fun(*this, &DocInfo::on_activation_timeout),
			ACTIVATION_DELAY);
	}
static gboolean
inf_user_table_is_local(InfUser* user)
{
  /* User counts as local when it has the local flag set and is available */
  if( (inf_user_get_flags(user) & INF_USER_LOCAL) == 0)
    return FALSE;
  if(inf_user_get_status(user) == INF_USER_UNAVAILABLE)
    return FALSE;

  return TRUE;
}
Beispiel #6
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;
	}
static void
infinoted_plugin_linekeeper_has_available_users_foreach_func(InfUser* user,
                                                             gpointer udata)
{
  InfinotedPluginLinekeeperHasAvailableUsersData* data;
  data = (InfinotedPluginLinekeeperHasAvailableUsersData*)udata;

  /* Return TRUE if there are non-local users connected */
  if(user != data->own_user &&
     inf_user_get_status(user) != INF_USER_UNAVAILABLE &&
     (inf_user_get_flags(user) & INF_USER_LOCAL) == 0)
  {
    data->has_available_user = TRUE;
  }
}
static void
inf_adopted_session_execute_request_cb(InfAdoptedAlgorithm* algorithm,
                                       InfAdoptedUser* user,
                                       InfAdoptedRequest* request,
                                       gboolean apply,
                                       gpointer user_data)
{
  InfAdoptedSession* session;
  InfAdoptedSessionPrivate* priv;
  GSList* item;
  InfAdoptedSessionLocalUser* local;
  guint id;

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

  if(inf_adopted_request_affects_buffer(request))
  {
    id = inf_adopted_request_get_user_id(request);

    /* A request has been executed, meaning we are no longer up to date. Send
     * a noop in some time, so that others know what we already processed. */
    for(item = priv->local_users; item != NULL; item = g_slist_next(item))
    {
      local = (InfAdoptedSessionLocalUser*)item->data;
      if(local->noop_time == 0)
        /* Except we issued the request ourselves, of course. */
        if(inf_user_get_id(INF_USER(local->user)) != id)
          inf_adopted_session_start_noop_timer(session, local);
    }
  }

  /* Mark inactive users active if they do something */
  /* Note: This behaviour is implicitly performed by both client and server,
   * and requires no further network traffic. However, users explictely have
   * to be set inactive. */
  if(inf_adopted_request_get_request_type(request) != INF_ADOPTED_REQUEST_DO ||
     !INF_ADOPTED_IS_NO_OPERATION(inf_adopted_request_get_operation(request)))
  {
    /* TODO: We should offer a virtual function to flush all requests for
     * local users, either here or even in InfSession via a vfunc, so that
     * we don't accidentally make local users active by a delayed request. */
    if(inf_user_get_status(INF_USER(user)) == INF_USER_INACTIVE)
      g_object_set(G_OBJECT(user), "status", INF_USER_ACTIVE, NULL);
  }
}
static void
user_name_data_func (GtkTreeViewColumn              *tree_column,
                     GtkCellRenderer                *cell,
                     GtkTreeModel                   *tree_model,
                     GtkTreeIter                    *iter,
                     GeditCollaborationWindowHelper *helper)
{
	InfUser *user;
	InfUserStatus status;
	const gchar *name;
	GtkStyle *style;
	GdkColor *color;
	PangoStyle user_style;

	gtk_tree_model_get (tree_model,
	                    iter,
	                    GEDIT_COLLABORATION_USER_STORE_COLUMN_USER,
	                    &user,
	                    -1);

	name = inf_user_get_name (user);
	status = inf_user_get_status (user);

	style = gtk_widget_get_style (helper->priv->tree_view_user_view);

	if (status == INF_USER_ACTIVE)
	{
		color = &style->fg[GTK_STATE_NORMAL];
		user_style = PANGO_STYLE_NORMAL;
	}
	else
	{
		color = &style->fg[GTK_STATE_INSENSITIVE];
		user_style = PANGO_STYLE_ITALIC;
	}

	g_object_set (cell,
	              "text", name,
	              "style", user_style,
	              "foreground-gdk", color,
	              NULL);

	g_object_unref (user);
}
static void
inf_text_gtk_viewport_user_added(InfTextGtkViewport* viewport,
                                 InfTextUser* user)
{
  InfTextGtkViewportPrivate* priv;
  priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport);

  /* Active user is guaranteed to be contained in user table, so if user was
   * just added then it can't be set as active user already. */
  g_assert(user != priv->active_user);

  g_signal_connect(
    user,
    "notify::status",
    G_CALLBACK(inf_text_gtk_viewport_user_notify_status_cb),
    viewport
  );

  if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE)
    inf_text_gtk_viewport_add_user(viewport, user);
}
Beispiel #11
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;
		}
	}
Beispiel #12
0
	void on_active_user_changed(InfUser* user)
	{
		if(m_active_user != NULL)
		{
			if(m_active)
				deactivate_user();

			g_signal_handler_disconnect(G_OBJECT(m_active_user),
			                            m_notify_status_handle);
		}

		m_active_user = user;

		if(user != NULL)
		{
			InfUserStatus user_status =
				inf_user_get_status(INF_USER(user));
			g_assert(user_status != INF_USER_UNAVAILABLE);

			m_notify_status_handle = g_signal_connect(
				G_OBJECT(user),
				"notify::status",
				G_CALLBACK(&on_user_notify_status_static),
				this
			);

			if( (user_status == INF_USER_ACTIVE && !m_active))
			{
				deactivate_user();
			}
			else if(user_status == INF_USER_INACTIVE && m_active)
			{
				activate_user();
			}
		}
	}
static InfCommunicationScope
inf_adopted_session_process_xml_run(InfSession* session,
                                    InfXmlConnection* connection,
                                    const xmlNodePtr xml,
                                    GError** error)
{
  InfAdoptedSessionPrivate* priv;
  InfAdoptedSessionClass* session_class;
  InfAdoptedRequest* request;
  InfAdoptedUser* user;

  gboolean has_num;
  guint num;
  GError* local_error;
  InfAdoptedRequest* copy_req;
  guint i;

  priv = INF_ADOPTED_SESSION_PRIVATE(session);

  if(strcmp((const char*)xml->name, "request") == 0)
  {
    session_class = INF_ADOPTED_SESSION_GET_CLASS(session);
    g_assert(session_class->xml_to_request != NULL);

    user = inf_adopted_session_user_from_request_xml(
      INF_ADOPTED_SESSION(session),
      xml,
      error
    );

    if(user == NULL)
      return INF_COMMUNICATION_SCOPE_PTP;

    if(inf_user_get_status(INF_USER(user)) == INF_USER_UNAVAILABLE ||
       inf_user_get_connection(INF_USER(user)) != connection)
    {
      g_set_error(
        error,
        inf_user_error_quark(),
        INF_USER_ERROR_NOT_JOINED,
        "%s",
        _("User did not join from this connection")
      );

      return INF_COMMUNICATION_SCOPE_PTP;
    }

    local_error = NULL;
    has_num = inf_xml_util_get_attribute_uint(xml, "num", &num, &local_error);
    if(local_error != NULL)
    {
      g_propagate_error(error, local_error);
      return INF_COMMUNICATION_SCOPE_PTP;
    }
    
    request = session_class->xml_to_request(
      INF_ADOPTED_SESSION(session),
      xml,
      inf_adopted_user_get_vector(user),
      FALSE,
      error
    );

    if(request == NULL)
      return INF_COMMUNICATION_SCOPE_PTP;

    inf_adopted_algorithm_receive_request(priv->algorithm, request);

    /* Apply the request more than once if num is given. This is mostly used
     * for multiple undos and redos, but is in general allowed for any
     * request. */
    if(has_num)
    {
      for(i = 1; i < num; ++i)
      {
        /* TODO: This is a bit of a hack since requests are normally
         * immutable. It avoids an additional vector copy here though. */
        copy_req = inf_adopted_request_copy(request);

        inf_adopted_state_vector_add(
          inf_adopted_request_get_vector(copy_req),
          inf_user_get_id(INF_USER(user)),
          i
        );

        inf_adopted_algorithm_receive_request(priv->algorithm, copy_req);
        g_object_unref(copy_req);
      }
    }

    g_object_unref(request);

    /* Requests can always be forwarded since user is given. */
    return INF_COMMUNICATION_SCOPE_GROUP;
  }

  return INF_SESSION_CLASS(parent_class)->process_xml_run(
    session,
    connection,
    xml,
    error
  );
}