Compare commits

..

128 Commits

Author SHA1 Message Date
Felipe Borges
7a7808272f 45.5
Signed-off-by: Felipe Borges <felipeborges@gnome.org>
2024-05-27 10:16:19 +02:00
Matthijs Velsink
907e5cf2c2 display: Fix crash from closing lid
When closing the lid on a laptop, the number of active monitors drops to
zero. However, `monitor_labeler_show()` always assumes at least one
monitor is active, as it unconditionally closes the `GVariantBuilder`.

This causes a crash when there is no monitor added to the
`GVariantBuilder`, however, as no value was added to it.

Instead, only close the `GVariantBuilder` when we're actually going to
use it and know a value was added.

Commit ca9228bb fixed a similar crash for when there are no outputs at
all. But in this case, there is still an output, it is just not active,
only with the active UI number as 0.

Fixes #3058

(cherry picked from commit 08e32e9573)
2024-05-22 16:25:41 +02:00
Balázs Úr
196ca6ce86 Update Hungarian translation 2024-05-17 19:00:40 +00:00
Christian Kirbach
f811bac8a8 Update German translation 2024-04-30 18:15:07 +00:00
Matthijs Velsink
2bec32d482 universal-access: Fix icon name in .desktop file
The full icon name is `org.gnome.Settings-accessibility-symbolic`. Even
though it was still being found due to the way icon lookup works, the
Fedora Update System (bodhi) Automated Testing tagged this with

Desktop file /usr/share/applications/gnome-universal-access-panel.desktop
on x86_64 references icon org.gnome.Settings-accessibility but no
subpackages contain org.gnome.Settings-accessibility

So, fix that.

