Commit 7c046af7 authored by Zander Brown's avatar Zander Brown Committed by Guido Gunther
Browse files

app-grid: AppGrid widget to launch installed applications

parent 5601b5d7
/*
* Copyright © 2019 Zander Brown <zbrown@gnome.org>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#define G_LOG_DOMAIN "phosh-app-grid"
#include "app-grid.h"
#include "app-grid-button.h"
#include "app-list-model.h"
#include "gtk-list-models/gtksortlistmodel.h"
#include "gtk-list-models/gtkfilterlistmodel.h"
typedef struct _PhoshAppGridPrivate PhoshAppGridPrivate;
struct _PhoshAppGridPrivate {
GtkFilterListModel *model;
GtkWidget *search;
GtkWidget *apps;
};
G_DEFINE_TYPE_WITH_PRIVATE (PhoshAppGrid, phosh_app_grid, GTK_TYPE_BOX)
static gint
sort_apps (gconstpointer a,
gconstpointer b,
gpointer data)
{
GAppInfo *info1 = G_APP_INFO (a);
GAppInfo *info2 = G_APP_INFO (b);
gchar *s1, *s2;
gint ret;
s1 = g_utf8_casefold (g_app_info_get_display_name (info1), -1);
s2 = g_utf8_casefold (g_app_info_get_display_name (info2), -1);
ret = g_strcmp0 (s1, s2);
g_free (s1);
g_free (s2);
return ret;
}
static gboolean
search_apps (gpointer item, gpointer data)
{
PhoshAppGrid *self = data;
PhoshAppGridPrivate *priv = phosh_app_grid_get_instance_private (self);
GAppInfo *info = item;
const char *search = NULL;
const char *str = NULL;
g_return_val_if_fail (priv != NULL, TRUE);
g_return_val_if_fail (priv->search != NULL, TRUE);
search = gtk_entry_get_text (GTK_ENTRY (priv->search));
if (search == NULL)
return TRUE;
if ((str = g_app_info_get_display_name (info)) && strstr (str, search))
return TRUE;
if ((str = g_app_info_get_name (info)) && strstr (str, search))
return TRUE;
if ((str = g_app_info_get_description (info)) && strstr (str, search))
return TRUE;
if ((str = g_app_info_get_executable (info)) && strstr (str, search))
return TRUE;
if (G_IS_DESKTOP_APP_INFO (info)) {
const char * const *kwds;
int i = 0;
if ((str = g_desktop_app_info_get_generic_name (G_DESKTOP_APP_INFO (info))) &&
strstr (str, search))
return TRUE;
if ((str = g_desktop_app_info_get_categories (G_DESKTOP_APP_INFO (info))) &&
strstr (str, search))
return TRUE;
kwds = g_desktop_app_info_get_keywords (G_DESKTOP_APP_INFO (info));
if (kwds) {
while ((str = kwds[i])) {
if (strstr (str, search))
return TRUE;
i++;
}
}
}
return FALSE;
}
static GtkWidget *
create_launcher (gpointer item,
gpointer user_data)
{
GtkWidget *btn = phosh_app_grid_button_new (G_APP_INFO (item));
gtk_widget_show (btn);
return btn;
}
static void
phosh_app_grid_init (PhoshAppGrid *self)
{
PhoshAppGridPrivate *priv = phosh_app_grid_get_instance_private (self);
GtkSortListModel *sorted;
gtk_widget_init_template (GTK_WIDGET (self));
/* fill the grid with apps */
sorted = gtk_sort_list_model_new (G_LIST_MODEL (phosh_app_list_model_get_default ()),
sort_apps,
NULL,
NULL);
priv->model = gtk_filter_list_model_new (G_LIST_MODEL (sorted),
search_apps,
self,
NULL);
gtk_flow_box_bind_model (GTK_FLOW_BOX (priv->apps), G_LIST_MODEL (priv->model),
create_launcher, self, NULL);
}
static void
phosh_app_grid_finalize (GObject *object)
{
PhoshAppGrid *self = PHOSH_APP_GRID (object);
PhoshAppGridPrivate *priv = phosh_app_grid_get_instance_private (self);
g_clear_object (&priv->model);
G_OBJECT_CLASS (phosh_app_grid_parent_class)->finalize (object);
}
static gboolean
phosh_app_grid_key_press_event (GtkWidget *widget,
GdkEventKey *event)
{
PhoshAppGrid *self = PHOSH_APP_GRID (widget);
PhoshAppGridPrivate *priv = phosh_app_grid_get_instance_private (self);
return gtk_search_entry_handle_event (GTK_SEARCH_ENTRY (priv->search),
(GdkEvent *) event);
}
static void
search_changed (GtkSearchEntry *entry,
PhoshAppGrid *self)
{
PhoshAppGridPrivate *priv = phosh_app_grid_get_instance_private (self);
gtk_filter_list_model_refilter (priv->model);
}
static void
phosh_app_grid_class_init (PhoshAppGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = phosh_app_grid_finalize;
widget_class->key_press_event = phosh_app_grid_key_press_event;
gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/phosh/ui/app-grid.ui");
gtk_widget_class_bind_template_child_private (widget_class, PhoshAppGrid, search);
gtk_widget_class_bind_template_child_private (widget_class, PhoshAppGrid, apps);
gtk_widget_class_bind_template_callback (widget_class, search_changed);
gtk_widget_class_set_css_name (widget_class, "phosh-app-grid");
}
GtkWidget *
phosh_app_grid_new (void)
{
return g_object_new (PHOSH_TYPE_APP_GRID, NULL);
}
/*
* Copyright © 2019 Zander Brown <zbrown@gnome.org>
*
* SPDX-License-Identifier: GPL-3.0+
*/
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#define HANDY_USE_UNSTABLE_API
#include <handy.h>
#pragma once
G_BEGIN_DECLS
#define PHOSH_TYPE_APP_GRID phosh_app_grid_get_type()
G_DECLARE_DERIVABLE_TYPE (PhoshAppGrid, phosh_app_grid, PHOSH, APP_GRID, GtkBox)
struct _PhoshAppGridClass
{
GtkBoxClass parent_class;
};
GtkWidget *phosh_app_grid_new (void);
G_END_DECLS
......@@ -31,6 +31,8 @@ libphosh_sources = [
phosh_enums,
'activity.c',
'activity.h',
'app-grid.c',
'app-grid.h',
'app-grid-button.c',
'app-grid-button.h',
'app-list-model.c',
......
......@@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/sm/puri/phosh">
<file preprocess="xml-stripblanks">ui/activity.ui</file>
<file preprocess="xml-stripblanks">ui/app-grid.ui</file>
<file preprocess="xml-stripblanks">ui/app-grid-button.ui</file>
<file preprocess="xml-stripblanks">ui/overview.ui</file>
<file preprocess="xml-stripblanks">ui/home.ui</file>
......
......@@ -157,6 +157,15 @@ phosh-home, .phosh-panel {
padding: 18px;
}
/* switcher */
phosh-favorites {
background: rgba(0,0,0,0.6);
}
phosh-app-grid {
background: rgba(0,0,0,0.4);
}
phosh-app-grid-button {
font-size: 0.8rem;
}
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="PhoshAppGrid" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchEntry" id="search">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<signal name="search-changed" handler="search_changed" object="PhoshAppGrid" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFlowBox" id="apps">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">3</property>
<property name="margin_right">3</property>
<property name="margin_bottom">3</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="selection_mode">none</property>
<property name="activate_on_single_click">False</property>
<property name="column-spacing">6</property>
<property name="row-spacing">6</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">-1</property>
</packing>
</child>
<child>
<object class="GtkFlowBox" id="favs">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<property name="selection_mode">none</property>
<property name="activate_on_single_click">False</property>
<property name="column-spacing">6</property>
<property name="row-spacing">6</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</template>
</interface>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment