summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Davis <christopherdavis@gnome.org>2022-12-15 18:11:49 -0500
committerChristopher Davis <christopherdavis@gnome.org>2022-12-15 18:28:06 -0500
commitf7e309a36e531881c354534b0c42dd4396ac9170 (patch)
treeaa22db700cf5e0334cdc71e34993c0b04c09b682
parent2f3a0ff306386ac5f08588ec6323c2936ed58337 (diff)
downloadgnome-control-center-wip/cdavis/default-apps.tar.gz
default-apps: Use new adwaita widgetry, drop deprecated APIwip/cdavis/default-apps
GTK has deprecated the AppChooser interface and related widgets. These APIs will be gone in GTK5, so we should move away from them as soon as possible. This MR takes the opportunity to change the design to match newer mockups while dropping deprecated APIs.
-rw-r--r--panels/default-apps/cc-default-apps-panel.c184
-rw-r--r--panels/default-apps/cc-default-apps-panel.ui136
-rw-r--r--panels/default-apps/cc-default-apps-row.c223
-rw-r--r--panels/default-apps/cc-default-apps-row.h30
-rw-r--r--panels/default-apps/meson.build3
5 files changed, 317 insertions, 259 deletions
diff --git a/panels/default-apps/cc-default-apps-panel.c b/panels/default-apps/cc-default-apps-panel.c
index 95da3e70a..35a011671 100644
--- a/panels/default-apps/cc-default-apps-panel.c
+++ b/panels/default-apps/cc-default-apps-panel.c
@@ -25,6 +25,7 @@
#endif
#include "cc-default-apps-panel.h"
+#include "cc-default-apps-row.h"
#include "cc-default-apps-resources.h"
#include "shell/cc-object-storage.h"
@@ -32,7 +33,6 @@
typedef struct
{
const char *content_type;
- gint label_offset;
/* Patterns used to filter supported mime types
when changing preferred applications. NULL
means no other types should be changed */
@@ -45,14 +45,14 @@ struct _CcDefaultAppsPanel
GtkWidget *default_apps_grid;
- GtkWidget *web_label;
- GtkWidget *mail_label;
- GtkWidget *calendar_label;
- GtkWidget *music_label;
- GtkWidget *video_label;
- GtkWidget *photos_label;
- GtkWidget *calls_label;
- GtkWidget *sms_label;
+ GtkWidget *web_row;
+ GtkWidget *mail_row;
+ GtkWidget *calendar_row;
+ GtkWidget *music_row;
+ GtkWidget *video_row;
+ GtkWidget *photos_row;
+ GtkWidget *calls_row;
+ GtkWidget *sms_row;
#ifdef BUILD_WWAN
MMManager *mm_manager;
@@ -62,155 +62,18 @@ struct _CcDefaultAppsPanel
G_DEFINE_TYPE (CcDefaultAppsPanel, cc_default_apps_panel, CC_TYPE_PANEL)
-static void
-default_app_changed (CcDefaultAppsPanel *self,
- GtkAppChooserButton *button)
-{
- g_autoptr(GAppInfo) info = NULL;
- g_autoptr(GError) error = NULL;
- DefaultAppData *app_data;
- int i;
-
- info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (button));
- app_data = g_object_get_data (G_OBJECT (button), "cc-default-app-data");
-
- if (g_app_info_set_as_default_for_type (info, app_data->content_type, &error) == FALSE)
- {
- g_warning ("Failed to set '%s' as the default application for '%s': %s",
- g_app_info_get_name (info), app_data->content_type, error->message);
- }
- else
- {
- g_debug ("Set '%s' as the default handler for '%s'",
- g_app_info_get_name (info), app_data->content_type);
- }
-
- if (app_data->extra_type_filter)
- {
- g_auto(GStrv) entries = NULL;
- const char *const *mime_types;
- g_autoptr(GPtrArray) patterns = NULL;
-
- entries = g_strsplit (app_data->extra_type_filter, ";", -1);
- patterns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free);
- for (i = 0; entries[i] != NULL; i++)
- {
- GPatternSpec *pattern = g_pattern_spec_new (entries[i]);
- g_ptr_array_add (patterns, pattern);
- }
-
- mime_types = g_app_info_get_supported_types (info);
- for (i = 0; mime_types && mime_types[i]; i++)
- {
- int j;
- gboolean matched = FALSE;
- g_autoptr(GError) local_error = NULL;
-
- for (j = 0; j < patterns->len; j++)
- {
- GPatternSpec *pattern = g_ptr_array_index (patterns, j);
- if (g_pattern_spec_match_string (pattern, mime_types[i]))
- matched = TRUE;
- }
- if (!matched)
- continue;
-
- if (g_app_info_set_as_default_for_type (info, mime_types[i], &local_error) == FALSE)
- {
- g_warning ("Failed to set '%s' as the default application for secondary "
- "content type '%s': %s",
- g_app_info_get_name (info), mime_types[i], local_error->message);
- }
- else
- {
- g_debug ("Set '%s' as the default handler for '%s'",
- g_app_info_get_name (info), mime_types[i]);
- }
- }
- }
-}
-
-#define OFFSET(x) (G_STRUCT_OFFSET (CcDefaultAppsPanel, x))
-#define WIDGET_FROM_OFFSET(x) (G_STRUCT_MEMBER (GtkWidget*, self, x))
-
-static void
-info_panel_setup_default_app (CcDefaultAppsPanel *self,
- DefaultAppData *data,
- guint column,
- guint row)
-{
- GtkWidget *button;
- GtkWidget *label;
-
- button = gtk_app_chooser_button_new (data->content_type);
- g_object_set_data (G_OBJECT (button), "cc-default-app-data", data);
-
- gtk_app_chooser_button_set_show_default_item (GTK_APP_CHOOSER_BUTTON (button), TRUE);
- gtk_grid_attach (GTK_GRID (self->default_apps_grid), button, column, row, 1, 1);
- g_signal_connect_object (G_OBJECT (button), "changed",
- G_CALLBACK (default_app_changed), self, G_CONNECT_SWAPPED);
-
- label = WIDGET_FROM_OFFSET (data->label_offset);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
-
- g_object_bind_property (G_OBJECT (label), "visible", G_OBJECT (button), "visible", G_BINDING_SYNC_CREATE);
-}
-
-static DefaultAppData preferred_app_infos[] = {
- { "x-scheme-handler/http", OFFSET (web_label), "text/html;application/xhtml+xml;x-scheme-handler/https" },
- { "x-scheme-handler/mailto", OFFSET (mail_label), NULL },
- { "text/calendar", OFFSET (calendar_label), NULL },
- { "audio/x-vorbis+ogg", OFFSET (music_label), "audio/*" },
- { "video/x-ogm+ogg", OFFSET (video_label), "video/*" },
- { "image/jpeg", OFFSET (photos_label), "image/*" },
- { "x-scheme-handler/tel", OFFSET(calls_label), NULL},
- { "x-scheme-handler/sms", OFFSET(sms_label), NULL},
-};
-
-static void
-info_panel_setup_default_apps (CcDefaultAppsPanel *self)
-{
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (preferred_app_infos); i++)
- {
- info_panel_setup_default_app (self, &preferred_app_infos[i],
- 1, i);
- }
-}
-
#ifdef BUILD_WWAN
static void
update_modem_apps_visibility (CcDefaultAppsPanel *self)
{
GList *devices;
- GtkWidget *calls_button;
- GtkWidget *sms_button;
- int count, row;
+ gboolean has_mm_objects;
devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->mm_manager));
- count = g_list_length (devices);
-
- gtk_grid_query_child (GTK_GRID (self->default_apps_grid), self->calls_label, NULL, &row, NULL, NULL);
- calls_button = gtk_grid_get_child_at (GTK_GRID (self->default_apps_grid), 1, row);
+ has_mm_objects = g_list_length (devices) > 0;
- gtk_grid_query_child (GTK_GRID (self->default_apps_grid), self->sms_label, NULL, &row, NULL, NULL);
- sms_button = gtk_grid_get_child_at (GTK_GRID (self->default_apps_grid), 1, row);
-
- if (count > 0)
- {
- gtk_widget_show (self->calls_label);
- gtk_widget_show (self->sms_label);
- gtk_widget_show (calls_button);
- gtk_widget_show (sms_button);
- }
- else
- {
- gtk_widget_hide (self->calls_label);
- gtk_widget_hide (self->sms_label);
- gtk_widget_hide (calls_button);
- gtk_widget_hide (sms_button);
- }
+ gtk_widget_set_visible (self->calls_row, has_mm_objects);
+ gtk_widget_set_visible (self->sms_row, has_mm_objects);
g_list_free_full (devices, (GDestroyNotify)g_object_unref);
}
@@ -222,15 +85,14 @@ cc_default_apps_panel_class_init (CcDefaultAppsPanelClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/default-apps/cc-default-apps-panel.ui");
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, default_apps_grid);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, web_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, mail_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, calendar_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, music_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, video_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, photos_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, calls_label);
- gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, sms_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, web_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, mail_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, calendar_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, music_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, video_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, photos_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, calls_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, sms_row);
}
static void
@@ -238,9 +100,9 @@ cc_default_apps_panel_init (CcDefaultAppsPanel *self)
{
g_resources_register (cc_default_apps_get_resource ());
- gtk_widget_init_template (GTK_WIDGET (self));
+ g_type_ensure (CC_TYPE_DEFAULT_APPS_ROW);
- info_panel_setup_default_apps (self);
+ gtk_widget_init_template (GTK_WIDGET (self));
#ifdef BUILD_WWAN
if (cc_object_storage_has_object ("CcObjectStorage::mm-manager"))
diff --git a/panels/default-apps/cc-default-apps-panel.ui b/panels/default-apps/cc-default-apps-panel.ui
index 7327f07ac..e4cb65f0d 100644
--- a/panels/default-apps/cc-default-apps-panel.ui
+++ b/panels/default-apps/cc-default-apps-panel.ui
@@ -2,129 +2,71 @@
<interface>
<template class="CcDefaultAppsPanel" parent="CcPanel">
<child type="content">
- <object class="GtkBox">
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="margin_top">32</property>
- <property name="margin_bottom">32</property>
- <property name="margin_start">24</property>
- <property name="margin_end">24</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="spacing">10</property>
- <property name="orientation">vertical</property>
+ <object class="AdwPreferencesPage">
<child>
- <object class="GtkGrid" id="default_apps_grid">
- <property name="column_spacing">12</property>
- <property name="row_spacing">12</property>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Links &amp;amp; Files</property>
+ <property name="description">Applications which are used to open common links and files.</property>
<child>
- <object class="GtkLabel" id="web_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Web</property>
- <property name="use_underline">True</property>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="CcDefaultAppsRow" id="web_row">
+ <property name="title" translatable="yes">_Web</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">x-scheme-handler/http</property>
+ <property name="filters">text/html;application/xhtml+xml;x-scheme-handler/https</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="mail_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Mail</property>
+ <object class="CcDefaultAppsRow" id="mail_row">
+ <property name="title" translatable="yes">_Mail</property>
<property name="use_underline">True</property>
- <layout>
- <property name="row">1</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="content-type">x-scheme-handler/mailto</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="calendar_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Calendar</property>
- <property name="use_underline">True</property>
- <layout>
- <property name="row">2</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="CcDefaultAppsRow" id="calendar_row">
+ <property name="title" translatable="yes">_Calendar</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">text/calendar</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="music_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">M_usic</property>
- <property name="use_underline">True</property>
- <layout>
- <property name="row">3</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="CcDefaultAppsRow" id="music_row">
+ <property name="title" translatable="yes">M_usic</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">audio/x-vorbis+ogg</property>
+ <property name="filters">audio/*</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="video_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Video</property>
- <property name="use_underline">True</property>
- <layout>
- <property name="row">4</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="CcDefaultAppsRow" id="video_row">
+ <property name="title" translatable="yes">_Video</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">video/x-ogm+ogg</property>
+ <property name="filters">video/*</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="photos_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Photos</property>
- <property name="use_underline">True</property>
- <layout>
- <property name="row">5</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="CcDefaultAppsRow" id="photos_row">
+ <property name="title" translatable="yes">_Photos</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">image/jpeg</property>
+ <property name="filters">image/*</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="calls_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Ca_lls</property>
- <property name="use_underline">True</property>
+ <object class="CcDefaultAppsRow" id="calls_row">
<property name="visible">False</property>
- <layout>
- <property name="row">6</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="title" translatable="yes">_Calls</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">x-scheme-handler/tel</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="sms_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_SMS</property>
- <property name="use_underline">True</property>
+ <object class="CcDefaultAppsRow" id="sms_row">
<property name="visible">False</property>
- <layout>
- <property name="row">7</property>
- <property name="column">0</property>
- </layout>
- <style>
- <class name="dim-label"/>
- </style>
+ <property name="title" translatable="yes">_SMS</property>
+ <property name="use-underline">True</property>
+ <property name="content-type">x-scheme-handler/sms</property>
</object>
</child>
</object>
diff --git a/panels/default-apps/cc-default-apps-row.c b/panels/default-apps/cc-default-apps-row.c
new file mode 100644
index 000000000..830aea6d0
--- /dev/null
+++ b/panels/default-apps/cc-default-apps-row.c
@@ -0,0 +1,223 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis@gnome.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "cc-default-apps-row.h"
+
+struct _CcDefaultAppsRow
+{
+ AdwComboRow parent_instance;
+
+ char *content_type;
+ char *filters;
+
+ GListStore *model;
+};
+
+G_DEFINE_FINAL_TYPE (CcDefaultAppsRow, cc_default_apps_row, ADW_TYPE_COMBO_ROW)
+
+enum {
+ PROP_0,
+ PROP_CONTENT_TYPE,
+ PROP_FILTERS,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+notify_selected_item_cb (CcDefaultAppsRow *self)
+{
+ g_autoptr(GAppInfo) info = NULL;
+ g_autoptr(GError) error = NULL;
+ int i;
+
+ info = G_APP_INFO (adw_combo_row_get_selected_item (ADW_COMBO_ROW (self)));
+
+ if (g_app_info_set_as_default_for_type (info, self->content_type, &error) == FALSE)
+ {
+ g_warning ("Failed to set '%s' as the default application for '%s': %s",
+ g_app_info_get_name (info), self->content_type, error->message);
+ }
+ else
+ {
+ g_debug ("Set '%s' as the default handler for '%s'",
+ g_app_info_get_name (info), self->content_type);
+ }
+
+ if (self->filters)
+ {
+ g_auto(GStrv) entries = NULL;
+ const char *const *mime_types;
+ g_autoptr(GPtrArray) patterns = NULL;
+
+ entries = g_strsplit (self->filters, ";", -1);
+ patterns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free);
+ for (i = 0; entries[i] != NULL; i++)
+ {
+ GPatternSpec *pattern = g_pattern_spec_new (entries[i]);
+ g_ptr_array_add (patterns, pattern);
+ }
+
+ mime_types = g_app_info_get_supported_types (info);
+ for (i = 0; mime_types && mime_types[i]; i++)
+ {
+ int j;
+ gboolean matched = FALSE;
+ g_autoptr(GError) local_error = NULL;
+
+ for (j = 0; j < patterns->len; j++)
+ {
+ GPatternSpec *pattern = g_ptr_array_index (patterns, j);
+ if (g_pattern_spec_match_string (pattern, mime_types[i]))
+ matched = TRUE;
+ }
+ if (!matched)
+ continue;
+
+ if (g_app_info_set_as_default_for_type (info, mime_types[i], &local_error) == FALSE)
+ {
+ g_warning ("Failed to set '%s' as the default application for secondary "
+ "content type '%s': %s",
+ g_app_info_get_name (info), mime_types[i], local_error->message);
+ }
+ else
+ {
+ g_debug ("Set '%s' as the default handler for '%s'",
+ g_app_info_get_name (info), mime_types[i]);
+ }
+ }
+ }
+}
+
+static char *
+get_app_display_name (GAppInfo *info)
+{
+ return g_strdup (g_app_info_get_display_name (info));
+}
+
+static void
+cc_default_apps_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, self->content_type);
+ break;
+ case PROP_FILTERS:
+ g_value_set_string (value, self->filters);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_default_apps_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTENT_TYPE:
+ self->content_type = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_FILTERS:
+ self->filters = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_default_apps_row_constructed (GObject *object)
+{
+ CcDefaultAppsRow *self;
+ g_autoptr (GAppInfo) default_app, app = NULL;
+ g_autoptr (GList) recommended_apps, l = NULL;
+ GtkExpression *name_expr;
+
+ G_OBJECT_CLASS (cc_default_apps_row_parent_class)->constructed (object);
+
+ self = CC_DEFAULT_APPS_ROW (object);
+ default_app = g_app_info_get_default_for_type (self->content_type, FALSE);
+ recommended_apps = g_app_info_get_recommended_for_type (self->content_type);
+ self->model = g_list_store_new (G_TYPE_APP_INFO);
+
+ /* Add the default separately because it may not be in the list of recommended apps */
+ if (default_app != NULL)
+ g_list_store_append (self->model, default_app);
+
+ for (l = recommended_apps; l != NULL; l = l->next) {
+ app = l->data;
+
+ if (default_app != NULL && g_app_info_equal (app, default_app))
+ continue;
+
+ g_list_store_append (self->model, app);
+ }
+
+ adw_combo_row_set_model (ADW_COMBO_ROW (self), G_LIST_MODEL (self->model));
+
+ g_signal_connect (self,
+ "notify::selected-item",
+ G_CALLBACK (notify_selected_item_cb), NULL);
+
+ name_expr = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
+ 0, NULL,
+ G_CALLBACK (get_app_display_name),
+ NULL, NULL);
+ adw_combo_row_set_expression (ADW_COMBO_ROW (self), name_expr);
+}
+
+static void
+cc_default_apps_row_class_init (CcDefaultAppsRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_default_apps_row_get_property;
+ object_class->set_property = cc_default_apps_row_set_property;
+ object_class->constructed = cc_default_apps_row_constructed;
+
+ properties[PROP_CONTENT_TYPE] =
+ g_param_spec_string ("content-type",
+ NULL, NULL, NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ properties[PROP_FILTERS] =
+ g_param_spec_string ("filters",
+ NULL, NULL, NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_default_apps_row_init (CcDefaultAppsRow *self)
+{
+
+}
diff --git a/panels/default-apps/cc-default-apps-row.h b/panels/default-apps/cc-default-apps-row.h
new file mode 100644
index 000000000..9ceae847f
--- /dev/null
+++ b/panels/default-apps/cc-default-apps-row.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis@gnome.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DEFAULT_APPS_ROW (cc_default_apps_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcDefaultAppsRow, cc_default_apps_row, CC, DEFAULT_APPS_ROW, AdwComboRow)
+
+G_END_DECLS
diff --git a/panels/default-apps/meson.build b/panels/default-apps/meson.build
index 89283ce06..a0b5c1a39 100644
--- a/panels/default-apps/meson.build
+++ b/panels/default-apps/meson.build
@@ -16,7 +16,8 @@ i18n.merge_file(
)
sources = files(
- 'cc-default-apps-panel.c'
+ 'cc-default-apps-panel.c',
+ 'cc-default-apps-row.c'
)
resource_data = files(