Introduce Applications panel

This is an initial implementation of most of the
intended functionality for this panel. Flatpak
integration itself is implemented by spawning
"flatpak info -m $appid", which gives us the
metadata in key file format, and allows flatpak
to be a runtime dependency.

Even after removing the .desktop suffix, there can
still be a difference between the app ID generated
in this way and the flatpak ID, since flatpaks are
allowed to export files whose prefix is the flatpak
ID. Fix this by pulling the X-Flatpak key out of
the desktop file. This would cause trouble for
org.libreoffice.LibreOffice-math.
This commit is contained in:
Georges Basile Stavracas Neto 2018-11-16 15:42:54 -02:00
parent a800e97510
commit 1245fd787b
No known key found for this signature in database
GPG key ID: 886C17EE170D1385
28 changed files with 3842 additions and 0 deletions

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/applications">
<file preprocess="xml-stripblanks">cc-action-row.ui</file>
<file preprocess="xml-stripblanks">cc-applications-panel.ui</file>
<file preprocess="xml-stripblanks">cc-applications-row.ui</file>
<file preprocess="xml-stripblanks">cc-info-row.ui</file>
<file preprocess="xml-stripblanks">cc-toggle-row.ui</file>
<file>cc-applications-panel.css</file>
</gresource>
</gresources>

View file

