model: Add visibility field
This field can be used to communicate the visibility of the panel from a static context (i.e. without any instances of a CcPanel nor any access to CcShell).
This commit is contained in:
parent
489a7ae5dd
commit
a78cbe3963
6 changed files with 246 additions and 63 deletions
|
@ -18,20 +18,24 @@
|
|||
* Author: Georges Basile Stavracas Neto <gbsneto@gnome.org>
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "cc-panel-list"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cc-debug.h"
|
||||
#include "cc-panel-list.h"
|
||||
#include "cc-util.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *row;
|
||||
GtkWidget *description_label;
|
||||
CcPanelCategory category;
|
||||
gchar *id;
|
||||
gchar *name;
|
||||
gchar *description;
|
||||
gchar **keywords;
|
||||
GtkWidget *row;
|
||||
GtkWidget *description_label;
|
||||
CcPanelCategory category;
|
||||
gchar *id;
|
||||
gchar *name;
|
||||
gchar *description;
|
||||
gchar **keywords;
|
||||
CcPanelVisibility visibility;
|
||||
} RowData;
|
||||
|
||||
struct _CcPanelList
|
||||
|
@ -106,6 +110,49 @@ get_listbox_from_view (CcPanelList *self,
|
|||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
get_listbox_from_category (CcPanelList *self,
|
||||
CcPanelCategory category)
|
||||
{
|
||||
|
||||
switch (category)
|
||||
{
|
||||
case CC_CATEGORY_DEVICES:
|
||||
return self->devices_listbox;
|
||||
break;
|
||||
|
||||
case CC_CATEGORY_DETAILS:
|
||||
return self->details_listbox;
|
||||
break;
|
||||
|
||||
default:
|
||||
return self->main_listbox;
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_row_below (CcPanelList *self,
|
||||
RowData *data)
|
||||
{
|
||||
GtkListBoxRow *next_row;
|
||||
GtkListBox *listbox;
|
||||
guint row_index;
|
||||
|
||||
row_index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (data->row));
|
||||
listbox = GTK_LIST_BOX (get_listbox_from_category (self, data->category));
|
||||
next_row = gtk_list_box_get_row_at_index (listbox, row_index + 1);
|
||||
|
||||
/* Try the previous one if the current is invalid */
|
||||
if (!next_row || next_row == self->devices_row || next_row == self->details_row)
|
||||
next_row = gtk_list_box_get_row_at_index (listbox, row_index - 1);
|
||||
|
||||
if (next_row)
|
||||
g_signal_emit_by_name (next_row, "activate");
|
||||
}
|
||||
|
||||
static CcPanelListView
|
||||
get_view_from_listbox (CcPanelList *self,
|
||||
GtkWidget *listbox)
|
||||
|
@ -159,12 +206,13 @@ row_data_free (RowData *data)
|
|||
}
|
||||
|
||||
static RowData*
|
||||
row_data_new (CcPanelCategory category,
|
||||
const gchar *id,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
gchar **keywords,
|
||||
const gchar *icon)
|
||||
row_data_new (CcPanelCategory category,
|
||||
const gchar *id,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
gchar **keywords,
|
||||
const gchar *icon,
|
||||
CcPanelVisibility visibility)
|
||||
{
|
||||
GtkWidget *label, *grid, *image;
|
||||
RowData *data;
|
||||
|
@ -222,6 +270,9 @@ row_data_new (CcPanelCategory category,
|
|||
|
||||
g_object_set_data_full (G_OBJECT (data->row), "data", data, (GDestroyNotify) row_data_free);
|
||||
|
||||
data->visibility = visibility;
|
||||
gtk_widget_set_visible (data->row, visibility == CC_PANEL_VISIBLE);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -766,18 +817,21 @@ cc_panel_list_activate (CcPanelList *self)
|
|||
{
|
||||
GtkListBoxRow *row;
|
||||
GtkWidget *listbox;
|
||||
guint i = 0;
|
||||
|
||||
CC_ENTRY;
|
||||
|
||||
g_return_val_if_fail (CC_IS_PANEL_LIST (self), FALSE);
|
||||
|
||||
listbox = get_listbox_from_view (self, self->view);
|
||||
|
||||
if (self->view == CC_PANEL_LIST_SEARCH)
|
||||
row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (listbox), 0);
|
||||
else
|
||||
row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (listbox), 0);
|
||||
/* Select the first visible row */
|
||||
do
|
||||
row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (listbox), i++);
|
||||
while (row && !gtk_widget_get_visible (GTK_WIDGET (row)));
|
||||
|
||||
/* If the row is valid, activate it */
|
||||
if (row)
|
||||
if (row && !gtk_list_box_row_is_selected (row))
|
||||
{
|
||||
gtk_list_box_select_row (GTK_LIST_BOX (listbox), row);
|
||||
gtk_widget_grab_focus (GTK_WIDGET (row));
|
||||
|
@ -785,7 +839,7 @@ cc_panel_list_activate (CcPanelList *self)
|
|||
g_signal_emit_by_name (row, "activate");
|
||||
}
|
||||
|
||||
return row != NULL;
|
||||
CC_RETURN (row != NULL);
|
||||
}
|
||||
|
||||
const gchar*
|
||||
|
@ -865,13 +919,14 @@ cc_panel_list_set_view (CcPanelList *self,
|
|||
}
|
||||
|
||||
void
|
||||
cc_panel_list_add_panel (CcPanelList *self,
|
||||
CcPanelCategory category,
|
||||
const gchar *id,
|
||||
const gchar *title,
|
||||
const gchar *description,
|
||||
gchar **keywords,
|
||||
const gchar *icon)
|
||||
cc_panel_list_add_panel (CcPanelList *self,
|
||||
CcPanelCategory category,
|
||||
const gchar *id,
|
||||
const gchar *title,
|
||||
const gchar *description,
|
||||
gchar **keywords,
|
||||
const gchar *icon,
|
||||
CcPanelVisibility visibility)
|
||||
{
|
||||
GtkWidget *listbox;
|
||||
RowData *data, *search_data;
|
||||
|
@ -879,27 +934,13 @@ cc_panel_list_add_panel (CcPanelList *self,
|
|||
g_return_if_fail (CC_IS_PANEL_LIST (self));
|
||||
|
||||
/* Add the panel to the proper listbox */
|
||||
data = row_data_new (category, id, title, description, keywords, icon);
|
||||
|
||||
switch (category)
|
||||
{
|
||||
case CC_CATEGORY_DEVICES:
|
||||
listbox = self->devices_listbox;
|
||||
break;
|
||||
|
||||
case CC_CATEGORY_DETAILS:
|
||||
listbox = self->details_listbox;
|
||||
break;
|
||||
|
||||
default:
|
||||
listbox = self->main_listbox;
|
||||
break;
|
||||
}
|
||||
data = row_data_new (category, id, title, description, keywords, icon, visibility);
|
||||
|
||||
listbox = get_listbox_from_category (self, category);
|
||||
gtk_container_add (GTK_CONTAINER (listbox), data->row);
|
||||
|
||||
/* And add to the search listbox too */
|
||||
search_data = row_data_new (category, id, title, description, keywords, icon);
|
||||
search_data = row_data_new (category, id, title, description, keywords, icon, visibility);
|
||||
gtk_container_add (GTK_CONTAINER (self->search_listbox), search_data->row);
|
||||
|
||||
g_hash_table_insert (self->id_to_data, data->id, data);
|
||||
|
@ -925,8 +966,19 @@ cc_panel_list_set_active_panel (CcPanelList *self,
|
|||
|
||||
g_assert (data != NULL);
|
||||
|
||||
/* Stop if row is supposed to be always hidden */
|
||||
if (data->visibility == CC_PANEL_HIDDEN)
|
||||
{
|
||||
g_debug ("Panel '%s' is always hidden, stopping.", id);
|
||||
cc_panel_list_activate (self);
|
||||
return;
|
||||
}
|
||||
|
||||
listbox = gtk_widget_get_parent (data->row);
|
||||
|
||||
/* The row might be hidden now, so make sure it's visible */
|
||||
gtk_widget_show (data->row);
|
||||
|
||||
gtk_list_box_select_row (GTK_LIST_BOX (listbox), GTK_LIST_BOX_ROW (data->row));
|
||||
gtk_widget_grab_focus (data->row);
|
||||
|
||||
|
@ -937,3 +989,38 @@ cc_panel_list_set_active_panel (CcPanelList *self,
|
|||
|
||||
g_signal_emit_by_name (data->row, "activate");
|
||||
}
|
||||
|
||||
/**
|
||||
* cc_panel_list_set_panel_visibility:
|
||||
* @self: a #CcPanelList
|
||||
* @id: the id of the panel
|
||||
* @visibility: visibility of panel with @id
|
||||
*
|
||||
* Sets the visibility of panel with @id. @id must be a valid
|
||||
* id with a corresponding panel.
|
||||
*/
|
||||
void
|
||||
cc_panel_list_set_panel_visibility (CcPanelList *self,
|
||||
const gchar *id,
|
||||
CcPanelVisibility visibility)
|
||||
{
|
||||
RowData *data;
|
||||
|
||||
g_return_if_fail (CC_IS_PANEL_LIST (self));
|
||||
|
||||
data = g_hash_table_lookup (self->id_to_data, id);
|
||||
|
||||
g_assert (data != NULL);
|
||||
|
||||
data->visibility = visibility;
|
||||
|
||||
/* If this is the currently selected row, and the panel can't be displayed
|
||||
* (i.e. visibility != VISIBLE), then select the next possible row */
|
||||
if (gtk_list_box_row_is_selected (GTK_LIST_BOX_ROW (data->row)) &&
|
||||
visibility != CC_PANEL_VISIBLE)
|
||||
{
|
||||
activate_row_below (self, data);
|
||||
}
|
||||
|
||||
gtk_widget_set_visible (data->row, visibility == CC_PANEL_VISIBLE);
|
||||
}
|
||||
|
|
|
@ -60,11 +60,16 @@ void cc_panel_list_add_panel (CcPanelList
|
|||
const gchar *title,
|
||||
const gchar *description,
|
||||
gchar **keywords,
|
||||
const gchar *icon);
|
||||
const gchar *icon,
|
||||
CcPanelVisibility visibility);
|
||||
|
||||
void cc_panel_list_set_active_panel (CcPanelList *self,
|
||||
const gchar *id);
|
||||
|
||||
void cc_panel_list_set_panel_visibility (CcPanelList *self,
|
||||
const gchar *id,
|
||||
CcPanelVisibility visibility);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* CC_PANEL_LIST_H */
|
||||
|
|
|
@ -36,6 +36,20 @@
|
|||
|
||||
G_DECLARE_DERIVABLE_TYPE (CcPanel, cc_panel, CC, PANEL, GtkBin)
|
||||
|
||||
/**
|
||||
* CcPanelVisibility:
|
||||
*
|
||||
* @CC_PANEL_HIDDEN: Panel is hidden from search and sidebar, and not reachable.
|
||||
* @CC_PANEL_VISIBLE_IN_SEARCH: Panel is hidden from main view, but can be accessed from search.
|
||||
* @CC_PANEL_VISIBLE: Panel is visible everywhere.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CC_PANEL_HIDDEN,
|
||||
CC_PANEL_VISIBLE_IN_SEARCH,
|
||||
CC_PANEL_VISIBLE,
|
||||
} CcPanelVisibility;
|
||||
|
||||
/* cc-shell.h requires CcPanel, so make sure it is defined first */
|
||||
#include "cc-shell.h"
|
||||
|
||||
|
|
|
@ -254,8 +254,8 @@ cc_shell_model_class_init (CcShellModelClass *klass)
|
|||
static void
|
||||
cc_shell_model_init (CcShellModel *self)
|
||||
{
|
||||
GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_APP_INFO, G_TYPE_STRING,
|
||||
G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV};
|
||||
GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_APP_INFO, G_TYPE_STRING, G_TYPE_UINT,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV, G_TYPE_UINT };
|
||||
|
||||
gtk_list_store_set_column_types (GTK_LIST_STORE (self),
|
||||
N_COLS, types);
|
||||
|
@ -318,6 +318,7 @@ cc_shell_model_add_item (CcShellModel *model,
|
|||
COL_CASEFOLDED_DESCRIPTION, casefolded_description,
|
||||
COL_GICON, icon,
|
||||
COL_KEYWORDS, keywords,
|
||||
COL_VISIBILITY, CC_PANEL_VISIBLE,
|
||||
-1);
|
||||
|
||||
g_free (casefolded_name);
|
||||
|
@ -399,3 +400,43 @@ cc_shell_model_set_sort_terms (CcShellModel *self,
|
|||
self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
cc_shell_model_set_panel_visibility (CcShellModel *self,
|
||||
const gchar *id,
|
||||
CcPanelVisibility visibility)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean valid;
|
||||
|
||||
g_return_if_fail (CC_IS_SHELL_MODEL (self));
|
||||
|
||||
model = GTK_TREE_MODEL (self);
|
||||
|
||||
/* Find the iter for the panel with the given id */
|
||||
valid = gtk_tree_model_get_iter_first (model, &iter);
|
||||
|
||||
while (valid)
|
||||
{
|
||||
g_autofree gchar *item_id = NULL;
|
||||
|
||||
gtk_tree_model_get (model, &iter, COL_ID, &item_id, -1);
|
||||
|
||||
/* Found the iter */
|
||||
if (g_str_equal (id, item_id))
|
||||
break;
|
||||
|
||||
/* If not found, continue */
|
||||
valid = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
|
||||
/* If we don't find any panel with the given id, we'll iterate until
|
||||
* valid == FALSE, so we can use this variable to determine if the
|
||||
* panel was found or not. It is a programming error to try to set
|
||||
* the visibility of a non-existant panel.
|
||||
*/
|
||||
g_assert (valid);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (self), &iter, COL_VISIBILITY, visibility, -1);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "cc-panel.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
@ -50,6 +52,7 @@ enum
|
|||
COL_CASEFOLDED_DESCRIPTION,
|
||||
COL_GICON,
|
||||
COL_KEYWORDS,
|
||||
COL_VISIBILITY,
|
||||
|
||||
N_COLS
|
||||
};
|
||||
|
@ -57,19 +60,23 @@ enum
|
|||
|
||||
CcShellModel* cc_shell_model_new (void);
|
||||
|
||||
void cc_shell_model_add_item (CcShellModel *model,
|
||||
CcPanelCategory category,
|
||||
GAppInfo *appinfo,
|
||||
const char *id);
|
||||
void cc_shell_model_add_item (CcShellModel *model,
|
||||
CcPanelCategory category,
|
||||
GAppInfo *appinfo,
|
||||
const char *id);
|
||||
|
||||
gboolean cc_shell_model_has_panel (CcShellModel *model,
|
||||
const char *id);
|
||||
gboolean cc_shell_model_has_panel (CcShellModel *model,
|
||||
const char *id);
|
||||
|
||||
gboolean cc_shell_model_iter_matches_search (CcShellModel *model,
|
||||
GtkTreeIter *iter,
|
||||
const char *term);
|
||||
gboolean cc_shell_model_iter_matches_search (CcShellModel *model,
|
||||
GtkTreeIter *iter,
|
||||
const char *term);
|
||||
|
||||
void cc_shell_model_set_sort_terms (CcShellModel *model,
|
||||
GStrv terms);
|
||||
void cc_shell_model_set_sort_terms (CcShellModel *model,
|
||||
GStrv terms);
|
||||
|
||||
void cc_shell_model_set_panel_visibility (CcShellModel *self,
|
||||
const gchar *id,
|
||||
CcPanelVisibility visible);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -162,11 +162,12 @@ get_symbolic_icon_name_from_g_icon (GIcon *gicon)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
activate_panel (CcWindow *self,
|
||||
const gchar *id,
|
||||
GVariant *parameters,
|
||||
const gchar *name,
|
||||
GIcon *gicon)
|
||||
activate_panel (CcWindow *self,
|
||||
const gchar *id,
|
||||
GVariant *parameters,
|
||||
const gchar *name,
|
||||
GIcon *gicon,
|
||||
CcPanelVisibility visibility)
|
||||
{
|
||||
g_autoptr (GTimer) timer = NULL;
|
||||
GtkWidget *box, *title_widget;
|
||||
|
@ -175,6 +176,9 @@ activate_panel (CcWindow *self,
|
|||
if (!id)
|
||||
return FALSE;
|
||||
|
||||
if (visibility == CC_PANEL_HIDDEN)
|
||||
return FALSE;
|
||||
|
||||
timer = g_timer_new ();
|
||||
|
||||
g_settings_set_string (self->settings, "last-panel", id);
|
||||
|
@ -283,6 +287,23 @@ update_list_title (CcWindow *self)
|
|||
gtk_header_bar_set_title (GTK_HEADER_BAR (self->header), title);
|
||||
}
|
||||
|
||||
static void
|
||||
on_row_changed_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
CcWindow *self)
|
||||
{
|
||||
g_autofree gchar *id = NULL;
|
||||
CcPanelVisibility visibility;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
COL_ID, &id,
|
||||
COL_VISIBILITY, &visibility,
|
||||
-1);
|
||||
|
||||
cc_panel_list_set_panel_visibility (CC_PANEL_LIST (self->panel_list), id, visibility);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_model (CcWindow *shell)
|
||||
{
|
||||
|
@ -309,6 +330,7 @@ setup_model (CcWindow *shell)
|
|||
g_autofree gchar *id = NULL;
|
||||
g_autofree gchar *icon_name = NULL;
|
||||
g_autofree GStrv keywords = NULL;
|
||||
CcPanelVisibility visibility;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
COL_CATEGORY, &category,
|
||||
|
@ -317,6 +339,7 @@ setup_model (CcWindow *shell)
|
|||
COL_ID, &id,
|
||||
COL_NAME, &name,
|
||||
COL_KEYWORDS, &keywords,
|
||||
COL_VISIBILITY, &visibility,
|
||||
-1);
|
||||
|
||||
icon_name = get_symbolic_icon_name_from_g_icon (icon);
|
||||
|
@ -327,10 +350,14 @@ setup_model (CcWindow *shell)
|
|||
name,
|
||||
description,
|
||||
keywords,
|
||||
icon_name);
|
||||
icon_name,
|
||||
visibility);
|
||||
|
||||
valid = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
|
||||
/* React to visibility changes */
|
||||
g_signal_connect_object (model, "row-changed", G_CALLBACK (on_row_changed_cb), shell, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -343,6 +370,7 @@ set_active_panel_from_id (CcShell *shell,
|
|||
{
|
||||
g_autoptr(GIcon) gicon = NULL;
|
||||
g_autofree gchar *name = NULL;
|
||||
CcPanelVisibility visibility;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *old_panel;
|
||||
CcWindow *self;
|
||||
|
@ -372,6 +400,7 @@ set_active_panel_from_id (CcShell *shell,
|
|||
COL_NAME, &name,
|
||||
COL_GICON, &gicon,
|
||||
COL_ID, &id,
|
||||
COL_VISIBILITY, &visibility,
|
||||
-1);
|
||||
|
||||
if (id && strcmp (id, start_id) == 0)
|
||||
|
|
Loading…
Add table
Reference in a new issue