(cherry picked from commit fd651824d9)
2024-04-25 10:20:16 +02:00
Felipe Borges
967b4d3ce9 45.4 2024-04-19 11:56:18 +02:00
Matthijs Velsink
42b05525b4 display: Fix crash due to shortcut propagation phase
For a managed GtkShortcutController, changing its propagation phase
away from `GTK_PHASE_BUBBLE` currently results in a lingering reference
due to a bug in GTK (gtk#6246). This means the Escape key shortcut
remains active even after leaving the Display panel, resulting in a
crash when pressing Escape in any panel after leaving the Display panel.

This is now fixed in GTK (gtk!7115), but there seems to be no reason for
changing the propagation phase at all anyways. Since the callback
returns `GDK_EVENT_PROPAGATE` when it does not activate, the event
should still make it to other handlers.

So, to speed up the fix for gnome-control-center, we remove the
propagation phase changes althogether. There is also no need to let the
shortcut have global scope, managed is enough.

Closes #2768

(cherry picked from commit e7e9753aac)
(cherry picked from commit 9eb2576f89)
2024-04-19 11:32:18 +02:00
Lukáš Tyrychtr
bfa3a1ce80 universal-access: Add a few activatable widgets in the typing page
This also fixes missing a11y labels for the sliders.
Fixes #2998.

(cherry picked from commit c3483b3a68)
(cherry picked from commit 06472e320d)
2024-04-19 11:32:05 +02:00
Maximiliano Sandoval
b4609b661c privacy: Remove rows that had their perms reset
When a permission for an app is reset, e.g. via:

    flatpak permission-reset APP_ID

the Changed signal simply contains one fewer entry in its dictionary. If
we had a row for an app_id, and such app_id is not in the new
permissions we remove the row from the list box.

Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2993
(cherry picked from commit 7f93969583)
(cherry picked from commit 13f533f3c5)
2024-04-19 11:31:59 +02:00
Maximiliano Sandoval
7f350031c2 privacy: Do not update on all Changed signals
The permission store emits more changes and these cause extra rows to
appear.

Partially fixes:
https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2993

(cherry picked from commit 6cdb19c6d7)
(cherry picked from commit 797defb3bd)
2024-04-19 11:31:53 +02:00
Maximiliano Sandoval
4adec45df7 privacy: location: Unpack GVariant inside GVariant
(cherry picked from commit 485f957a62)
2024-04-19 11:31:47 +02:00
Maximiliano Sandoval
d00302f518 privacy: camera: Unpack GVariant inside GVariant
Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2982
(cherry picked from commit 55afa6df47)
(cherry picked from commit 01bca6902c)
2024-04-19 11:31:34 +02:00
Felipe Borges
60316c0fe8 privacy, help: Link to "Screen Lock" documentation
When in the "Screen Lock" page, hitting F1 or going for Help should
open help:gnome-help/privacy-screen-lock

(cherry picked from commit b46f21d424)
2024-04-19 11:31:01 +02:00
Felipe Borges
eabdb0d758 privacy, help: Fix broken link to "Location Services" docs
The subpage tag name AND the correspondent docs page name were wrong.

(cherry picked from commit f4a1f9e9c3)
2024-04-19 11:30:53 +02:00
Felipe Borges
2d3ac85730 privacy, help: Remove links to pages without correspondent docs
(cherry picked from commit 7a9f5a3056)
2024-04-19 11:30:43 +02:00
Felipe Borges
23c57ccda2 privacy, help: Default to opening "Privacy Settings" help page
When in the main page or in a subpage without docs, the Help link
should open the "Privacy Settings" page at help:gnome-help/privacy

(cherry picked from commit a4074198a3)
2024-04-19 11:30:37 +02:00
Felipe Borges
7cdfba94a5 common: Check for valid GDateTime object before comparing
Avoids the critical below at runtime
11:14:36.7796                   **[873815]:CRITICAL: cc_util_get_smart_date: assertion 'date != NULL' failed
11:14:36.7802                   **[873815]:CRITICAL: cc_util_get_smart_date: assertion 'date != NULL' failed

Which comes from the location panel passing a NULL date object.

\#0  _g_log_abort (breakpoint=1) at ../shell/cc-log.c:72
        debugger_present = 1
\#1  0x000000000045c3c4 in cc_log_write
    (log_level=10, log_domain=0x7ffff7d592eb "GLib", log_message=0x234c400 "g_date_time_difference: assertion 'begin != NULL' failed", fields=0x7fffffffd740, n_fields=4, user_data=0x0)
    at ../shell/cc-log.c:315
        log_str = 0x234b8d0
        stream = 0x7ffff5dbb4e0 <_IO_2_1_stderr_>
        can_color = 1
\#2  0x000000000045c4f5 in cc_log_handler (log_level=G_LOG_LEVEL_CRITICAL, fields=0x7fffffffd740, n_fields=4, user_data=0x0) at ../shell/cc-log.c:348
        log_domain = 0x7ffff7d592eb "GLib"
        log_message = 0x234c400 "g_date_time_difference: assertion 'begin != NULL' failed"
\#3  0x00007ffff7c9f534 in g_log_structured_array () at /lib64/libglib-2.0.so.0
\#4  0x00007ffff7ca4f57 in g_log_default_handler () at /lib64/libglib-2.0.so.0
\#5  0x00007ffff7c9be29 in g_logv () at /lib64/libglib-2.0.so.0
\#6  0x00007ffff7c9c193 in g_log () at /lib64/libglib-2.0.so.0
\#7  0x00007ffff7c787fa in g_date_time_difference () at /lib64/libglib-2.0.so.0
\#8  0x000000000059c186 in cc_util_get_smart_date (date=0x0) at ../panels/common/cc-util.c:124
        today = 0x2350130
        local = 0x2350100
        span = 10791504
\#9  0x00000000004f8a20 in add_location_app (self=0x1dee1c0, app_id=0x232fef0 "org.gnome.Calendar", enabled=1, last_used=459618461810) at ../panels/privacy/cc-location-page.c:209
        data = 0xffffda80
        app_info = 0x2341c50
        t = 0x0
        row = 0x2348280
        w = 0x234fe00
        icon = 0x2345310
        last_used_str = 0x0
        desktop_id = 0x7fffcc034c30 "DL\310\375\a"
\#10 0x00000000004f8db4 in update_perm_store (self=0x1dee1c0, permissions=0x7fffcc04e2c0, permissions_data=0x7fffcc04ee80) at ../panels/privacy/cc-location-page.c:282
        enabled = 1
        last_used = 459618461810
        iter = {x = {140736616260288, 2, 0, 6386038, 140736616096608, 36922576, 16, 3579507750, 140737488345904, 140737350561909, 33733184, 36922576, 140737488345936, 140737350702366, 36922576, 3278251457363369984}}
        key = 0x232fef0 "org.gnome.Calendar"
        value = 0x7fffcc04e090
\#11 0x00000000004f8f4e in on_perm_store_lookup_done (source_object=0x1e24040, res=0x202ba40, user_data=0x1dee1c0) at ../panels/privacy/cc-location-page.c:324
        error = 0x0
        ret = 0x7fffcc04eef0
        permissions = 0x7fffcc04e2c0
        permissions_data = 0x7fffcc04ee80
\#12 0x00007ffff7e9082c in g_task_return_now () at /lib64/libgio-2.0.so.0
\#13 0x00007ffff7e944c3 in g_task_return () at /lib64/libgio-2.0.so.0
\#14 0x00007ffff7efe88b in reply_cb () at /lib64/libgio-2.0.so.0
\#15 0x00007ffff7e9082c in g_task_return_now () at /lib64/libgio-2.0.so.0
\#16 0x00007ffff7e944c3 in g_task_return () at /lib64/libgio-2.0.so.0

(cherry picked from commit 544c146ea8)
2024-04-19 11:29:51 +02:00
Robert Ancell
f4c430e7e1 Remove myself from the maintainers list.
I'm no longer engaged enough to be a maintainer so it's best to make that clear.
Still happy to review and be involved if others need it!
This is a great project and if you want to be more involved in GNOME I'd recommend it.

(cherry picked from commit e6de817031)
2024-04-19 11:28:56 +02:00
Matthijs Velsink
ee87c36201 datetime: Avoid emitted signals for manual changes
When setting widget values manually, block the callbacks to prevent
trying to change system time inadvertently.

Backport of 535404bb for GNOME 45.

See #2943
2024-04-16 14:51:43 +00:00
Felipe Borges
769c790ff8 ci: Use a F39 container image for the stable gnome-45 branch 2024-04-16 16:40:40 +02:00
Felipe Borges
afa9438155 ci: Build the gtk4 version in F39 to match container image 2024-04-16 16:40:40 +02:00
Peter Hutterer
d64153160d CI: Remove systemtap-runtime to avoid podman failures
Fixes podman issue
  Error: Error reading blob sha256:4bb4a44c73af78e20e3d4c36bc1ce95b4b77a546f11a65babf752f869f1ca655:
  open /var/lib/containers/storage/vfs/dir/9b8cfd27e86ef18db67fbda7d61d72046f3f5d8ad312655713d4cd8b065c80cd/usr/bin/staprun: permission denied

Related to https://gitlab.gnome.org/Infrastructure/Infrastructure/-/issues/1247
2024-04-16 16:21:10 +02:00
Athmane MOKRAOUI
dd13023893 Update Kabyle translation 2024-04-13 15:12:26 +00:00
Daniel Rusek
cc00aa9a9a Update Czech translation 2024-03-30 10:04:20 +00:00
Ekaterine Papava
9814dae52a Update Georgian translation 2024-03-25 05:47:21 +00:00
Daniel Rusek
9605ac5785 Update Czech translation 2024-03-14 11:18:16 +00:00
Ekaterine Papava
7b10a54d58 Update Georgian translation 2024-03-13 14:49:48 +00:00
Christian Kirbach
c2958255e0 Update German translation 2024-02-27 22:49:53 +00:00
Felipe Borges
4e107fa212 45.3 2024-02-12 13:23:54 +01:00
Matthijs Velsink
bc52ef0e52 datetime: Fix invalid pointer type with cast
Fixes build with -Wincompatible-pointer-types.
2024-02-06 06:58:31 +00:00
Matthijs Velsink
87fcec6529 wifi: Fix invalid pointer type with cast
Fixes build with -Wincompatible-pointer-types.
2024-02-06 06:58:31 +00:00
Christian Kirbach
f628a1ada3 Update German translation 2024-02-03 23:05:01 +00:00
zayar lwin
c6611f1cb8 Update Burmese translation 2024-02-02 12:39:27 +00:00
Jürgen Benvenuti
b362343b04 Update German translation 2024-01-28 13:14:14 +00:00
Daniel Rusek
1d723270ff Update Czech translation 2024-01-24 01:22:29 +00:00
Yosef Or Boczko
e0fbbd6279 Update Hebrew translation 2024-01-20 18:32:09 +00:00
Quentin PAGÈS
c90adb673e Update Occitan translation 2024-01-17 19:31:20 +00:00
Efstathios Iosifidis
65f151dfec Update Greek translation 2024-01-06 14:27:25 +00:00
Efstathios Iosifidis
42e994c6d5 Update Greek translation 2024-01-06 08:51:05 +00:00
Efstathios Iosifidis
25194046e7 Update Greek translation 2024-01-05 22:01:46 +00:00
Alynx Zhou
9670d032e7 system/region: Prevent preview crash from accessing invalid pointer
In !2051, we switch back to real locale before setting the label text,
however, according to nl_langinfo's manpage, the returned pointer could
be invalid after switching locale or creating new locale, so the program
may crash.

To fix this, we save the result before switching locale, so we won't
access the invalid pointer after switching locale.
2024-01-04 11:24:29 +08:00
Efstathios Iosifidis
0a8e61c9eb Update Greek translation 2024-01-03 20:10:05 +00:00
Efstathios Iosifidis
4ef09d387a Update Greek translation 2024-01-01 21:00:38 +00:00
Efstathios Iosifidis
1c83dcf37a Update Greek translation 2024-01-01 19:04:47 +00:00
Efstathios Iosifidis
a57a45ae18 Update Greek translation 2024-01-01 11:10:39 +00:00
Efstathios Iosifidis
4a1b9b2a2c Update Greek translation 2023-12-31 23:15:58 +00:00
Fabio Tomat
6d11167a3a Update Friulian translation 2023-12-28 20:49:15 +00:00
Matej Urbančič
92acbff00a Update Slovenian translation 2023-12-27 19:57:44 +00:00
Ekaterine Papava
88b0ab9204 Update Georgian translation 2023-12-17 16:00:05 +00:00
Automeris naranja
649d06d954 cc-panel-list: Wrap the text when showing "No Results Found"
https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/2024 fixed https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2788, but it's for gnome-46.
This commit fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2788 with small changes (because it's for the
stable branch), using the same properties that AdwStatusPage uses for
its title and subtitle/description:

https://gitlab.gnome.org/GNOME/libadwaita/-/blob/libadwaita-1-4/src/adw-status-page.ui
2023-12-11 22:16:54 +00:00
Felipe Borges
cc5da95fec 45.2 2023-12-07 11:50:36 +01:00
Andre Klapper
84a69d0289 DOAP: Replace defunct mailing list with Discourse support forum 2023-12-07 11:31:08 +01:00
Felipe Borges
2a104f26d8 privacy: Make firmware page visibility check cancellable
So that the page doesn't crash when closing the panel before the
firmware page visibility has been set.
2023-12-07 11:29:57 +01:00
Felipe Borges
8aa48007a1 privacy: Make Bolt page visibility check cancellable
When the Bolt page gets disposed before it finishes initializing
its client object we get a crash. See #2700

A way to trigger the crash is to switch panels fast enough so that
the sync dbus call is not finished by the time the panel is disposed.

This is not a guaranteed fix since I can't reproduce the issue
consistently.
2023-12-07 11:29:46 +01:00
Jonathan Kang
77ab990e12 network-connection-editor: Close the editor when nm-connection-editor exits
Previously, when editing a connection that doesn't have native editor
support, nm-connection-editor is spawned to do the work. But after
closing nm-connection-editor, an empty editor dialog still exists.

Fix that in this commit.
2023-12-07 11:28:59 +01:00
Bruce Cowan
5a93a42041 Update British English translation 2023-12-06 12:57:39 +00:00
velsinki
64537f6bc3 background: Improve chooser performance
The size of the background item is currently never used, but setting it
using `gnome_bg_get_image_size ()` is expensive, since that actually
does a thumbnail retrieval.

Instead, we can retrieve the size of the background file directly,
improving the rendering performance of the chooser significantly.
2023-11-28 14:47:16 +01:00
Felipe Borges
0efaa27bea mouse: Prevent arrows in Test window from interfering with mouse events
Fixes #2769
2023-11-28 10:31:44 +01:00
Artur S0
22956cba01 Update Russian translation 2023-11-27 16:24:27 +00:00
Lukáš Tyrychtr
a8f74e39f1 sound: When setting mixer control for a stream row, update muted state as well
We were updating the volume state, but not the mute one, so, do both.

Fixes #2749
2023-11-27 12:52:26 +01:00
velsinki
e736e1b259 system/region: Preview measurement format in current locale
The Formats preview tries to find the measurement format of the locale
to preview, and then displays it. However, it displays the text in the
default locale, instead of in the real current locale, as newlocale ()
with base = (locale_t) 0 will use the default locale.

This is fixed by switching back to the real locale before setting the
label text.

Fixes #2458

Part-of: <https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/2051>
2023-11-27 12:48:42 +01:00
Maximiliano Sandoval R
3250055ebf window: Set the main window height request to 294
This is the size you get on a mobile screen on landscape mode. See
https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/migrating-to-breakpoints.html.
2023-11-27 12:47:38 +01:00
Marcos Miller
1aa75612e9 network: Show top buttons on unsupported network daemon page
When entering the network panel without the network daemon,
the window decoration buttons do not appear because the whole panel
content was overwritten by an AdwStatusPage.

Now only the content of the AdwToolbarView is changed, preserving
the AdwHeaderBar and buttons.

Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2695
2023-11-27 12:47:21 +01:00
Ismael
318f87cdbc network: Share WPA3 (SAE) networks with QR Code 2023-11-27 12:45:19 +01:00
Ondřej Pohořelský
9a5e225752 wifi: hide QR code icon when connection not successful
Don't show QR code icon when there is no info about connection being
valid and successful. Also hide it when we are connecting and when WiFi
has no password.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/2030>
2023-11-27 12:45:13 +01:00
Ondřej Pohořelský
cc529478dc network: remove wpa-none from key_mgmt
Network Manager dropped `wpa-none` value from `key_mgmt` a while ago[0]
There is no need to test for this option anymore.

[0]c97e0ce30b
2023-11-27 12:45:06 +01:00
Yaron Shahrabani
2a409e7872 Update Hebrew translation 2023-11-26 12:32:43 +00:00
Milo Casagrande
8c6e673c94 Update Italian translation 2023-11-24 15:02:12 +00:00
velsinki
9d57e857cf apps: Fix status page glitch on initialization
For an unknown reason, the AdwNavigationSplitView loading takes some
time, in which the Apps panel is not yet initialized. During that time,
the top item of the GtkStack, namely the No Apps AdwStatusPage will
show. This appears glitchy.

To work around this, make the first item of the GtkStack a "fake" empty
GtkBox that can show instead of the AdwStatusPage.

Fixes #2665
2023-11-24 10:40:11 +00:00
Sabri Ünal
3cc13bf47f Update Turkish translation 2023-11-23 17:07:24 +00:00
Lukáš Tyrychtr
ad47ec14c3 po: Fix missing closing tag in pt_BR locale
Fixes #2766
2023-11-23 11:38:06 +01:00
velsinki
b3afa91f1a background: Improve preview performance
Since 7cef6dc5, the background previews are rendered at the full
resolution. However, this is expensive and causes considerable lag,
especially for resizes. Since then, the thumbnail size has doubled to
256 pixels, making the previews sharper even at larger sizes.

So, to improve performance, let's effectively revert 7cef6dc5. The
revert is not possible without disabling frame = 0 retrieval, since that
is broken for non-slideshow backgrounds and was not used before anyways
with force_size = TRUE.

Related to #674
Related to #704
Related to #2448
2023-11-23 09:45:49 +01:00
Hugo Carvalho
39f12a7d1b Update Portuguese translation 2023-11-22 13:33:33 +00:00
Yuri Chornoivan
f6215b0c0c Update Ukrainian translation 2023-11-21 09:08:50 +00:00
velsinki
bd328beba4 applications: Fix File & Link Associations UI
When removing a File & Link Association from the dialog, or resetting
them, the UI does not update. Fix this by rebuilding the handler dialog
on both unset and reset.

Fixes #389
Fixes #2172
2023-11-21 15:57:13 +13:00
Felipe Borges
ff0052ceff user-accounts: Sync lock tooltip for the Avatar
We were adding the "Unlock" tooltip to the avatar widget but not
removing it when the panel was unlocked.

Fixes #2738
2023-11-10 12:10:30 +01:00
Ekaterine Papava
6f19ba27e0 Update Georgian translation 2023-11-09 09:54:14 +00:00
Jose Riha
295c5f7916 Update Slovak translation 2023-11-09 09:06:09 +00:00
velsinki
b5c7708093 privacy: Fix crash from free bug in cc-camera-page
The GVariant constructor g_variant_new () gives a floating reference,
which will be sunk by the g_dbus_..._call () methods. Unless the
constructed GVariant is manually referenced, it should not be used in a
g_autoptr () setting. Otherwise a use-after-free might occur in the
async g_dbus_..._call () methods.

This problem occurs here, which is simply prevented by not having the
g_autoptr () declaration for the GVariant.

Fixes #2647
Fixes #2704
Fixes #2635
Fixes #2706
2023-11-08 14:49:05 +01:00
Ekaterine Papava
d92c5bc9a6 Update Georgian translation 2023-11-05 22:35:57 +00:00
Asier Sarasua Garmendia
80772d947b Update Basque translation 2023-11-05 08:05:35 +00:00
Ngọc Quân Trần
1307efed3a Update Vietnamese translation 2023-11-05 02:29:21 +00:00
Daniel Rusek
cc0630b39e Update Czech translation 2023-11-05 01:54:21 +00:00
Daniel Rusek
c47512abf4 Update Czech translation 2023-11-05 00:14:31 +00:00
Artur S0
f14eef644e Update Russian translation 2023-11-04 02:09:19 +00:00
Felipe Borges
2af7116f59 ci: Stop building GLib from the source 2023-10-27 17:11:28 +02:00
Felipe Borges
5d6447b0b9 default-apps: Workaround AdwComboRow item selection at startup
Our callback handler for the AdwComboRow::selected-item property
changes gets called at startup, resulting in a slow and unnecessary
default app change.

This is a workaround to avoid calling g_app_info_set_as_default_for_type
without user input.

This is a backport of commit 6fb324634a

Fixes #2626
Fixes #2683
2023-10-27 17:06:33 +02:00
velsinki
b7309b1f19 network-connection-editor: Align Routes labels
Even though the routes_metric_label is in a GtkSizeGroup with the
GtkEntry for the metric, its size was set too big after adding the entry
to the size group. To fix this, add all the other labels and
corresponding entries to size groups as well. The hexpand can then be
removed as well on the labels.

Fixes #1235
2023-10-26 21:07:46 -05:00
Марко Костић
076e4f46f0 Update Serbian translation 2023-10-25 06:04:17 +00:00
Felipe Borges
a95ab55060 45.1 2023-10-23 15:24:35 +02:00
Maximiliano Sandoval R
0d01819cbd keyboard-shortcut-dialog: Allow escape to close
At the moment the search entry is consuming the Escape key press, so we
have to manually tell it what to do with it.

We clear the search on the first press, if there is input, and close the
window otherwise.
2023-10-23 10:49:22 +02:00
Marco Melorio
b083248538 mouse-panel: Increase AdwBreakpoint width to avoid videos being blurry
When reducing the window width, CCSplitRow won't have enough width
to display videos without blurriness. This change increases the
AdwBreakpoint width so CCSplitRow shows vertically before that problem
described earlier happens.

See also: https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1960#note_1869031

Part-of: <https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1960>

Partially fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2631
2023-10-23 10:48:58 +02:00
Marco Melorio
f2df7c50ab cc-split-row: Reduce GtkPicture horizontal margins to avoid blurriness
There is a difference between the aspect ratio of the CCSplitRow widget
and the videos from the Mouse & Touchpad panel, which causes the videos
to appear blurry.

This change reduces the video margins so they can better align with the pixel grid.
See also: https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1960#note_1869031

Part-of: <https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1960>

Partially fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2631
2023-10-23 10:48:40 +02:00
Felipe Borges
7397765226 a11y: Make Cursor size dialog close on Escape key
Addresses comment
https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1951#note_1865060
2023-10-23 10:48:12 +02:00
Marco Melorio
c0cbf0b566 illustrated-row: Use correct property to scale down image
This widget was using halign instead of content-fit to scale down the
image to the correct resolution, and it was making the image blurry in
some cases.

Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2382.
2023-10-23 10:47:42 +02:00
Ekaterine Papava
41ad0d9471 Update Georgian translation 2023-10-20 05:35:32 +00:00
Florentina Mușat
1bdb56b1d6 Update Romanian translation 2023-10-18 18:19:58 +00:00
Daniel Mustieles
55774c6e44 Updated Spanish translation 2023-10-17 15:53:30 +02:00
Artur S0
f565c9b4c4 Update Russian translation 2023-10-16 11:29:15 +00:00
Sabri Ünal
74dfd288a3 Update Turkish translation 2023-10-14 07:08:26 +00:00
Asier Sarasua Garmendia
454955aada Update Basque translation 2023-10-12 06:49:28 +00:00
Michael Catanzaro
30eda57465 Revert "network: Disable DNS entry if the automatic option is enabled"
This reverts commit 8a4a80b7b2.

This is a manual revert, because the code changed considerably in
a2b9620b1b. Anyway, although this seemed
like a good idea, problem is it clobbers the original state of the
connection without any explicit user action if the connection is
configured to use both manual and auto DNS. And this happens in practice
for imported Wireguard connections, which uselessly have auto DNS
enabled due to this NetworkManager bug:

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1399

Additional discussion:

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1745#note_2112420

The simplest solution is to not try to prevent the user from configuring
both manual and auto DNS. Instead, let's just warn the user that this
configuration may not be intended in a follow-up commit.

Fixes #2617

Part-of: <https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1944>
2023-10-09 21:09:01 +00:00
Daniel Rusek
b7b56e65c2 Update Czech translation 2023-10-09 21:04:46 +00:00
Daniel Șerbănescu
e9ffde0036 Update Romanian translation 2023-10-09 16:12:25 +00:00
Cyber Phantom
3f2488d553 info-overview: Don't set key binding twice 2023-10-09 12:20:52 +02:00
Sabri Ünal
98d52f881d Update Turkish translation 2023-10-07 06:35:42 +00:00
Daniel Rusek
2e59005b6f Update Czech translation 2023-10-06 22:56:54 +00:00
Michael Catanzaro
c7684fec5c network: fix editing connections without a device
For example, fix adding new VPN connections.

In 60b4956c05 I correctly observed that we
need to not run code that requires a device when there is no device.
NetConnectionEditor is a multipurpose dialog and self->device is
optional when creating the dialog. E.g. when modifying VPN
configuration, we update just the configuration, not an NMDevice.

However, I added this check too soon, before updating the connection
configuration. We need to update the configuration first, then only bail
before proceeding to update the device, not sooner.

Fix #2668
2023-10-03 13:04:08 +02:00
Felipe Borges
130c4ecbae mouse: Fix linked style of primary mouse button in RTL
Commit d980e0ffee fixed an issue when the "Left" button would appear
at the right side for RTL languages given that GtkBox would reorder
its horizontal children to RTL direction.

The solution at the time was to force the primary-button box to stay
in LTR direction when the rest of the interface is shown in RTL.
This introduced a regression where the CSS "linked" style of the
buttons used was the LTR one, breaking the "linked" styling.

This fix will manually reorder the Left/Right buttons rather than
calling gtk_widget_set_direction on the primary-button-box.

Fixes #2649
2023-10-03 11:01:58 +02:00
Sabri Ünal
ee7058adc2 Update Turkish translation 2023-10-01 18:30:08 +00:00
Aurimas Černius
38b0bc5667 Update Lithuanian translation 2023-09-25 20:09:39 +00:00
Rafael Fontenelle
cef09dfa7d Update Brazilian Portuguese translation 2023-09-25 13:26:57 +00:00
Martin
a9d37c85d1 Update Slovenian translation 2023-09-24 15:35:29 +00:00
Danial Behzadi
8922e6220c Update Persian translation 2023-09-24 12:35:23 +00:00
Piotr Drąg
a8be38080b Update Polish translation 2023-09-24 14:27:41 +02:00
Kristjan SCHMIDT
aacba75357 Update Esperanto translation 2023-09-23 23:34:37 +00:00
Danial Behzadi
538201116f Update Persian translation 2023-09-23 15:24:39 +00:00
Balázs Úr
59cfa336ab Update Hungarian translation 2023-09-22 22:40:51 +00:00
Jordi Mas i Hernandez
63818b7ae0 Update Catalan translation 2023-09-22 15:52:02 +00:00
Guillaume Bernard
165fd55ec2 Update French translation 2023-09-22 14:23:10 +00:00
Marco Melorio
b01cba0a82 privacy: Fix crash in the firmware security page
Make sure the timeouts are stopped when the page is finalized.
2023-09-22 12:41:56 +02:00
Kristjan SCHMIDT
8cfd9bb72c Update Esperanto translation 2023-09-21 22:30:34 +00:00
Asier Sarasua Garmendia
43ca1672c8 Update Basque translation 2023-09-21 17:28:25 +00:00
Baurzhan Muftakhidinov
47e856a4cf Update Kazakh translation 2023-09-21 15:27:07 +00:00
Boyuan Yang
b364cc063f Update Chinese (China) translation 2023-09-21 14:14:10 +00:00
Fran Dieguez
d0668ffcde Update Galician translation 2023-09-21 10:22:16 +00:00
Anders Jonsson
009b2fc1be Update Swedish translation 2023-09-21 08:27:34 +00:00
Sabri Ünal
234390e803 Update Turkish translation 2023-09-20 19:02:01 +00:00
401 changed files with 39897 additions and 32974 deletions

View File

@@ -1,12 +0,0 @@
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
BasedOnStyle: GNU
AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None
BinPackParameters: false
SpaceAfterCStyleCast: true
PointerAlignment: Right
# Our column limit is actually 80, but setting that results in clang-format
# making a lot of dubious hanging-indent choices; disable it and assume the
# developer will line wrap appropriately. clang-format will still check
# existing hanging indents.
ColumnLimit: 0

View File

@@ -32,7 +32,7 @@ stages:
.Build procedure: &build_procedure
echo "== Building ==" &&
dnf install -y dnf5-plugins &&
git clone https://gitlab.gnome.org/GNOME/gtk.git &&
git clone --depth 1 --branch 4.12.5 https://gitlab.gnome.org/GNOME/gtk.git &&
cd gtk &&
dnf5 builddep -y gtk4 &&
meson setup . _build -Dprefix=/usr -Dlibdir=lib64 &&
@@ -59,8 +59,8 @@ stages:
# stable branch.
# Could probably also switch away from rawhide,
# to stable fedora branch as well.
FDO_DISTRIBUTION_TAG: '2023-06-07.0-main'
FDO_DISTRIBUTION_VERSION: rawhide
FDO_DISTRIBUTION_TAG: '2024-04-16.0-main'
FDO_DISTRIBUTION_VERSION: 39
#############################################
# Create CI Docker Images #
@@ -131,8 +131,8 @@ build.container.fedora@x86_64:
xorg-x11-server-Xvfb
mesa-dri-drivers
libsecret-devel
libgweather4-devel
geocode-glib2-devel
libgweather-devel
lcms2-devel
geoclue2-devel
libnotify-devel
@@ -184,7 +184,8 @@ build.container.fedora@x86_64:
meson . _build --prefix=/usr && \
ninja -C _build && \
ninja -C _build install && \
cd ..
cd .. && \
dnf remove -y systemtap-runtime
##
# Stage: Build
@@ -221,21 +222,8 @@ build:
##
# Stage: Test
#
# Runs static checks.
# Runs the unit tests.
##
style-check-diff:
extends:
- '.fdo.distribution-image@fedora'
- '.fedora.container.common'
needs:
- build.container.fedora@x86_64
stage: test
when: always
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
test:
extends:
- '.fdo.distribution-image@fedora'

View File

@@ -1,133 +0,0 @@
#!/usr/bin/env python3
#
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===---------------------------------------------------------------------=== #
"""
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
import subprocess
import sys
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', action='store_true', default=False,
help='apply edits to files instead of displaying a '
'diff')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to reformat '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN',
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
r'|js|ts|proto|protodevel|java|cs)',
help='custom pattern selecting file paths to reformat '
'(case insensitive, overridden by -regex)')
parser.add_argument('-sort-includes', action='store_true', default=False,
help='let clang-format sort include blocks')
parser.add_argument('-v', '--verbose', action='store_true',
help='be more verbose, ineffective without -i')
parser.add_argument('-style',
help='formatting style to apply (LLVM, Google, '
'Chromium, Mozilla, WebKit)')
parser.add_argument('-binary', default='clang-format',
help='location of binary to use for clang-format')
args = parser.parse_args()
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
['-lines', str(start_line) + ':' + str(end_line)])
# Reformat files containing changes in place.
# We need to count amount of bytes generated in the output of
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
# means there is nothing to format.
format_line_counter = 0
for filename, lines in lines_by_file.items():
if args.i and args.verbose:
print('Formatting {}'.format(filename))
command = [args.binary, filename]
if args.i:
command.append('-i')
if args.sort_includes:
command.append('-sort-includes')
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=None,
stdin=subprocess.PIPE,
universal_newlines=True)
stdout, _ = p.communicate()
if p.returncode != 0:
sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(code, formatted_code,
filename, filename,
'(before formatting)',
'(after formatting)')
diff_string = ''.join(diff)
if diff_string:
format_line_counter += sys.stdout.write(diff_string)
if format_line_counter > 0:
sys.exit(1)
if __name__ == '__main__':
main()

View File

@@ -1,62 +0,0 @@
#!/bin/bash
set -e
ancestor_horizon=31 # days (one month)
# Recently, git is picky about directory ownership. Tell it not to worry.
git config --global --add safe.directory "$PWD"
# We need to add a new remote for the upstream target branch, since this script
# could be running in a personal fork of the repository which has out of date
# branches.
#
# Limit the fetch to a certain date horizon to limit the amount of data we get.
# If the branch was forked from origin/main before this horizon, it should
# probably be rebased.
if ! git ls-remote --exit-code upstream >/dev/null 2>&1 ; then
git remote add upstream https://gitlab.gnome.org/GNOME/gnome-control-center.git
fi
# Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be
# `upstream/main` or `upstream/glib-2-62`).
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` or `${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}`
# are only defined if were running in a merge request pipeline,
# fall back to `${CI_DEFAULT_BRANCH}` or `${CI_COMMIT_BRANCH}` respectively
# otherwise.
source_branch="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-${CI_COMMIT_BRANCH}}"
target_branch="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" origin "${source_branch}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" upstream "${target_branch}"
newest_common_ancestor_sha=$(git merge-base upstream/${target_branch} origin/${source_branch})
if [ -z "${newest_common_ancestor_sha}" ]; then
echo "Couldnt find common ancestor with upstream main branch. This typically"
echo "happens if you branched from main a long time ago. Please update"
echo "your clone, rebase, and re-push your branch."
exit 1
fi
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
exit_status=$?
# The style check is not infallible. The clang-format configuration cannot
# perfectly describe GGNOME Settings coding style: in particular, it cannot align
# function arguments. The documented coding style for GNOME Settings takes priority over
# clang-format suggestions. Hopefully we can eventually improve clang-format to
# be configurable enough for our coding style. Thats why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# its wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesnt make sense to tidy up the wider coding
# style with the changes theyre making.)
echo ""
echo "Note that clang-format output is advisory and cannot always match the"
echo "GNOME Settings coding style, documented at:"
echo " https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODING_STYLE.md"
echo "Warnings from this tool can be ignored in favour of the documented "
echo "coding style, or in favour of matching the style of existing"
echo "surrounding code."
exit ${exit_status}

99
NEWS
View File

@@ -1,3 +1,102 @@
============
Version 45.5
============
- Translation updates
Display
- Fix crash when closing laptop lid
============
Version 45.4
============
- Various translation updates
- CI fixes
Accessibility
- Improve accessibility of "Typing" settings sliders
Datetime
- Prevent unnecessary calls to auto time synchronization
Privacy
- Fix F1/Help link to panel's documentation
- Fix issues with writting camera/location permission-store data
- Fix issue with app listing as a result of flatpak permission-reset
============
Version 45.3
============
Datetime
- Fix build with -Wincompatible-pointer-types
Region
- Prevent preview crash from accessing invalid pointer
Wifi
- Fix build with -Wincompatible-pointer-types
============
Version 45.2
============
Apps
- Fix status page glitch on initialization
- Fix "File and Link Association" interface not reflecting changes
Background
- Improve background preview and chooser performance
Default Apps
- Fix undesired resetting of default apps during startup
Mouse
- Fix interference issue with scroll event in Mouse Test window
Network
- Close network editor when using non-native nm-connection-editor
- Show decoration buttons on empty-state (no network device found page)
- Share WPA3 (SAE) networks with QR Code
- Hide QR Code icon when connection is not successful
- Remove deprecated 'wpa-none'
- Fix route label alignments
Privacy
- Fix crash from free bug in the Camera page
- Fix potential crash on Bolt page visibility
Region
- Show preview measurement format in current locale
Sound
- Update mute state when setting mixer control for a stream
Users
- Show tooltip information for the Avatar widget
============
Version 45.1
============
About
- Add more types of processor support
Accessibility
- Make Cursor Size dialog close on Escape key
Keyboard
- Allow closing Shortcuts dialog with Escape key
Mouse
- Fix linked style of primary mouse button in RTL languages
- Avoid making videos blurry
Network
- Fix editing connections without a device
- Revert "Disable DNS entry if automatic DNS option is enabled"
============
Version 45.0
============

View File

@@ -302,8 +302,6 @@
"buildsystem" : "meson",
"config-opts" : [
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
"-Dudevrulesdir=/app/lib/udev",
"-Dudevhwdbdir=/app/lib/udev",
"-Dgtk-doc=false",
"-Dman=false",
"-Dintrospection=disabled"
@@ -311,8 +309,7 @@
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/upower/upower.git",
"tag" : "v1.90.2"
"url" : "git://anongit.freedesktop.org/upower"
}
]
},
@@ -363,8 +360,7 @@
"-Dqt=false",
"-Dselinux=false",
"-Dsession_tracking=no",
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
"-Dudev_dir=/app/lib/udev",
"-Dsystemdsystemunitdir='no'",
"-Dsystemd_journal=false",
"-Dtests=no",
"-Dvapi=false"
@@ -428,14 +424,8 @@
"config-opts" : [
"-Dintrospection=false",
"-Dbash_completion=false",
"-Dudevdir=/app/lib/udev",
"-Dudevdir=/app/lib",
"-Dsystemdsystemunitdir=/app/lib/systemd/system",
"-Ddbus_policy_dir=/app/etc/dbus-1/system.d",
"-Dsystemd_journal=false",
"-Dtests=false",
"-Dman=false",
"-Dfuzzer=false",
"-Dexamples=false",
"-Dmbim=false",
"-Dplugin_dell=disabled",
"-Dplugin_foxconn=disabled",
@@ -446,7 +436,7 @@
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git",
"url" : "git://anongit.freedesktop.org/ModemManager/ModemManager",
"branch" : "main"
}
]
@@ -455,7 +445,6 @@
"name" : "gnome-settings-daemon",
"buildsystem" : "meson",
"config-opts" : [
"-Dudev_dir=/app/lib/udev",
"-Dsystemd=false"
],
"sources" : [
@@ -629,54 +618,6 @@
}
]
},
{
"name": "python3-jinja2",
"buildsystem": "simple",
"build-commands": [
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"jinja2\" --no-build-isolation"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/1d/97/2288fe498044284f39ab8950703e88abbac2abbdf65524d576157af70556/MarkupSafe-2.1.1.tar.gz",
"sha256": "7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl",
"sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
}
]
},
{
"name": "python3-attrs",
"buildsystem": "simple",
"build-commands": [
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"attrs\" --no-build-isolation"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl",
"sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"
}
]
},
{
"name" : "libei",
"buildsystem" : "meson",
"config-opts" : [
"-Dliboeffis=disabled",
"-Dtests=disabled"
],
"sources" : [
{
"type" : "git",
"branch" : "main",
"url" : "https://gitlab.freedesktop.org/libinput/libei.git"
}
]
},
{
"name" : "mutter",
"buildsystem" : "meson",
@@ -695,7 +636,6 @@
"-Dintrospection=true",
"-Ddocs=false",
"-Dtests=false",
"-Dnative_tests=false",
"-Dprofiler=false"
],
"sources" : [
@@ -803,7 +743,6 @@
"-Dman=false",
"-Dtests=false",
"-Dnetworkmanager=false",
"-Dcamera_monitor=false",
"-Dsystemd=false"
],
"sources" : [
@@ -836,8 +775,6 @@
}
],
"config-opts" : [
"-Dsnap=false",
"-Dtests=false",
"-Dprofile=development"
]
}

View File

@@ -1,49 +0,0 @@
# These are the people responsible for Settings panels and domain-specific
# parts of the GNOME Settings codebase.
#
# If you open a merge request for files listed here, please add the following
# people to the list of reviewers.
# The syntax of this file is defined by GitLab:
# https://docs.gitlab.com/ee/user/project/code_owners.html
# Which, in turn, is similar to the .gitignore and .gitattributes files:
#
# - comments start with `#`
# - the first column contains paths and globs
# - the second column contains GitLab user names or email addresses,
# separated by spaces
#
# The last matching glob (rather than the union of *all* matching globs) gives
# the owners of a piece of code.
#
# If you want to be responsible for code reviews in specific sections of
# the GNOME Settings code base, add yourself here.
# General maintainers
* @felipeborges @robert_ancell
# Panels
## About
panels/info-overview/* @cyberphantom52
## Accessibility
panels/universal-access/* @pksadiq
## Apps
panels/applications/cc-default-apps-* @nishalkulkarni
panels/applications/cc-removable-media-settings* @nishalkulkarni
## Bluetooth
panels/bluetooth/* @hadess
## Printers
panels/printers/* @mkasik
## Sound
panels/sound/* @melix99
## Wacom
panels/wacom/* @carlosg
## WWAN (Cellular)
panels/wwan/* @pksadiq

View File

@@ -22,15 +22,6 @@
</foaf:Person>
</maintainer>
<!-- General -->
<maintainer>
<foaf:Person>
<foaf:name>Robert Ancell</foaf:name>
<foaf:mbox rdf:resource="mailto:robert.ancell@canonical.com" />
<gnome:userid>rancell</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Bluetooth -->
<maintainer>
<foaf:Person>
@@ -40,6 +31,15 @@
</foaf:Person>
</maintainer>
<!-- Display -->
<maintainer>
<foaf:Person>
<foaf:name>Benjamin Berg</foaf:name>
<foaf:mbox rdf:resource="mailto:bberg@gnome.org" />
<gnome:userid>bberg</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Printers -->
<maintainer>
<foaf:Person>

View File

@@ -1,8 +1,8 @@
project(
'gnome-control-center', 'c',
version : '46.alpha',
version : '45.5',
license : 'GPL2+',
meson_version : '>= 0.58.0'
meson_version : '>= 0.57.0'
)
control_center_prefix = get_option('prefix')
@@ -73,15 +73,6 @@ config_h.set('USER_DIR_MODE', '0700',
# compiler flags
common_flags = ['-DHAVE_CONFIG_H']
# We have so many deprecation warnings that it becomes impossible to notice any other useful
# warning, thus making the compiler output completely useless. Ideally, we should fix all
# of those but, until then, it's better to add this flag so that we avoid adding even more
# warnings by accident. If you want to fix some of those, just build Settings with:
# meson _build -Ddeprecated-declarions=enabled
if get_option('deprecated-declarations').disabled()
common_flags += '-Wno-deprecated-declarations'
endif
# Only add this when optimizing is enabled (default)
optimized_src = '''
#if __OPTIMIZE__ == 0
@@ -176,7 +167,7 @@ accounts_dep = dependency('accountsservice', version: '>= 0.6.39')
colord_dep = dependency('colord', version: '>= 0.1.34')
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.23.0')
gio_dep = dependency('gio-2.0')
glib_dep = dependency('glib-2.0', version: '>= 2.76.6')
glib_dep = dependency('glib-2.0', version: '>= 2.75.0')
gnome_desktop_dep = dependency('gnome-desktop-4')
gnome_bg_dep = dependency('gnome-bg-4')
gnome_rr_dep = dependency('gnome-rr-4')
@@ -255,8 +246,9 @@ config_h.set10('HAVE_FN_EXPLICIT_BZERO',
# Snap support
enable_snap = get_option('snap')
if enable_snap
json_glib_dep = dependency('json-glib-1.0')
libsoup_dep = dependency('libsoup-3.0')
snapd_glib_deps = [
dependency('snapd-glib-2', version: '>= 1.62')
]
endif
config_h.set('HAVE_SNAP', enable_snap,
description: 'Define to 1 if Snap support is enabled')

View File

@@ -1,8 +1,7 @@
option('deprecated-declarations', type: 'feature', value: 'disabled', description: 'build with deprecated declaration warnings')
option('documentation', type: 'boolean', value: false, description: 'build documentation')
option('ibus', type: 'boolean', value: true, description: 'build with IBus support')
option('privileged_group', type: 'string', value: 'wheel', description: 'name of group that has elevated permissions')
option('snap', type: 'boolean', value: true, description: 'build with Snap support')
option('snap', type: 'boolean', value: false, description: 'build with Snap support')
option('tests', type: 'boolean', value: true, description: 'build tests')
option('wayland', type: 'boolean', value: true, description: 'build with Wayland support')
option('profile', type: 'combo', choices: ['default','development'], value: 'default')

View File

@@ -2,8 +2,6 @@
<gresources>
<gresource prefix="/org/gnome/control-center/applications">
<file preprocess="xml-stripblanks">cc-applications-panel.ui</file>
<file preprocess="xml-stripblanks">cc-default-apps-page.ui</file>
<file preprocess="xml-stripblanks">cc-removable-media-settings.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-snap-row.ui</file>

View File

@@ -23,6 +23,9 @@
#include <config.h>
#include <glib/gi18n.h>
#ifdef HAVE_SNAP
#include <snapd-glib/snapd-glib.h>
#endif
#ifdef HAVE_MALCONTENT
#include <libmalcontent/malcontent.h>
#endif
@@ -32,14 +35,11 @@
#include "cc-applications-panel.h"
#include "cc-applications-row.h"
#include "cc-info-row.h"
#include "cc-default-apps-page.h"
#include "cc-removable-media-settings.h"
#include "cc-applications-resources.h"
#include "cc-util.h"
#ifdef HAVE_SNAP
#include "cc-snapd-client.h"
#include "cc-snap-row.h"
#endif
#include "cc-util.h"
#include "globs.h"
#include "search.h"
#include "utils.h"
@@ -53,20 +53,12 @@
struct _CcApplicationsPanel
{
CcPanel parent;
CcDefaultAppsPage *default_apps_page;
CcRemovableMediaSettings *removable_media_settings;
AdwNavigationView *navigation_view;
AdwNavigationPage *app_settings_page;
GtkListBox *app_listbox;
GtkEntry *app_search_entry;
GtkWidget *empty_search_placeholder;
GtkStack *app_listbox_stack;
AdwNavigationPage *sidebar_box;
GtkListBox *sidebar_listbox;
GtkEntry *sidebar_search_entry;
GAppInfoMonitor *monitor;
gulong monitor_id;
GListModel *app_model;
GListModel *filter_model;
GtkFilter *filter;
#ifdef HAVE_MALCONTENT
GCancellable *cancellable;
@@ -88,12 +80,14 @@ struct _CcApplicationsPanel
GtkButton *view_details_button;
GDBusProxy *perm_store;
GtkListBoxRow *perm_store_pending_row;
GSettings *notification_settings;
GSettings *location_settings;
GSettings *privacy_settings;
GSettings *search_settings;
GtkStack *stack;
GtkWidget *empty_box;
GtkWidget *settings_box;
GtkButton *install_button;
AdwPreferencesGroup *integration_section;
@@ -116,7 +110,9 @@ struct _CcApplicationsPanel
GtkWindow *builtin_dialog;
AdwPreferencesPage *builtin_page;
GtkListBox *builtin_list;
#ifdef HAVE_SNAP
GList *snap_permission_rows;
#endif
GtkButton *handler_reset;
GtkWindow *handler_dialog;
@@ -703,9 +699,11 @@ add_snap_permissions (CcApplicationsPanel *self,
const gchar *app_id)
{
const gchar *snap_name;
g_autoptr(CcSnapdClient) client = NULL;
g_autoptr(JsonArray) plugs = NULL;
g_autoptr(JsonArray) slots = NULL;
g_autoptr(SnapdClient) client = NULL;
g_autoptr(GPtrArray) interfaces = NULL;
g_autoptr(GPtrArray) plugs = NULL;
g_autoptr(GPtrArray) slots = NULL;
SnapdInterface *interface = NULL;
gint added = 0;
g_autoptr(GError) error = NULL;
g_autoptr(GError) interfaces_error = NULL;
@@ -714,20 +712,31 @@ add_snap_permissions (CcApplicationsPanel *self,
return FALSE;
snap_name = app_id + strlen (PORTAL_SNAP_PREFIX);
client = cc_snapd_client_new ();
client = snapd_client_new ();
if (!cc_snapd_client_get_all_connections_sync (client, &plugs, &slots, cc_panel_get_cancellable (CC_PANEL (self)), &error))
interfaces = snapd_client_get_interfaces2_sync (client,
SNAPD_GET_INTERFACES_FLAGS_NONE,
NULL,
NULL, &interfaces_error);
if (interfaces == NULL)
g_warning ("Failed to get snap interfaces: %s", interfaces_error->message);
if (!snapd_client_get_connections2_sync (client,
SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL,
NULL, NULL,
NULL, NULL,
&plugs, &slots,
NULL, &error))
{
g_warning ("Failed to get snap connections: %s", error->message);
return FALSE;
}
for (guint i = 0; i < json_array_get_length (plugs); i++)
for (int i = 0; i < plugs->len; i++)
{
JsonObject *plug = json_array_get_object_element (plugs, i);
const gchar *plug_interface;
SnapdPlug *plug = g_ptr_array_index (plugs, i);
CcSnapRow *row;
g_autoptr(JsonArray) available_slots = NULL;
g_autoptr(GPtrArray) available_slots = NULL;
const gchar * const hidden_interfaces[] = { "content",
"desktop", "desktop-legacy",
"mir",
@@ -737,25 +746,34 @@ add_snap_permissions (CcApplicationsPanel *self,
NULL };
/* Skip if not relating to this snap */
if (g_strcmp0 (json_object_get_string_member (plug, "snap"), snap_name) != 0)
if (g_strcmp0 (snapd_plug_get_snap (plug), snap_name) != 0)
continue;
/* Ignore interfaces that are too low level to make sense to show or disable */
plug_interface = json_object_get_string_member (plug, "interface");
if (g_strv_contains (hidden_interfaces, plug_interface))
if (g_strv_contains (hidden_interfaces, snapd_plug_get_interface (plug)))
continue;
available_slots = json_array_new ();
for (guint j = 0; j < json_array_get_length (slots); j++)
available_slots = g_ptr_array_new_with_free_func (g_object_unref);
for (int j = 0; j < slots->len; j++)
{
JsonObject *slot = json_array_get_object_element (slots, j);
if (g_strcmp0 (plug_interface, json_object_get_string_member (slot, "interface")) != 0)
SnapdSlot *slot = g_ptr_array_index (slots, j);
if (g_strcmp0 (snapd_plug_get_interface (plug), snapd_slot_get_interface (slot)) != 0)
continue;
json_array_add_object_element (available_slots, slot);
g_ptr_array_add (available_slots, g_object_ref (slot));
}
row = cc_snap_row_new (cc_panel_get_cancellable (CC_PANEL (self)), plug, available_slots);
if (interfaces != NULL)
{
for (int j = 0; j < interfaces->len; j++)
{
SnapdInterface *i = g_ptr_array_index (interfaces, j);
if (g_strcmp0 (snapd_interface_get_name (i), snapd_plug_get_interface (plug)) == 0)
interface = i;
}
}
row = cc_snap_row_new (cc_panel_get_cancellable (CC_PANEL (self)), interface, plug, available_slots);
adw_preferences_group_add (self->integration_section, GTK_WIDGET (row));
self->snap_permission_rows = g_list_prepend (self->snap_permission_rows, row);
added++;
@@ -839,7 +857,7 @@ add_static_permissions (CcApplicationsPanel *self,
static void
remove_static_permissions (CcApplicationsPanel *self)
{
gtk_list_box_remove_all (self->builtin_list);
listbox_remove_all (self->builtin_list);
}
/* --- header section --- */
@@ -941,9 +959,9 @@ update_integration_section (CcApplicationsPanel *self,
gtk_widget_set_visible (GTK_WIDGET (self->no_location), set && disabled);
has_any |= set;
#ifdef HAVE_SNAP
#ifdef HAVE_SNAP
has_any |= add_snap_permissions (self, info, portal_app_id);
#endif
#endif
}
else
{
@@ -976,10 +994,15 @@ unset_cb (CcApplicationsPanel *self,
GtkButton *button)
{
const gchar *type;
GtkListBoxRow *selected;
GAppInfo *info;
selected = gtk_list_box_get_selected_row (self->sidebar_listbox);
info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (selected));
type = (const gchar *)g_object_get_data (G_OBJECT (button), "type");
g_app_info_remove_supports_type (self->current_app_info, type, NULL);
g_app_info_remove_supports_type (info, type, NULL);
update_handler_dialog (self, self->current_app_info);
}
@@ -1085,10 +1108,15 @@ app_info_recommended_for (GAppInfo *info,
static void
handler_reset_cb (CcApplicationsPanel *self)
{
GtkListBoxRow *selected;
GAppInfo *info;
const gchar **types;
gint i;
types = g_app_info_get_supported_types (self->current_app_info);
selected = gtk_list_box_get_selected_row (self->sidebar_listbox);
info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (selected));
types = g_app_info_get_supported_types (info);
if (types == NULL || types[0] == NULL)
return;
@@ -1096,7 +1124,7 @@ handler_reset_cb (CcApplicationsPanel *self)
for (i = 0; types[i]; i++)
{
gchar *ctype = g_content_type_from_mime_type (types[i]);
g_app_info_add_supports_type (self->current_app_info, ctype, NULL);
g_app_info_add_supports_type (info, ctype, NULL);
}
g_signal_handler_unblock (self->monitor, self->monitor_id);
g_signal_emit_by_name (self->monitor, "changed");
@@ -1208,23 +1236,6 @@ on_storage_row_activated_cb (CcApplicationsPanel *self)
gtk_window_present (self->storage_dialog);
}
static void
on_items_changed_cb (GListModel *list,
guint position,
guint removed,
guint added,
gpointer data)
{
CcApplicationsPanel *self = data;
if (g_list_model_get_n_items (list) == 0)
gtk_stack_set_visible_child (self->app_listbox_stack,
self->empty_search_placeholder);
else
gtk_stack_set_visible_child (self->app_listbox_stack,
GTK_WIDGET (self->app_listbox));
}
static void
update_total_size (CcApplicationsPanel *self)
{
@@ -1395,22 +1406,23 @@ update_panel (CcApplicationsPanel *self,
if (self->perm_store == NULL)
{
/* Async permission store not initialized, row will be re-activated in the callback */
self->perm_store_pending_row = row;
g_message ("No permissions store proxy yet, come back later");
return;
}
if (row == NULL)
{
g_message ("No app selected, try again");
adw_navigation_page_set_title (ADW_NAVIGATION_PAGE (self), _("Apps"));
gtk_stack_set_visible_child (self->stack, self->empty_box);
gtk_widget_set_visible (GTK_WIDGET (self->view_details_button), FALSE);
return;
}
info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (row));
adw_navigation_page_set_title (self->app_settings_page,
adw_navigation_page_set_title (ADW_NAVIGATION_PAGE (self),
g_app_info_get_display_name (info));
adw_navigation_view_push_by_tag(self->navigation_view, "settings-box");
gtk_stack_set_visible_child (self->stack, self->settings_box);
gtk_widget_set_visible (GTK_WIDGET (self->view_details_button), gnome_software_is_installed ());
g_clear_pointer (&self->current_app_id, g_free);
@@ -1426,45 +1438,19 @@ update_panel (CcApplicationsPanel *self,
self->current_portal_app_id = get_portal_app_id (info);
}
static gint
compare_rows (gconstpointer a,
gconstpointer b,
gpointer data)
{
GAppInfo *item1 = (GAppInfo *) a;
GAppInfo *item2 = (GAppInfo *) b;
g_autofree gchar *key1 = NULL;
g_autofree gchar *key2 = NULL;
key1 = g_utf8_casefold (g_app_info_get_display_name (item1), -1);
key2 = g_utf8_casefold (g_app_info_get_display_name (item2), -1);
const gchar *sort_key1 = g_utf8_collate_key (key1, -1);
const gchar *sort_key2 = g_utf8_collate_key (key2, -1);
return strcmp (sort_key1, sort_key2);
}
static void
populate_applications (CcApplicationsPanel *self)
{
g_autolist(GObject) infos = NULL;
GList *l;
g_list_store_remove_all (G_LIST_STORE (self->app_model));
listbox_remove_all (self->sidebar_listbox);
#ifdef HAVE_MALCONTENT
g_signal_handler_block (self->manager, self->app_filter_id);
#endif
infos = g_app_info_get_all ();
if (!infos)
gtk_widget_set_visible (GTK_WIDGET (self->app_search_entry), 0);
else
gtk_widget_set_visible (GTK_WIDGET (self->app_search_entry), 1);
for (l = infos; l; l = l->next)
{
GAppInfo *info = l->data;
@@ -1480,33 +1466,45 @@ populate_applications (CcApplicationsPanel *self)
#endif
row = GTK_WIDGET (cc_applications_row_new (info));
g_list_store_insert_sorted (G_LIST_STORE (self->app_model), info, compare_rows, NULL);
gtk_list_box_insert (self->sidebar_listbox, row, -1);
id = get_app_id (info);
if (g_strcmp0 (id, self->current_app_id) == 0)
gtk_list_box_select_row (self->app_listbox, GTK_LIST_BOX_ROW (row));
gtk_list_box_select_row (self->sidebar_listbox, GTK_LIST_BOX_ROW (row));
}
#ifdef HAVE_MALCONTENT
g_signal_handler_unblock (self->manager, self->app_filter_id);
#endif
}
static gint
compare_rows (GtkListBoxRow *row1,
GtkListBoxRow *row2,
gpointer data)
{
const gchar *key1 = cc_applications_row_get_sort_key (CC_APPLICATIONS_ROW (row1));
const gchar *key2 = cc_applications_row_get_sort_key (CC_APPLICATIONS_ROW (row2));
return strcmp (key1, key2);
}
static gboolean
filter_app_rows (GObject *item,
gpointer data)
filter_sidebar_rows (GtkListBoxRow *row,
gpointer data)
{
CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (data);
g_autofree gchar *app_name = NULL;
g_autofree gchar *search_text = NULL;
const gchar *text;
GAppInfo *info = G_APP_INFO (item);
GAppInfo *info;
text = gtk_editable_get_text (GTK_EDITABLE (self->app_search_entry));
text = gtk_editable_get_text (GTK_EDITABLE (self->sidebar_search_entry));
/* Only filter after the second character */
if (g_utf8_strlen (text, -1) < 2)
return TRUE;
info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (row));
app_name = cc_util_normalize_casefold_and_unaccent (g_app_info_get_name (info));
search_text = cc_util_normalize_casefold_and_unaccent (text);
@@ -1534,6 +1532,7 @@ row_activated_cb (CcApplicationsPanel *self,
GtkListBoxRow *row)
{
update_panel (self, row);
g_signal_emit_by_name (self, "sidebar-activated");
}
static void
@@ -1556,10 +1555,7 @@ on_perm_store_ready (GObject *source_object,
self->perm_store = proxy;
if (self->perm_store_pending_row)
g_signal_emit_by_name (self->perm_store_pending_row, "activate");
self->perm_store_pending_row = NULL;
update_panel (self, gtk_list_box_get_selected_row (self->sidebar_listbox));
}
static void
@@ -1569,7 +1565,7 @@ select_app (CcApplicationsPanel *self,
{
GtkWidget *child;
for (child = gtk_widget_get_first_child (GTK_WIDGET (self->app_listbox));
for (child = gtk_widget_get_first_child (GTK_WIDGET (self->sidebar_listbox));
child;
child = gtk_widget_get_next_sibling (child))
{
@@ -1577,7 +1573,7 @@ select_app (CcApplicationsPanel *self,
GAppInfo *info = cc_applications_row_get_info (row);
if (g_str_has_prefix (g_app_info_get_id (info), app_id))
{
gtk_list_box_select_row (self->app_listbox, GTK_LIST_BOX_ROW (row));
gtk_list_box_select_row (self->sidebar_listbox, GTK_LIST_BOX_ROW (row));
if (emit_activate)
g_signal_emit_by_name (row, "activate");
break;
@@ -1604,38 +1600,38 @@ on_launch_button_clicked_cb (CcApplicationsPanel *self)
&error);
if (error)
g_warning ("Error launching app: %s", error->message);
g_warning ("Error launching application: %s", error->message);
}
static void
on_app_search_entry_activated_cb (CcApplicationsPanel *self)
on_sidebar_search_entry_activated_cb (CcApplicationsPanel *self)
{
GtkListBoxRow *row;
row = gtk_list_box_get_row_at_y (self->app_listbox, 0);
row = gtk_list_box_get_row_at_y (self->sidebar_listbox, 0);
if (!row)
return;
/* Show the app */
gtk_list_box_select_row (self->app_listbox, row);
gtk_list_box_select_row (self->sidebar_listbox, row);
g_signal_emit_by_name (row, "activate");
/* Cleanup the entry */
gtk_editable_set_text (GTK_EDITABLE (self->app_search_entry), "");
gtk_widget_grab_focus (GTK_WIDGET (self->app_search_entry));
gtk_editable_set_text (GTK_EDITABLE (self->sidebar_search_entry), "");
gtk_widget_grab_focus (GTK_WIDGET (self->sidebar_search_entry));
}
static void
on_app_search_entry_search_changed_cb (CcApplicationsPanel *self)
on_sidebar_search_entry_search_changed_cb (CcApplicationsPanel *self)
{
gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT);
gtk_list_box_invalidate_filter (self->sidebar_listbox);
}
static void
on_app_search_entry_search_stopped_cb (CcApplicationsPanel *self)
on_sidebar_search_entry_search_stopped_cb (CcApplicationsPanel *self)
{
gtk_editable_set_text (GTK_EDITABLE (self->app_search_entry), "");
gtk_editable_set_text (GTK_EDITABLE (self->sidebar_search_entry), "");
}
static void
@@ -1725,33 +1721,103 @@ cc_applications_panel_set_property (GObject *object,
static void
cc_applications_panel_constructed (GObject *object)
{
CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (object);
GtkListBoxRow *row;
G_OBJECT_CLASS (cc_applications_panel_parent_class)->constructed (object);
/* Select the first row */
row = gtk_list_box_get_row_at_index (self->sidebar_listbox, 0);
gtk_list_box_select_row (self->sidebar_listbox, row);
}
static void
notify_collapsed_cb (CcApplicationsPanel *self)
{
GtkSelectionMode selection_mode;
gboolean collapsed;
GtkRoot *root;
g_assert (CC_IS_APPLICATIONS_PANEL (self));
root = gtk_widget_get_root (GTK_WIDGET (self));
g_object_get (root, "collapsed", &collapsed, NULL);
selection_mode = collapsed ? GTK_SELECTION_NONE : GTK_SELECTION_SINGLE;
gtk_list_box_set_selection_mode (self->sidebar_listbox, selection_mode);
if (!collapsed)
{
if (self->current_app_id)
select_app (self, self->current_app_id, FALSE);
else
{
GtkListBoxRow *row;
row = gtk_list_box_get_row_at_index (self->sidebar_listbox, 0);
row_activated_cb (self, row);
}
}
}
static void
cc_applications_panel_root (GtkWidget *widget)
{
CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (widget);
GtkRoot *root;
GTK_WIDGET_CLASS (cc_applications_panel_parent_class)->root (widget);
root = gtk_widget_get_root (widget);
g_signal_connect_swapped (root, "notify::collapsed", G_CALLBACK (notify_collapsed_cb), self);
notify_collapsed_cb (self);
}
static void
cc_applications_panel_unroot (GtkWidget *widget)
{
CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (widget);
GtkRoot *root = gtk_widget_get_root (widget);
g_signal_handlers_disconnect_by_func (root, notify_collapsed_cb, self);
GTK_WIDGET_CLASS (cc_applications_panel_parent_class)->unroot (widget);
}
static AdwNavigationPage*
cc_applications_panel_get_sidebar_widget (CcPanel *panel)
{
CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (panel);
return self->sidebar_box;
}
static void
cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
{
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
g_type_ensure (CC_TYPE_DEFAULT_APPS_PAGE);
g_type_ensure (CC_TYPE_REMOVABLE_MEDIA_SETTINGS);
object_class->dispose = cc_applications_panel_dispose;
object_class->finalize = cc_applications_panel_finalize;
object_class->constructed = cc_applications_panel_constructed;
object_class->set_property = cc_applications_panel_set_property;
widget_class->root = cc_applications_panel_root;
widget_class->unroot = cc_applications_panel_unroot;
panel_class->get_sidebar_widget = cc_applications_panel_get_sidebar_widget;
g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-applications-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_icon_image);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_listbox);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_name_label);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_search_entry);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_settings_page);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_dialog);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_page);
@@ -1760,9 +1826,7 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, camera);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, clear_cache_button);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, data);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, default_apps_page);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, empty_search_placeholder);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_listbox_stack);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, empty_box);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_dialog);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_page);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_file_group);
@@ -1774,7 +1838,6 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, launch_button);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, location);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, microphone);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, navigation_view);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_camera);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_location);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_microphone);
@@ -1783,11 +1846,15 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, notification);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, background);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, wallpaper);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, removable_media_settings);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, screenshot);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, shortcuts);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_box);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_listbox);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_search_entry);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, search);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, settings_box);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sound);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, stack);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_dialog);
gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, total);
@@ -1811,21 +1878,11 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_callback (widget_class, on_builtin_row_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_handler_row_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_launch_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, on_app_search_entry_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_app_search_entry_search_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_app_search_entry_search_stopped_cb);
gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_search_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_search_stopped_cb);
gtk_widget_class_bind_template_callback (widget_class, on_storage_row_activated_cb);
}
static GtkWidget *
app_row_new (gpointer item,
gpointer user_data)
{
GAppInfo *info = item;
return GTK_WIDGET (cc_applications_row_new (info));
}
gtk_widget_class_bind_template_callback (widget_class, on_storage_row_activated_cb);}
static void
cc_applications_panel_init (CcApplicationsPanel *self)
@@ -1843,7 +1900,7 @@ cc_applications_panel_init (CcApplicationsPanel *self)
gtk_widget_set_visible (GTK_WIDGET (self->install_button), gnome_software_is_installed ());
g_signal_connect_object (self->app_listbox, "row-activated",
g_signal_connect_object (self->sidebar_listbox, "row-activated",
G_CALLBACK (row_activated_cb), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->view_details_button,
@@ -1852,20 +1909,13 @@ cc_applications_panel_init (CcApplicationsPanel *self)
self,
G_CONNECT_SWAPPED);
self->filter = GTK_FILTER (gtk_custom_filter_new ((GtkCustomFilterFunc) filter_app_rows,
self, NULL));
gtk_list_box_set_sort_func (self->sidebar_listbox,
compare_rows,
NULL, NULL);
self->app_model = G_LIST_MODEL (g_list_store_new (G_TYPE_APP_INFO));
self->filter_model = G_LIST_MODEL (gtk_filter_list_model_new (self->app_model,
GTK_FILTER (self->filter)));
g_signal_connect (self->filter_model, "items-changed",
G_CALLBACK (on_items_changed_cb), self);
gtk_list_box_bind_model (self->app_listbox,
self->filter_model,
app_row_new,
NULL,
NULL);
gtk_list_box_set_filter_func (self->sidebar_listbox,
filter_sidebar_rows,
self, NULL);
self->location_settings = g_settings_new ("org.gnome.system.location");
self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");

View File

@@ -2,403 +2,335 @@
<interface>
<template class="CcApplicationsPanel" parent="CcPanel">
<property name="child">
<object class="AdwNavigationView" id="navigation_view">
<!-- App Search Page (Main Ladning Page) -->
<child>
<object class="AdwNavigationPage">
<property name="title" translatable="yes">Apps</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="AdwPreferencesPage" id="app_search_stack_page">
<!-- Searchbar -->
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="AdwClamp">
<property name="maximum-size">280</property>
<child>
<object class="GtkSearchEntry" id="app_search_entry">
<property name="placeholder_text" translatable="yes">Search apps</property>
<signal name="activate" handler="on_app_search_entry_activated_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="search-changed" handler="on_app_search_entry_search_changed_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="stop-search" handler="on_app_search_entry_search_stopped_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
</object>
</child>
</object>
</child>
<!-- Default Apps Row -->
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="CcListRow">
<property name="activatable">True</property>
<property name="title" translatable="yes">_Default Apps</property>
<property name="use-underline">True</property>
<property name="show-arrow">True</property>
<property name="action-name">navigation.push</property>
<property name="action-target">'default-apps'</property>
</object>
</child>
</object>
</child>
<!-- Apps List -->
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="GtkStack" id="app_listbox_stack">
<property name="vhomogeneous">False</property>
<child>
<!-- Empty search results placeholder -->
<object class="GtkBox" id="empty_search_placeholder">
<!--AdwStatusPage can't be used here, see: https://gitlab.gnome.org/GNOME/libadwaita/-/issues/697-->
<property name="orientation">vertical</property>
<property name="valign">center</property>
<!--Use AdwClamp like AdwStatusPage-->
<child>
<object class="AdwClamp">
<style>
<class name="status-page"/>
</style>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="pixel_size">128</property>
<property name="icon_name">computer-fail-symbolic</property>
<style>
<class name="dim-label"/>
<class name="icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">No Apps Found</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title"/>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="install_button">
<property name="label" translatable="yes">_Find in Software</property>
<property name="use_underline">True</property>
<property name="halign">center</property>
<signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
<style>
<class name="pill"/>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="app_listbox">
<property name="selection-mode">none</property>
<style>
<class name="boxed-list" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<!-- Default Apps Page -->
<child>
<object class="AdwNavigationPage">
<property name="title" translatable="yes">Default Apps</property>
<property name="tag">default-apps</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="GtkStack" id="stack">
<property name="content">
<object class="AdwPreferencesPage">
<!-- Default Apps Settings -->
<child>
<object class="CcDefaultAppsPage" id="default_apps_page" />
</child>
<!-- This "fake" empty box is there to show instead of the AdwStatusPage before the panel is initialized -->
<child>
<object class="GtkBox"/>
</child>
<!-- Removable Media Settings -->
<child>
<object class="CcRemovableMediaSettings" id="removable_media_settings" />
</child>
<child>
<object class="AdwStatusPage" id="empty_box">
<property name="icon-name">org.gnome.Software-symbolic</property>
<property name="title" translatable="yes">No Apps</property>
<child>
<object class="GtkButton" id="install_button">
<property name="label" translatable="yes">_Install Some…</property>
<property name="use-underline">True</property>
<property name="halign">center</property>
<signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
<style>
<class name="pill" />
</style>
</object>
</property>
</object>
</property>
</object>
</child>
<!-- App Settings Page -->
<child>
<object class="AdwNavigationPage" id="app_settings_page">
<property name="title" translatable="yes">App Settings</property>
<property name="tag">settings-box</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesPage" id="settings_box">
<!-- App icon & buttons -->
<child>
<object class="AdwPreferencesGroup">
<property name="content">
<object class="AdwPreferencesPage" id="settings_box">
<!-- App icon & buttons -->
<child>
<object class="AdwPreferencesGroup">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<child>
<object class="GtkImage" id="app_icon_image">
<property name="icon-name">org.gnome.Software</property>
<property name="pixel-size">96</property>
<style>
<class name="icon-dropshadow" />
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="app_name_label">
<property name="wrap">True</property>
<style>
<class name="title" />
<class name="title-1" />
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="halign">center</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="spacing">18</property>
<child>
<object class="GtkImage" id="app_icon_image">
<property name="icon-name">org.gnome.Software</property>
<property name="pixel-size">96</property>
<object class="GtkButton" id="launch_button">
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">True</property>
<property name="can-shrink">True</property>
<signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="yes" />
<style>
<class name="icon-dropshadow" />
<class name="pill" />
<class name="suggested-action" />
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="app_name_label">
<property name="wrap">True</property>
<object class="GtkButton" id="view_details_button">
<property name="label" translatable="yes">App _Details</property>
<property name="use-underline">True</property>
<property name="can-shrink">True</property>
<style>
<class name="title" />
<class name="title-1" />
<class name="pill" />
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="halign">center</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="spacing">18</property>
<child>
<object class="GtkButton" id="launch_button">
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">True</property>
<property name="can-shrink">True</property>
<signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="yes" />
<style>
<class name="pill" />
<class name="suggested-action" />
</style>
</object>
</child>
<child>
<object class="GtkButton" id="view_details_button">
<property name="label" translatable="yes">App _Details</property>
<property name="use-underline">True</property>
<property name="can-shrink">True</property>
<style>
<class name="pill" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup" id="integration_section">
<child>
<object class="AdwSwitchRow" id="search">
<property name="title" translatable="yes">_Search</property>
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="search_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_search">
<property name="title" translatable="yes">_Search</property>
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="notification">
<property name="title" translatable="yes">_Notifications</property>
<property name="subtitle" translatable="yes">Show system notifications</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="background">
<property name="title" translatable="yes">_Run in Background</property>
<property name="subtitle" translatable="yes">Allow activity when the app is closed</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="background_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="screenshot">
<property name="title" translatable="yes">Scr_eenshots</property>
<property name="subtitle" translatable="yes">Take pictures of the screen at any time</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="wallpaper">
<property name="title" translatable="yes">Change _Wallpaper</property>
<property name="subtitle" translatable="yes">Change the desktop wallpaper.</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="wallpaper_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="sound">
<property name="title" translatable="yes">So_unds</property>
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_sound">
<property name="title" translatable="yes">So_unds</property>
<property name="subtitle" translatable="yes">Reproduce sounds</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="shortcuts">
<property name="title" translatable="yes">_Inhibit Shortcuts</property>
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="shortcuts_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="camera">
<property name="title" translatable="yes">Camera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
<signal name="notify::active" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_camera">
<property name="title" translatable="yes">C_amera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="microphone">
<property name="title" translatable="yes">_Microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="microphone_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_microphone">
<property name="title" translatable="yes">_Microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="location">
<property name="title" translatable="yes">_Location Services</property>
<property name="subtitle" translatable="yes">Access device location data</property>
<property name="use-underline">True</property>
<signal name="notify::active" handler="location_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_location">
<property name="title" translatable="yes">_Location Services</property>
<property name="subtitle" translatable="yes">Access device location data</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup" id="integration_section">
<child>
<object class="AdwPreferencesGroup" id="usage_section">
<child>
<object class="CcInfoRow" id="builtin">
<property name="title" translatable="yes">Re_quired Access</property>
<property name="subtitle" translatable="yes">System access that is required by the app</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
<signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<child>
<object class="CcInfoRow" id="handler_row">
<property name="title" translatable="yes">_File &amp;amp; Link Associations</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
<signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<child>
<object class="CcInfoRow" id="storage">
<property name="title" translatable="yes">S_torage</property>
<property name="has-expander">1</property>
<property name="is-link">1</property>
<signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<object class="AdwSwitchRow" id="search">
<property name="title" translatable="yes">Search</property>
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
<signal name="notify::active" handler="search_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_search">
<property name="title" translatable="yes">Search</property>
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="notification">
<property name="title" translatable="yes">Notifications</property>
<property name="subtitle" translatable="yes">Show system notifications</property>
<signal name="notify::active" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="background">
<property name="title" translatable="yes">Run in Background</property>
<property name="subtitle" translatable="yes">Allow activity when the app is closed</property>
<signal name="notify::active" handler="background_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="screenshot">
<property name="title" translatable="yes">Screenshots</property>
<property name="subtitle" translatable="yes">Take pictures of the screen at any time</property>
<signal name="notify::active" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="wallpaper">
<property name="title" translatable="yes">Change Wallpaper</property>
<property name="subtitle" translatable="yes">Change the desktop wallpaper.</property>
<signal name="notify::active" handler="wallpaper_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="sound">
<property name="title" translatable="yes">Sounds</property>
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
<signal name="notify::active" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_sound">
<property name="title" translatable="yes">Sounds</property>
<property name="subtitle" translatable="yes">Reproduce sounds</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="shortcuts">
<property name="title" translatable="yes">Inhibit Shortcuts</property>
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts</property>
<signal name="notify::active" handler="shortcuts_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="camera">
<property name="title" translatable="yes">Camera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
<signal name="notify::active" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_camera">
<property name="title" translatable="yes">Camera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="microphone">
<property name="title" translatable="yes">Microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
<signal name="notify::active" handler="microphone_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_microphone">
<property name="title" translatable="yes">Microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="AdwSwitchRow" id="location">
<property name="title" translatable="yes">Location Services</property>
<property name="subtitle" translatable="yes">Access device location data</property>
<signal name="notify::active" handler="location_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcInfoRow" id="no_location">
<property name="title" translatable="yes">Location Services</property>
<property name="subtitle" translatable="yes">Access device location data</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
</object>
</property>
</child>
<child>
<object class="AdwPreferencesGroup" id="usage_section">
<child>
<object class="CcInfoRow" id="builtin">
<property name="title" translatable="yes">Required Access</property>
<property name="subtitle" translatable="yes">System access that is required by the app</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
<signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<child>
<object class="CcInfoRow" id="handler_row">
<property name="title" translatable="yes">File &amp;amp; Link Associations</property>
<property name="has-expander">True</property>
<property name="is-link">True</property>
<signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
<child>
<object class="CcInfoRow" id="storage">
<property name="title" translatable="yes">Storage</property>
<property name="has-expander">1</property>
<property name="is-link">1</property>
<signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
<!-- Sidebar -->
<object class="AdwNavigationPage" id="sidebar_box">
<property name="title" translatable="yes">Apps</property>
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<child type="top">
<object class="AdwBin">
<style>
<class name="toolbar"/>
</style>
<property name="child">
<object class="GtkSearchEntry" id="sidebar_search_entry">
<property name="placeholder_text" translatable="yes">Search apps</property>
<signal name="activate" handler="on_sidebar_search_entry_activated_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="search-changed" handler="on_sidebar_search_entry_search_changed_cb" object="CcApplicationsPanel" swapped="yes" />
<signal name="stop-search" handler="on_sidebar_search_entry_search_stopped_cb" object="CcApplicationsPanel" swapped="yes" />
</object>
</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="child">
<object class="GtkListBox" id="sidebar_listbox">
<property name="selection-mode">browse</property>
<style>
<class name="navigation-sidebar" />
</style>
<child type="placeholder">
<object class="GtkBox" id="empty_search_placeholder">
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="can_focus">False</property>
<property name="pixel_size">64</property>
<property name="icon_name">edit-find-symbolic</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="can_focus">False</property>
<property name="label" translatable="yes">No results found</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Try a different search</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</template>
</object>
<!-- Built-in Permissions dialog -->
<object class="AdwWindow" id="builtin_dialog">
@@ -493,13 +425,10 @@
<object class="GtkButton" id="handler_reset">
<property name="valign">center</property>
<property name="margin-top">12</property>
<property name="label" translatable="yes">_Reset</property>
<property name="use-underline">True</property>
<property name="halign">center</property>
<property name="label" translatable="yes">Reset</property>
<signal name="clicked" handler="handler_reset_cb" object="CcApplicationsPanel" swapped="yes"/>
<style>
<class name="destructive-action" />
<class name="pill" />
</style>
</object>
</child>
@@ -519,8 +448,7 @@
<property name="resizable">True</property>
<property name="hide-on-close">True</property>
<property name="default-width">420</property>
<property name="width-request">360</property>
<property name="height-request">294</property>
<property name="default-height">420</property>
<child>
<object class="GtkShortcutController">
<property name="scope">managed</property>
@@ -572,13 +500,9 @@
<object class="AdwPreferencesGroup">
<child>
<object class="GtkButton" id="clear_cache_button">
<property name="label" translatable="yes">_Clear Cache</property>
<property name="label" translatable="yes">_Clear Cache</property>
<property name="use-underline">True</property>
<property name="halign">center</property>
<signal name="clicked" handler="clear_cache_cb" object="CcApplicationsPanel" swapped="yes"/>
<style>
<class name="pill" />
</style>
</object>
</child>
</object>

View File

@@ -26,12 +26,17 @@
struct _CcApplicationsRow
{
AdwActionRow parent;
GtkListBoxRow parent;
GAppInfo *info;
gchar *sortkey;
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
};
G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, ADW_TYPE_ACTION_ROW)
G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, GTK_TYPE_LIST_BOX_ROW)
static void
cc_applications_row_finalize (GObject *object)
@@ -39,6 +44,7 @@ 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);
}
@@ -52,6 +58,10 @@ cc_applications_row_class_init (CcApplicationsRowClass *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
@@ -64,26 +74,23 @@ CcApplicationsRow *
cc_applications_row_new (GAppInfo *info)
{
CcApplicationsRow *self;
g_autoptr(GIcon) icon = NULL;
GtkWidget *w;
g_autofree gchar *key = NULL;
GIcon *icon;
self = g_object_new (CC_TYPE_APPLICATIONS_ROW, NULL);
self->info = g_object_ref (info);
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE);
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self),
g_markup_escape_text (g_app_info_get_display_name (info), -1));
key = g_utf8_casefold (g_app_info_get_display_name (info), -1);
self->sortkey = g_utf8_collate_key (key, -1);
icon = g_app_info_get_icon (info);
if (icon != NULL)
g_object_ref (icon);
gtk_image_set_from_gicon (GTK_IMAGE (self->image), g_app_info_get_icon (info));
else
icon = g_themed_icon_new ("application-x-executable");
w = gtk_image_new_from_gicon (icon);
gtk_style_context_add_class (gtk_widget_get_style_context (w), "lowres-icon");
gtk_image_set_icon_size (GTK_IMAGE (w), GTK_ICON_SIZE_LARGE);
adw_action_row_add_prefix (ADW_ACTION_ROW (self), w);
gtk_image_set_from_icon_name (GTK_IMAGE (self->image), "application-x-executable");
gtk_label_set_label (GTK_LABEL (self->label), g_app_info_get_display_name (info));
return self;
}
@@ -93,3 +100,9 @@ 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

@@ -21,15 +21,16 @@
#pragma once
#include <gtk/gtk.h>
#include <adwaita.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, AdwActionRow)
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

@@ -1,12 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcApplicationsRow" parent="AdwActionRow">
<child type="suffix">
<object class="GtkImage">
<property name="icon-name">go-next-symbolic</property>
<template class="CcApplicationsRow" parent="GtkListBoxRow">
<child>
<object class="GtkBox" id="box">
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkImage" id="image">
<property name="pixel-size">32</property>
<style>
<class name="lowres-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="xalign">0</property>
<property name="ellipsize">end</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcDefaultAppsPage" parent="AdwPreferencesGroup">
<property name="title" translatable="yes">Links &amp;amp; Files</property>
<property name="description" translatable="yes">Apps which are used to open common links and files</property>
<child>
<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>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<object class="CcDefaultAppsRow" id="mail_row">
<property name="title" translatable="yes">_Mail</property>
<property name="use_underline">True</property>
<property name="content-type">x-scheme-handler/mailto</property>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<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>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<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>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<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>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<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>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<object class="CcDefaultAppsRow" id="calls_row">
<property name="visible">False</property>
<property name="title" translatable="yes" comments="Translators: This is a telephone call">Ca_lls</property>
<property name="use-underline">True</property>
<property name="content-type">x-scheme-handler/tel</property>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
<child>
<object class="CcDefaultAppsRow" id="sms_row">
<property name="visible">False</property>
<property name="title" translatable="yes">_SMS</property>
<property name="use-underline">True</property>
<property name="content-type">x-scheme-handler/sms</property>
<signal name="notify::selected-item" handler="on_row_selected_item_changed"/>
</object>
</child>
</template>
</interface>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcInfoRow" parent="AdwActionRow">
<property name="use-underline">True</property>
<child>
<object class="GtkLabel" id="info">
<property name="valign">center</property>

View File

@@ -1,210 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcRemovableMediaSettings" parent="AdwPreferencesGroup">
<property name="title" translatable="yes">Removable Media</property>
<property name="description" translatable="yes">Apps which are launched when media or drives are connected</property>
<child>
<object class="AdwActionRow" id="disable_autostart_row">
<property name="title" translatable="yes">D_isable Autostart</property>
<property name="subtitle" translatable="yes">Never prompt or start apps on media insertion</property>
<property name="use_underline">True</property>
<property name="activatable_widget">autorun_never_switch</property>
<child>
<object class="GtkSwitch" id="autorun_never_switch">
<property name="receives_default">False</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="cd_audio_row">
<property name="title" translatable="yes">CD _Audio</property>
<property name="use_underline">True</property>
<property name="activatable_widget">audio_cdda_chooser</property>
<child>
<object class="GtkAppChooserButton" id="audio_cdda_chooser">
<property name="valign">center</property>
<property name="content_type">x-content/audio-cdda</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="dvd_video_row">
<property name="title" translatable="yes">_DVD Video</property>
<property name="use_underline">True</property>
<property name="activatable_widget">video_dvd_chooser</property>
<child>
<object class="GtkAppChooserButton" id="video_dvd_chooser">
<property name="valign">center</property>
<property name="content_type">x-content/video-dvd</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="music_player_row">
<property name="title" translatable="yes">Music Pla_yer</property>
<property name="use_underline">True</property>
<property name="activatable_widget">music_player_chooser</property>
<child>
<object class="GtkAppChooserButton" id="music_player_chooser">
<property name="valign">center</property>
<property name="content_type">x-content/audio-player</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="photos_row">
<property name="title" translatable="yes">P_hotos</property>
<property name="use_underline">True</property>
<property name="activatable_widget">dcf_chooser</property>
<child>
<object class="GtkAppChooserButton" id="dcf_chooser">
<property name="valign">center</property>
<property name="content_type">x-content/image-dcf</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="software_row">
<property name="title" translatable="yes">Sof_tware</property>
<property name="use_underline">True</property>
<property name="activatable_widget">software_chooser</property>
<child>
<object class="GtkAppChooserButton" id="software_chooser">
<property name="valign">center</property>
<property name="content_type">x-content/unix-software</property>
</object>
</child>
</object>
</child>
<child>
<object class="CcListRow" id="other_media_row">
<property name="title" translatable="yes">_Other Media</property>
<property name="use_underline">True</property>
<property name="show-arrow">True</property>
<property name="subtitle" translatable="yes">Select how other media should be handled</property>
<signal name="activated" handler="on_extra_options_button_clicked" object="CcRemovableMediaSettings"/>
</object>
</child>
</template>
<object class="GtkSizeGroup">
<widgets>
<widget name="audio_cdda_chooser"/>
<widget name="video_dvd_chooser"/>
<widget name="music_player_chooser"/>
<widget name="dcf_chooser"/>
<widget name="software_chooser"/>
</widgets>
</object>
<object class="AdwWindow" id="other_type_dialog">
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="destroy_with_parent">True</property>
<property name="hide-on-close">True</property>
<signal name="close-request" handler="on_extra_options_dialog_close_request" object="CcRemovableMediaSettings" swapped="yes"/>
<child>
<object class="GtkShortcutController">
<property name="scope">managed</property>
<child>
<object class="GtkShortcut">
<property name="trigger">Escape</property>
<property name="action">action(window.close)</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="GtkBox">
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="spacing">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="spacing">6</property>
<property name="margin-start">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="column_spacing">6</property>
<property name="row_spacing">10</property>
<child>
<object class="GtkComboBox" id="other_type_combo_box">
<property name="model">other_type_list_store</property>
<signal name="changed" handler="on_other_type_combo_box_changed" object="CcRemovableMediaSettings" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="other_action_label">
<property name="xalign">0</property>
<property name="label" translatable="yes">_Action:</property>
<property name="use_underline">True</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="other_action_box">
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="label" translatable="yes">_Type:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">other_type_combo_box</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
<object class="GtkListStore" id="other_type_list_store">
<columns>
<!-- column-name description -->
<column type="gchararray"/>
<!-- column-name content-type -->
<column type="gchararray"/>
</columns>
</object>
</interface>

View File

@@ -23,39 +23,37 @@
#include "cc-snap-row.h"
#include "cc-applications-resources.h"
#include "cc-snapd-client.h"
#define CHANGE_POLL_TIME 100
struct _CcSnapRow
{
AdwActionRow parent;
GtkSwitch *slot_toggle;
GtkComboBox *slots_combo;
GtkListStore *slots_combo_model;
GtkSwitch *slot_toggle;
GtkComboBox *slots_combo;
GtkListStore *slots_combo_model;
GCancellable *cancellable;
GCancellable *cancellable;
CcSnapdClient *client;
JsonObject *plug;
JsonObject *connected_slot;
JsonArray *slots;
JsonObject *target_slot;
gchar *change_id;
guint change_timeout;
SnapdPlug *plug;
SnapdSlot *connected_slot;
GPtrArray *slots;
};
G_DEFINE_TYPE (CcSnapRow, cc_snap_row, ADW_TYPE_ACTION_ROW)
typedef struct
{
CcSnapRow *self;
SnapdSlot *slot;
} ConnectData;
static void
update_state (CcSnapRow *self)
{
gboolean have_single_option;
GtkTreeIter iter;
have_single_option = json_array_get_length (self->slots) == 1;
have_single_option = self->slots->len == 1;
gtk_widget_set_visible (GTK_WIDGET (self->slot_toggle), have_single_option);
gtk_widget_set_visible (GTK_WIDGET (self->slots_combo), !have_single_option);
@@ -65,7 +63,7 @@ update_state (CcSnapRow *self)
{
do
{
JsonObject *slot;
SnapdSlot *slot;
gtk_tree_model_get (GTK_TREE_MODEL (self->slots_combo_model), &iter, 0, &slot, -1);
if (slot == self->connected_slot)
@@ -88,111 +86,96 @@ enable_controls (CcSnapRow *self)
gtk_widget_set_sensitive (GTK_WIDGET (self->slots_combo), TRUE);
}
static void
change_complete (CcSnapRow *self)
static ConnectData *
connect_data_new (CcSnapRow *self, SnapdSlot *slot)
{
g_clear_object (&self->client);
g_clear_pointer (&self->target_slot, json_object_unref);
g_clear_pointer (&self->change_id, g_free);
g_clear_handle_id (&self->change_timeout, g_source_remove);
ConnectData *data;
data = g_new0 (ConnectData, 1);
data->self = self;
data->slot = g_object_ref (slot);
return data;
}
static void
connect_data_free (ConnectData *data)
{
g_clear_object (&data->slot);
g_free (data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ConnectData, connect_data_free)
static void
connect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
{
g_autoptr(ConnectData) data = user_data;
CcSnapRow *self = data->self;
SnapdSlot *slot = data->slot;
g_autoptr(GError) error = NULL;
if (snapd_client_connect_interface_finish (SNAPD_CLIENT (client), result, &error))
{
g_clear_object (&self->connected_slot);
self->connected_slot = g_object_ref (slot);
}
else
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Failed to connect interface: %s", error->message);
}
update_state (self);
enable_controls (self);
}
static gboolean
poll_change_cb (gpointer user_data)
{
CcSnapRow *self = user_data;
g_autoptr(JsonObject) change = NULL;
g_autoptr(GError) error = NULL;
change = cc_snapd_client_get_change_sync (self->client, self->change_id, self->cancellable, &error);
if (change == NULL)
{
g_warning ("Failed to monitor change %s: %s", self->change_id, error->message);
change_complete (self);
return G_SOURCE_REMOVE;
}
if (json_object_get_boolean_member (change, "ready"))
{
const gchar *status = json_object_get_string_member (change, "status");
if (g_strcmp0 (status, "Done") == 0)
{
g_clear_pointer (&self->connected_slot, json_object_unref);
self->connected_slot = self->target_slot ? json_object_ref (self->target_slot) : NULL;
}
else
{
g_warning ("Change completed with status %s", status);
}
change_complete (self);
return G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
}
static void
monitor_change (CcSnapRow *self, const gchar *change_id)
connect_plug (CcSnapRow *self, SnapdSlot *slot)
{
g_free (self->change_id);
self->change_id = g_strdup (change_id);
g_clear_handle_id (&self->change_timeout, g_source_remove);
self->change_timeout = g_timeout_add (CHANGE_POLL_TIME, poll_change_cb, self);
}
static CcSnapdClient *
get_client(CcSnapRow *self)
{
if (self->client == NULL)
self->client = cc_snapd_client_new ();
return self->client;
}
static void
connect_plug (CcSnapRow *self, JsonObject *slot)
{
g_autofree gchar *change_id = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(SnapdClient) client = NULL;
/* already connected */
if (self->connected_slot != NULL &&
g_strcmp0 (json_object_get_string_member (self->connected_slot, "snap"),
json_object_get_string_member (slot, "snap")) == 0 &&
g_strcmp0 (json_object_get_string_member (self->connected_slot, "slot"),
json_object_get_string_member (slot, "slot")) == 0)
if (self->connected_slot == slot)
return;
disable_controls (self);
change_id = cc_snapd_client_connect_interface_sync (get_client (self),
json_object_get_string_member (self->plug, "snap"),
json_object_get_string_member (self->plug, "plug"),
json_object_get_string_member (slot, "snap"),
json_object_get_string_member (slot, "slot"),
self->cancellable,
&error);
if (change_id == NULL)
client = snapd_client_new ();
snapd_client_connect_interface_async (client,
snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
snapd_slot_get_snap (slot), snapd_slot_get_name (slot),
NULL, NULL,
self->cancellable,
connect_interface_cb, connect_data_new (self, slot));
}
static void
disconnect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
{
CcSnapRow *self = user_data;
g_autoptr(GError) error = NULL;
if (snapd_client_disconnect_interface_finish (SNAPD_CLIENT (client), result, &error))
{
g_warning ("Failed to connect plug: %s", error->message);
change_complete (self);
return;
g_clear_object (&self->connected_slot);
}
else
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Failed to disconnect interface: %s", error->message);
}
g_clear_pointer (&self->target_slot, json_object_unref);
self->target_slot = json_object_ref (slot);
monitor_change (self, change_id);
update_state (self);
enable_controls (self);
}
static void
disconnect_plug (CcSnapRow *self)
{
g_autofree gchar *change_id = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(SnapdClient) client = NULL;
/* already disconnected */
if (self->connected_slot == NULL)
@@ -200,20 +183,13 @@ disconnect_plug (CcSnapRow *self)
disable_controls (self);
change_id = cc_snapd_client_disconnect_interface_sync (get_client (self),
json_object_get_string_member (self->plug, "snap"),
json_object_get_string_member (self->plug, "plug"),
"", "",
self->cancellable, &error);
if (change_id == NULL)
{
g_warning ("Failed to disconnect plug: %s", error->message);
change_complete (self);
return;
}
g_clear_pointer (&self->target_slot, json_object_unref);
monitor_change (self, change_id);
client = snapd_client_new ();
snapd_client_disconnect_interface_async (client,
snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
NULL, NULL,
NULL, NULL,
self->cancellable,
disconnect_interface_cb, self);
}
static void
@@ -221,8 +197,8 @@ switch_changed_cb (CcSnapRow *self)
{
if (gtk_switch_get_active (self->slot_toggle))
{
if (json_array_get_length (self->slots) == 1)
connect_plug (self, json_array_get_object_element (self->slots, 0));
if (self->slots->len == 1)
connect_plug (self, g_ptr_array_index (self->slots, 0));
}
else
{
@@ -234,7 +210,7 @@ static void
combo_changed_cb (CcSnapRow *self)
{
GtkTreeIter iter;
JsonObject *slot = NULL;
SnapdSlot *slot = NULL;
if (!gtk_combo_box_get_active_iter (self->slots_combo, &iter))
return;
@@ -246,134 +222,14 @@ combo_changed_cb (CcSnapRow *self)
disconnect_plug (self);
}
static const gchar *
make_interface_label (const gchar *interface_name)
{
if (strcmp (interface_name, "account-control") == 0)
return _("Add user accounts and change passwords");
else if (strcmp (interface_name, "alsa") == 0)
return _("Play and record sound");
else if (strcmp (interface_name, "audio-playback") == 0)
return _("Play audio");
else if (strcmp (interface_name, "audio-record") == 0)
return _("Record audio");
else if (strcmp (interface_name, "avahi-observe") == 0)
return _("Detect network devices using mDNS/DNS-SD (Bonjour/zeroconf)");
else if (strcmp (interface_name, "bluetooth-control") == 0)
return _("Access bluetooth hardware directly");
else if (strcmp (interface_name, "bluez") == 0)
return _("Use bluetooth devices");
else if (strcmp (interface_name, "camera") == 0)
return _("Use your camera");
else if (strcmp (interface_name, "cups-control") == 0)
return _("Print documents");
else if (strcmp (interface_name, "joystick") == 0)
return _("Use any connected joystick");
else if (strcmp (interface_name, "docker") == 0)
return _("Allow connecting to the Docker service");
else if (strcmp (interface_name, "firewall-control") == 0)
return _("Configure network firewall");
else if (strcmp (interface_name, "fuse-support") == 0)
return _("Setup and use privileged FUSE filesystems");
else if (strcmp (interface_name, "fwupd") == 0)
return _("Update firmware on this device");
else if (strcmp (interface_name, "hardware-observe") == 0)
return _("Access hardware information");
else if (strcmp (interface_name, "hardware-random-control") == 0)
return _("Provide entropy to hardware random number generator");
else if (strcmp (interface_name, "hardware-random-observe") == 0)
return _("Use hardware-generated random numbers");
else if (strcmp (interface_name, "home") == 0)
return _("Access files in your home folder");
else if (strcmp (interface_name, "libvirt") == 0)
return _("Access libvirt service");
else if (strcmp (interface_name, "locale-control") == 0)
return _("Change system language and region settings");
else if (strcmp (interface_name, "location-control") == 0)
return _("Change location settings and providers");
else if (strcmp (interface_name, "location-observe") == 0)
return _("Access your location");
else if (strcmp (interface_name, "log-observe") == 0)
return _("Read system and application logs");
else if (strcmp (interface_name, "lxd") == 0)
return _("Access LXD service");
else if (strcmp (interface_name, "modem-manager") == 0)
return _("Use and configure modems");
else if (strcmp (interface_name, "mount-observe") == 0)
return _("Read system mount information and disk quotas");
else if (strcmp (interface_name, "mpris") == 0)
return _("Control music and video players");
else if (strcmp (interface_name, "network-control") == 0)
return _("Change low-level network settings");
else if (strcmp (interface_name, "network-manager") == 0)
return _("Access the NetworkManager service to read and change network settings");
else if (strcmp (interface_name, "network-observe") == 0)
return _("Read access to network settings");
else if (strcmp (interface_name, "network-setup-control") == 0)
return _("Change network settings");
else if (strcmp (interface_name, "network-setup-observe") == 0)
return _("Read network settings");
else if (strcmp (interface_name, "ofono") == 0)
return _("Access the ofono service to read and change network settings for mobile telephony");
else if (strcmp (interface_name, "openvswitch") == 0)
return _("Control Open vSwitch hardware");
else if (strcmp (interface_name, "optical-drive") == 0)
return _("Read from CD/DVD");
else if (strcmp (interface_name, "password-manager-service") == 0)
return _("Read, add, change, or remove saved passwords");
else if (strcmp (interface_name, "ppp") == 0)
return _("Access pppd and ppp devices for configuring Point-to-Point Protocol connections");
else if (strcmp (interface_name, "process-control") == 0)
return _("Pause or end any process on the system");
else if (strcmp (interface_name, "pulseaudio") == 0)
return _("Play and record sound");
else if (strcmp (interface_name, "raw-usb") == 0)
return _("Access USB hardware directly");
else if (strcmp (interface_name, "removable-media") == 0)
return _("Read/write files on removable storage devices");
else if (strcmp (interface_name, "screen-inhibit-control") == 0)
return _("Prevent screen sleep/lock");
else if (strcmp (interface_name, "serial-port") == 0)
return _("Access serial port hardware");
else if (strcmp (interface_name, "shutdown") == 0)
return _("Restart or power off the device");
else if (strcmp (interface_name, "snapd-control") == 0)
return _("Install, remove and configure software");
else if (strcmp (interface_name, "storage-framework-service") == 0)
return _("Access Storage Framework service");
else if (strcmp (interface_name, "system-observe") == 0)
return _("Read process and system information");
else if (strcmp (interface_name, "system-trace") == 0)
return _("Monitor and control any running program");
else if (strcmp (interface_name, "time-control") == 0)
return _("Change the date and time");
else if (strcmp (interface_name, "timeserver-control") == 0)
return _("Change time server settings");
else if (strcmp (interface_name, "timezone-control") == 0)
return _("Change the time zone");
else if (strcmp (interface_name, "udisks2") == 0)
return _("Access the UDisks2 service for configuring disks and removable media");
else if (strcmp (interface_name, "upower-observe") == 0)
return _("Access energy usage data");
else if (strcmp (interface_name, "u2f-devices") == 0)
return _("Read/write access to U2F devices exposed");
else
return interface_name;
}
static void
cc_snap_row_finalize (GObject *object)
{
CcSnapRow *self = CC_SNAP_ROW (object);
g_clear_object (&self->cancellable);
g_clear_object (&self->client);
g_clear_pointer (&self->plug, json_object_unref);
g_clear_pointer (&self->slots, json_array_unref);
g_clear_pointer (&self->target_slot, json_object_unref);
g_clear_pointer (&self->change_id, g_free);
g_clear_handle_id (&self->change_timeout, g_source_remove);
self->change_timeout = 0;
g_clear_object (&self->plug);
g_clear_pointer (&self->slots, g_ptr_array_unref);
G_OBJECT_CLASS (cc_snap_row_parent_class)->finalize (object);
}
@@ -403,48 +259,51 @@ cc_snap_row_init (CcSnapRow *self)
}
CcSnapRow *
cc_snap_row_new (GCancellable *cancellable, JsonObject *plug, JsonArray *slots)
cc_snap_row_new (GCancellable *cancellable, SnapdInterface *interface, SnapdPlug *plug, GPtrArray *slots)
{
CcSnapRow *self;
const gchar *label = NULL;
GPtrArray *connected_slots;
g_autofree gchar *label = NULL;
GtkTreeIter iter;
g_return_val_if_fail (SNAPD_IS_PLUG (plug), NULL);
self = CC_SNAP_ROW (g_object_new (CC_TYPE_SNAP_ROW, NULL));
self->cancellable = g_object_ref (cancellable);
self->plug = json_object_ref (plug);
self->slots = json_array_ref (slots);
self->plug = g_object_ref (plug);
self->slots = g_ptr_array_ref (slots);
if (json_object_has_member (plug, "connections"))
connected_slots = snapd_plug_get_connected_slots (plug);
if (connected_slots->len > 0)
{
JsonArray *connected_slots = json_object_get_array_member (plug, "connections");
JsonObject *connected_slot_ref = json_array_get_object_element (connected_slots, 0);
SnapdSlotRef *connected_slot_ref = g_ptr_array_index (connected_slots, 0);
for (guint i = 0; i < json_array_get_length (slots); i++)
for (int i = 0; i < slots->len; i++)
{
JsonObject *slot = json_array_get_object_element (slots, i);
SnapdSlot *slot = g_ptr_array_index (slots, i);
if (g_strcmp0 (json_object_get_string_member (slot, "snap"),
json_object_get_string_member (connected_slot_ref, "snap")) == 0 &&
g_strcmp0 (json_object_get_string_member (slot, "slot"),
json_object_get_string_member (connected_slot_ref, "slot")) == 0)
if (g_strcmp0 (snapd_slot_get_snap (slot), snapd_slot_ref_get_snap (connected_slot_ref)) == 0 &&
g_strcmp0 (snapd_slot_get_name (slot), snapd_slot_ref_get_slot (connected_slot_ref)) == 0)
self->connected_slot = slot;
}
}
label = make_interface_label (json_object_get_string_member (plug, "interface"));
if (interface != NULL)
label = snapd_interface_make_label (interface);
else
label = g_strdup (snapd_plug_get_interface (plug));
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), label);
/* Add option into combo box */
gtk_list_store_append (self->slots_combo_model, &iter);
gtk_list_store_set (self->slots_combo_model, &iter, 1, "--", -1);
for (guint i = 0; i < json_array_get_length (slots); i++)
for (int i = 0; i < slots->len; i++)
{
JsonObject *slot = json_array_get_object_element (slots, i);
SnapdSlot *slot = g_ptr_array_index (slots, i);
g_autofree gchar *label = NULL;
label = g_strdup_printf ("%s:%s", json_object_get_string_member (slot, "snap"),
json_object_get_string_member (slot, "slot"));
label = g_strdup_printf ("%s:%s", snapd_slot_get_snap (slot), snapd_slot_get_name (slot));
gtk_list_store_append (self->slots_combo_model, &iter);
gtk_list_store_set (self->slots_combo_model, &iter, 0, slot, 1, label, -1);
}

View File

@@ -21,7 +21,7 @@
#pragma once
#include <adwaita.h>
#include <json-glib/json-glib.h>
#include <snapd-glib/snapd-glib.h>
G_BEGIN_DECLS
@@ -29,7 +29,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CcSnapRow, cc_snap_row, CC, SNAP_ROW, AdwActionRow)
CcSnapRow* cc_snap_row_new (GCancellable *cancellable,
JsonObject *plug,
JsonArray *slots);
SnapdInterface *interface,
SnapdPlug *plug,
GPtrArray *slots);
G_END_DECLS

View File

@@ -3,7 +3,7 @@
<object class="GtkListStore" id="slots_combo_model">
<columns>
<!-- column-name slot -->
<column type="JsonObject"/>
<column type="GObject"/>
<!-- column-name label -->
<column type="gchararray"/>
</columns>

View File

@@ -1,290 +0,0 @@
/* cc-snapd-client.c
*
* Copyright 2023 Canonical Ltd.
*
* 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 <libsoup/soup.h>
#include "cc-snapd-client.h"
// Unix socket that snapd communicates on.
#define SNAPD_SOCKET_PATH "/var/run/snapd.socket"
struct _CcSnapdClient
{
GObject parent;
// HTTP connection to snapd.
SoupSession *session;
};
G_DEFINE_TYPE (CcSnapdClient, cc_snapd_client, G_TYPE_OBJECT)
// Make an HTTP request to send to snapd.
static SoupMessage *
make_message (const gchar *method, const gchar *path, JsonNode *request_body)
{
g_autofree gchar *uri = NULL;
SoupMessage *msg;
SoupMessageHeaders *request_headers;
uri = g_strdup_printf("http://locahost%s", path);
msg = soup_message_new (method, uri);
request_headers = soup_message_get_request_headers (msg);
// Allow authentication via polkit.
soup_message_headers_append (request_headers, "X-Allow-Interaction", "true");
if (request_body != NULL)
{
g_autoptr(JsonGenerator) generator = NULL;
g_autofree gchar *body_text = NULL;
gsize body_length;
g_autoptr(GBytes) body_bytes = NULL;
generator = json_generator_new ();
json_generator_set_root (generator, request_body);
body_text = json_generator_to_data (generator, &body_length);
body_bytes = g_bytes_new (body_text, body_length);
soup_message_set_request_body_from_bytes (msg, "application/json", body_bytes);
}
return msg;
}
// Process an HTTP response recveived from snapd.
static JsonObject *
process_body (SoupMessage *msg, GBytes *body, GError **error)
{
const gchar *content_type;
g_autoptr(JsonParser) parser = NULL;
const gchar *body_data;
size_t body_length;
JsonNode *root;
JsonObject *response;
gint64 status_code;
g_autoptr(GError) internal_error = NULL;
content_type = soup_message_headers_get_one (soup_message_get_response_headers (msg), "Content-Type");
if (g_strcmp0 (content_type, "application/json") != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid content type %s returned", content_type);
return NULL;
}
parser = json_parser_new ();
body_data = g_bytes_get_data (body, &body_length);
if (!json_parser_load_from_data (parser, body_data, body_length, &internal_error))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to decode JSON content: %s", internal_error->message);
return NULL;
}
root = json_parser_get_root (parser);
if (!JSON_NODE_HOLDS_OBJECT (root))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Returned JSON not an object");
return NULL;
}
response = json_node_get_object (root);
status_code = json_object_get_int_member (response, "status-code");
if (status_code != SOUP_STATUS_OK && status_code != SOUP_STATUS_ACCEPTED)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid status code %" G_GINT64_FORMAT, status_code);
return NULL;
}
return json_object_ref (response);
}
// Send an HTTP request to snapd and process the response.
static JsonObject *
call_sync (CcSnapdClient *self,
const gchar *method, const gchar *path, JsonNode *request_body,
GCancellable *cancellable, GError **error)
{
g_autoptr(SoupMessage) msg = NULL;
g_autoptr(GBytes) response_body = NULL;
msg = make_message (method, path, request_body);
response_body = soup_session_send_and_read (self->session, msg, cancellable, error);
if (response_body == NULL)
return NULL;
return process_body (msg, response_body, error);
}
// Perform a snap interface action.
static gchar *
call_interfaces_sync (CcSnapdClient *self,
const gchar *action,
const gchar *plug_snap, const gchar *plug_name,
const gchar *slot_snap, const gchar *slot_name,
GCancellable *cancellable, GError **error)
{
g_autoptr(JsonBuilder) builder = NULL;
g_autoptr(JsonObject) response = NULL;
const gchar *change_id;
builder = json_builder_new();
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "action");
json_builder_add_string_value (builder, action);
json_builder_set_member_name (builder, "plugs");
json_builder_begin_array (builder);
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "snap");
json_builder_add_string_value (builder, plug_snap);
json_builder_set_member_name (builder, "plug");
json_builder_add_string_value (builder, plug_name);
json_builder_end_object (builder);
json_builder_end_array (builder);
json_builder_set_member_name (builder, "slots");
json_builder_begin_array (builder);
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "snap");
json_builder_add_string_value (builder, slot_snap);
json_builder_set_member_name (builder, "slot");
json_builder_add_string_value (builder, slot_name);
json_builder_end_object (builder);
json_builder_end_array (builder);
json_builder_end_object (builder);
response = call_sync (self, "POST", "/v2/interfaces",
json_builder_get_root (builder), cancellable, error);
if (response == NULL)
return NULL;
change_id = json_object_get_string_member (response, "change");
return g_strdup (change_id);
}
static void
cc_snapd_client_dispose (GObject *object)
{
CcSnapdClient *self = CC_SNAPD_CLIENT (object);
g_clear_object(&self->session);
G_OBJECT_CLASS (cc_snapd_client_parent_class)->dispose (object);
}
static void
cc_snapd_client_class_init (CcSnapdClientClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = cc_snapd_client_dispose;
}
static void
cc_snapd_client_init (CcSnapdClient *self)
{
g_autoptr(GSocketAddress) address = g_unix_socket_address_new (SNAPD_SOCKET_PATH);
self->session = soup_session_new_with_options ("remote-connectable", address, NULL);
}
CcSnapdClient *
cc_snapd_client_new (void)
{
return CC_SNAPD_CLIENT (g_object_new (CC_TYPE_SNAPD_CLIENT, NULL));
}
JsonObject *
cc_snapd_client_get_snap_sync (CcSnapdClient *self, const gchar *name, GCancellable *cancellable, GError **error)
{
g_autofree gchar *path = NULL;
g_autoptr(JsonObject) response = NULL;
JsonObject *result;
path = g_strdup_printf ("/v2/snaps/%s", name);
response = call_sync (self, "GET", path, NULL, cancellable, error);
if (response == NULL)
return NULL;
result = json_object_get_object_member (response, "result");
if (result == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to %s", path);
return NULL;
}
return json_object_ref (result);
}
JsonObject *
cc_snapd_client_get_change_sync (CcSnapdClient *self, const gchar *change_id, GCancellable *cancellable, GError **error)
{
g_autofree gchar *path = NULL;
g_autoptr(JsonObject) response = NULL;
JsonObject *result;
path = g_strdup_printf ("/v2/changes/%s", change_id);
response = call_sync (self, "GET", path, NULL, cancellable, error);
if (response == NULL)
return NULL;
result = json_object_get_object_member (response, "result");
if (result == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to %s", path);
return NULL;
}
return json_object_ref (result);
}
gboolean
cc_snapd_client_get_all_connections_sync (CcSnapdClient *self,
JsonArray **plugs, JsonArray **slots,
GCancellable *cancellable, GError **error)
{
g_autoptr(JsonObject) response = NULL;
JsonObject *result;
response = call_sync (self, "GET", "/v2/connections?select=all", NULL, cancellable, error);
if (response == NULL)
return FALSE;
result = json_object_get_object_member (response, "result");
if (result == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid response to /v2/connections");
return FALSE;
}
*plugs = json_array_ref (json_object_get_array_member (result, "plugs"));
*slots = json_array_ref (json_object_get_array_member (result, "slots"));
return TRUE;
}
gchar *
cc_snapd_client_connect_interface_sync (CcSnapdClient *self,
const gchar *plug_snap, const gchar *plug_name,
const gchar *slot_snap, const gchar *slot_name,
GCancellable *cancellable, GError **error)
{
return call_interfaces_sync (self, "connect", plug_snap, plug_name, slot_snap, slot_name, cancellable, error);
}
gchar *
cc_snapd_client_disconnect_interface_sync (CcSnapdClient *self,
const gchar *plug_snap, const gchar *plug_name,
const gchar *slot_snap, const gchar *slot_name,
GCancellable *cancellable, GError **error)
{
return call_interfaces_sync (self, "disconnect", plug_snap, plug_name, slot_snap, slot_name, cancellable, error);
}

View File

@@ -1,70 +0,0 @@
/* cc-snapd-client.h
*
* Copyright 2023 Canonical Ltd.
*
* 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 <json-glib/json-glib.h>
G_BEGIN_DECLS
#define CC_TYPE_SNAPD_CLIENT (cc_snapd_client_get_type())
G_DECLARE_FINAL_TYPE (CcSnapdClient, cc_snapd_client, CC, SNAPD_CLIENT, GObject)
// Creates a client to contact snapd.
CcSnapdClient *cc_snapd_client_new (void);
// Get information on an installed snap.
JsonObject *cc_snapd_client_get_snap_sync (CcSnapdClient *client,
const gchar *name,
GCancellable *cancellable,
GError **error);
// Get information on a snap change.
JsonObject *cc_snapd_client_get_change_sync (CcSnapdClient *client,
const gchar *change_id,
GCancellable *cancellable,
GError **error);
// Get the state of the snap interface connections.
gboolean cc_snapd_client_get_all_connections_sync (CcSnapdClient *client,
JsonArray **plugs,
JsonArray **slots,
GCancellable *cancellable,
GError **error);
// Connect a plug to a slot. Returns the change ID to monitor for completion of this task.
gchar *cc_snapd_client_connect_interface_sync (CcSnapdClient *client,
const gchar *plug_snap,
const gchar *plug_name,
const gchar *slot_snap,
const gchar *slot_name,
GCancellable *cancellable,
GError **error);
// Disconnect a plug to a slot. Returns the change ID to monitor for completion of this task.
gchar *cc_snapd_client_disconnect_interface_sync (CcSnapdClient *client,
const gchar *plug_snap,
const gchar *plug_name,
const gchar *slot_snap,
const gchar *slot_name,
GCancellable *cancellable,
GError **error);
G_END_DECLS

View File

@@ -12,4 +12,5 @@ StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
OnlyShowIn=GNOME;Unity;
# Translators: Search terms to find the Apps panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=application;flatpak;permission;setting;default;preferred;media;autorun;cd;dvd;usb;audio;video;disc;removable;device;system;
Keywords=application;flatpak;permission;setting;
X-GNOME-ControlCenter-HasSidebar=true

View File

@@ -2,13 +2,3 @@ install_data(
'scalable/org.gnome.Settings-applications-symbolic.svg',
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
)
install_data(
'scalable/org.gnome.Settings-default-apps-symbolic.svg',
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
)
install_data(
'scalable/org.gnome.Settings-removable-media-symbolic.svg',
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
)

View File

@@ -14,37 +14,23 @@ sources = files(
'cc-applications-panel.c',
'cc-applications-row.c',
'cc-info-row.c',
'cc-default-apps-page.c',
'cc-default-apps-row.c',
'cc-removable-media-settings.c',
'globs.c',
'search.c',
'utils.c',
)
resource_data = files(
'cc-applications-panel.ui',
'cc-default-apps-page.ui',
'cc-removable-media-settings.ui',
)
sources += gnome.compile_resources(
'cc-' + cappletname + '-resources',
cappletname + '.gresource.xml',
c_name : 'cc_' + cappletname,
dependencies: resource_data,
export : true
)
deps = common_deps
if host_is_linux
deps += mm_dep
endif
if enable_snap
deps += [ json_glib_dep, libsoup_dep ]
sources += [ 'cc-snap-row.c', 'cc-snapd-client.c' ]
deps += snapd_glib_deps
sources += files('cc-snap-row.c')
endif
if enable_malcontent

View File

@@ -24,15 +24,15 @@
#include <config.h>
#include <glib/gi18n.h>
#ifdef HAVE_SNAP
#include <snapd-glib/snapd-glib.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <ftw.h>
#include "utils.h"
#ifdef HAVE_SNAP
#include "cc-snapd-client.h"
#endif
static gint
ftw_remove_cb (const gchar *path,
@@ -142,6 +142,15 @@ file_size_finish (GFile *file,
return TRUE;
}
void
listbox_remove_all (GtkListBox *listbox)
{
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (listbox))))
gtk_list_box_remove (listbox, child);
}
static gchar *
get_output_of (const gchar **argv)
{
@@ -227,19 +236,19 @@ guint64
get_snap_app_size (const gchar *snap_name)
{
#ifdef HAVE_SNAP
g_autoptr(CcSnapdClient) client = NULL;
g_autoptr(JsonObject) snap = NULL;
g_autoptr(SnapdClient) client = NULL;
g_autoptr(SnapdSnap) snap = NULL;
g_autoptr(GError) error = NULL;
client = cc_snapd_client_new ();
snap = cc_snapd_client_get_snap_sync (client, snap_name, NULL, &error);
client = snapd_client_new ();
snap = snapd_client_get_snap_sync (client, snap_name, NULL, &error);
if (snap == NULL)
{
g_warning ("Failed to get snap size: %s", error->message);
return 0;
}
return json_object_get_int_member (snap, "installed-size");
return snapd_snap_get_installed_size (snap);
#else
return 0;
#endif

View File

@@ -44,6 +44,8 @@ gboolean file_size_finish (GFile *file,
guint64 *size,
GError **error);
void listbox_remove_all (GtkListBox *listbox);
GKeyFile* get_flatpak_metadata (const gchar *app_id);
guint64 get_flatpak_app_size (const gchar *app_id);

View File

@@ -143,8 +143,6 @@ create_widget_func (gpointer model_item,
gtk_widget_add_css_class (button, "circular");
gtk_widget_add_css_class (button, "remove-button");
gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Remove Background"));
g_signal_connect (button,
"clicked",
G_CALLBACK (on_delete_background_clicked_cb),

View File

@@ -3,7 +3,6 @@
<template class="CcListRowInfoButton" parent="GtkWidget">
<child>
<object class="GtkMenuButton" id="button">
<property name="tooltip-text" translatable="yes">More Information</property>
<property name="icon-name">info-symbolic</property>
<style>
<class name="flat"/>

View File

@@ -2,7 +2,6 @@
<interface>
<template class="CcListRow" parent="AdwActionRow">
<property name="activatable">True</property>
<property name="use-underline">True</property>
<!-- Secondary Label -->
<child type="suffix">

View File

@@ -60,7 +60,6 @@
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="use-underline">True</property>
<property name="xalign">0.0</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
@@ -143,7 +142,6 @@
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="use-underline">True</property>
<property name="xalign">0.0</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>

View File

@@ -114,6 +114,9 @@ cc_util_get_smart_date (GDateTime *date)
g_autoptr(GDateTime) local = NULL;
GTimeSpan span;
if (date == NULL)
return NULL;
/* Set today date */
local = g_date_time_new_now_local ();
today = g_date_time_new_local (g_date_time_get_year (local),
@@ -135,7 +138,6 @@ cc_util_get_smart_date (GDateTime *date)
if (g_date_time_get_year (date) == g_date_time_get_year (today))
{
/* Translators: This is a date format string in the style of "Feb 24". */
/* xgettext:no-c-format */
return g_date_time_format (date, _("%b %e"));
}
else

View File

@@ -1,9 +1,6 @@
/*
* cc-datetime-page.c
*
* Copyright (C) 2010 Intel, Inc
* Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com>
* Copyright 2023 Gotam Gorabh <gautamy672@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
@@ -18,12 +15,16 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Thomas Wood <thomas.wood@intel.com>
*
*/
#include "config.h"
#include "cc-list-row.h"
#include "cc-time-editor.h"
#include "cc-datetime-page.h"
#include "cc-datetime-panel.h"
#include "cc-datetime-resources.h"
#include "cc-list-row.h"
#include <langinfo.h>
#include <sys/time.h>
@@ -66,9 +67,9 @@
#define DATETIME_SCHEMA "org.gnome.desktop.datetime"
#define AUTO_TIMEZONE_KEY "automatic-timezone"
struct _CcDateTimePage
struct _CcDateTimePanel
{
CcSystemPage parent_instance;
CcPanel parent_instance;
GList *toplevels;
@@ -89,9 +90,8 @@ struct _CcDateTimePage
AdwActionRow *datetime_row;
GtkWindow *datetime_dialog;
GtkLabel *datetime_label;
AdwSpinRow *day_spin_row;
GtkToggleButton *twentyfour_format_button;
GtkToggleButton *ampm_format_button;
GtkSpinButton *day_spinbutton;
AdwComboRow *timeformat_row;
GtkSpinButton *h_spinbutton;
GtkWidget *weekday_row;
GtkWidget *weekday_switch;
@@ -100,15 +100,17 @@ struct _CcDateTimePage
GtkWidget *week_numbers_switch;
GtkLockButton *lock_button;
GtkListBox *date_box;
AdwActionRow *day_row;
GtkSingleSelection *month_model;
GtkPopover *month_popover;
CcListRow *month_row;
AdwActionRow *year_row;
GtkSwitch *network_time_switch;
CcTimeEditor *time_editor;
AdwActionRow *timezone_row;
CcTzDialog *timezone_dialog;
GtkLabel *timezone_label;
AdwSpinRow *year_spin_row;
GtkSpinButton *year_spinbutton;
GnomeWallClock *clock_tracker;
@@ -124,14 +126,19 @@ struct _CcDateTimePage
int month; /* index starts from 1 */
};
G_DEFINE_TYPE (CcDateTimePage, cc_date_time_page, CC_TYPE_SYSTEM_PAGE)
CC_PANEL_REGISTER (CcDateTimePanel, cc_date_time_panel)
static void update_time (CcDateTimePage *self);
static void update_time (CcDateTimePanel *self);
static void on_month_selection_changed_cb (CcDateTimePanel *self);
static void time_changed_cb (CcDateTimePanel *self,
CcTimeEditor *editor);
static void
cc_date_time_page_dispose (GObject *object)
cc_date_time_panel_dispose (GObject *object)
{
CcDateTimePage *self = CC_DATE_TIME_PAGE (object);
CcDateTimePanel *self = CC_DATE_TIME_PANEL (object);
if (self->cancellable)
{
@@ -157,24 +164,45 @@ cc_date_time_page_dispose (GObject *object)
g_clear_pointer (&self->date, g_date_time_unref);
G_OBJECT_CLASS (cc_date_time_page_parent_class)->dispose (object);
G_OBJECT_CLASS (cc_date_time_panel_parent_class)->dispose (object);
}
static void clock_settings_changed_cb (CcDateTimePage *self,
gchar *key);
static const char *
cc_date_time_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/clock";
}
static void clock_settings_changed_cb (CcDateTimePanel *self,
gchar *key);
static char *
format_clock_name_cb (AdwEnumListItem *item,
gpointer user_data)
{
switch (adw_enum_list_item_get_value (item))
{
case G_DESKTOP_CLOCK_FORMAT_24H:
return g_strdup (_("24-hour"));
case G_DESKTOP_CLOCK_FORMAT_12H:
return g_strdup (_("AM / PM"));
default:
return NULL;
}
}
static void
change_clock_settings (CcDateTimePage *self)
change_clock_settings (CcDateTimePanel *self)
{
GDesktopClockFormat value;
AdwEnumListItem *item;
g_signal_handlers_block_by_func (self->clock_settings, clock_settings_changed_cb,
self);
if (gtk_toggle_button_get_active (self->twentyfour_format_button))
value = G_DESKTOP_CLOCK_FORMAT_24H;
else
value = G_DESKTOP_CLOCK_FORMAT_12H;
item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (self->timeformat_row));
value = adw_enum_list_item_get_value (item);
g_settings_set_enum (self->clock_settings, CLOCK_FORMAT_KEY, value);
g_settings_set_enum (self->filechooser_settings, CLOCK_FORMAT_KEY, value);
@@ -187,33 +215,29 @@ change_clock_settings (CcDateTimePage *self)
}
static void
clock_settings_changed_cb (CcDateTimePage *self,
gchar *key)
clock_settings_changed_cb (CcDateTimePanel *self,
gchar *key)
{
GDesktopClockFormat value;
value = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
self->clock_format = value;
g_signal_handlers_block_by_func (self->ampm_format_button, change_clock_settings, self);
g_signal_handlers_block_by_func (self->twentyfour_format_button, change_clock_settings, self);
g_signal_handlers_block_by_func (self->timeformat_row, change_clock_settings, self);
adw_combo_row_set_selected (self->timeformat_row, value);
gtk_toggle_button_set_active (self->twentyfour_format_button,
value == G_DESKTOP_CLOCK_FORMAT_24H);
gtk_toggle_button_set_active (self->ampm_format_button,
value == G_DESKTOP_CLOCK_FORMAT_12H);
cc_time_editor_set_am_pm (self->time_editor,
value == G_DESKTOP_CLOCK_FORMAT_12H);
update_time (self);
g_signal_handlers_unblock_by_func (self->twentyfour_format_button, change_clock_settings, self);
g_signal_handlers_unblock_by_func (self->ampm_format_button, change_clock_settings, self);
g_signal_handlers_unblock_by_func (self->timeformat_row, change_clock_settings, self);
}
/* Update the widgets based on the system time */
static void
update_time (CcDateTimePage *self)
update_time (CcDateTimePanel *self)
{
g_autofree gchar *label = NULL;
gboolean use_ampm;
@@ -223,9 +247,11 @@ update_time (CcDateTimePage *self)
else
use_ampm = FALSE;
g_signal_handlers_block_by_func (self->time_editor, time_changed_cb, self);
cc_time_editor_set_time (self->time_editor,
g_date_time_get_hour (self->date),
g_date_time_get_minute (self->date));
g_signal_handlers_unblock_by_func (self->time_editor, time_changed_cb, self);
/* Update the time on the listbow row */
if (use_ampm)
@@ -240,7 +266,9 @@ update_time (CcDateTimePage *self)
}
self->month = g_date_time_get_month (self->date);
g_signal_handlers_block_by_func (self->month_model, on_month_selection_changed_cb, self);
gtk_single_selection_set_selected (self->month_model, self->month - 1);
g_signal_handlers_unblock_by_func (self->month_model, on_month_selection_changed_cb, self);
gtk_label_set_text (self->datetime_label, label);
}
@@ -249,7 +277,7 @@ set_time_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
CcDateTimePage *self = user_data;
CcDateTimePanel *self = user_data;
g_autoptr(GError) error = NULL;
if (!timedate1_call_set_time_finish (self->dtm,
@@ -270,7 +298,7 @@ set_timezone_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
CcDateTimePage *self = user_data;
CcDateTimePanel *self = user_data;
g_autoptr(GError) error = NULL;
if (!timedate1_call_set_timezone_finish (self->dtm,
@@ -287,7 +315,7 @@ set_using_ntp_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
CcDateTimePage *self = user_data;
CcDateTimePanel *self = user_data;
g_autoptr(GError) error = NULL;
if (!timedate1_call_set_ntp_finish (self->dtm,
@@ -304,7 +332,7 @@ set_using_ntp_cb (GObject *source,
}
static void
queue_set_datetime (CcDateTimePage *self)
queue_set_datetime (CcDateTimePanel *self)
{
gint64 unixtime;
@@ -321,8 +349,8 @@ queue_set_datetime (CcDateTimePage *self)
}
static void
queue_set_ntp (CcDateTimePage *self,
gboolean using_ntp)
queue_set_ntp (CcDateTimePanel *self,
gboolean using_ntp)
{
self->pending_ntp_state = using_ntp;
timedate1_call_set_ntp (self->dtm,
@@ -334,7 +362,7 @@ queue_set_ntp (CcDateTimePage *self,
}
static void
queue_set_timezone (CcDateTimePage *self)
queue_set_timezone (CcDateTimePanel *self)
{
/* for now just do it */
if (self->current_location)
@@ -349,22 +377,24 @@ queue_set_timezone (CcDateTimePage *self)
}
static void
change_date (CcDateTimePage *self)
change_date (CcDateTimePanel *self)
{
guint y, d;
g_autoptr(GDateTime) old_date = NULL;
y = (guint)adw_spin_row_get_value (self->year_spin_row);
d = (guint)adw_spin_row_get_value (self->day_spin_row);
y = gtk_spin_button_get_value_as_int (self->year_spinbutton);
d = gtk_spin_button_get_value_as_int (self->day_spinbutton);
old_date = self->date;
self->date = g_date_time_new_local (y, self->month, d,
g_date_time_get_hour (old_date),
g_date_time_get_minute (old_date),
g_date_time_get_second (old_date));
g_signal_handlers_block_by_func (self->time_editor, time_changed_cb, self);
cc_time_editor_set_time (self->time_editor,
g_date_time_get_hour (self->date),
g_date_time_get_minute (self->date));
g_signal_handlers_unblock_by_func (self->time_editor, time_changed_cb, self);
queue_set_datetime (self);
}
@@ -397,7 +427,7 @@ translated_city_name (TzLocation *loc)
}
static void
update_timezone (CcDateTimePage *self)
update_timezone (CcDateTimePanel *self)
{
g_autofree gchar *city_country = NULL;
g_autofree gchar *label = NULL;
@@ -413,7 +443,7 @@ update_timezone (CcDateTimePage *self)
}
static void
get_initial_timezone (CcDateTimePage *self)
get_initial_timezone (CcDateTimePanel *self)
{
const gchar *timezone;
@@ -431,48 +461,48 @@ get_initial_timezone (CcDateTimePage *self)
}
static void
day_changed (CcDateTimePage *self)
day_changed (CcDateTimePanel *self)
{
change_date (self);
}
static void
month_year_changed (CcDateTimePage *self)
month_year_changed (CcDateTimePanel *self)
{
guint y;
guint num_days;
GtkAdjustment *adj;
y = (guint)adw_spin_row_get_value (self->year_spin_row);
y = gtk_spin_button_get_value_as_int (self->year_spinbutton);
/* Check the number of days in that month */
num_days = g_date_get_days_in_month (self->month, y);
adj = GTK_ADJUSTMENT (adw_spin_row_get_adjustment (self->day_spin_row));
adj = GTK_ADJUSTMENT (gtk_spin_button_get_adjustment (self->day_spinbutton));
gtk_adjustment_set_upper (adj, num_days + 1);
if ((guint)adw_spin_row_get_value (self->day_spin_row) > num_days)
adw_spin_row_set_value (self->day_spin_row, num_days);
if (gtk_spin_button_get_value_as_int (self->day_spinbutton) > num_days)
gtk_spin_button_set_value (self->day_spinbutton, num_days);
change_date (self);
}
static void
on_date_box_row_activated_cb (CcDateTimePage *self,
GtkListBoxRow *row)
on_date_box_row_activated_cb (CcDateTimePanel *self,
GtkListBoxRow *row)
{
g_assert (CC_IS_DATE_TIME_PAGE (self));
g_assert (CC_IS_DATE_TIME_PANEL (self));
if (row == GTK_LIST_BOX_ROW (self->month_row))
gtk_popover_popup (self->month_popover);
}
static void
on_month_selection_changed_cb (CcDateTimePage *self)
on_month_selection_changed_cb (CcDateTimePanel *self)
{
guint i;
g_assert (CC_IS_DATE_TIME_PAGE (self));
g_assert (CC_IS_DATE_TIME_PANEL (self));
i = gtk_single_selection_get_selected (self->month_model);
g_assert (i >= 0 && i < 12);
@@ -484,8 +514,8 @@ on_month_selection_changed_cb (CcDateTimePage *self)
}
static void
on_clock_changed (CcDateTimePage *self,
GParamSpec *pspec)
on_clock_changed (CcDateTimePanel *self,
GParamSpec *pspec)
{
g_date_time_unref (self->date);
self->date = g_date_time_new_now_local ();
@@ -494,8 +524,8 @@ on_clock_changed (CcDateTimePage *self,
}
static gboolean
change_ntp (CcDateTimePage *self,
gboolean state)
change_ntp (CcDateTimePanel *self,
gboolean state)
{
queue_set_ntp (self, state);
@@ -504,7 +534,7 @@ change_ntp (CcDateTimePage *self,
}
static gboolean
is_ntp_available (CcDateTimePage *self)
is_ntp_available (CcDateTimePanel *self)
{
g_autoptr(GVariant) value = NULL;
gboolean ntp_available = TRUE;
@@ -523,7 +553,7 @@ is_ntp_available (CcDateTimePage *self)
}
static void
on_permission_changed (CcDateTimePage *self)
on_permission_changed (CcDateTimePanel *self)
{
gboolean allowed, location_allowed, tz_allowed, auto_timezone, using_ntp;
@@ -547,26 +577,26 @@ on_permission_changed (CcDateTimePage *self)
}
static void
on_location_settings_changed (CcDateTimePage *self)
on_location_settings_changed (CcDateTimePanel *self)
{
on_permission_changed (self);
}
static void
on_can_ntp_changed (CcDateTimePage *self)
on_can_ntp_changed (CcDateTimePanel *self)
{
gtk_widget_set_visible (GTK_WIDGET (self->auto_datetime_row), is_ntp_available (self));
}
static void
on_timezone_changed (CcDateTimePage *self)
on_timezone_changed (CcDateTimePanel *self)
{
get_initial_timezone (self);
}
static void
on_timedated_properties_changed (CcDateTimePage *self,
GVariant *changed_properties,
on_timedated_properties_changed (CcDateTimePanel *self,
GVariant *changed_properties,
const gchar **invalidated_properties)
{
guint i;
@@ -596,22 +626,22 @@ on_timedated_properties_changed (CcDateTimePage *self,
}
static void
present_window (CcDateTimePage *self,
GtkWindow *window)
present_window (CcDateTimePanel *self,
GtkWindow *window)
{
GtkNative *native;
GtkWidget *parent;
native = gtk_widget_get_native (GTK_WIDGET (self));
parent = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
gtk_window_set_transient_for (window, GTK_WINDOW (native));
gtk_window_set_transient_for (window, GTK_WINDOW (parent));
gtk_window_present (window);
}
static gboolean
tz_switch_to_row_transform_func (GBinding *binding,
const GValue *source_value,
GValue *target_value,
CcDateTimePage *self)
tz_switch_to_row_transform_func (GBinding *binding,
const GValue *source_value,
GValue *target_value,
CcDateTimePanel *self)
{
gboolean active;
gboolean allowed;
@@ -628,10 +658,10 @@ tz_switch_to_row_transform_func (GBinding *binding,
}
static gboolean
switch_to_row_transform_func (GBinding *binding,
const GValue *source_value,
GValue *target_value,
CcDateTimePage *self)
switch_to_row_transform_func (GBinding *binding,
const GValue *source_value,
GValue *target_value,
CcDateTimePanel *self)
{
gboolean active;
gboolean allowed;
@@ -645,9 +675,9 @@ switch_to_row_transform_func (GBinding *binding,
}
static void
bind_switch_to_row (CcDateTimePage *self,
GtkSwitch *gtkswitch,
GtkWidget *listrow)
bind_switch_to_row (CcDateTimePanel *self,
GtkSwitch *gtkswitch,
GtkWidget *listrow)
{
g_object_bind_property_full (gtkswitch, "active",
listrow, "sensitive",
@@ -657,17 +687,17 @@ bind_switch_to_row (CcDateTimePage *self,
}
static void
panel_tz_selection_changed_cb (CcDateTimePage *self)
panel_tz_selection_changed_cb (CcDateTimePanel *self)
{
g_assert (CC_IS_DATE_TIME_PAGE (self));
g_assert (CC_IS_DATE_TIME_PANEL (self));
self->current_location = cc_tz_dialog_get_selected_location (self->timezone_dialog);
queue_set_timezone (self);
}
static void
list_box_row_activated (CcDateTimePage *self,
GtkListBoxRow *row)
list_box_row_activated (CcDateTimePanel *self,
GtkListBoxRow *row)
{
if (row == GTK_LIST_BOX_ROW (self->datetime_row))
@@ -681,12 +711,12 @@ list_box_row_activated (CcDateTimePage *self,
}
static void
time_changed_cb (CcDateTimePage *self,
CcTimeEditor *editor)
time_changed_cb (CcDateTimePanel *self,
CcTimeEditor *editor)
{
g_autoptr(GDateTime) old_date = NULL;
g_assert (CC_IS_DATE_TIME_PAGE (self));
g_assert (CC_IS_DATE_TIME_PANEL (self));
g_assert (CC_IS_TIME_EDITOR (editor));
old_date = self->date;
@@ -702,7 +732,7 @@ time_changed_cb (CcDateTimePage *self,
}
static void
setup_datetime_dialog (CcDateTimePage *self)
setup_datetime_dialog (CcDateTimePanel *self)
{
GtkAdjustment *adjustment;
GdkDisplay *display;
@@ -732,35 +762,37 @@ setup_datetime_dialog (CcDateTimePage *self)
g_date_time_get_year (self->date));
adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_day_of_month (self->date), 1,
num_days + 1, 1, 10, 1);
adw_spin_row_set_adjustment (self->day_spin_row, adjustment);
g_signal_connect_object (G_OBJECT (self->day_spin_row), "changed",
gtk_spin_button_set_adjustment (self->day_spinbutton, adjustment);
g_signal_connect_object (G_OBJECT (self->day_spinbutton), "value-changed",
G_CALLBACK (day_changed), self, G_CONNECT_SWAPPED);
/* Year */
adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_year (self->date),
1, G_MAXDOUBLE, 1,
10, 1);
adw_spin_row_set_adjustment (self->year_spin_row, adjustment);
g_signal_connect_object (G_OBJECT (self->year_spin_row), "changed",
gtk_spin_button_set_adjustment (self->year_spinbutton, adjustment);
g_signal_connect_object (G_OBJECT (self->year_spinbutton), "value-changed",
G_CALLBACK (month_year_changed), self, G_CONNECT_SWAPPED);
/* Month */
self->month = g_date_time_get_month (self->date);
g_signal_handlers_block_by_func (self->month_model, on_month_selection_changed_cb, self);
gtk_single_selection_set_selected (self->month_model, self->month - 1);
g_signal_handlers_unblock_by_func (self->month_model, on_month_selection_changed_cb, self);
}
static int
sort_date_box (GtkListBoxRow *a,
GtkListBoxRow *b,
CcDateTimePage *self)
sort_date_box (GtkListBoxRow *a,
GtkListBoxRow *b,
CcDateTimePanel *self)
{
GtkListBoxRow *day_row, *month_row, *year_row;
g_assert (CC_IS_DATE_TIME_PAGE (self));
g_assert (CC_IS_DATE_TIME_PANEL (self));
day_row = GTK_LIST_BOX_ROW (self->day_spin_row);
day_row = GTK_LIST_BOX_ROW (self->day_row);
month_row = GTK_LIST_BOX_ROW (self->month_row);
year_row = GTK_LIST_BOX_ROW (self->year_spin_row);
year_row = GTK_LIST_BOX_ROW (self->year_row);
switch (date_endian_get_default (FALSE)) {
case DATE_ENDIANESS_BIG:
@@ -796,72 +828,68 @@ sort_date_box (GtkListBoxRow *a,
}
static void
update_page_summary (CcDateTimePage *self)
{
gboolean enabled =
gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
cc_system_page_set_summary (CC_SYSTEM_PAGE (self), enabled ?
_("Automatic date and time") :
gtk_label_get_text (self->timezone_label));
}
static void
cc_date_time_page_class_init (CcDateTimePageClass *klass)
cc_date_time_panel_class_init (CcDateTimePanelClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
object_class->dispose = cc_date_time_page_dispose;
object_class->dispose = cc_date_time_panel_dispose;
panel_class->get_help_uri = cc_date_time_panel_get_help_uri;
g_type_ensure (CC_TYPE_LIST_ROW);
g_type_ensure (CC_TYPE_TIME_EDITOR);
g_type_ensure (CC_TYPE_TZ_DIALOG);
g_type_ensure (G_DESKTOP_TYPE_DESKTOP_CLOCK_FORMAT);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/system/datetime/cc-datetime-page.ui");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/datetime/cc-datetime-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, auto_datetime_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, auto_timezone_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, auto_timezone_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, date_box);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, datetime_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, datetime_dialog);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, datetime_label);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, day_spin_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, twentyfour_format_button);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, ampm_format_button);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, weekday_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, date_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, seconds_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, week_numbers_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, lock_button);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, month_model);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, month_popover);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, month_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, network_time_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, time_editor);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, timezone_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, timezone_dialog);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, timezone_label);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePage, year_spin_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_datetime_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_box);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_dialog);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_label);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_spinbutton);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timeformat_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, weekday_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, seconds_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, week_numbers_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, lock_button);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_model);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_popover);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, network_time_switch);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, time_editor);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_dialog);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_label);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_row);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_spinbutton);
gtk_widget_class_bind_template_callback (widget_class, panel_tz_selection_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, list_box_row_activated);
gtk_widget_class_bind_template_callback (widget_class, time_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, change_clock_settings);
gtk_widget_class_bind_template_callback (widget_class, format_clock_name_cb);
gtk_widget_class_bind_template_callback (widget_class, on_date_box_row_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_month_selection_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, update_page_summary);
bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
g_type_ensure (CC_TYPE_TIME_EDITOR);
}
static void
cc_date_time_page_init (CcDateTimePage *self)
cc_date_time_panel_init (CcDateTimePanel *self)
{
g_autoptr(GError) error = NULL;
g_resources_register (cc_datetime_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
self->cancellable = g_cancellable_new ();
@@ -911,8 +939,6 @@ cc_date_time_page_init (CcDateTimePage *self)
/* setup_timezone_dialog (self); */
setup_datetime_dialog (self);
update_page_summary (self);
/* set up network time switch */
bind_switch_to_row (self,
self->network_time_switch,

View File

@@ -1,6 +1,4 @@
/*
* cc-region-page.h
*
* Copyright (C) 2010 Intel, Inc
*
* This program is free software; you can redistribute it and/or modify
@@ -16,20 +14,17 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Sergey Udaltsov <svu@gnome.org>
* Gotam Gorabh <gautamy672@gmail.com>
* Author: Thomas Wood <thomas.wood@intel.com>
*
*/
#pragma once
#include "cc-system-page.h"
#include <shell/cc-panel.h>
G_BEGIN_DECLS
#define CC_TYPE_REGION_PAGE (cc_region_page_get_type ())
G_DECLARE_FINAL_TYPE (CcRegionPage, cc_region_page, CC, REGION_PAGE, CcSystemPage)
#define CC_TYPE_DATE_TIME_PANEL (cc_date_time_panel_get_type ())
G_DECLARE_FINAL_TYPE (CcDateTimePanel, cc_date_time_panel, CC, DATE_TIME_PANEL, CcPanel)
G_END_DECLS

View File

@@ -56,20 +56,24 @@
<!-- Year row -->
<child>
<object class="AdwSpinRow" id="year_spin_row">
<property name="title" translatable="yes">_Year</property>
<property name="use-underline">True</property>
<property name="valign">center</property>
<property name="width-chars">4</property>
<property name="numeric">True</property>
<object class="AdwActionRow" id="year_row">
<property name="title" translatable="yes">Year</property>
<property name="activatable-widget">year_spinbutton</property>
<child>
<object class="GtkSpinButton" id="year_spinbutton">
<property name="valign">center</property>
<property name="width-chars">4</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<!-- Month row -->
<child>
<object class="CcListRow" id="month_row">
<property name="title" translatable="yes">_Month</property>
<property name="use-underline">True</property>
<property name="title" translatable="yes">Month</property>
<binding name="secondary-label">
<lookup name="string" type="GtkStringObject">
<lookup name="selected-item">month_model</lookup>
@@ -95,12 +99,16 @@
<!-- Day row -->
<child>
<object class="AdwSpinRow" id="day_spin_row">
<property name="title" translatable="yes">_Day</property>
<property name="use-underline">True</property>
<property name="valign">center</property>
<property name="width-chars">3</property>
<property name="numeric">True</property>
<object class="AdwActionRow" id="day_row">
<property name="title" translatable="yes">Day</property>
<property name="activatable-widget">day_spinbutton</property>
<child>
<object class="GtkSpinButton" id="day_spinbutton">
<property name="valign">center</property>
<property name="width-chars">3</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
@@ -114,9 +122,7 @@
</object>
</property>
</object>
<template class="CcDateTimePage" parent="CcSystemPage">
<property name="title" translatable="yes">Date &amp; Time</property>
<property name="tag">system-date-time-page</property>
<template class="CcDateTimePanel" parent="CcPanel">
<property name="child">
<object class="AdwToolbarView">
<child type="top">
@@ -142,7 +148,6 @@
<child>
<object class="GtkSwitch" id="network_time_switch">
<property name="valign">center</property>
<signal name="notify::active" handler="update_page_summary" object="CcDateTimePage" swapped="yes"/>
</object>
</child>
</object>
@@ -210,33 +215,18 @@
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="AdwActionRow">
<object class="AdwComboRow" id="timeformat_row">
<property name="title" translatable="yes">Time _Format</property>
<property name="use_underline">True</property>
<child type="suffix">
<object class="GtkBox">
<property name="valign">center</property>
<property name="homogeneous">True</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkToggleButton" id="twentyfour_format_button">
<property name="label" translatable="yes">_24-hour</property>
<property name="use-underline">True</property>
<property name="group">ampm_format_button</property>
<signal name="toggled" handler="change_clock_settings" object="CcDateTimePage" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="ampm_format_button">
<property name="label" translatable="yes">AM / _PM</property>
<property name="use-underline">True</property>
<signal name="toggled" handler="change_clock_settings" object="CcDateTimePage" swapped="yes"/>
</object>
</child>
<signal name="notify::selected-item" handler="change_clock_settings" object="CcDateTimePanel" swapped="yes"/>
<property name="model">
<object class="AdwEnumListModel">
<property name="enum-type">GDesktopClockFormat</property>
</object>
</child>
</property>
<property name="expression">
<closure type="gchararray" function="format_clock_name_cb"/>
</property>
</object>
</child>
</object>
@@ -247,7 +237,7 @@
<property name="description" translatable="yes">Control how the time and date is shown in the top bar</property>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">_Week Day</property>
<property name="title" translatable="yes">Week Day</property>
<property name="use_underline">True</property>
<property name="activatable_widget">weekday_switch</property>
<child>
@@ -259,7 +249,7 @@
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">D_ate</property>
<property name="title" translatable="yes">Date</property>
<property name="use_underline">True</property>
<property name="activatable_widget">date_switch</property>
<child>
@@ -271,7 +261,7 @@
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">_Seconds</property>
<property name="title" translatable="yes">Seconds</property>
<property name="use_underline">True</property>
<property name="activatable_widget">seconds_switch</property>
<child>
@@ -283,8 +273,7 @@
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Week _Numbers</property>
<property name="subtitle" translatable="yes">Shown in the dropdown calendar</property>
<property name="title" translatable="yes">Week Numbers</property>
<property name="use_underline">True</property>
<property name="activatable_widget">week_numbers_switch</property>
<child>
@@ -317,7 +306,7 @@
</style>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/org/gnome/control-center/system/datetime/cc-month-row.ui</property>
<property name="resource">/org/gnome/control-center/datetime/cc-month-row.ui</property>
</object>
</property>
<property name="model">

View File

@@ -168,18 +168,6 @@ tz_dialog_search_changed_cb (CcTzDialog *self)
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static void
tz_dialog_search_stopped_cb (CcTzDialog *self)
{
const char *search_text;
search_text = gtk_editable_get_text (GTK_EDITABLE (self->location_entry));
if (search_text && g_strcmp0 (search_text, "") != 0)
gtk_editable_set_text (GTK_EDITABLE (self->location_entry), "");
else
gtk_window_close (GTK_WINDOW (self));
}
static void
tz_dialog_row_activated_cb (CcTzDialog *self,
guint position)
@@ -240,7 +228,7 @@ cc_tz_dialog_class_init (CcTzDialogClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/control-center/"
"system/datetime/cc-tz-dialog.ui");
"datetime/cc-tz-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, location_entry);
@@ -250,8 +238,9 @@ cc_tz_dialog_class_init (CcTzDialogClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, tz_view);
gtk_widget_class_bind_template_callback (widget_class, tz_dialog_search_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, tz_dialog_search_stopped_cb);
gtk_widget_class_bind_template_callback (widget_class, tz_dialog_row_activated_cb);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
}
static void

View File

@@ -5,9 +5,8 @@
<property name="hide-on-close">True</property>
<property name="title" translatable="yes">Select Time Zone</property>
<property name="width-request">360</property>
<property name="height-request">294</property>
<property name="height-request">300</property>
<property name="default-height">540</property>
<property name="default-width">400</property>
<style>
<class name="view"/>
</style>
@@ -32,7 +31,6 @@
<property name="halign">center</property>
<property name="width-chars">24</property>
<signal name="search-changed" handler="tz_dialog_search_changed_cb" swapped="yes"/>
<signal name="stop-search" handler="tz_dialog_search_stopped_cb" swapped="yes"/>
</object>
</child>
</object>
@@ -61,7 +59,7 @@
<signal name="activate" handler="tz_dialog_row_activated_cb" swapped="yes"/>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/org/gnome/control-center/system/datetime/cc-tz-row.ui</property>
<property name="resource">/org/gnome/control-center/datetime/cc-tz-row.ui</property>
</object>
</property>
</object>

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
@@ -68,7 +67,6 @@
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="ellipsize">end</property>
<binding name="label">
<lookup name="zone" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/datetime">
<file preprocess="xml-stripblanks">cc-datetime-panel.ui</file>
<file preprocess="xml-stripblanks">cc-month-row.ui</file>
<file preprocess="xml-stripblanks">cc-tz-dialog.ui</file>
<file preprocess="xml-stripblanks">cc-tz-row.ui</file>
<file>backward</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,16 @@
[Desktop Entry]
Name=Date & Time
Comment=Change the date and time, including time zone
Exec=gnome-control-center datetime
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Settings-time-symbolic
Terminal=false
Type=Application
NoDisplay=true
StartupNotify=true
Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
OnlyShowIn=GNOME;
# Translators: Search terms to find the Date and Time panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=Clock;Timezone;Location;
# Notifications are emitted by gnome-settings-daemon
X-GNOME-UsesNotifications=true

View File

@@ -1,4 +1,4 @@
install_data(
'org.gnome.Settings-region-symbolic.svg',
'scalable/org.gnome.Settings-time-symbolic.svg',
install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
)

View File

Before

Width:  |  Height:  |  Size: 820 B

After

Width:  |  Height:  |  Size: 820 B

123
panels/datetime/meson.build Normal file
View File

@@ -0,0 +1,123 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
i18n.merge_file(
type: 'desktop',
input: desktop + '.in',
output: desktop,
po_dir: po_dir,
install: true,
install_dir: control_center_desktopdir
)
polkit = 'org.gnome.controlcenter.@0@.policy'.format(cappletname)
i18n.merge_file(
input: polkit + '.in',
output: polkit,
po_dir: po_dir,
install: true,
install_dir: join_paths(control_center_datadir, 'polkit-1', 'actions')
)
resources = gnome.compile_resources(
'cc-' + cappletname + '-resources',
cappletname + '.gresource.xml',
c_name: 'cc_' + cappletname,
export: true
)
sources = files(
'cc-datetime-panel.c',
'cc-tz-item.c',
'cc-tz-dialog.c',
'date-endian.c',
'tz.c'
)
enums = 'gdesktop-enums-types'
enums_header = files(
gsettings_desktop_dep.get_variable(pkgconfig: 'prefix') + '/include/gsettings-desktop-schemas/gdesktop-enums.h',
'cc-datetime-panel.h'
)
sources += gnome.mkenums(
enums + '.h',
sources: enums_header,
fhead: '#pragma once\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n',
fprod: '/* enumerations from "@filename@" */\n',
vhead: 'GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define G_DESKTOP_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n',
ftail: 'G_END_DECLS\n'
)
sources += gnome.mkenums(
enums + '.c',
sources: enums_header,
fhead: '#include <gdesktop-enums.h>\n#include "gdesktop-enums-types.h"\n#include "cc-datetime-panel.h"',
fprod: '\n/* enumerations from "@filename@" */',
vhead: 'GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {',
vprod: ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n'
)
gdbus = 'timedated'
gdbus_iface_xml = gdbus + '1-interface.xml'
# This requires running d-bus session and accessible timedate1 daemon
# FIXME: need to find a way how to filter out unnecessary d-bus stuff (introspectable, properties)
#timedated1-interface.xml:
# gdbus introspect \
# --xml \
# --system \
# --dest org.freedesktop.timedate1 \
# --object-path /org/freedesktop/timedate1 \
# > timedated1-interface.xml
'''
gdbus_iface = custom_target(
gdbus_iface_xml,
output: gdbus_iface_xml,
capture: true,
command: [
find_program('gdbus'),
'introspect',
'--xml',
'--system',
'--dest', 'org.freedesktop.timedate1',
'--object-path', '/org/freedesktop/timedate1'
],
)
'''
sources += gnome.gdbus_codegen(
gdbus,
gdbus_iface_xml,
interface_prefix: 'org.freedesktop.'
)
deps = common_deps + [
gdk_pixbuf_dep,
gnome_desktop_dep,
polkit_gobject_dep
]
cflags += [
'-DGNOMECC_DATA_DIR="@0@"'.format(control_center_pkgdatadir)
]
datetime_panel_lib = static_library(
cappletname,
sources: sources + resources,
include_directories: [ top_inc, common_inc ],
dependencies: deps,
c_args: cflags
)
panels_libs += datetime_panel_lib
datetime_panel_lib_dep = declare_dependency(
sources : resources,
include_directories : [top_inc, include_directories('.')],
link_with : datetime_panel_lib
)
subdir('po-timezones')
subdir('icons')

Some files were not shown because too many files have changed in this diff Show More