@ -0,0 +1,218 @@
/* cc-action-row.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include <glib/gi18n.h>
#include "cc-action-row.h"
#include "cc-applications-resources.h"
struct _CcActionRow
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *subtitle;
GtkWidget *button;
};
G_DEFINE_TYPE (CcActionRow, cc_action_row, GTK_TYPE_LIST_BOX_ROW)
static int activated_signal;
enum
{
PROP_0,
PROP_TITLE,
PROP_SUBTITLE,
PROP_ACTION,
PROP_ENABLED,
PROP_DESTRUCTIVE
};
static void
clicked_cb (CcActionRow *row)
{
g_signal_emit (row, activated_signal, 0);
}
static void
cc_action_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcActionRow *row = CC_ACTION_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
case PROP_SUBTITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->subtitle)));
break;
case PROP_ACTION:
g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (row->button)));
break;
case PROP_ENABLED:
g_value_set_boolean (value, gtk_widget_get_sensitive (row->button));
break;
case PROP_DESTRUCTIVE:
g_value_set_boolean (value,
gtk_style_context_has_class (gtk_widget_get_style_context (row->button), "destructive-action"));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_action_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcActionRow *row = CC_ACTION_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
case PROP_SUBTITLE:
gtk_label_set_label (GTK_LABEL (row->subtitle), g_value_get_string (value));
gtk_widget_set_visible (row->subtitle, strlen (g_value_get_string (value)) > 0);
break;
case PROP_ACTION:
gtk_button_set_label (GTK_BUTTON (row->button), g_value_get_string (value));
break;
case PROP_ENABLED:
gtk_widget_set_sensitive (row->button, g_value_get_boolean (value));
break;
case PROP_DESTRUCTIVE:
if (g_value_get_boolean (value))
gtk_style_context_add_class (gtk_widget_get_style_context (row->button), "destructive-action");
else
gtk_style_context_remove_class (gtk_widget_get_style_context (row->button), "destructive-action");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_action_row_class_init (CcActionRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_action_row_get_property;
object_class->set_property = cc_action_row_set_property;
g_object_class_install_property (object_class,
PROP_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SUBTITLE,
g_param_spec_string ("subtitle", "subtitle", "subtitle",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ACTION,
g_param_spec_string ("action", "action", "action",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ENABLED,
g_param_spec_boolean ("enabled", "enabled", "enabled",
TRUE, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DESTRUCTIVE,
g_param_spec_boolean ("destructive", "destructive", "destructive",
FALSE, G_PARAM_READWRITE));
activated_signal = g_signal_new ("activated",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-action-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcActionRow, title);
gtk_widget_class_bind_template_child (widget_class, CcActionRow, subtitle);
gtk_widget_class_bind_template_child (widget_class, CcActionRow, button);
gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
}
static void
cc_action_row_init (CcActionRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcActionRow *
cc_action_row_new (void)
{
return CC_ACTION_ROW (g_object_new (CC_TYPE_ACTION_ROW, NULL));
}
void
cc_action_row_set_title (CcActionRow *row,
const gchar *name)
{
gtk_label_set_label (GTK_LABEL (row->title), name);
}
void
cc_action_row_set_subtitle (CcActionRow *row,
const gchar *name)
{
gtk_label_set_label (GTK_LABEL (row->subtitle), name);
gtk_widget_set_visible (row->subtitle, strlen (name) > 0);
}
void
cc_action_row_set_action (CcActionRow *row,
const gchar *action,
gboolean sensitive)
{
gtk_button_set_label (GTK_BUTTON (row->button), action);
gtk_widget_set_sensitive (row->button, sensitive);
}

View file

@ -0,0 +1,42 @@
/* cc-action-row.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_ACTION_ROW (cc_action_row_get_type())
G_DECLARE_FINAL_TYPE (CcActionRow, cc_action_row, CC, ACTION_ROW, GtkListBoxRow)
CcActionRow* cc_action_row_new (void);
void cc_action_row_set_title (CcActionRow *row,
const gchar *label);
void cc_action_row_set_subtitle (CcActionRow *row,
const gchar *label);
void cc_action_row_set_action (CcActionRow *row,
const gchar *action,
gboolean sensitive);
G_END_DECLS

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcActionRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
</object>
<packing>
<property name="expand">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="subtitle">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="visible">1</property>
<property name="valign">center</property>
<signal name="clicked" handler="clicked_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
</template>
</interface>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
.section-title {
font-weight: bold;
}
.section-subtitle {
opacity: 0.55;
}

View file

@ -0,0 +1,30 @@
/* cc-applications-panel.h
*
* Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <shell/cc-panel.h>
G_BEGIN_DECLS
#define CC_TYPE_APPLICATIONS_PANEL (cc_applications_panel_get_type())
G_DECLARE_FINAL_TYPE (CcApplicationsPanel, cc_applications_panel, CC, APPLICATIONS_PANEL, CcPanel)
G_END_DECLS

View file

@ -0,0 +1,531 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcApplicationsPanel" parent="CcPanel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkScrolledWindow" id="main_scroll">
<property name="visible">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="HdyColumn">
<property name="visible">True</property>
<property name="maximum_width">600</property>
<property name="linear_growth_width">400</property>
<property name="margin_top">32</property>
<property name="margin_bottom">32</property>
<property name="margin_start">12</property>
<property name="margin_end">12</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">1</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="visible">1</property>
<property name="valign">start</property>
<property name="pixel-size">80</property>
<property name="icon-name">org.gnome.Software-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="fill">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="margin-bottom">15</property>
<property name="label" translatable="yes">No applications</property>
<style>
<class name="dim-label"/>
</style>
<attributes>
<attribute name="scale" value="1.2"/>
</attributes>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Install some…</property>
<property name="visible">1</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="halign">center</property>
<signal name="clicked" handler="open_software_cb"/>
</object>
<packing>
<property name="fill">0</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">empty</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<property name="hexpand">1</property>
<child>
<object class="GtkBox" id="permission_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Permissions &amp; Access</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Data and services that this app has asked for access to and permissions that it requires.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="permission_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="permission_row_activated_cb"/>
<child>
<object class="CcToggleRow" id="camera">
<property name="title" translatable="yes">Camera</property>
<signal name="notify::allowed" handler="camera_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_camera">
<property name="title" translatable="yes">Camera</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="microphone">
<property name="title" translatable="yes">Microphone</property>
<signal name="notify::allowed" handler="microphone_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_microphone">
<property name="title" translatable="yes">Microphone</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="location">
<property name="title" translatable="yes">Location Services</property>
<signal name="notify::allowed" handler="location_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_location">
<property name="title" translatable="yes">Location Services</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcInfoRow" id="builtin">
<property name="title" translatable="yes">Built-in Permissions</property>
<property name="info" translatable="yes">Cannot be changed</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Individual permissions for applications can be reviewed in the &lt;a href=&quot;privacy&quot;&gt;Privacy&lt;/a&gt; Settings.</property>
<property name="use-markup">1</property>
<signal name="activate-link" handler="privacy_link_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="integration_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Integration</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">System features used by this application.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="integration_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<child>
<object class="CcToggleRow" id="search">
<property name="title" translatable="yes">Search</property>
<signal name="notify::allowed" handler="search_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_search">
<property name="title" translatable="yes">Search</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="notification">
<property name="title" translatable="yes">Notifications</property>
<signal name="notify::allowed" handler="notification_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="sound">
<property name="title" translatable="yes">Sounds</property>
<signal name="notify::allowed" handler="sound_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_sound">
<property name="title" translatable="yes">Sounds</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="handler_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="spacing">6</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Default Handlers</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">Types of files and links that this application opens.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="handler_reset">
<property name="visible">1</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Reset</property>
<signal name="clicked" handler="handler_reset_cb"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="handler_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="handler_row_activated_cb"/>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="usage_section">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<style>
<class name="section"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Usage</property>
<style>
<class name="section-title"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">How much resources this application is using.</property>
<style>
<class name="section-subtitle"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="usage_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="storage_row_activated_cb"/>
<child>
<object class="CcInfoRow" id="storage">
<property name="title" translatable="yes">Storage</property>
<property name="info">unknown</property>
<property name="has-expander">1</property>
<property name="is-link">1</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">settings</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
<object class="GtkLabel" id="title_label">
<property name="visible">1</property>
<property name="label" translatable="yes">Applications</property>
<style>
<class name="title"/>
</style>
</object>
<object class="GtkButton" id="header_button">
<property name="visible">1</property>
<property name="label" translatable="yes">Open in Software</property>
</object>
<object class="GtkListBox" id="sidebar_listbox">
<property name="visible">1</property>
<property name="selection-mode">browse</property>
</object>
<!-- Built-in Permissions dialog -->
<object class="GtkDialog" id="builtin_dialog">
<property name="title" translatable="yes">Built-in Permissions</property>
<property name="modal">1</property>
<property name="type-hint">dialog</property>
<property name="use-header-bar">1</property>
<property name="resizable">0</property>
<property name="border-width">24</property>
<signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="builtin_label">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label">Yadda Yadda</property>
</object>
</child>
<child>
<object class="GtkListBox" id="builtin_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
</object>
</child>
</object>
<!-- Storage dialog -->
<object class="GtkDialog" id="storage_dialog">
<property name="title" translatable="yes">Storage</property>
<property name="modal">1</property>
<property name="type-hint">dialog</property>
<property name="use-header-bar">1</property>
<property name="resizable">0</property>
<property name="border-width">24</property>
<signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="max-width-chars">50</property>
<property name="label" translatable="yes">How much disk space this application is occupying with app data and caches.</property>
</object>
</child>
<child>
<object class="GtkListBox" id="storage_list">
<property name="visible">1</property>
<property name="selection-mode">none</property>
<child>
<object class="CcInfoRow" id="app">
<property name="title" translatable="yes">Application</property>
<property name="info">Unknown</property>
</object>
</child>
<child>
<object class="CcInfoRow" id="data">
<property name="title" translatable="yes">Data</property>
<property name="info">Unknown</property>
</object>
</child>
<child>
<object class="CcInfoRow" id="cache">
<property name="title" translatable="yes">Cache</property>
<property name="info">Unknown</property>
</object>
</child>
<child>
<object class="CcInfoRow" id="total">
<property name="title" translatable="yes">&lt;b&gt;Total&lt;/b&gt;</property>
<property name="use-markup">1</property>
<property name="info">Unknown</property>
</object>
</child>
<style>
<class name="view"/>
<class name="frame"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<child>
<object class="GtkButton" id="clear_cache_button">
<property name="visible">1</property>
<property name="label" translatable="yes">Clear Cache…</property>
<signal name="clicked" handler="clear_cache_cb" swapped="yes"/>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View file

@ -0,0 +1,102 @@
/* cc-applications-row.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include <glib/gi18n.h>
#include "cc-applications-row.h"
#include "cc-applications-resources.h"
struct _CcApplicationsRow
{
GtkListBoxRow parent;
GAppInfo *info;
gchar *sortkey;
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
};
G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, GTK_TYPE_LIST_BOX_ROW)
static void
cc_applications_row_finalize (GObject *object)
{
CcApplicationsRow *self = CC_APPLICATIONS_ROW (object);
g_object_unref (self->info);
g_free (self->sortkey);
G_OBJECT_CLASS (cc_applications_row_parent_class)->finalize (object);
}
static void
cc_applications_row_class_init (CcApplicationsRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = cc_applications_row_finalize;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-applications-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, box);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, image);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, label);
}
static void
cc_applications_row_init (CcApplicationsRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcApplicationsRow *
cc_applications_row_new (GAppInfo *info)
{
CcApplicationsRow *self;
g_autofree gchar *key = NULL;
self = g_object_new (CC_TYPE_APPLICATIONS_ROW, NULL);
self->info = g_object_ref (info);
key = g_utf8_casefold (g_app_info_get_display_name (info), -1);
self->sortkey = g_utf8_collate_key (key, -1);
gtk_image_set_from_gicon (GTK_IMAGE (self->image), g_app_info_get_icon (info), GTK_ICON_SIZE_BUTTON);
gtk_label_set_label (GTK_LABEL (self->label), g_app_info_get_display_name (info));
return self;
}
GAppInfo *
cc_applications_row_get_info (CcApplicationsRow *self)
{
return self->info;
}
const gchar *
cc_applications_row_get_sort_key (CcApplicationsRow *self)
{
return self->sortkey;
}

View file

@ -0,0 +1,36 @@
/* cc-applications-row.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_APPLICATIONS_ROW (cc_applications_row_get_type())
G_DECLARE_FINAL_TYPE (CcApplicationsRow, cc_applications_row, CC, APPLICATIONS_ROW, GtkListBoxRow)
CcApplicationsRow *cc_applications_row_new (GAppInfo *info);
GAppInfo *cc_applications_row_get_info (CcApplicationsRow *row);
const gchar *cc_applications_row_get_sort_key (CcApplicationsRow *row);
G_END_DECLS

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcApplicationsRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkBox" id="box">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkImage" id="image">
<property name="visible">1</property>
<property name="pixel-size">16</property>
<style>
<class name="sidebar-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="ellipsize">end</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -0,0 +1,215 @@
/* cc-info-row.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include <glib/gi18n.h>
#include "cc-info-row.h"
#include "cc-applications-resources.h"
struct _CcInfoRow
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *info;
GtkWidget *expander;
gboolean expanded;
gboolean link;
};
G_DEFINE_TYPE (CcInfoRow, cc_info_row, GTK_TYPE_LIST_BOX_ROW)
enum
{
PROP_0,
PROP_TITLE,
PROP_USE_MARKUP,
PROP_INFO,
PROP_HAS_EXPANDER,
PROP_IS_LINK,
PROP_EXPANDED
};
static void
cc_info_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcInfoRow *row = CC_INFO_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
case PROP_INFO:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->info)));
break;
case PROP_HAS_EXPANDER:
g_value_set_boolean (value, gtk_widget_get_visible (row->expander));
break;
case PROP_USE_MARKUP:
g_value_set_boolean (value, gtk_label_get_use_markup (GTK_LABEL (row->title)));
break;
case PROP_IS_LINK:
g_value_set_boolean (value, row->link);
break;
case PROP_EXPANDED:
g_value_set_boolean (value, cc_info_row_get_expanded (row));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
update_expander (CcInfoRow *row)
{
if (row->link)
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "go-next-symbolic", GTK_ICON_SIZE_BUTTON);
else if (row->expanded)
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
else
gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-end-symbolic", GTK_ICON_SIZE_BUTTON);
}
static void
cc_info_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcInfoRow *row = CC_INFO_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
case PROP_INFO:
gtk_label_set_label (GTK_LABEL (row->info), g_value_get_string (value));
break;
case PROP_HAS_EXPANDER:
gtk_widget_set_visible (row->expander, g_value_get_boolean (value));
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), g_value_get_boolean (value));
break;
case PROP_USE_MARKUP:
gtk_label_set_use_markup (GTK_LABEL (row->title), g_value_get_boolean (value));
break;
case PROP_IS_LINK:
row->link = g_value_get_boolean (value);
update_expander (row);
break;
case PROP_EXPANDED:
cc_info_row_set_expanded (row, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_info_row_class_init (CcInfoRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_info_row_get_property;
object_class->set_property = cc_info_row_set_property;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-info-row.ui");
g_object_class_install_property (object_class,
PROP_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_INFO,
g_param_spec_string ("info", "info", "info",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_USE_MARKUP,
g_param_spec_boolean ("use-markup", "use-markup", "use-markup",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_HAS_EXPANDER,
g_param_spec_boolean ("has-expander", "has-expander", "has-expander",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_EXPANDED,
g_param_spec_boolean ("expanded", "expanded", "expanded",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_IS_LINK,
g_param_spec_boolean ("is-link", "is-link", "is-link",
FALSE, G_PARAM_READWRITE));
gtk_widget_class_bind_template_child (widget_class, CcInfoRow, title);
gtk_widget_class_bind_template_child (widget_class, CcInfoRow, info);
gtk_widget_class_bind_template_child (widget_class, CcInfoRow, expander);
}
static void
cc_info_row_init (CcInfoRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcInfoRow *
cc_info_row_new (void)
{
return CC_INFO_ROW (g_object_new (CC_TYPE_INFO_ROW, NULL));
}
gboolean
cc_info_row_get_expanded (CcInfoRow *row)
{
return row->expanded;
}
void
cc_info_row_set_expanded (CcInfoRow *row,
gboolean expanded)
{
if (row->expanded == expanded)
return;
row->expanded = expanded;
update_expander (row);
g_object_notify (G_OBJECT (row), "expanded");
}

View file

@ -0,0 +1,37 @@
/* cc-info-row.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_INFO_ROW (cc_info_row_get_type())
G_DECLARE_FINAL_TYPE (CcInfoRow, cc_info_row, CC, INFO_ROW, GtkListBoxRow)
CcInfoRow* cc_info_row_new (void);
void cc_info_row_set_expanded (CcInfoRow *row,
gboolean expanded);
gboolean cc_info_row_get_expanded (CcInfoRow *row);
G_END_DECLS

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcInfoRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkLabel" id="info">
<property name="visible">1</property>
<property name="valign">center</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkImage" id="expander">
<property name="valign">center</property>
<property name="icon-name">pan-end-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -0,0 +1,144 @@
/* cc-toggle-row.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include <glib/gi18n.h>
#include "cc-toggle-row.h"
#include "cc-applications-resources.h"
struct _CcToggleRow
{
GtkListBoxRow parent;
GtkWidget *title;
GtkWidget *toggle;
};
G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, GTK_TYPE_LIST_BOX_ROW)
enum
{
PROP_0,
PROP_TITLE,
PROP_ALLOWED
};
static void
changed_cb (CcToggleRow *row)
{
g_object_notify (G_OBJECT (row), "allowed");
}
static void
cc_toggle_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcToggleRow *row = CC_TOGGLE_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->title)));
break;
case PROP_ALLOWED:
g_value_set_boolean (value, cc_toggle_row_get_allowed (row));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_toggle_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcToggleRow *row = CC_TOGGLE_ROW (object);
switch (prop_id)
{
case PROP_TITLE:
gtk_label_set_label (GTK_LABEL (row->title), g_value_get_string (value));
break;
case PROP_ALLOWED:
cc_toggle_row_set_allowed (row, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cc_toggle_row_class_init (CcToggleRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_toggle_row_get_property;
object_class->set_property = cc_toggle_row_set_property;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-toggle-row.ui");
g_object_class_install_property (object_class,
PROP_TITLE,
g_param_spec_string ("title", "title", "title",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ALLOWED,
g_param_spec_boolean ("allowed", "allowed", "allowed",
FALSE, G_PARAM_READWRITE));
gtk_widget_class_bind_template_child (widget_class, CcToggleRow, title);
gtk_widget_class_bind_template_child (widget_class, CcToggleRow, toggle);
gtk_widget_class_bind_template_callback (widget_class, changed_cb);
}
static void
cc_toggle_row_init (CcToggleRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcToggleRow *
cc_toggle_row_new (void)
{
return CC_TOGGLE_ROW (g_object_new (CC_TYPE_TOGGLE_ROW, NULL));
}
void
cc_toggle_row_set_allowed (CcToggleRow *self,
gboolean allowed)
{
gtk_switch_set_active (GTK_SWITCH (self->toggle), allowed);
}
gboolean
cc_toggle_row_get_allowed (CcToggleRow *self)
{
return gtk_switch_get_active (GTK_SWITCH (self->toggle));
}

View file

@ -0,0 +1,37 @@
/* cc-toggle-row.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_TOGGLE_ROW (cc_toggle_row_get_type())
G_DECLARE_FINAL_TYPE (CcToggleRow, cc_toggle_row, CC, TOGGLE_ROW, GtkListBoxRow)
CcToggleRow* cc_toggle_row_new (void);
void cc_toggle_row_set_allowed (CcToggleRow *row,
gboolean allowed);
gboolean cc_toggle_row_get_allowed (CcToggleRow *row);
G_END_DECLS

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcToggleRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="border-width">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="toggle">
<property name="visible">1</property>
<property name="valign">center</property>
<signal name="notify::active" handler="changed_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -0,0 +1,62 @@
/* globs.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include "globs.h"
/* parse mime/globs and return a string->string hash table */
GHashTable *
parse_globs (void)
{
GHashTable *globs;
const gchar * const *dirs;
gint i;
globs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i]; i++)
{
g_autofree gchar *file = g_build_filename (dirs[i], "mime", "globs", NULL);
g_autofree gchar *contents = NULL;
if (g_file_get_contents (file, &contents, NULL, NULL))
{
g_auto(GStrv) strv = NULL;
int i;
strv = g_strsplit (contents, "\n", 0);
for (i = 0; strv[i]; i++)
{
g_auto(GStrv) parts = NULL;
if (strv[i][0] == '#' || strv[i][0] == '\0')
continue;
parts = g_strsplit (strv[i], ":", 2);
g_hash_table_insert (globs, g_strdup (parts[0]), g_strdup (parts[1]));
}
}
}
return globs;
}

View file

@ -0,0 +1,29 @@
/* globs.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gio/gio.h>
G_BEGIN_DECLS
GHashTable* parse_globs (void);
G_END_DECLS

View file

@ -0,0 +1,15 @@
[Desktop Entry]
Name=Applications
Comment=Control various application permissions and settings
Exec=gnome-control-center applications
# FIXME
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=application-x-executable-symbolic
Terminal=false
Type=Application
NoDisplay=true
StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
OnlyShowIn=GNOME;Unity;
# Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=application;flatpak;permission;setting;

View file

@ -0,0 +1,49 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input : desktop + '.in.in',
output : desktop + '.in',
configuration : desktop_conf
)
i18n.merge_file(
desktop,
type : 'desktop',
input : desktop_in,
output : desktop,
po_dir : po_dir,
install : true,
install_dir : control_center_desktopdir
)
sources = files(
'cc-applications-panel.c',
'cc-applications-row.c',
'cc-toggle-row.c',
'cc-info-row.c',
'cc-action-row.c',
'globs.c',
'search.c',
'utils.c',
)
resource_data = files('cc-applications-panel.ui')
sources += gnome.compile_resources(
'cc-' + cappletname + '-resources',
cappletname + '.gresource.xml',
c_name : 'cc_' + cappletname,
dependencies : resource_data,
export : true
)
cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
panels_libs += static_library(
cappletname,
sources : sources,
include_directories : [ top_inc, common_inc ],
dependencies : common_deps,
c_args : cflags
)

View file

@ -0,0 +1,133 @@
/* search.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#include <config.h>
#include "search.h"
#define SHELL_PROVIDER_GROUP "Shell Search Provider"
static void
add_one_provider (GHashTable *search_providers,
GFile *file)
{
g_autoptr(GKeyFile) keyfile = NULL;
g_autoptr(GError) error = NULL;
g_autofree gchar *app_id = NULL;
g_autofree gchar *path = NULL;
gboolean default_disabled;
path = g_file_get_path (file);
keyfile = g_key_file_new ();
g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error);
if (error != NULL)
{
g_warning ("Error loading %s: %s - search provider will be ignored",
path, error->message);
return;
}
if (!g_key_file_has_group (keyfile, SHELL_PROVIDER_GROUP))
{
g_debug ("Shell search provider group missing from '%s', ignoring", path);
return;
}
app_id = g_key_file_get_string (keyfile, SHELL_PROVIDER_GROUP, "DesktopId", &error);
if (error != NULL)
{
g_warning ("Unable to read desktop ID from %s: %s - search provider will be ignored",
path, error->message);
return;
}
if (g_str_has_suffix (app_id, ".desktop"))
app_id[strlen (app_id) - strlen (".desktop")] = '\0';
default_disabled = g_key_file_get_boolean (keyfile, SHELL_PROVIDER_GROUP, "DefaultDisabled", NULL);
g_hash_table_insert (search_providers, g_strdup (app_id), GINT_TO_POINTER (default_disabled));
}
static void
parse_search_providers_one_dir (GHashTable *search_providers,
const gchar *system_dir)
{
g_autoptr(GFileEnumerator) enumerator = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) providers_location = NULL;
g_autofree gchar *providers_path = NULL;
providers_path = g_build_filename (system_dir, "gnome-shell", "search-providers", NULL);
providers_location = g_file_new_for_path (providers_path);
enumerator = g_file_enumerate_children (providers_location,
"standard::type,standard::name,standard::content-type",
G_FILE_QUERY_INFO_NONE,
NULL, &error);
if (error != NULL)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Error opening %s: %s - search provider configuration won't be possible",
providers_path, error->message);
return;
}
while (TRUE)
{
GFile *provider = NULL;
if (!g_file_enumerator_iterate (enumerator, NULL, &provider, NULL, &error))
{
g_warning ("Error while reading %s: %s - search provider configuration won't be possible",
providers_path, error->message);
return;
}
if (provider == NULL)
break;
add_one_provider (search_providers, provider);
}
}
/* parse gnome-shell/search-provider files and return a string->boolean hash table */
GHashTable *
parse_search_providers (void)
{
GHashTable *search_providers;
const gchar * const *dirs;
gint i;
search_providers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i]; i++)
parse_search_providers_one_dir (search_providers, dirs[i]);
return search_providers;
}

View file

@ -0,0 +1,29 @@
/* globs.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gio/gio.h>
G_BEGIN_DECLS
GHashTable* parse_search_providers (void);
G_END_DECLS

209
panels/applications/utils.c Normal file
View file

@ -0,0 +1,209 @@
/* utils.c
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include <config.h>
#include <glib/gi18n.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ftw.h>
#include "utils.h"
static gint
ftw_remove_cb (const gchar *path,
const struct stat *sb,
gint typeflags,
struct FTW *ftwbuf)
{
remove (path);
return 0;
}
static void
file_remove_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
GFile *file = source_object;
g_autofree gchar *path = g_file_get_path (file);
nftw (path, ftw_remove_cb, 20, FTW_DEPTH);
}
void
file_remove_async (GFile *file,
GAsyncReadyCallback callback,
gpointer data)
{
g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
g_task_run_in_thread (task, file_remove_thread_func);
}
static GPrivate size_key = G_PRIVATE_INIT (g_free);
static gint
ftw_size_cb (const gchar *path,
const struct stat *sb,
gint typeflags,
struct FTW *ftwbuf)
{
guint64 *size = (guint64*)g_private_get (&size_key);
if (typeflags == FTW_F)
*size += sb->st_size;
return 0;
}
static void
file_size_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
GFile *file = source_object;
g_autofree gchar *path = g_file_get_path (file);
guint64 *total;
g_private_replace (&size_key, g_new0 (guint64, 1));
nftw (path, ftw_size_cb, 20, FTW_DEPTH);
total = g_new0 (guint64, 1);
*total = *(guint64*)g_private_get (&size_key);
g_object_set_data_full (G_OBJECT (task), "size", total, g_free);
}
void
file_size_async (GFile *file,
GAsyncReadyCallback callback,
gpointer data)
{
g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
g_task_run_in_thread (task, file_size_thread_func);
}
void
container_remove_all (GtkContainer *container)
{
g_autoptr(GList) children = NULL;
GList *l;
children = gtk_container_get_children (container);
for (l = children; l; l = l->next)
gtk_widget_destroy (GTK_WIDGET (l->data));
}
static gchar *
get_output_of (const gchar **argv)
{
g_autofree gchar *output = NULL;
int status;
if (!g_spawn_sync (NULL,
(gchar**) argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL, NULL,
&output, NULL,
&status, NULL))
return NULL;
if (!g_spawn_check_exit_status (status, NULL))
return NULL;
return g_steal_pointer (&output);
}
GKeyFile *
get_flatpak_metadata (const gchar *app_id)
{
const gchar *argv[5] = { "flatpak", "info", "-m", "app", NULL };
g_autofree gchar *data = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) keyfile = NULL;
argv[3] = app_id;
data = get_output_of (argv);
if (data == NULL)
return NULL;
keyfile = g_key_file_new ();
if (!g_key_file_load_from_data (keyfile, data, -1, 0, &error))
{
g_warning ("%s", error->message);
return NULL;
}
return g_steal_pointer (&keyfile);
}
guint64
get_flatpak_app_size (const gchar *app_id)
{
const gchar *argv[5] = { "flatpak", "info", "-s", "app", NULL };
g_autofree gchar *data = NULL;
guint64 factor;
double val;
argv[3] = app_id;
data = get_output_of (argv);
if (data == NULL)
return 0;
data = g_strstrip (data);
if (g_str_has_suffix (data, "kB") || g_str_has_suffix (data, "kb"))
factor = 1000;
else if (g_str_has_suffix (data, "MB") || g_str_has_suffix (data, "Mb"))
factor = 1000 * 1000;
else if (g_str_has_suffix (data, "GB") || g_str_has_suffix (data, "Gb"))
factor = 1000 * 1000 * 1000;
else if (g_str_has_suffix (data, "KiB") || g_str_has_suffix (data, "Kib"))
factor = 1024;
else if (g_str_has_suffix (data, "MiB") || g_str_has_suffix (data, "Mib"))
factor = 1024 * 1024;
else if (g_str_has_suffix (data, "GiB") || g_str_has_suffix (data, "Gib"))
factor = 1024 * 1024 * 1024;
else
factor = 1;
val = g_ascii_strtod (data, NULL);
return (guint64)(val * factor);
}
char *
get_app_id (GAppInfo *info)
{
gchar *app_id = g_strdup (g_app_info_get_id (info));
if (g_str_has_suffix (app_id, ".desktop"))
app_id[strlen (app_id) - strlen (".desktop")] = '\0';
return app_id;
}

View file

@ -0,0 +1,44 @@
/* utils.h
*
* Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
*
* 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 3 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-3.0-or-later
*/
#pragma once
#include <gio/gio.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
void file_remove_async (GFile *file,
GAsyncReadyCallback callback,
gpointer data);
void file_size_async (GFile *file,
GAsyncReadyCallback callback,
gpointer data);
void container_remove_all (GtkContainer *container);
GKeyFile* get_flatpak_metadata (const gchar *app_id);
guint64 get_flatpak_app_size (const gchar *app_id);
gchar* get_app_id (GAppInfo *info);
G_END_DECLS

View file

@ -1,6 +1,7 @@
subdir('common')
panels = [
'applications',
'background',
'color',
'datetime',

View file

@ -386,6 +386,7 @@ static const gchar * const panel_order[] = {
"universal-access",
"online-accounts",
"privacy",
"applications",
"sharing",
"sound",
"power",

View file

@ -31,6 +31,7 @@
#ifndef CC_PANEL_LOADER_NO_GTYPES
/* Extension points */
extern GType cc_applications_panel_get_type (void);
extern GType cc_background_panel_get_type (void);
#ifdef BUILD_BLUETOOTH
extern GType cc_bluetooth_panel_get_type (void);
@ -83,6 +84,7 @@ extern void cc_wacom_panel_static_init_func (void);
static CcPanelLoaderVtable default_panels[] =
{
PANEL_TYPE("applications", cc_applications_panel_get_type, NULL),
PANEL_TYPE("background", cc_background_panel_get_type, NULL),
#ifdef BUILD_BLUETOOTH
PANEL_TYPE("bluetooth", cc_bluetooth_panel_get_type, NULL),