Compare commits

..

155 Commits
44.4 ... 42.10

Author SHA1 Message Date
Felipe Borges
55c4da8f14 42.10 2023-03-17 17:05:05 +01:00
Nelson Benítez León
1ea311c99a user-accounts: Initialize CcAvatarChooser a bit earlier
Fixes following warning when activating Users panel:
user-accounts-cc-panel-WARNING **: Error retrieving app filter for user (null): User 4294967295 does not exist

Initialize CcAvatarChooser a bit earlier so it does
not get used by show_user() before creation.

Fixes #2219
2023-03-17 11:35:23 +01:00
Jan Pokorný
a67273baee display: Add 32:9 to known aspect ratios
Resolution dropdown previously did not show an aspect ratio hint for
32:9 resolutions. This adds the 32:9 aspect ratio to recognized ones.

Fixes #2334
2023-03-17 11:35:17 +01:00
Hari Rana
3e1af78e68 user: Remove duplicate group property 2023-03-17 11:35:11 +01:00
Nicolai Syvertsen
690eb414cb display: Fix monitor order
Using prepend for optimization but forgot to reverse list.
2023-03-17 11:35:05 +01:00
Kukuh Syafaat
689df1196d Update Indonesian translation 2023-03-15 12:10:02 +00:00
Jürgen Benvenuti
009841d96f Update German translation 2023-03-15 11:03:20 +00:00
Sabri Ünal
b1de78f49c Update Turkish translation 2023-03-15 06:00:30 +00:00
Hugo Carvalho
50db1aa131 Update Portuguese translation 2023-03-15 00:00:03 +00:00
Anders Jonsson
ef888ffb03 Update Swedish translation 2023-03-14 21:17:25 +00:00
Aleksandr Melman
bf3f73935a Update Russian translation 2023-03-14 20:59:39 +00:00
Piotr Drąg
ec59d41d95 Update Polish translation 2023-03-14 17:11:38 +01:00
Yuri Chornoivan
321b62439a Update Ukrainian translation 2023-03-14 13:11:11 +00:00
Martin
076554379f Update Slovenian translation 2023-03-14 09:18:50 +00:00
Ekaterine Papava
5fb204781c Update Georgian translation 2023-03-14 04:25:27 +00:00
Balázs Úr
df390a2d58 Update Hungarian translation 2023-03-14 01:56:47 +00:00
Balázs Úr
e7f5d53457 Update Hungarian translation 2023-03-14 00:21:10 +00:00
Robert Ancell
2d8f17006f Post-release version bump 2023-02-13 11:10:04 +13:00
Robert Ancell
dfe78834b4 42.9 2023-02-13 10:27:01 +13:00
Bastien Nocera
34a96eee19 tests: Fix possible race in test_connection_multi_add_activate()
Wait for the "state" property to change as well as the "state-reason".
We only update the UI when the former arrives, but the test was working
correctly on faster machines, making it difficult to pinpoint.

Closes: #1768
2023-01-18 17:25:10 +01:00
Sergej A
136f731c32 Update Russian translation 2023-01-10 12:37:50 +00:00
Felipe Borges
41648dad9f 42.5 2023-01-09 19:17:16 +00:00
Bastien Nocera
e03e1e08bb info-overview: Load GNOME version from gnome-shell
See https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5406
2023-01-09 19:17:16 +00:00
Michael Catanzaro
933ef2f682 Update rawhide CI image
We need a newer image to get GTK 4.8
2023-01-09 19:17:16 +00:00
Felipe Borges
061ce1aeb3 display: Fix typo in labelled-by accessibility tag 2023-01-09 19:17:16 +00:00
Marco Melorio
0936bc098a ci: Disable rotfiles-fuse from flatpak build
It makes the build fail apparently.
2023-01-09 19:17:16 +00:00
Marco Melorio
116442edb3 ci: Remove unneeded copying in the flatpak build
This was missing out the `polkit-autogen` file, so the flatpak build was
failing because of that. Fix this by removing the copying phase and use
the correct manifest path directly instead.
2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
dc924f640b ci: Install setxkbmap needed for tests and upgrade image
Otherwise, any other operation running the tests has the utility missing
2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
b3cba63f06 ci: Make sure the project is built before running the tests 2023-01-09 19:17:16 +00:00
TheEvilSkeleton
7ab65011ab display: Set underscanning_row as activatable widget 2023-01-09 19:17:16 +00:00
TheEvilSkeleton
adc440f793 mouse: Set rows as activatable widgets 2023-01-09 19:17:16 +00:00
Benjamin Berg
2208b9c301 avatar-chooser: Return a proper widget if images cannot be loaded
GTK assumes that a widget will be created for a flow box item. So always
return one instead of falling back to returning NULL. This can primarily
happen if an image loader is missing.
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
2085196638 common: Don't Handle list-row switch state manually
This was a hack added for libhandy-0, which is no longer required.
Also, this hack results in the switch not working when gtk animations
are turned off.
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
6e5bafd3fd color: Select first device row only if non-NULL
Otherwise we might read some invalid memory resulting in a crash
2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
4daf99ad3a wwan: wait for apn_list to exist to add SIM providers
This avoids the situation where a duplicate entry is created if
Settings is started with the wwan panel disabled, a previous connection
exists, and the panel is later enabled.

Fixes #1468
2023-01-09 19:17:16 +00:00
Barnabás Pőcze
ac9055aac3 object-cache: Avoid use after free of task error
The error should not be touched after passing it to
`g_task_return_error()` as noted by its documentation:

  Note that since the task takes ownership of @error, and since the
  task may be completed before returning from g_task_return_error(),
  you cannot assume that @error is still valid after calling this.

However, previously, the code did try to free error since the
`local_error` was defined with `g_autoptr(GError)`.


(cherry picked from commit f00fd653cb)
2023-01-09 19:17:16 +00:00
Jake Dane
467089b8cd network: Fix 802.1x TLS file chooser filters
If on the Security tab in the connection editor one selected 802.1x
with TLS authentication, the 3 file chooser dialogs there didn't
let one select any file. This was because allowed extensions were
passed to gtk_file_filter_add_suffix () with the leading dot but that
function expects them without the leading dot.

This could be fixed in the code by skipping over the dot but as per
discussion on !1433 it is preferable to use mime types instead. The
code is changed to use mime types for the file chooser dialog filter
and for checking a file is of the right type.

Fixes #2022.
2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
1335f85c7b region: fix warning of uninitialized variables
../panels/region/cc-region-panel.c: In function 'set_restart_notification_visible':
../panels/region/cc-region-panel.c:131:17: warning: 'current_locale' may be used uninitialized [-Wmaybe-uninitialized]
  131 |                 uselocale (current_locale);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
../panels/region/cc-region-panel.c:115:18: note: 'current_locale' was declared here
  115 |         locale_t current_locale;
      |                  ^~~~~~~~~~~~~~
../panels/region/cc-region-panel.c:130:34: warning: 'new_locale' may be used uninitialized [-Wmaybe-uninitialized]
  130 |         if (locale && new_locale != (locale_t) 0) {
      |                       ~~~~~~~~~~~^~~~~~~~~~~~~~~
../panels/region/cc-region-panel.c:114:18: note: 'new_locale' was declared here
  114 |         locale_t new_locale;
      |                  ^~~~~~~~~~
2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
7066feab5e region: fix permissions_acquired always returning FALSE 2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
3fbd0ba7da keyboard: fix permission_acquired always returning FALSE 2023-01-09 19:17:16 +00:00
Marek Kasik
3ed6b8cc4e printers: Show empty-state after removal of the last printer
Check whether the currently removed printer was last. Also
check whether there are other printer being removed by CUPS
right now (their amount is still part of self->num_dests).

Do this check also in actualize_printers_list_cb() to catch
corner cases from timing point of view. This will handle them
with some delay if they show up.

When undone, just check whether the number of printers is higher
than 0 and show the printers-list page.

Fixes #2023
2023-01-09 19:17:16 +00:00
Felipe Borges
c1f37877c4 printers: Pass correct argument to gtk_builder_add_objects_from_resource
This is detectable with -Wincompatible-pointer-types and warns with
[1/7] Compiling C object panels/printers/libprinters.a.p/cc-printers-panel.c.o
../panels/printers/cc-printers-panel.c: In function ‘cc_printers_panel_init’:
../panels/printers/cc-printers-panel.c:1228:59: warning: passing argument 3 of ‘gtk_builder_add_objects_from_resource’ from incompatible pointer type [-Wincompatible-pointer-types]
 1228 |                                                           objects, &error);
      |                                                           ^~~~~~~
      |                                                           |
      |                                                           gchar ** {aka char **}
In file included from /usr/include/gtk-4.0/gtk/gtkbuildable.h:26,
                 from /usr/include/gtk-4.0/gtk/gtk.h:56,
                 from /usr/local/include/libadwaita-1/adwaita.h:9,
                 from ../shell/cc-panel.h:25,
                 from ../panels/printers/cc-printers-panel.h:21,
                 from ../panels/printers/cc-printers-panel.c:23:
/usr/include/gtk-4.0/gtk/gtkbuilder.h:122:66: note: expected ‘const char **’ but argument is of type ‘gchar **’ {aka ‘char **’}
  122 |                                                   const char   **object_ids,
      |                                                   ~~~~~~~~~~~~~~~^~~~~~~~~~
[7/7] Linking target tests/network/test-wifi-panel-text
2023-01-09 19:17:16 +00:00
Felipe Borges
b81449836d search: Use "action" to connect to Move up/down actions for rows
Using "action-name" wasn't triggering the callback.

Fixes #2013
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
156f9f503c panel-list: Select panel iff non-folded when search is cancelled
If the window is folded, the previous panel shouldn’t be shown when search
is cancelled. The panel selection list should be shown instead.
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
553ebc3c6e online-accounts: Fix a possible crash on parsing NULL string
If the goa helper fails to find goa helper executable (which happened when run
without install), %NULL is returned.  Avoid feeding g_variant_parse(), the %NULL
variable in those case as it is not nullable and avoid the crash that follows.
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
ee8a64a184 keyboard: Fix activation of input source toggle button
When the options are changed, the first item was never shown as
active when selected.  Fix it by binding to the inverse of the
button state instead of binding both toggle buttons to settings.

Fixes #1653
2023-01-09 19:17:16 +00:00
Georges Basile Stavracas Neto
8f76e1fb93 online-accounts: Mark run_goa_helper_sync as NULL-terminated
Spotted while porting GNOME Initial Setup [1]

[1]
https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/merge_requests/134
2023-01-09 19:17:16 +00:00
Lubomir Rintel
e03fe497a8 wwan: do not insist SIM ID being present
It is perfectly possible for mm_sim_dup_identifier() to return NULL if
the SIM ID wasn't provided by the modem for any reason, leading to an
assertion failure:

  (gnome-control-center:910641): cc-wwan-data-CRITICAL **: 12:43:51.573:
    cc_wwan_data_set_default_apn: assertion 'self->sim_id != NULL' failed

Handle the NULL SIM ID gracefully.
2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
8bcd8fdb88 Fix a typo 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
438dee2585 Add a few missing labels in the wacom settings 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
9901e697ee Add a11y labels for close notification buttons in the thunderbolt panel 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
8e8b89c000 Make the presentation of the main panel list a little bit nicer by adding an a11y label 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
57def32b32 Fix a missing a11y tag 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
c929b64cd2 Make the universal panel more accessible by adding some a11y described by relations and a few labels 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
18aed24592 Improve accessibility of the wwan settings panel 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
ab63e495e4 Fix indent 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
14aa827aaa Add a missing label to the automatic timezone switch 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
91b2885ce1 Add a label to the master mic switch 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
d59b6e79ab Add a missing label 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
6c6513913e Add an a11y label to the switch 2023-01-09 19:17:16 +00:00
Jan Tojnar
157ac67ace region: Fix critical when changing language
Changing user’s language resets the formats (region) by passing `NULL` to `update_region`.
However, updating the region calls `maybe_notify`, whose callback `maybe_notify_finish`
tries to parse the `mnd->target_locale` (the `NULL`), producing a critical:

    GLib-CRITICAL **: g_regex_match_full: assertion 'string != NULL' failed

Since updating the language itself already triggers the notification check,
let’s just skip calling `maybe_notify` here in that case.
2023-01-09 19:17:16 +00:00
Jan Tojnar
c7b618f873 region: Fix creating rows for locales without country
When creating a language row for Esperanto (eo.UTF-8), gnome-desktop throws a critical:

    gnome_get_country_from_code: assertion 'code != NULL' failed
2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
5a8f72176a Add a missing a11y label to the search box in the country selection dialog 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
2434b6006f Add missing a11y labels and fix accessibility related markup in UI files in the search panel 2023-01-09 19:17:16 +00:00
Bastien Nocera
d32d75c638 info-overview: Don't load version.xml info we don't use
We don't use the distributor or date info from gnome-desktop's version.xml
so no need to parse it.
2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
a91f0e620a Ensure that the activatable widgets of the multitasking rows have the proper labels 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
da3723e7d0 Add a label to the close notification button in online account settings 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
c44953c776 Fix indentation 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
5087cf97e1 Improve accessibility of the background panel 2023-01-09 19:17:16 +00:00
Pablo Correa Gómez
8e0a0f7672 power: Only update ALS state if it has changed
Ambient light sensors can be quite sensitive and the LightLevel
property might be changing very often. That has two undesired
consequences:
* The `als_enabled_state_changed` callback gets constantly called
  due to a change in a property which it does not care about, as
  only `HasAmbientLight` is relevant. Therefore, limit the code
  execution to when something needs to be changed.
* During debugging, the terminal gets spammed with "ALS enabled: on/off"
  messages.
2023-01-09 19:17:16 +00:00
Mohammed Sadiq
4ae8f1a369 wwan: Strip remote dbus error before it's presented
That's more useful for the users
2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
0000570007 Add some missing a11y labels in the keyboard panel 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
1e69fe0e40 Add labels to the toggles in the lock settings 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
e4c67b67e9 Add missing labels 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
b771c3b972 Add an a11y label to the enable switch 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
2eeee2e097 Fix indent 2023-01-09 19:17:16 +00:00
Lukáš Tyrychtr
706b7bdc41 A missing label in the camera panel 2023-01-09 19:17:16 +00:00
Nart Tlisha
a5b66b405f Add Abkhazian translation 2023-01-06 09:32:50 +00:00
Georges Basile Stavracas Neto
86c996e006 applications: Don't recurse into symlinks when clearing cache
Oh boy... what can I say.

Sadly Builder symlinks to somewhere where we eventually end up in
the home folder. And delete all files.

:(

Pass the FTW_PHYS flag to nftw() so it doesn't follow symlinks.

Closes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2153
2022-12-21 18:46:43 +01:00
Vasil Pupkin
4012ca17fd Update Belarusian translation 2022-12-16 16:35:17 +00:00
Alynx Zhou
63025db137 network: Fix wrong signal of SEA password visibility toggle
Wrong pointer is used because of missing `_swapped`.
2022-12-01 16:28:46 +13:00
Michael Catanzaro
36f53768ca network: fix crashes in eap-method-simple
When the stored password is missing, we will crash passing NULL to a
non-nullable GTK API function.

Fixes #1905
2022-10-24 12:28:47 +02:00
Hendrik Müller
f69926a95a wifi: Allow accessing settings of known wifi networks
Currently it is only possible to access the settings for the currently
connected wifi network.
Being able to configure a wifi network, even though it is not connected,
would be useful for example to share the password for a network that is
not in range.

To achieve this, a new property was added to CcWifiConnectionRow.
The new property "known_connection" signals whether this connection is
known and thus whether the options button for configuring it should be
displayed.

The property "known_connections" will be set to TRUE in two cases:
- when the list of connections is shown in the "Known Networks" dialog
- when the connection is known, but not the active connection

Closes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1906
Closes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1858
2022-10-20 13:30:56 +00:00
Georges Basile Stavracas Neto
a91663d714 Post-release version bump 2022-10-17 23:11:16 -03:00
Georges Basile Stavracas Neto
ddfd4343e2 42.4 2022-10-17 23:09:19 -03:00
Alessandro Bono
608aac8fff net-device-ethernet: Don't check device iface name
If the interface name is wrong we shouldn't add the device in the first
place. The device comes from NM. If the interface name is wrong is a bug
at NM level.
2022-10-12 14:46:59 +02:00
Alessandro Bono
6f6fcb463c net-device-ethernet: Prevent double free
Fixes: ee53bfd8b6
2022-10-12 14:46:53 +02:00
Luciano da Silva Ribas
2145e0d8de network: Fixed Network profiles shown on wrong device
Added missing interface name during network profile creation.

Fixes #353
2022-10-12 10:54:27 +02:00
Felipe Borges
19d95a72fa user-accounts: Disconnect fingerprint reading devices when closing dialog
Otherwise when users close and reopen the window they will face a
“Failed to claim fingerprint device Synoptics Sensors: the device is
already claimed by another process” error message.

Fixes #1983
2022-09-23 09:49:17 +02:00
Felipe Borges
9d7d3d1781 printers: Set "use-underline" for Authenticate button in Jobs dialog
The label of the button indicates a mnemonic (_Authenticate).

Fixes #2062
2022-09-19 16:39:48 +02:00
Bastien Nocera
0fbe64d6d9 power: Don't assert if we can't find the widget for a profile
In some cases, it was possible for a profile to be set (directly, or
through a hold) even though it wasn't supported. Don't assert in those
cases.

Closes: #1504
2022-09-16 11:52:48 +02:00
Matthias Clasen
ae9f9df102 background: Allow all images
The code was filtering with a small list of known
image mimetypes, needlessly. Just allow any
image/* mimetypes.

Fixes: #2036
2022-09-16 11:49:31 +02:00
Felipe Borges
8052e1bc89 display: Fix primary monitor selection issue with AdwComboRow
We were connecting to the selected-index property when AdwComboRow
actually has a selected-item property. This is the same as
issue #2025

Fixes #2028
2022-09-12 14:02:04 +02:00
Felipe Borges
55b09def37 power: Fix "Power Button Behavior" setting now applying
The AdwComboRow widget has a selected-item property, while we were
connecting to selected-index (which doesn't exist.

It is likely that selected-index existed in the past in libhandy
or libadwaita and this is a regression during the port to GTK4.

Fixes #2025
2022-09-12 13:57:58 +02:00
Felipe Borges
7ac1301b26 power: Fix blank-screen settings not applying
The AdwComboRow widget has a selected-item property, while we were
connecting to selected-index (which doesn't exist.

It is likely that selected-index existed in the past in libhandy
or libadwaita and this is a regression during the port to GTK4.

Fixes #2025
2022-09-12 13:57:56 +02:00
Goran Vidović
2ca936f0e8 Update Croatian translation 2022-09-10 23:14:07 +00:00
Sveinn í Felli
8a3cc50ed6 Update Icelandic translation 2022-09-05 18:04:35 +00:00
Sveinn í Felli
086aaacab2 Update Icelandic translation 2022-09-05 14:55:56 +00:00
Goran Vidović
210d11b974 Update Croatian translation 2022-09-03 12:20:59 +00:00
Balázs Úr
9cafaf0606 Update Hungarian translation 2022-09-02 23:15:44 +00:00
Marek Černocký
3eba181d7b Updated Czech translation 2022-09-02 22:19:18 +02:00
Goran Vidović
7e726c0c46 Update Croatian translation 2022-08-26 10:45:47 +00:00
Yosef Or Boczko
1f28814b88 Update Hebrew translation 2022-08-22 19:59:59 +00:00
Goran Vidović
00c3fad3b1 Update Croatian translation 2022-08-18 14:48:27 +00:00
Jordi Mas
9c864bf34a Update Catalan translation 2022-08-13 13:55:03 +02:00
Daniel Mustieles
28af0f16d3 Updated Spanish translation 2022-08-08 12:41:35 +02:00
Benjamin Berg
4a20dcb2ed shell: Deactivate old panel before creating new one
We need to cancel internal operations before starting to create a new
panel, otherwise panels might be creating the same object for the cache
in parallel and this is not supported by the object cache.

The alternative to this would be to handle this inside the object
store to allow parallel creation of the same key.

Fixes: #1685
2022-08-04 11:34:30 +02:00
Andy Holmes
a8c1b82ed8 notifications: fix potential null dereference in app_info_get_id()
Although apparently unlikely, `strlen()` is called on the return value
of `desktop_id` instead of `ret`, which may result in a null
dereference.
2022-08-04 11:33:40 +02:00
David King
8ae2d124c7 network: Fix VPN with unescaped ampersand
Much like in commit 47c586a82e for the
wifi panel, fix escaping of titles for VPNs.

https://bugzilla.redhat.com/show_bug.cgi?id=2090996
2022-08-04 11:31:59 +02:00
Mpho Jele
f794b14bc9 user-accounts: Make back button switch to current user or panels list
When the window AdwLeaflet is folded the back button should either
switch to the panels list if the selected user is the current user
or switch to the current user if the selected user is from the
"other users" list
2022-08-04 11:30:33 +02:00
Mpho Jele
51fc40a60e user-accounts: Show the back button when window leaflet folds
Currently the back button is only shown when viewing a user from the
"other users" list.
These changes show the back button when the window AdwLeaflet is
folded or when the selected is from the "other users" list but never
when the window is not folded and the selected user is the current
user.

Fixes: #1719
2022-08-04 11:29:33 +02:00
Hendrik Müller
aad990ed17 wifi: Fix state of "Forget" button in "Known Wi-Fi Networks" dialog
The "Forget" button would only update it's sensitivity after the first
select and deselect, when selecting and deselecting rows in the
"Known Wi-Fi Networks" dialog.
When selecting the first row, it would go from disabled to enabled.
Then deselecting that row would cause the button to go from enabled to
disabled.
Selecting any rows after that would no longer update the sensitivity and
make the dialog essentially useless.

The issue was, that the signals "add" and "remove" where being
expected to be emitted when the connection list updates its rows.
However, neither CcWifiConnectionList nor GtkListBox emit these signals.
The fix was, to emit these two signals at the appropriate locations.
The signals have also been renamed to "add-row" and "remove-row" to
make their purpose more clear.

Closes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1824
Closes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1993
2022-08-04 11:27:54 +02:00
Aleksandr Melman
41e2f537e6 Update Russian translation 2022-08-01 13:12:09 +00:00
Zurab Kargareteli
bf0e6ccff2 Update Georgian translation 2022-07-22 13:43:54 +00:00
grumpey
7d884a6e9b background: Restore support for multiple file selection
This was previously implemented under !715 but we regressed during the port to GTK4.

Fixes #889
2022-07-12 09:27:24 +00:00
Jens Alpers
fe26b96b14 sharing: Don't set remote-desktop password entry if pw_generate fails
Fixes #1846
2022-07-11 14:30:47 +02:00
Pauli Virtanen
afadaf363c subprojects: revert accidental libgvc downgrade
Re-do the libgvc version upgrade from 8c84b9f0d3 ("subprojects: Update
libgvc"), which was accidentally reverted in 95de2049c7 ("shell:
Initialise locale early") without comment.
2022-07-07 16:26:28 +02:00
Nathan Follens
ed5693624b Update Dutch translation 2022-07-04 08:40:08 +00:00
Мирослав Николић
cbcb717f68 Update Serbian translation 2022-07-03 02:02:48 +00:00
Robert Ancell
3005d4abc1 Post-release version bump 2022-07-01 11:17:31 +12:00
Robert Ancell
ff5ab8f715 42.3 2022-07-01 11:12:42 +12:00
Gianvito Cavasoli
0151a0ac25 Update Italian translation 2022-06-28 11:14:45 +00:00
Jonas Ådahl
e6cc73fd1d display: Use virtual clone modes when mirroring
These are not real modes, but just as place holders when generating
'mirror' configurations. The clone modes will be just to match the
flag/dimension, while the actual mode applied will be individual for
each monitor.

This allows monitors to have their own refresh rates, which is possible
since a few mutter versions back. This also matches how mutter itself
generates mirror modes when doing so via the key binding.
2022-06-27 19:08:48 +02:00
Jonas Ådahl
b068891cf3 display: Add 'is_preferred()' mode getter 2022-06-27 19:08:48 +02:00
Pablo Correa Gómez
063d89abe8 user-accounts: run-passwd: Redirect stderr to stdout in the child
The previous code was prone to race conditions if the child already
started writing to stdout before the dup2 call happened. This has
been detected in postmarketOS[1] and I also reproduced it in Alpine
Linux. Since passwd writes to stderr and linux-pam to stdout, the
redirection was needed. However, linux-pam was failing with
"Conversation error" since an fprintf(stdout, ...) call wasn't
able to write to an already-closed stdout.

This problem is fixed by setting the redirection in the child setup
function and ignoring the stderr pipe. It also fixes a leak, where
the stderr fd was simply ignored and never closed.

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/1449
2022-06-20 13:45:23 +12:00
Amy
8e6b89dbbd network: prevent crash by disconnecting device
When a device is registered with add_wifi_device, a corresponding signal
is registered for events. The associated remove_wifi_device clears the
associated pages, but does not disconnect the signal. This causes the
assertion NET_IS_DEVICE_WIFI to fail.

This patch corrects this error, resolving #1889 as per the suggested fix
from Benjamin (@bberg).
2022-06-20 13:32:50 +12:00
Maximiliano Sandoval R
a8b62b25e0 ce-page-details: Do not set children for CheckBtn
This widget does not support adding arbitrary children, a warning was
issued when it was disposed for still having children.
2022-06-20 13:25:08 +12:00
Milo Casagrande
b593dc4e64 Update Italian translation 2022-06-14 15:29:27 +00:00
Zurab Kargareteli
0d0504aea1 Update Georgian translation 2022-06-11 09:59:58 +00:00
Bastien Nocera
c928bd14b8 network: Fix Wi-Fi network with "&" in name not appearing
My neighbours' Wi-Fi makes the Wi-Fi panel throw an error:
(gnome-control-center:346639): Gtk-WARNING **: 15:16:21.993: Failed to set text 'Bbox Hugo & Laura' from markup due to error parsing markup: Error on line 1: Entity did not end with a semicolon; most likely you used an ampersand character without intending to start an entity — escape ampersand as &

Escape the SSID before using it to set the label.


(cherry picked from commit 47c586a82e)
2022-06-10 11:28:52 +00:00
Robert Ancell
107685efdc Post-release version bump 2022-05-27 15:58:45 +12:00
Robert Ancell
0bbcc3b8b3 42.2 2022-05-27 15:53:24 +12:00
lsnow
099948e3ff applications: crash when switching between two apps
The GIcon returned by g_app_info_get_icon() does
not need to be freed.

See: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1817
2022-05-27 15:38:43 +12:00
Jeremy Bicha
c6a111c15e sharing: Turn off RDP gsettings key when turning off RDP
Closes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1825
2022-05-27 15:38:39 +12:00
Bastien Nocera
3b8fb9c0f3 shell: Initialise locale early
Otherwise glib will make internal calls before setlocale is called:
** (process:1124144): WARNING **: 10:16:58.983: dcgettext("(null)", "", 5) called before setlocale()

 #0  0x00007ffff7c80f77 in g_logv () at /lib64/libglib-2.0.so.0
 #1  0x00007ffff7c81233 in g_log () at /lib64/libglib-2.0.so.0
 #2  0x00007ffff7fbb6c6 in dcgettext (__domainname=<optimized out>, __msgid=0x7ffff7ce6c5a "", __category=<optimized out>) at ../../../../Projects/jhbuild/gettext-pseudolocale/gettext-pseudolocale.c:194
 #3  0x00007ffff7c6478e in _g_dgettext_should_translate () at /lib64/libglib-2.0.so.0
 #4  0x00007ffff7c6484b in g_dgettext () at /lib64/libglib-2.0.so.0
 #5  0x00007ffff7e98974 in g_application_class_intern_init () at /lib64/libgio-2.0.so.0
 #6  0x00007ffff7d9cfb8 in g_type_class_ref () at /lib64/libgobject-2.0.so.0
 #7  0x00007ffff7d9cc95 in g_type_class_ref () at /lib64/libgobject-2.0.so.0
 #8  0x00007ffff7d9cc95 in g_type_class_ref () at /lib64/libgobject-2.0.so.0
 #9  0x00007ffff7d9cc95 in g_type_class_ref () at /lib64/libgobject-2.0.so.0
 #10 0x00007ffff7d8671a in g_object_new_valist () at /lib64/libgobject-2.0.so.0
 #11 0x00007ffff7d867fd in g_object_new () at /lib64/libgobject-2.0.so.0
 #12 0x0000000000449bcc in cc_application_new () at ../../../../Projects/jhbuild/gnome-control-center/shell/cc-application.c:294
 #13 0x0000000000448fa6 in main (argc=1, argv=0x7fffffffd138) at ../../../../Projects/jhbuild/gnome-control-center/shell/main.c:55
2022-05-27 15:38:37 +12:00
Ian Douglas Scott
f185cda349 keyboard: Avoid segfault due to no "data" for custom_shortcut_add_row
Ultimately it would be good to get rid of the use of
`g_object_set_data`/`g_object_get_data` here, but this works for now.

Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1373.
2022-05-27 15:38:34 +12:00
Sebastian Keller
af469c99b6 sound: Update theme directory modification time after bell sound changes
The sound plugin of gnome-settings-daemon which flushes the pulseaudio
sample cache does non-recursive monitoring of the sounds directory. If
the custom theme directory used for switching between bell sounds
already exists due to previous bell sound changes, subsequent changes
within that directory will not be noticed. The old bell sample will thus
remain in the cache until the next session restart. Avoid this problem
by manually updating the modification time of the directory.

The alternative solution of adding recursive monitoring to the sound
plugin would require significantly more complicated code as there is no
support for this in glib itself. Given that sound themes never really
caught on and there is an ongoing discussion of removing support for
them entirely, going with this simple solution seems like the better
choice.

Fixes: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/681
2022-05-27 15:38:31 +12:00
Robert Ancell
60e3f003bb applications: Update snap permissions code to recent changes
Fixes #1845
2022-05-26 11:41:40 +12:00
Christian Kirbach
3b9e94a03f Update German translation 2022-05-24 08:40:18 +00:00
Pawan Chitrakar
79c2c4578b Update Nepali translation 2022-05-22 08:07:28 +00:00
Robert Ancell
44bd8b4d9b applications: Fix CcInfoRow having the wrong parent.
Introduced in 9e38b89752


(cherry picked from commit fc1b750f19)
2022-05-17 00:58:19 +00:00
Jordi Mas
0a64988649 Update Catalan translation 2022-05-16 22:35:55 +02:00
Jordi Mas
c1520aac66 Update Catalan translation 2022-05-16 22:33:47 +02:00
Changwoo Ryu
a23cd79762 Update Korean translation 2022-05-16 12:08:20 +00:00
Felipe Borges
8df3f8c9e5 sharing: Let GtkWindowControls add its own buttons
On the Verify Encryption dialog we were adding a GtkWindowControls
widget with a button child. This is a misunderstanding of the behavior
of GtkWindowControls, which adds its own buttons to the window.

Let's remove our custom close-button and its callback, since the
previous commit disabled this codepath for hiding the dialog.
2022-05-13 15:35:30 +02:00
Felipe Borges
d39ec251af sharing: Set Verify Encryption dialog to "hide-on-close"
This way GtkWindow handles the hiding of the dialog instead of the
callback of the close-button.

Fixes #1832
2022-05-13 15:35:25 +02:00
Cheng-Chia Tseng
4ed667e4e5 Update Chinese (Taiwan) translation 2022-05-12 07:10:34 +00:00
Aurimas Černius
01a42dfea1 Updated Lithuanian translation 2022-05-08 22:02:12 +03:00
Kukuh Syafaat
49f5fd9b78 Update Indonesian translation 2022-05-08 04:59:58 +00:00
Sabri Ünal
d8aaec6a98 Update Turkish translation 2022-05-07 05:56:48 +00:00
Quentin PAGÈS
3481206fa9 Update Occitan translation 2022-05-05 18:04:04 +00:00
Sebastian Keller
da2f0e52c7 background: Make sure the size of the light/dark previews is the same
Without homogeneous columns the difference in the size of the light/dark
labels could cause one preview to be larger.

Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1810


(cherry picked from commit 5df1519d7d)
2022-05-05 13:31:28 +00:00
Felipe Borges
f8a05fe2dc connection-editor: Unparent child widget on dispose
WirelessSecurityWPAEAP is a GtkWidget owned by the CEPage8021xSecurity
widget, which is supposed to "unparent" it on "dispose" (since parents
hold a reference to child widgets). Instead we were calling
g_clear_object on it.

Fixes #1671
2022-05-04 10:28:31 +02:00
Alexander Shopov
946919c850 Update Bulgarian translation 2022-04-28 12:19:52 +00:00
Danial Behzadi
2d263f5ea9 Update Persian translation 2022-04-27 09:19:02 +00:00
682 changed files with 135390 additions and 213344 deletions

4
.gitignore vendored
View File

@@ -1,5 +1,3 @@
__pycache__
_build/
**/*~
/subprojects/*
!/subprojects/*.wrap
**/*~

View File

@@ -31,12 +31,6 @@ stages:
.Build procedure: &build_procedure
echo "== Building ==" &&
git clone https://gitlab.gnome.org/GNOME/gtk.git &&
cd gtk &&
dnf install -y dnf-plugins-core && dnf builddep -y gtk4 &&
meson setup . _build -Dprefix=/usr -Dlibdir=lib64 &&
ninja -C _build install &&
cd .. &&
rm -rf _build/ &&
meson . _build ${BUILD_OPTS} -Dprofile=development &&
ninja -C _build 2>&1 | tee compilation.log
@@ -58,7 +52,7 @@ stages:
# stable branch.
# Could probably also switch away from rawhide,
# to stable fedora branch as well.
FDO_DISTRIBUTION_TAG: '2023-03-14.0-main'
FDO_DISTRIBUTION_TAG: '2022-10-25.0-main'
FDO_DISTRIBUTION_VERSION: rawhide
#############################################
@@ -112,7 +106,7 @@ build.container.fedora@x86_64:
libnotify-devel
libpwquality-devel
libsmbclient-devel
libsoup3-devel
libsoup-devel
libudisks2-devel
libwacom-devel
libX11-devel
@@ -128,14 +122,13 @@ build.container.fedora@x86_64:
xorg-x11-server-Xvfb
mesa-dri-drivers
libsecret-devel
geocode-glib2-devel
geocode-glib-devel
libgweather-devel
lcms2-devel
geoclue2-devel
libnotify-devel
alsa-lib-devel
nss-devel
gcr3-devel
gcr-devel
setxkbmap
FDO_DISTRIBUTION_EXEC: |-
@@ -256,7 +249,7 @@ coverage:
BUILD_OPTS: "-Db_coverage=true"
coverage: '/^Lines:.\d+.\d+.(\d+\.\d+\%)/'
only:
- main@GNOME/gnome-control-center
- master@GNOME/gnome-control-center
script:
- *environment_information
@@ -296,7 +289,7 @@ pages:
paths:
- public
only:
- main@GNOME/gnome-control-center
- master@GNOME/gnome-control-center
except:
variables:
@@ -310,7 +303,7 @@ pages:
##
flatpak:
stage: manual
image: quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
artifacts:
name: package
paths:
@@ -356,7 +349,7 @@ flatpak:
except:
- tags
- gnome-3-.*
- main@GNOME/gnome-control-center
- master@GNOME/gnome-control-center
# Runs the sanitizers [address, thread, undefined, and memory].

View File

@@ -4,7 +4,7 @@ Not following the communication guidelines [1] will mean your issue or comment
will be removed. Read it carefully before submitting this issue.
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
-->

View File

@@ -4,7 +4,7 @@ Not following the communication guidelines [1] will mean your issue or comment
will be removed. Read it carefully before submitting this issue.
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
[1] https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guideline
-->

321
NEWS
View File

@@ -1,276 +1,151 @@
================
Version 44.4
Version 42.10
================
- Hide QR Code button for unsupported security.
- Fix issue when icon theme changes to HighContrast can't be reverted.
- Write to mru-sources setting if it has never been set before.
- Fix critical debug messages when keyboard input chooser is destroyed.
- Fix issue on network connection editor not closing when changes are applied.
- Fix out-of-bounds write in printer names.
- Fix input row movement in Search and Keyboard settings.
- Hide "Automatic Suspend" row in virtual machines.
- Various memory leak fixes.
- Update translations.
- Fix monitor order in display settings
- Add 32:9 aspect ration in display settings
- Fix warning in user panel in initialization of avatar widget
- Updated translations
================
Version 44.3
================
- Updated translations.
================
Version 44.2
================
- Updated translations.
- Various small accessibility fixes.
- Fixes in Gtk template usage that causes crashes on some systems.
Appearance
- Clear dconf when resetting to defaults.
Mouse
- Hide entire "Touchpad" row when touchpad cannot be disabled
Network
- Fix racy radio buttons in connection editor.
Users:
- Remove autologin row tooltip when unlocked.
================
Version 44.1
Version 42.9
================
- Updated translations
Common
- Update hostname only after apply is clicked
- Add widget name and css class to CcIllustratedRow and CcSplitRow
Color
- Do not try to access to null pointer in destruction
Date & Time
- Fix NTP switch getting out of sync
Display
- Allow configuring all monitors and apply settings at once
- Disconnect config manager changed handler
- Don't leak config manager proxy
Network
- Fix crash when removing a connection
Region
- Fix label of formats for the login screen
Sharing
- Fix network row visible name bug
Shell
- Add workaround to make disabled pictures are painted as such
Sound
- Prevent duplicate sound device entries
- Revert accidental libgvc downgrade
Network:
- Fix possible race in tests
================
Version 44.0
Version 42.4
================
- Updated translations
Mouse
- Prevent infinit loop on Mouse setting changes
Usage
- Fix confirmation dialog when clearing file history
Notifications
- Replace occurrence of "Applications" with "Apps" string
Power
- Label the main "batery" as UPS when that's what it is
================
Version 44.rc
================
- Improve state of switchers throughout the app
- Updated translations
Keyboard
- Various fixes to the shortcut editor
Mouse & Touchpad
- Polish the panel redesign
Printers
- Update to more modern CUPS APIs
================
Version 44.beta
================
- Redesigned Sound panel
- Redesigned Mouse & Touchpad panel
- Share Wi-Fi networks using QR code
- Many consistency improvements
- WireGuard support
- Updated translations
Mouse & Touchpad
- Redesign the panel with videos of the preferences
- Move mouse test into a separate dialog
Network
- Add support for sharing Wi-Fi networks through QR code
- Add WireGuard support
Sound
- Move application volumes to a dialog
- Move sound themes to a dialog
================
Version 44.alpha
================
- Redesigned Accessibility panel
- Many consistency improvements
- Updated translations
- Added various accessibility labels
- Initialize locale early
About
- Add "Firmware Version" row
- Don't load version.xml info we don't use
Accessibility
- Redesign the panel with new a navigation pattern
Applications
- Don't recurse into symlinks when clearing app cache
Color
- Fix crash when there's no device rows to show
Cellular
- Various fixes
- Improve dbus error messaging
- Handle cases when SIM ID is not present
- Prevent duplicate entries in the SIM providers list
Date & Time
- Improve month selector
Keyboard
- Fix activation of input source toggle button
- Fix permission_acquired always returning FALSE
Device Security
- Improve date and time formatting
- Simplify technical descriptions
Display
- Improve error state of Night Light
Sound
- Start implementing the new designs
Thunderbolt
- Hide panel if no Thunderbolt device is found
================
Version 43.1
================
- Updated translations
Mouse
- Set rows as actiavatable widgets
Network
- Fix crashes editing networks
- Fix crashes when EAP password is missing
- Fix wrong signal of SEA password visibility toggle
- Prevent crash when disconnecting wifi device
- Use mime-types for file chooser filtering TLS files
Online Accounts
- Fix crash when failing to find GOA helper executable
Power
- Don't assert if we can't find the widget for a profile
- Prevent terminal from getting spammed with ALS logs
Printers
- Small visual improvements
- Fix loading of UI resources
- Show empty-state when removing the last printer
Region
- Fix creating rows for locales without a country
- Fix critical when changing language
- Fix permission_acquired always returning FALSE
Search
- Fix reordering of list rows
Users
- Show a fallback avatar when failing to load one
Wifi
- Allow accessing settings of known wifi networks
================
Version 43.0
Version 42.4
================
- Updated translations
================
Version 43.rc
================
- Fix initial AM/PM label value
- Remove no longer used icon
- Select panel only if non-folded when search is canceled
- Updated translations
Appearance
- Allow backgrounds to use any image format
Device Security
- Several UI improvements
Background
- Restore support for multiple file selection
- Allow more image formats
Display
- Fix primary monitor selection
Info
- Improve dark theme support
Keyboard
- Fix activation of input source toggle button
- Improve handling of Shift shortcuts
Network
- Fix network profiles shown on wrong device
- Various crash fixes
Power
- Fix blank screen and power button behavior settings
Printers
- Show empty state after removing last printer
Search
- Fix Move Up and Move Down actions
Sound
- Fix sound alert selection
Wacom
- Better support Wacom Express Key Remote
================
Version 43.beta
================
- Updated translations
Cellular
- Add WWAN 5G connection support
Device Security
- Polish failure messages
- Various style updates
Display
- Support privacy screens
Info
- Show build id in a separate row
Network
- Fix VPN empty state
Sound
- Update default sounds
- Fix blank-screen settings not applying
- Fix "Power Button Behavior" setting not applying
User Accounts
- Fix back button not appearing sometimes
- Disconnect fingerprint reading devices when closing dialog
Sharing
- Don't set remote-desktop password entry if pw_generate fails
- Don't assert if we can't find the widget for a profile
================
Version 43.alpha
Version 42.3
================
- Improved accessibility in various panels
- New Device Security panel
- Updated translations
Date & Time
- Update visual style of the timezone map
Display
- Various visual improvements
- Use virtual clone modes when mirroring
Network
- Prevent crash by disconnecting device.
- Fix Wi-Fi network with "&" in name not appearing.
- Fix warning when panel closed.
================
Version 42.2
================
- Updated translations
Applications
- Fix Snap permissions support failing to compile
- Fix CcInfoRow having the wrong parent
- Fix crash crash when switching between two apps
Background
- Make sure the size of the light/dark previews are the same
Keyboard
- Fix crash resetting all keyboard shortcuts
Network:
- Stop freeze when closing wired connection properties with Escape
Sharing
- Fix close button on Verify Encryption dialog
- Turn off RDP gsettings key when turning off RDP
Shell
- Initialise locale early
Sound
- Remove dog barking sounds
- Update theme correctly so other apps respond to change
================
Version 42.1

View File

@@ -1,6 +1,6 @@
[![Build Status](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/main/pipeline.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
[![Coverage report](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/main/coverage.svg)](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
[![License](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/COPYING)
[![Build Status](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/master/pipeline.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines)
[![Coverage report](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/master/coverage.svg)](https://gnome.pages.gitlab.gnome.org/gnome-control-center/)
[![License](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/COPYING)
GNOME Settings
====================
@@ -9,7 +9,7 @@ GNOME Settings is GNOME's main interface for configuration of various aspects of
## Contributing
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/CODING_STYLE.md`
See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/HACKING.md`
for the coding style guidelines.
## Reporting Bugs
@@ -60,4 +60,4 @@ Note that GNOME Settings Flatpak will only work if you are running
the latest GNOME version in your host system.
[communication-guidelines]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/CODE_OF_CONDUCT.md#communication-guidelines
[communication-guidelines]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/CONTRIBUTING.md#communication-guidelines

View File

@@ -26,10 +26,7 @@
"cxxflags" : "-O2 -g",
"env" : {
"V" : "1"
},
"build-args": [
"--share=network"
]
}
},
"x-run-args" : [
"--verbose"
@@ -59,13 +56,13 @@
]
},
{
"name" : "intltool",
"cleanup" : [ "*" ],
"sources" : [
"name": "intltool",
"cleanup": [ "*" ],
"sources": [
{
"type" : "archive",
"url" : "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
"sha256" : "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
"type": "archive",
"url": "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz",
"sha256": "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
}
]
},
@@ -75,6 +72,7 @@
"config-opts" : [
"--disable-polkitd",
"--disable-man-pages",
"--disable-introspection",
"--disable-examples",
"--disable-gtk-doc",
"--disable-libelogind",
@@ -110,18 +108,20 @@
]
},
{
"name" : "accountsservice",
"name" : "accountservice",
"buildsystem" : "meson",
"config-opts" : [
"-Dsystemdsystemunitdir=no",
"-Ddocbook=false",
"-Delogind=false",
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dvapi=false"
"-Dsystemd=false",
"-Dsystemdsystemunitdir=no"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/accountsservice/accountsservice",
"branch" : "main"
"url" : "git://anongit.freedesktop.org/accountsservice"
}
]
},
@@ -186,6 +186,20 @@
}
]
},
{
"name" : "gudev",
"buildsystem" : "meson",
"config-opts" : [
"-Dtests=disabled",
"-Dintrospection=disabled"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgudev.git"
}
]
},
{
"name" : "colord",
"buildsystem" : "meson",
@@ -224,14 +238,11 @@
},
{
"name" : "rest",
"buildsystem" : "meson",
"config-opts" : [
"-Dgtk_doc=false"
],
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"branch" : "master",
"branch" : "librest-0-7",
"url" : "https://gitlab.gnome.org/GNOME/librest.git"
}
]
@@ -268,10 +279,9 @@
"name" : "geocode-glib",
"buildsystem" : "meson",
"config-opts" : [
"-Denable-installed-tests=false",
"-Denable-introspection=false",
"-Denable-gtk-doc=false",
"-Dsoup2=false"
"-Denable-introspection=false",
"-Denable-installed-tests=false"
],
"sources" : [
{
@@ -284,10 +294,9 @@
"name" : "libgweather",
"buildsystem" : "meson",
"config-opts" : [
"-Dglade_catalog=false",
"-Denable_vala=false",
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dtests=false"
"-Dgtk_doc=false"
],
"sources" : [
{
@@ -348,10 +357,14 @@
"config-opts" : [
"-Dlibaudit=no",
"-Ddbus_conf_dir=/app/etc/dbus-1/system.d",
"-Ddbus_ifaces_dir=/app/share/dbus-1/interfaces",
"-Ddbus_sys_dir=/app/share/dbus-1/system.d",
"-Ddnsmasq=/usr/bin/true",
"-Ddocs=false",
"-Dintrospection=false",
"-Diptables=/usr/bin/true",
"-Djson_validation=false",
"-Dlibnm_glib=false",
"-Dlibpsl=false",
"-Dmodem_manager=false",
"-Dnmtui=false",
@@ -406,9 +419,12 @@
"buildsystem" : "meson",
"config-opts" : [
"-Dappindicator=no",
"-Dwwan=false",
"-Dgtk_doc=false",
"-Dintrospection=false",
"-Dlibnm_gtk=false",
"-Dselinux=false",
"-Dteam=false"
"-Dteam=false",
"-Dwwan=false"
],
"sources" : [
{
@@ -618,142 +634,6 @@
}
]
},
{
"name" : "mutter",
"buildsystem" : "meson",
"config-opts" : [
"-Dgles2=false",
"-Dglx=false",
"-Dxwayland=false",
"-Dwayland=false",
"-Dsystemd=false",
"-Dnative_backend=false",
"-Dremote_desktop=false",
"-Degl_device=false",
"-Dudev=false",
"-Dstartup_notification=false",
"-Dsm=false",
"-Dintrospection=true",
"-Ddocs=false",
"-Dtests=false",
"-Dprofiler=false"
],
"sources" : [
{
"type" : "git",
"branch" : "main",
"url" : "https://gitlab.gnome.org/gnome/mutter.git"
}
]
},
{
"name" : "libical",
"buildsystem" : "cmake",
"config-opts" : [
"-DICAL_BUILD_DOCS=false",
"-DICAL_GLIB=true",
"-DLIBICAL_BUILD_TESTING=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/libical/libical.git"
}
]
},
{
"name" : "evolution-data-server",
"buildsystem" : "cmake",
"config-opts" : [
"-DWITH_LIBDB=OFF"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/evolution-data-server.git"
}
]
},
{
"name" : "libstartup-notification",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/xdg/startup-notification.git"
}
]
},
{
"name" : "sassc",
"buildsystem" : "simple",
"sources" : [
{
"type" : "git",
"url" : "https://github.com/sass/libsass"
},
{
"type" : "git",
"url" : "https://github.com/sass/sassc.git",
"dest" : "sassc"
}
],
"build-commands" : [
"make -C sassc",
"PREFIX=/app make -C sassc install"
]
},
{
"name" : "cogl",
"buildsystem" : "autotools",
"sources" : [
{
"type" : "git",
"tag" : "cogl-1.22",
"url" : "https://gitlab.gnome.org/Archive/cogl.git"
}
]
},
{
"name" : "clutter",
"buildsystem" : "meson",
"config-opts" : [
"-Dbackends='system'",
"-Ddrivers='all'",
"-Dbuild_tests=false",
"-Dbuild_examples=false",
"-Ddocumentation=false",
"-Dintrospection=true",
"-Dpixbuf_tests=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/clutter.git"
}
]
},
{
"name" : "gnome-shell",
"buildsystem" : "meson",
"config-opts" : [
"-Dextensions_tool=false",
"-Dextensions_app=false",
"-Dgtk_doc=false",
"-Dman=false",
"-Dtests=false",
"-Dnetworkmanager=false",
"-Dsystemd=false"
],
"sources" : [
{
"type" : "git",
"branch" : "main",
"url" : "https://gitlab.gnome.org/GNOME/gnome-shell.git"
}
]
},
{
"name" : "gnome-backgrounds",
"buildsystem" : "meson",
@@ -770,11 +650,12 @@
"buildsystem" : "meson",
"sources" : [
{
"type" : "dir",
"path" : "../../"
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gnome-control-center.git"
}
],
"config-opts" : [
"-Dtracing=true",
"-Dprofile=development"
]
}

1
build-aux/meson.build Normal file
View File

@@ -0,0 +1 @@
meson.add_install_script('meson/meson_post_install.py', control_center_datadir)

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
gsettingsschemadir = os.path.join(sys.argv[1], 'glib-2.0', 'schemas')
icondir = os.path.join(sys.argv[1], 'icons', 'hicolor')
if not os.environ.get('DESTDIR'):
print('Compiling gsettings schemas...')
subprocess.call(['glib-compile-schemas', gsettingsschemadir])
print('Update icon cache...')
subprocess.call(['gtk-update-icon-cache', '-f', '-t', icondir])

View File

@@ -1,184 +0,0 @@
# Code of Conduct
GNOME Settings is a project developed based on GNOME Code of Conduct and GitHub's community
guidelines. You can read it below:
## Summary
GNOME creates software for a better world. We achieve this by behaving well towards
each other.
Therefore this document suggests what we consider ideal behaviour, so you know what
to expect when getting involved in GNOME. This is who we are and what we want to be.
There is no official enforcement of these principles, and this should not be interpreted
like a legal document.
## Advice
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
attacks. Remember that a community where people feel uncomfortable is not a productive one.
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
suggest specific documentation or more appropriate venues where appropriate, but avoid
aggressive or vague responses such as "RTFM".
* **Assume people mean well**: Remember that decisions are often a difficult choice between
competing priorities. If you disagree, please do so politely. If something seems outrageous,
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
makes it difficult to follow, and people often feel personally attacked if they receive multiple
messages telling them the same thing.
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Communication Guidelines
It is of ultimate importance to maintain a community in which everyone feels free to express
themselves, review, and comment on each others ideas, both technical and otherwise. Correspondingly,
an environment in which individuals are silenced, berated, or are otherwise afraid to speak up is
unlikely to foster fruitful dialog.
Everyone interacting with members of the community should always keep in mind the asymmetry of
communication: while your interaction with community members (and in particular, maintainers and
long-term contributors) may be singular and fleeting, these members generally interact with a high
volume of individuals each day. Before writing a comment, opening a new issue, or engaging as part
of any forum or IRC discussion, please take a moment to appreciate that fact.
While communicating, it is expected that all involved participants be respectful and civil at all
times and refrain from personal attacks.
### Communication Rules
The following behavior will not be tolerated on any occasion:
* **Threats of violence**: You may not threaten violence towards others or use the site to organize,
promote, or incite acts of real-world violence or terrorism. Think carefully about the words you
use, the images you post, and even the software you write, and how they may be interpreted by
others. Even if you mean something as a joke, it might not be received that way. If you think
that someone else might interpret the content you post as a threat or as promoting violence or
terrorism, stop. Don't post it. In extraordinary cases, we may report threats of violence to law
enforcement if we think there may be a genuine risk of physical harm or a threat to public safety.
* **Hate speech and discrimination**: While it is not forbidden to broach topics such as age, body
size, disability, ethnicity, gender identity and expression, level of experience, nationality,
personal appearance, race, religion, or sexual identity and orientation, we do not tolerate speech
that attacks a person or group of people on the basis of who they are. When approached in an
aggressive or insulting manner these (and other) sensitive topics can make others feel unwelcome,
or perhaps even unsafe. While there's always the potential for misunderstandings, we expect our
community members to remain respectful and civil when discussing sensitive topics.
* **Bullying and harassment**: We do not tolerate bullying, harassment, or any other means of
habitual badgering or intimidation targeted at a specific person or group of people. In general,
if your actions are unwanted and you cease to terminate this form of engagement, there is a good
chance that your behavior will be classified as bullying or harassment.
* **Impersonation**: You may not seek to mislead others as to your identity by copying another
person's avatar, posting content under their email address, using a similar username, or otherwise
posing as someone else. Impersonation and identity theft is a form of harassment.
* **Doxxing and invasion of privacy**: Don't post other people's personal information, such as phone
numbers, private email addresses, physical addresses, credit card numbers, Social Security/National
Identity numbers, or passwords. Depending on the context, we may consider such behavior to be an
invasion of privacy, with particularly egregious examples potentially escalating to the point of
legal action, such as when the released material presents a safety risk to the subject.
* **Obscene content**: In essence, do not post pornography, gore, or any other depiction of violence.
### General Advice
The following advice will help to increase the efficiency of communication with community members:
* Do not post "me too" comments. Use the GitLab reactions instead, e.g. “thumbs up” or “thumbs down”.
* Avoid adding priority, time, or relevance hints if you are not involved with the development of
the application. For example, `“This is an urgent issue”`, or `“This should be fixed now”`, or
even `“The majority of users need this feature”`.
* Do not use passive-aggressive communication tactics.
* When reporting technical problems with the application, such as misbehavior or crashes, focus on
sharing as many details as possible and avoid adding non-technical information to it.
An example of a **good** issue report:
```
GNOME Settings crashes when opening the Wi-Fi panel with 3+ Wi-Fi adapters
Steps to reproduce (assuming 3+ Wi-Fi adapters are present):
1. Open GNOME Settings
2. Select the Wi-Fi panel
3. Observe the crash
This does not happen with 2 or less adapters. Here is a backtrace of the
crash: backtrace.txt
```
In contrast, here is an example of a **bad** issue report:
```
GNOME Settings crashed while I was trying to connect to the internet. How can such
a thing happen and nobody notice? Did you not test it before releasing it?
This should be fixed as quick as possible!
```
* When asking for new features, try and add as much information as possible to justify its relevance,
why should it not be implemented as an auxiliary program, what problems it would solve, and offer
suggestions about how you think it should be implemented.
Example of a **good** feature request:
```
GNOME Settings needs to expose IPv6 options
As of now, the connection editor dialog does not allow editing various IPv6
options. This is relevant because without some of these options, it is not
possible to have a valid IPv6 configuration and, consequently, not have access
to various websites and services.
The list of missing configurations that are essential is:
* <Feature A>
* <Feature B>
Optionally, the following configurations can also be added:
* <Feature C>
* <Feature D>
Here is a quick sketch I have made showing how I think these options
should be exposed as a user interface: sketch.png.
```
Example of a **bad** feature request:
```
Merge GNOME Tweaks in GNOME Settings
The options in GNOME Tweaks are absolutely essential to the majority of us
users. Why was it not merged already? This is an urgent issue and should
have been addressed years ago. You should allocate all your resources on
merging those two applications.
```
### What happens if someone breaks these rules or guidelines?
Actions that may be taken in response to an abusive comment include but are not limited to:
* Content removal (when breaking any of the guidelines or rules)
* Content blocking (when breaking any of the guidelines or rules)
* Formal report to the Code of Conduct Committee (when breaking any of the rules)
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
[maintainers]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/docs/MAINTAINERS.md

View File

@@ -1,97 +1,212 @@
# Contributing
Thank you for considering contributing to Settings!
All code contributions are made using merge requests.
When contributing to the development of GNOME Settings, please first discuss the change you wish to
make via issue, email, or any other method with the maintainers before making a change.
Please note we have a Code of Conduct, please follow it in all your interactions with the project.
## Creating Merge Requests
## Pull Request Process
To open a merge request fork the Settings project, and then create a branch for your change.
When the change is ready, submit a merge request.
1. Create a fork in GitLab and push your work to there
2. Open a Merge Request
1. Always allow maintainer edits
2. Mark the Merge Request as WIP if your work is not ready to be reviewed
3. Assign the correct maintainer to the Merge Request (see [`MAINTAINERS.md`][maintainers] to select
the correct maintainer)
4. Format commit messages as follows:
```
component: <summary>
A paragraph explaining the problem and its context.
Another one explaining how you solved that.
<link to the issue>
```
4. You may merge the pull request in once you have the sign-off of the maintainers, or if you
do not have permission to do that, you may request the second reviewer to merge it for you.
The following guidelines will help your change be successfully merged:
## Code of Conduct
* Keep the change as small as possible. If you can split it into multiple merge requests please do
so.
* Use multiple commits. This makes is easier to review and helps to diagnose bugs in the future.
* Use clear commit messages (see below).
* Attach screenshots of the change.
* Link to relevant issues this change is related to.
* Always set the merge request to allow maintainer edits - this makes it easier
for a maintainer to make small improvements to land the change faster.
GNOME Settings is a project developed based on GNOME Code of Conduct and GitHub's community
guidelines. You can read it below:
Please format commit messages as follows:
### Summary
```
component: <summary>
GNOME creates software for a better world. We achieve this by behaving well towards
each other.
A paragraph explaining the problem and its context.
Therefore this document suggests what we consider ideal behaviour, so you know what
to expect when getting involved in GNOME. This is who we are and what we want to be.
There is no official enforcement of these principles, and this should not be interpreted
like a legal document.
Another one explaining how you solved that.
### Advice
<link to issue(s) this change fixes>
```
* **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal
attacks. Remember that a community where people feel uncomfortable is not a productive one.
## Bug Fixes
* **Be patient and generous**: If someone asks for help it is because they need it. Do politely
suggest specific documentation or more appropriate venues where appropriate, but avoid
aggressive or vague responses such as "RTFM".
Changes that fix bugs include:
* **Assume people mean well**: Remember that decisions are often a difficult choice between
competing priorities. If you disagree, please do so politely. If something seems outrageous,
check that you did not misinterpret it. Ask for clarification, but do not assume the worst.
* Correcting code that crashes.
* Spelling mistakes in labels.
* Small layout issues (e.g. spacing).
* Use of deprecated APIs.
* Restructuring of code for improved safety.
* **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger
makes it difficult to follow, and people often feel personally attacked if they receive multiple
messages telling them the same thing.
Please include clear information in the commit message(s) and merge request that indicate what is
being fixed by the change.
These changes will be reviewed for correctness, and then merged once this is complete.
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## User Experience Changes
### Communication Guideline
Changes that impact the user experience of Settings require approval from the
[Design Team][design-team]. This includes:
It is of ultimate importance to maintain a community in which everyone feels free to express
themselves, review, and comment on each others ideas, both technical and otherwise. Correspondingly,
an environment in which individuals are silenced, berated, or are otherwise afraid to speak up is
unlikely to foster fruitful dialog.
* Addition or removal of features in existing panels.
* Changes to the layout of panels.
* New panels.
Everyone interacting with members of the community should always keep in mind the asymmetry of
communication: while your interaction with community members (and in particular, maintainers and
long-term contributors) may be singular and fleeting, these members generally interact with a high
volume of individuals each day. Before writing a comment, opening a new issue, or engaging as part
of any forum or IRC discussion, please take a moment to appreciate that fact.
Please include before/after screenshots in the merge request to show what is being changed.
While communicating, it is expected that all involved participants be respectful and civil at all
times and refrain from personal attacks.
For one of these changes to be merged one of the following is required:
#### Communication Rules
* The change is shown in an existing mockup done by the design team (linked to in the merge request
or issue).
* A comment from a design team member in the merge request or issue approving the change.
The following behavior will not be tolerated on any occasion:
If a merge request is opened without the above the "Needs Design" label attached to it and will not
be merged until design approval is received.
* **Threats of violence**: You may not threaten violence towards others or use the site to organize,
promote, or incite acts of real-world violence or terrorism. Think carefully about the words you
use, the images you post, and even the software you write, and how they may be interpreted by
others. Even if you mean something as a joke, it might not be received that way. If you think
that someone else might interpret the content you post as a threat or as promoting violence or
terrorism, stop. Don't post it. In extraordinary cases, we may report threats of violence to law
enforcement if we think there may be a genuine risk of physical harm or a threat to public safety.
Once design approval is obtained, the change will be reviewed for correctness, and then merged once
this is complete.
If design approval is not obtained, the merge request will be closed.
* **Hate speech and discrimination**: While it is not forbidden to broach topics such as age, body
size, disability, ethnicity, gender identity and expression, level of experience, nationality,
personal appearance, race, religion, or sexual identity and orientation, we do not tolerate speech
that attacks a person or group of people on the basis of who they are. When approached in an
aggressive or insulting manner these (and other) sensitive topics can make others feel unwelcome,
or perhaps even unsafe. While there's always the potential for misunderstandings, we expect our
community members to remain respectful and civil when discussing sensitive topics.
[design-team]: https://gitlab.gnome.org/Teams/Design
* **Bullying and harassment**: We do not tolerate bullying, harassment, or any other means of
habitual badgering or intimidation targeted at a specific person or group of people. In general,
if your actions are unwanted and you cease to terminate this form of engagement, there is a good
chance that your behavior will be classified as bullying or harassment.
## Reviews
* **Impersonation**: You may not seek to mislead others as to your identity by copying another
person's avatar, posting content under their email address, using a similar username, or otherwise
posing as someone else. Impersonation and identity theft is a form of harassment.
All changes require approval from one or more Settings maintainers.
Reviews are likely to ask for changes to be made, please respond to these as soon as you are able
and ask for clarification if the requests are not clear.
* **Doxxing and invasion of privacy**: Don't post other people's personal information, such as phone
numbers, private email addresses, physical addresses, credit card numbers, Social Security/National
Identity numbers, or passwords. Depending on the context, we may consider such behavior to be an
invasion of privacy, with particularly egregious examples potentially escalating to the point of
legal action, such as when the released material presents a safety risk to the subject.
When the change is ready to land a maintainer will mark it as approved.
Then the change can be merged by either a maintainer or the submitter if they have suitable
permissions.
* **Obscene content**: In essence, do not post pornography, gore, or any other depiction of violence.
## Draft Merge Requests
#### General Advice
Merge requests marked as draft will not be reviewed by Settings maintainers or merged.
When the change is ready for review please mark the merge request as ready.
The following advice will help to increase the efficiency of communication with community members:
## Inactive Merge Requests
* Do not post "me too" comments. Use the GitLab reactions instead, e.g. “thumbs up” or “thumbs down”.
* Avoid adding priority, time, or relevance hints if you are not involved with the development of
the application. For example, `“This is an urgent issue”`, or `“This should be fixed now”`, or
even `“The majority of users need this feature”`.
* Do not use passive-aggressive communication tactics.
* When reporting technical problems with the application, such as misbehavior or crashes, focus on
sharing as many details as possible and avoid adding non-technical information to it.
If a merge request has comments from maintainers that have not been responded to within 4 weeks this
merge request is considered to be inactive and will be closed. The reporter may re-open it at a
later date if they respond to the comments.
An example of a **good** issue report:
```
GNOME Settings crashes when opening the Wi-Fi panel with 3+ Wi-Fi adapters
Steps to reproduce (assuming 3+ Wi-Fi adapters are present):
1. Open GNOME Settings
2. Select the Wi-Fi panel
3. Observe the crash
This does not happen with 2 or less adapters. Here is a backtrace of the
crash: backtrace.txt
```
In contrast, here is an example of a **bad** issue report:
```
GNOME Settings crashed while I was trying to connect to the internet. How can such
a thing happen and nobody notice? Did you not test it before releasing it?
This should be fixed as quick as possible!
```
* When asking for new features, try and add as much information as possible to justify its relevance,
why should it not be implemented as an auxiliary program, what problems it would solve, and offer
suggestions about how you think it should be implemented.
Example of a **good** feature request:
```
GNOME Settings needs to expose IPv6 options
As of now, the connection editor dialog does not allow editing various IPv6
options. This is relevant because without some of these options, it is not
possible to have a valid IPv6 configuration and, consequently, not have access
to various websites and services.
The list of missing configurations that are essential is:
* <Feature A>
* <Feature B>
Optionally, the following configurations can also be added:
* <Feature C>
* <Feature D>
Here is a quick sketch I have made showing how I think these options
should be exposed as a user interface: sketch.png.
```
Example of a **bad** feature request:
```
Merge GNOME Tweaks in GNOME Settings
The options in GNOME Tweaks are absolutely essential to the majority of us
users. Why was it not merged already? This is an urgent issue and should
have been addressed years ago. You should allocate all your resources on
merging those two applications.
```
#### What happens if someone breaks these rules or guidelines?
Actions that may be taken in response to an abusive comment include but are not limited to:
* Content removal (when breaking any of the guidelines or rules)
* Content blocking (when breaking any of the guidelines or rules)
* Formal report to the Code of Conduct Committee (when breaking any of the rules)
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
[maintainers]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/docs/MAINTAINERS.md

View File

@@ -50,7 +50,7 @@ by being explicit. Suggested acceptance phrase:
Urgency commits should never happen, but in case they're needed, they are defined by the following
criteria:
* On stable branches (or `main` right after a stable release)
* On stable branches (or master right after a stable release)
* Symptoms:
* Always OR often reproducible; AND
* Crash; OR
@@ -59,4 +59,4 @@ criteria:
* Quickly followed by an emergency release (at most 2 days after the commit)
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/main/gnome-control-center.doap
[doap]: https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/gnome-control-center.doap

View File

@@ -13,6 +13,15 @@
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>C</programming-language>
<!-- General, Multitasking -->
<maintainer>
<foaf:Person>
<foaf:name>Georges Basile Stavracas Neto</foaf:name>
<foaf:mbox rdf:resource="mailto:gbsneto@gnome.org" />
<gnome:userid>gbsneto</gnome:userid>
</foaf:Person>
</maintainer>
<!-- General, Region & Language -->
<maintainer>
<foaf:Person>
@@ -40,7 +49,7 @@
</foaf:Person>
</maintainer>
<!-- About, Camera, File History & Trash, Location, Microphone, Mouse & Touchpad, Printers, Search, Thunderbolt, User Accounts -->
<!-- Mouse & Touchpad, Printers -->
<maintainer>
<foaf:Person>
<foaf:name>Felipe Borges</foaf:name>
@@ -66,6 +75,15 @@
</foaf:Person>
</maintainer>
<!-- Thunderbolt -->
<maintainer>
<foaf:Person>
<foaf:name>Christian Kellner</foaf:name>
<foaf:mbox rdf:resource="mailto:gicmo@gnome.org" />
<gnome:userid>gicmo</gnome:userid>
</foaf:Person>
</maintainer>
<!-- Wacom -->
<maintainer>
<foaf:Person>

View File

@@ -1,8 +1,8 @@
project(
'gnome-control-center', 'c',
version : '44.4',
version : '42.10',
license : 'GPL2+',
meson_version : '>= 0.57.0'
meson_version : '>= 0.53.0'
)
control_center_prefix = get_option('prefix')
@@ -25,19 +25,15 @@ host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390
cc = meson.get_compiler('c')
# Tracing
enable_tracing = get_option('tracing')
config_h = configuration_data()
py = import('python')
python = py.find_installation('python3')
config_h.set_quoted('TEST_NM_PYTHON', python.full_path())
if get_option('profile') == 'development'
profile = 'Devel'
else
profile = ''
endif
application_id = 'org.gnome.Settings@0@'.format(profile)
config_h.set_quoted('TEST_NM_PYTHON', python.path())
# defines
set_defines = [
@@ -54,17 +50,6 @@ foreach define: set_defines
config_h.set_quoted(define[0], define[1])
endforeach
distributor_logo = get_option('distributor_logo')
if (distributor_logo != '')
config_h.set_quoted('DISTRIBUTOR_LOGO', distributor_logo,
description: 'Define to absolute path of distributor logo')
dark_mode_distributor_logo = get_option('dark_mode_distributor_logo')
if (dark_mode_distributor_logo != '')
config_h.set_quoted('DARK_MODE_DISTRIBUTOR_LOGO', dark_mode_distributor_logo,
description: 'Define to absolute path of distributor logo for use in dark mode')
endif
endif
# meson does not support octal values, so it must be handled as a
# string. See: https://github.com/mesonbuild/meson/issues/2047
config_h.set('USER_DIR_MODE', '0700',
@@ -117,22 +102,9 @@ libgvc_dep = libgvc.get_variable('libgvc_dep')
goa_req_version = '>= 3.25.3'
pulse_req_version = '>= 2.0'
gtk_dep = dependency(
'gtk4',
version: '>= 4.9.3',
fallback: ['gtk', 'gtk_dep'],
default_options: [
'introspection=disabled',
'demos=false',
'build-testsuite=false',
'build-tests=false',
'build-examples=false',
]
)
libadwaita_dep = dependency(
'libadwaita-1',
version: '>= 1.2.alpha',
version: '>= 1.1',
fallback: ['libadwaita', 'libadwaita_dep'],
default_options: ['examples=false', 'introspection=disabled', 'tests=false', 'vapi=false'],
)
@@ -141,7 +113,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.75.0')
glib_dep = dependency('glib-2.0', version: '>= 2.68.0')
gnome_desktop_dep = dependency('gnome-desktop-4')
gnome_bg_dep = dependency('gnome-bg-4')
gnome_rr_dep = dependency('gnome-rr-4')
@@ -153,7 +125,7 @@ pulse_dep = dependency('libpulse', version: pulse_req_version)
pulse_mainloop_dep = dependency('libpulse-mainloop-glib', version: pulse_req_version)
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8')
gudev_dep = dependency('gudev-1.0', version: '>= 232')
x11_dep = dependency('x11', version: '>= 1.8')
x11_dep = dependency('x11')
xi_dep = dependency('xi', version: '>= 1.2')
epoxy_dep = dependency('epoxy')
gcr_dep = dependency('gcr-base-3')
@@ -168,7 +140,7 @@ common_deps = [
libadwaita_dep,
dependency('gio-unix-2.0'),
dependency('gthread-2.0'),
gtk_dep,
dependency('gtk4', version: '>= 4.4'),
]
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103')
@@ -239,11 +211,10 @@ config_h.set('HAVE_MALCONTENT', enable_malcontent,
if host_is_linux
# network manager
mm_dep = dependency('mm-glib', version: '>= 0.7')
network_manager_deps = [
dependency('libnm', version: '>= 1.24.0'),
dependency('libnma-gtk4', version: '>= 1.10.2'),
mm_dep,
dependency('libnma-gtk4', version: '>= 1.8.0'),
dependency('mm-glib', version: '>= 0.7')
]
endif
config_h.set('BUILD_NETWORK', host_is_linux,
@@ -285,6 +256,9 @@ gnome = import('gnome')
i18n = import('i18n')
pkg = import('pkgconfig')
desktop_conf = configuration_data()
desktop_conf.set('VERSION', meson.project_version())
po_dir = join_paths(meson.source_root(), 'po')
its_dir = join_paths(meson.source_root(), 'gettext')
@@ -296,6 +270,7 @@ install_subdir(
top_inc = include_directories('.')
shell_inc = include_directories('shell')
subdir('build-aux')
subdir('data/icons')
subdir('po')
subdir('panels')
@@ -310,11 +285,6 @@ if get_option('documentation')
subdir('man')
endif
gnome.post_install(
glib_compile_schemas: true,
gtk_update_icon_cache: true,
)
configure_file(
output: 'config.h',
configuration: config_h
@@ -323,6 +293,7 @@ configure_file(
summary({
'Documentation': get_option('documentation'),
'Tests': get_option('tests'),
'Tracing': enable_tracing,
'Optimized': control_center_optimized,
})

View File

@@ -3,8 +3,7 @@ option('ibus', type: 'boolean', value: true, description: 'build with IBus suppo
option('privileged_group', type: 'string', value: 'wheel', description: 'name of group that has elevated permissions')
option('snap', type: 'boolean', value: false, description: 'build with Snap support')
option('tests', type: 'boolean', value: true, description: 'build tests')
option('tracing', type: 'boolean', value: false, description: 'add extra debugging information')
option('wayland', type: 'boolean', value: true, description: 'build with Wayland support')
option('profile', type: 'combo', choices: ['default','development'], value: 'default')
option('malcontent', type: 'boolean', value: false, description: 'build with malcontent support')
option('distributor_logo', type: 'string', description: 'absolute path to distributor logo for the About panel')
option('dark_mode_distributor_logo', type: 'string', description: 'absolute path to distributor logo dark mode variant')

View File

@@ -96,7 +96,6 @@ struct _CcApplicationsPanel
CcToggleRow *notification;
CcToggleRow *background;
CcToggleRow *wallpaper;
CcToggleRow *screenshot;
CcToggleRow *sound;
CcInfoRow *no_sound;
CcToggleRow *search;
@@ -516,37 +515,6 @@ wallpaper_cb (CcApplicationsPanel *self)
set_wallpaper_allowed (self, cc_toggle_row_get_allowed (self->wallpaper));
}
/* --- screenshot --- */
static void
get_screenshot_allowed (CcApplicationsPanel *self,
const gchar *app_id,
gboolean *set,
gboolean *allowed)
{
g_auto(GStrv) perms = get_portal_permissions (self, "screenshot", "screenshot", app_id);
*set = perms != NULL;
*allowed = perms == NULL || strcmp (perms[0], "no") != 0;
}
static void
set_screenshot_allowed (CcApplicationsPanel *self,
gboolean allowed)
{
const gchar *perms[2] = { NULL, NULL };
perms[0] = allowed ? "yes" : "no";
set_portal_permissions (self, "screenshot", "screenshot", self->current_app_id, perms);
}
static void
screenshot_cb (CcApplicationsPanel *self)
{
if (self->current_app_id)
set_screenshot_allowed (self, cc_toggle_row_get_allowed (self->screenshot));
}
/* --- shortcuts permissions (flatpak) --- */
static void
@@ -576,7 +544,7 @@ set_shortcuts_allowed (CcApplicationsPanel *self,
/* "GRANTED" and "DENIED" here match the values set by the "inhibit shortcut
* dialog" is GNOME Shell:
* https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/inhibitShortcutsDialog.js
* https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/inhibitShortcutsDialog.js
*/
perms[0] = granted ? "GRANTED" : "DENIED";
perms[1] = NULL;
@@ -847,7 +815,7 @@ add_static_permissions (CcApplicationsPanel *self,
if (str && g_str_equal (str, "talk"))
added += add_static_permission_row (self, _("Settings"), _("Can change settings"));
text = g_strdup_printf (_("%s requires access to the following system resources. To stop this access, the app must be removed."), g_app_info_get_display_name (info));
text = g_strdup_printf (_("%s has the following permissions built-in. These cannot be altered. If you are concerned about these permissions, consider removing this application."), g_app_info_get_display_name (info));
adw_preferences_group_set_description (self->builtin_group, text);
return added > 0;
@@ -901,7 +869,7 @@ update_integration_section (CcApplicationsPanel *self,
}
else
{
gtk_widget_set_visible (GTK_WIDGET (self->shortcuts), FALSE);
gtk_widget_hide (GTK_WIDGET (self->shortcuts));
}
#ifdef HAVE_SNAP
@@ -926,11 +894,6 @@ update_integration_section (CcApplicationsPanel *self,
gtk_widget_set_visible (GTK_WIDGET (self->wallpaper), set);
has_any |= set;
get_screenshot_allowed (self, portal_app_id, &set, &allowed);
cc_toggle_row_set_allowed (self->screenshot, allowed);
gtk_widget_set_visible (GTK_WIDGET (self->screenshot), set);
has_any |= set;
disabled = g_settings_get_boolean (self->privacy_settings, "disable-sound-output");
get_device_allowed (self, "speakers", portal_app_id, &set, &allowed);
cc_toggle_row_set_allowed (self->sound, allowed);
@@ -970,17 +933,16 @@ update_integration_section (CcApplicationsPanel *self,
gtk_widget_set_visible (GTK_WIDGET (self->notification), set);
has_any |= set;
gtk_widget_set_visible (GTK_WIDGET (self->background), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->wallpaper), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->screenshot), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->sound), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->no_sound), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->camera), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->no_camera), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->microphone), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->no_microphone), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->location), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->no_location), FALSE);
gtk_widget_hide (GTK_WIDGET (self->background));
gtk_widget_hide (GTK_WIDGET (self->wallpaper));
gtk_widget_hide (GTK_WIDGET (self->sound));
gtk_widget_hide (GTK_WIDGET (self->no_sound));
gtk_widget_hide (GTK_WIDGET (self->camera));
gtk_widget_hide (GTK_WIDGET (self->no_camera));
gtk_widget_hide (GTK_WIDGET (self->microphone));
gtk_widget_hide (GTK_WIDGET (self->no_microphone));
gtk_widget_hide (GTK_WIDGET (self->location));
gtk_widget_hide (GTK_WIDGET (self->no_location));
}
gtk_widget_set_visible (GTK_WIDGET (self->integration_section), has_any);
@@ -1029,7 +991,7 @@ add_scheme (CcApplicationsPanel *self,
g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
gtk_widget_set_visible (GTK_WIDGET (self->handler_link_group), TRUE);
gtk_widget_show (GTK_WIDGET (self->handler_link_group));
adw_preferences_group_add (self->handler_link_group, GTK_WIDGET (row));
self->link_handler_rows = g_list_prepend (self->link_handler_rows, row);
@@ -1061,7 +1023,7 @@ add_file_type (CcApplicationsPanel *self,
g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
gtk_widget_set_visible (GTK_WIDGET (self->handler_file_group), TRUE);
gtk_widget_show (GTK_WIDGET (self->handler_file_group));
adw_preferences_group_add (self->handler_file_group, GTK_WIDGET (row));
self->file_handler_rows = g_list_prepend (self->file_handler_rows, row);
@@ -1071,7 +1033,7 @@ static void
add_handler_row (CcApplicationsPanel *self,
const gchar *type)
{
gtk_widget_set_visible (GTK_WIDGET (self->handler_row), TRUE);
gtk_widget_show (GTK_WIDGET (self->handler_row));
if (g_content_type_is_a (type, "x-scheme-handler/*"))
add_scheme (self, type);
@@ -1154,9 +1116,9 @@ update_handler_dialog (CcApplicationsPanel *self,
remove_all_handler_rows (self);
gtk_widget_set_visible (GTK_WIDGET (self->handler_row), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->handler_file_group), FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->handler_link_group), FALSE);
gtk_widget_hide (GTK_WIDGET (self->handler_row));
gtk_widget_hide (GTK_WIDGET (self->handler_file_group));
gtk_widget_hide (GTK_WIDGET (self->handler_link_group));
types = g_app_info_get_supported_types (info);
if (types == NULL || types[0] == NULL)
@@ -1248,7 +1210,7 @@ update_total_size (CcApplicationsPanel *self)
g_object_set (self->total, "info", formatted_size, NULL);
/* Translators: '%s' is the formatted size, e.g. "26.2 MB" */
subtitle = g_strdup_printf (_("%s of disk space used."), formatted_size);
subtitle = g_strdup_printf (_("%s of disk space used"), formatted_size);
g_object_set (self->storage, "subtitle", subtitle, NULL);
}
@@ -1412,9 +1374,9 @@ update_panel (CcApplicationsPanel *self,
if (row == NULL)
{
adw_window_title_set_title (self->header_title, _("Apps"));
adw_window_title_set_title (self->header_title, _("Applications"));
gtk_stack_set_visible_child (self->stack, self->empty_box);
gtk_widget_set_visible (GTK_WIDGET (self->view_details_button), FALSE);
gtk_widget_hide (GTK_WIDGET (GTK_WIDGET (self->view_details_button)));
return;
}
@@ -1782,7 +1744,6 @@ 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, 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);
@@ -1804,7 +1765,6 @@ cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
gtk_widget_class_bind_template_callback (widget_class, notification_cb);
gtk_widget_class_bind_template_callback (widget_class, background_cb);
gtk_widget_class_bind_template_callback (widget_class, wallpaper_cb);
gtk_widget_class_bind_template_callback (widget_class, screenshot_cb);
gtk_widget_class_bind_template_callback (widget_class, shortcuts_cb);
gtk_widget_class_bind_template_callback (widget_class, privacy_link_cb);
gtk_widget_class_bind_template_callback (widget_class, sound_cb);

View File

@@ -16,7 +16,7 @@
</child>
<property name="title-widget">
<object class="AdwWindowTitle" id="header_title">
<property name="title" translatable="yes">Apps</property>
<property name="title" translatable="yes">Applications</property>
</object>
</property>
</object>
@@ -28,7 +28,7 @@
<child>
<object class="AdwStatusPage" id="empty_box">
<property name="icon-name">org.gnome.Software-symbolic</property>
<property name="title" translatable="yes">No apps</property>
<property name="title" translatable="yes">No applications</property>
<child>
<object class="GtkButton" id="install_button">
<property name="label" translatable="yes">Install some…</property>
@@ -91,7 +91,7 @@
</child>
<child>
<object class="GtkButton" id="view_details_button">
<property name="label" translatable="yes">App Details</property>
<property name="label" translatable="yes">View Details</property>
<style>
<class name="pill" />
</style>
@@ -110,38 +110,31 @@
<child>
<object class="CcToggleRow" id="search">
<property name="title" translatable="yes">Search</property>
<property name="subtitle" translatable="yes">Receive system searches and send results</property>
<property name="subtitle" translatable="yes">Receive system searches and send results.</property>
<signal name="notify::allowed" 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="subtitle" translatable="yes">Receive system searches and send results.</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="notification">
<property name="title" translatable="yes">Notifications</property>
<property name="subtitle" translatable="yes">Show system notifications</property>
<property name="subtitle" translatable="yes">Show system notifications.</property>
<signal name="notify::allowed" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" 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="title" translatable="yes">Run in background</property>
<property name="subtitle" translatable="yes">Allow activity when the app is closed.</property>
<signal name="notify::allowed" handler="background_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" 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::allowed" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="wallpaper">
<property name="title" translatable="yes">Change Wallpaper</property>
@@ -159,56 +152,56 @@
<child>
<object class="CcInfoRow" id="no_sound">
<property name="title" translatable="yes">Sounds</property>
<property name="subtitle" translatable="yes">Reproduce sounds</property>
<property name="subtitle" translatable="yes">Reproduce sounds.</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="shortcuts">
<property name="title" translatable="yes">Inhibit Shortcuts</property>
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts</property>
<property name="subtitle" translatable="yes">Block standard keyboard shortcuts.</property>
<signal name="notify::allowed" handler="shortcuts_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="CcToggleRow" id="camera">
<property name="title" translatable="yes">Camera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera</property>
<property name="subtitle" translatable="yes">Take pictures with the camera.</property>
<signal name="notify::allowed" 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="subtitle" translatable="yes">Take pictures with the camera.</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="microphone">
<property name="title" translatable="yes">Microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone</property>
<property name="subtitle" translatable="yes">Record audio with the microphone.</property>
<signal name="notify::allowed" 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="subtitle" translatable="yes">Record audio with the microphone.</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
<child>
<object class="CcToggleRow" id="location">
<property name="title" translatable="yes">Location Services</property>
<property name="subtitle" translatable="yes">Access device location data</property>
<property name="subtitle" translatable="yes">Access device location data.</property>
<signal name="notify::allowed" 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="subtitle" translatable="yes">Access device location data.</property>
<property name="info" translatable="yes">Disabled</property>
</object>
</child>
@@ -219,7 +212,7 @@
<object class="AdwPreferencesGroup" id="usage_section">
<child>
<object class="CcInfoRow" id="builtin">
<property name="title" translatable="yes">Required Access</property>
<property name="title" translatable="yes">Built-in Permissions</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>
@@ -323,15 +316,11 @@
<!-- Built-in Permissions dialog -->
<object class="GtkDialog" id="builtin_dialog">
<property name="title" translatable="yes">Required Access</property>
<property name="title" translatable="yes">Built-in Permissions</property>
<property name="modal">1</property>
<property name="use-header-bar">1</property>
<property name="resizable">True</property>
<property name="hide-on-close">True</property>
<property name="default-width">500</property>
<property name="default-height">400</property>
<property name="width-request">360</property>
<property name="height-request">294</property>
<child>
<object class="AdwPreferencesPage">
<child>
@@ -359,8 +348,6 @@
<property name="hide-on-close">True</property>
<property name="default-width">500</property>
<property name="default-height">400</property>
<property name="width-request">360</property>
<property name="height-request">294</property>
<child>
<object class="AdwPreferencesPage">
@@ -420,10 +407,10 @@
<object class="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<property name="description" translatable="yes">How much disk space this app is occupying with app data and caches.</property>
<property name="description" translatable="yes">How much disk space this application is occupying with app data and caches.</property>
<child>
<object class="CcInfoRow" id="app">
<property name="title" translatable="yes">App</property>
<property name="title" translatable="yes">Application</property>
<property name="info">Unknown</property>
</object>
</child>

View File

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

View File

@@ -1,9 +1,15 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input : desktop + '.in.in',
output : desktop + '.in',
configuration : desktop_conf
)
i18n.merge_file(
type : 'desktop',
input : desktop + '.in',
input : desktop_in,
output : desktop,
po_dir : po_dir,
install : true,

View File

@@ -35,32 +35,6 @@ struct _BgWallpapersSource
G_DEFINE_TYPE (BgWallpapersSource, bg_wallpapers_source, BG_TYPE_SOURCE)
static int
sort_func (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
CcBackgroundItem *item_a;
CcBackgroundItem *item_b;
const char *name_a;
const char *name_b;
item_a = (CcBackgroundItem *) a;
item_b = (CcBackgroundItem *) b;
name_a = cc_background_item_get_name (item_a);
name_b = cc_background_item_get_name (item_b);
if (name_a && strcmp (name_a, "Default Background") == 0)
return -1;
if (name_b && strcmp (name_b, "Default Background") == 0)
return 1;
return strcmp (cc_background_item_get_name (item_a),
cc_background_item_get_name (item_b));
}
static void
load_wallpapers (gchar *key,
CcBackgroundItem *item,
@@ -74,7 +48,7 @@ load_wallpapers (gchar *key,
if (deleted)
return;
g_list_store_insert_sorted (store, item, sort_func, NULL);
g_list_store_append (store, item);
}
static void

View File

@@ -157,10 +157,10 @@ create_widget_func (gpointer model_item,
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), check);
if (button)
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
GTK_ACCESSIBLE_PROPERTY_LABEL,
cc_background_item_get_name (item),
-1);
gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
GTK_ACCESSIBLE_PROPERTY_LABEL,
cc_background_item_get_name (item),
-1);
child = gtk_flow_box_child_new ();

View File

@@ -57,14 +57,15 @@ struct _CcBackgroundPanel
GSettings *lock_settings;
GSettings *interface_settings;
GnomeDesktopThumbnailFactory *thumb_factory;
GDBusProxy *proxy;
CcBackgroundItem *current_background;
CcBackgroundChooser *background_chooser;
CcBackgroundPreview *default_preview;
CcBackgroundPreview *light_preview;
CcBackgroundPreview *dark_preview;
GtkToggleButton *default_toggle;
GtkToggleButton *light_toggle;
GtkToggleButton *dark_toggle;
};
@@ -83,7 +84,7 @@ load_custom_css (CcBackgroundPanel *self)
}
static void
reload_color_scheme_toggles (CcBackgroundPanel *self)
reload_light_dark_toggles (CcBackgroundPanel *self)
{
GDesktopColorScheme scheme;
@@ -91,7 +92,7 @@ reload_color_scheme_toggles (CcBackgroundPanel *self)
if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
{
gtk_toggle_button_set_active (self->default_toggle, TRUE);
gtk_toggle_button_set_active (self->light_toggle, TRUE);
}
else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
{
@@ -99,7 +100,7 @@ reload_color_scheme_toggles (CcBackgroundPanel *self)
}
else
{
gtk_toggle_button_set_active (self->default_toggle, FALSE);
gtk_toggle_button_set_active (self->light_toggle, FALSE);
gtk_toggle_button_set_active (self->dark_toggle, FALSE);
}
}
@@ -148,9 +149,9 @@ set_color_scheme (CcBackgroundPanel *self,
/* Color schemes */
static void
on_color_scheme_toggle_active_cb (CcBackgroundPanel *self)
on_light_dark_toggle_active_cb (CcBackgroundPanel *self)
{
if (gtk_toggle_button_get_active (self->default_toggle))
if (gtk_toggle_button_get_active (self->light_toggle))
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT);
else if (gtk_toggle_button_get_active (self->dark_toggle))
set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK);
@@ -181,7 +182,7 @@ update_preview (CcBackgroundPanel *panel)
CcBackgroundItem *current_background;
current_background = panel->current_background;
cc_background_preview_set_item (panel->default_preview, current_background);
cc_background_preview_set_item (panel->light_preview, current_background);
cc_background_preview_set_item (panel->dark_preview, current_background);
}
@@ -268,54 +269,6 @@ create_save_dir (void)
return TRUE;
}
static void
reset_settings_if_defaults (CcBackgroundPanel *panel,
GSettings *settings,
gboolean check_dark)
{
gsize i;
const char *keys[] = {
WP_URI_KEY, /* this key needs to be first */
WP_URI_DARK_KEY,
WP_OPTIONS_KEY,
WP_SHADING_KEY,
WP_PCOLOR_KEY,
WP_SCOLOR_KEY,
NULL
};
for (i = 0; keys[i] != NULL; i++)
{
g_autoptr (GVariant) default_value = NULL;
g_autoptr (GVariant) user_value = NULL;
gboolean setting_is_default;
if (!check_dark && g_str_equal (keys[i], WP_URI_DARK_KEY))
continue;
default_value = g_settings_get_default_value (settings, keys[i]);
user_value = g_settings_get_value (settings, keys[i]);
setting_is_default = g_variant_equal (default_value, user_value);
/* As a courtesy to distros that are a little lackadaisical about making sure
* schema defaults match the settings in the background item with the default
* picture, we only look at the URI to determine if we shouldn't clean out dconf.
*
* In otherwords, we still clean out the picture-uri key from dconf when a user
* selects the default background in control-center, even if after selecting it
* e.g., primary-color still mismatches with schema defaults.
*/
if (g_str_equal (keys[i], WP_URI_KEY) && !setting_is_default)
return;
if (setting_is_default)
g_settings_reset (settings, keys[i]);
}
g_settings_apply (settings);
}
static void
set_background (CcBackgroundPanel *panel,
GSettings *settings,
@@ -368,9 +321,6 @@ set_background (CcBackgroundPanel *panel,
/* Apply all changes */
g_settings_apply (settings);
/* Clean out dconf if the user went back to distro defaults */
reset_settings_if_defaults (panel, settings, set_dark);
/* Save the source XML if there is one */
filename = get_save_path ();
if (create_save_dir ())
@@ -405,6 +355,7 @@ cc_background_panel_dispose (GObject *object)
g_clear_object (&panel->settings);
g_clear_object (&panel->lock_settings);
g_clear_object (&panel->interface_settings);
g_clear_object (&panel->thumb_factory);
g_clear_object (&panel->proxy);
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
@@ -438,12 +389,12 @@ cc_background_panel_class_init (CcBackgroundPanelClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, light_preview);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, light_toggle);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle);
gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb);
gtk_widget_class_bind_template_callback (widget_class, on_light_dark_toggle_active_cb);
gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb);
gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb);
}
@@ -464,6 +415,8 @@ cc_background_panel_init (CcBackgroundPanel *panel)
panel->connection = g_application_get_dbus_connection (g_application_get_default ());
panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
panel->settings = g_settings_new (WP_PATH_ID);
g_settings_delay (panel->settings);
@@ -480,11 +433,11 @@ cc_background_panel_init (CcBackgroundPanel *panel)
g_signal_connect_object (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel, G_CONNECT_SWAPPED);
/* Interface settings */
reload_color_scheme_toggles (panel);
reload_light_dark_toggles (panel);
g_signal_connect_object (panel->interface_settings,
"changed::" INTERFACE_COLOR_SCHEME_KEY,
G_CALLBACK (reload_color_scheme_toggles),
G_CALLBACK (reload_light_dark_toggles),
panel,
G_CONNECT_SWAPPED);

View File

@@ -27,13 +27,13 @@
<property name="margin-bottom">12</property>
<property name="hexpand">True</property>
<child>
<object class="GtkToggleButton" id="default_toggle">
<object class="GtkToggleButton" id="light_toggle">
<accessibility>
<relation name="labelled-by">default_label</relation>
<relation name="labelled-by">light_label</relation>
</accessibility>
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
<signal name="notify::active" handler="on_light_dark_toggle_active_cb" swapped="true"/>
<child>
<object class="CcBackgroundPreview" id="default_preview"/>
<object class="CcBackgroundPreview" id="light_preview"/>
</child>
<style>
<class name="background-preview-button"/>
@@ -45,8 +45,8 @@
</object>
</child>
<child>
<object class="GtkLabel" id="default_label">
<property name="label" translatable="yes">Default</property>
<object class="GtkLabel" id="light_label">
<property name="label" translatable="yes">Light</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
@@ -55,11 +55,11 @@
</child>
<child>
<object class="GtkToggleButton" id="dark_toggle">
<property name="group">default_toggle</property>
<property name="group">light_toggle</property>
<accessibility>
<relation name="labelled-by">dark_label</relation>
</accessibility>
<signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
<signal name="notify::active" handler="on_light_dark_toggle_active_cb" swapped="true"/>
<child>
<object class="CcBackgroundPreview" id="dark_preview">
<property name="is-dark">True</property>

View File

@@ -11,4 +11,4 @@ StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
OnlyShowIn=GNOME;
# Translators: Search terms to find the Appearance panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;Appearance;
Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;

View File

@@ -1,9 +1,15 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input: desktop + '.in.in',
output: desktop + '.in',
configuration: desktop_conf
)
i18n.merge_file(
type: 'desktop',
input: desktop + '.in',
input: desktop_in,
output: desktop,
po_dir: po_dir,
install: true,

View File

@@ -12,6 +12,7 @@ background-preview .window {
background-preview .window .header-bar {
min-height: 15px;
box-shadow: inset 0 -1px @borders;
}
background-preview .window.light {
@@ -19,10 +20,6 @@ background-preview .window.light {
color: alpha(black, .8);
}
background-preview .window.light .header-bar {
box-shadow: inset 0 -1px alpha(black, .07);
}
background-preview .window.front.light .header-bar {
background-color: #ebebeb;
}
@@ -32,10 +29,6 @@ background-preview .window.dark {
color: white;
}
background-preview .window.dark .header-bar {
box-shadow: inset 0 -1px alpha(black, .36);
}
background-preview .window.front.dark .header-bar {
background-color: #303030;
}

View File

@@ -117,8 +117,8 @@ class GccDBusTestCase(DBusTestCase):
adapter.UpdateProperties('org.bluez.Adapter1',
{'Powered': dbus.Boolean(self.hci0_powered, variant_level=1)})
self.devices = []
self.add_device('hci0', '22:33:44:55:66:77', "Bastienʼs mouse", True, 0x580, 'input-mouse')
self.add_device('hci0', '22:33:44:55:66:78', 'Bloutouf keyboard & keys', True, 0x540, 'input-keyboard')
self.add_device('hci0', '22:33:44:55:66:77', "Bastien's mouse", True, 0x580, 'input-mouse')
self.add_device('hci0', '22:33:44:55:66:78', 'Bloutouf keyboard', True, 0x540, 'input-keyboard')
self.add_device('hci0', '60:8B:0E:55:66:79', 'iPhoone 19S', True, 0x20C, 'phone')
# Uncategorised audio device
self.add_device('hci0', '22:33:44:55:66:79', 'MEGA Speakers', True, 0x200400, 'audio-card')

View File

@@ -80,29 +80,25 @@ airplane_mode_changed_cb (GObject *source_object,
{
g_autoptr(GVariant) ret = NULL;
g_autoptr(GError) error = NULL;
gboolean state = GPOINTER_TO_UINT (user_data);
if (!g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
res, &error)) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
CcBluetoothPanel *self = CC_BLUETOOTH_PANEL (user_data);
gboolean state = gtk_switch_get_active (self->enable_switch);
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to change Bluetooth killswitch state to %s: %s",
state ? "on" : "off", error->message);
}
} else {
CcBluetoothPanel *self = CC_BLUETOOTH_PANEL (user_data);
gboolean state = gtk_switch_get_active (self->enable_switch);
CcBluetoothPanel *self = user_data;
g_debug ("Changed Bluetooth killswitch state to %s",
state ? "on" : "off");
gtk_switch_set_state (self->enable_switch, state);
if (!bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget))
bluetooth_settings_widget_set_default_adapter_powered(self->settings_widget, TRUE);
}
}
static gboolean
static void
enable_switch_state_set_cb (CcBluetoothPanel *self, gboolean state)
{
g_debug ("Power switched to %s", state ? "on" : "off");
@@ -114,8 +110,6 @@ enable_switch_state_set_cb (CcBluetoothPanel *self, gboolean state)
-1,
cc_panel_get_cancellable (CC_PANEL (self)),
airplane_mode_changed_cb, self);
return TRUE;
}
static void
@@ -162,7 +156,7 @@ adapter_status_changed_cb (CcBluetoothPanel *self)
gtk_widget_set_valign (GTK_WIDGET (self->stack), valign);
gtk_widget_set_sensitive (GTK_WIDGET (self->header_box), sensitive);
g_signal_handlers_block_by_func (self->enable_switch, enable_switch_state_set_cb, self);
gtk_switch_set_active (self->enable_switch, powered);
gtk_switch_set_state (self->enable_switch, powered);
g_signal_handlers_unblock_by_func (self->enable_switch, enable_switch_state_set_cb, self);
gtk_stack_set_visible_child (self->stack, page);

View File

@@ -29,14 +29,14 @@
<object class="AdwStatusPage" id="disabled_page">
<property name="icon-name">bluetooth-active-symbolic</property>
<property name="title" translatable="yes">Bluetooth Turned Off</property>
<property name="description" translatable="yes">Turn on to connect devices and receive file transfers</property>
<property name="description" translatable="yes">Turn on to connect devices and receive file transfers.</property>
</object>
</child>
<child>
<object class="AdwStatusPage" id="airplane_page">
<property name="icon-name">airplane-mode-symbolic</property>
<property name="title" translatable="yes">Airplane Mode is On</property>
<property name="description" translatable="yes">Bluetooth is disabled when airplane mode is on</property>
<property name="description" translatable="yes">Bluetooth is disabled when airplane mode is on.</property>
<property name="child">
<object class="GtkButton">
<property name="label" translatable="yes">Turn Off Airplane Mode</property>
@@ -45,7 +45,6 @@
<signal name="clicked" handler="airplane_mode_off_button_clicked_cb" object="CcBluetoothPanel" swapped="yes"/>
<style>
<class name="pill"/>
<class name="suggested-action"/>
</style>
</object>
</property>

View File

@@ -10,5 +10,9 @@ NoDisplay=true
Categories=GTK;GNOME;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
OnlyShowIn=GNOME;Unity;
StartupNotify=true
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-bluetooth
X-GNOME-Bugzilla-Component=properties
X-GNOME-Bugzilla-Version=@VERSION@
# Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=share;sharing;bluetooth;obex;

View File

@@ -1,9 +1,15 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input: desktop + '.in.in',
output: desktop + '.in',
configuration: desktop_conf
)
i18n.merge_file(
type: 'desktop',
input: desktop + '.in',
input: desktop_in,
output: desktop,
po_dir: po_dir,
install: true,

View File

@@ -20,7 +20,6 @@
#include "cc-camera-panel.h"
#include "cc-camera-resources.h"
#include "cc-list-row.h"
#include "cc-util.h"
#include <adwaita.h>
@@ -34,8 +33,9 @@ struct _CcCameraPanel
{
CcPanel parent_instance;
GtkStack *stack;
GtkListBox *camera_apps_list_box;
CcListRow *camera_row;
GtkSwitch *main_switch;
GSettings *privacy_settings;
@@ -101,17 +101,14 @@ on_camera_app_state_set (GtkSwitch *widget,
GVariant *params;
const gchar *key;
gchar **value;
gboolean active_camera;
self = data->self;
if (data->changing_state)
return TRUE;
active_camera = !g_settings_get_boolean (self->privacy_settings,
"disable-camera");
data->changing_state = TRUE;
data->pending_state = active_camera && state;
data->pending_state = state;
g_variant_iter_init (&iter, self->camera_apps_perms);
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
@@ -154,25 +151,6 @@ on_camera_app_state_set (GtkSwitch *widget,
return TRUE;
}
static gboolean
update_app_switch_state (GValue *value,
GVariant *variant,
gpointer data)
{
GtkSwitch *w = GTK_SWITCH (data);
gboolean active_camera;
gboolean active_app;
gboolean state;
active_camera = !g_variant_get_boolean (variant);
active_app = gtk_switch_get_active (w);
state = active_camera && active_app;
g_value_set_boolean (value, state);
return TRUE;
}
static void
add_camera_app (CcCameraPanel *self,
const gchar *app_id,
@@ -212,17 +190,11 @@ add_camera_app (CcCameraPanel *self,
gtk_switch_set_active (GTK_SWITCH (w), enabled);
gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
g_settings_bind_with_mapping (self->privacy_settings,
"disable-camera",
w,
"state",
G_SETTINGS_BIND_GET,
update_app_switch_state,
NULL,
g_object_ref (w),
g_object_unref);
g_settings_bind (self->privacy_settings,
"disable-camera",
w,
"sensitive",
G_SETTINGS_BIND_INVERT_BOOLEAN);
g_hash_table_insert (self->camera_app_switches,
g_strdup (app_id),
g_object_ref (w));
@@ -241,6 +213,20 @@ add_camera_app (CcCameraPanel *self,
}
/* Steals permissions and permissions_data references */
static gboolean
to_child_name (GBinding *binding,
const GValue *from,
GValue *to,
gpointer user_data)
{
if (g_value_get_boolean (from))
g_value_set_string (to, "content");
else
g_value_set_string (to, "empty");
return TRUE;
}
static void
update_perm_store (CcCameraPanel *self,
GVariant *permissions,
@@ -386,8 +372,9 @@ cc_camera_panel_class_init (CcCameraPanelClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/camera/cc-camera-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, stack);
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, camera_apps_list_box);
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, camera_row);
gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, main_switch);
}
static void
@@ -402,9 +389,16 @@ cc_camera_panel_init (CcCameraPanel *self)
self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
g_settings_bind (self->privacy_settings, "disable-camera",
self->camera_row, "active",
self->main_switch, "active",
G_SETTINGS_BIND_INVERT_BOOLEAN);
g_object_bind_property_full (self->main_switch, "active",
self->stack, "visible-child-name",
G_BINDING_SYNC_CREATE,
to_child_name,
NULL,
NULL, NULL);
self->camera_app_switches = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,

View File

@@ -2,50 +2,73 @@
<interface>
<template class="CcCameraPanel" parent="CcPanel">
<child type="titlebar-end">
<object class="GtkSwitch" id="main_switch">
<accessibility>
<property name="label" translatable="yes">Enable</property>
</accessibility>
<property name="valign">center</property>
</object>
</child>
<child type="content">
<object class="AdwPreferencesPage">
<object class="GtkStack" id="stack">
<!-- Empty page -->
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="CcListRow" id="camera_row">
<property name="title" translatable="yes">_Camera Access</property>
<property name="subtitle" translatable="yes">Allow permitted apps to use cameras</property>
<property name="use-underline">True</property>
<property name="show-switch">True</property>
<object class="GtkStackPage">
<property name="name">empty</property>
<property name="child">
<object class="AdwStatusPage">
<property name="icon-name">camera-disabled-symbolic</property>
<property name="title" translatable="yes">Camera is Turned Off</property>
<property name="description" translatable="yes">No applications can capture photos or video.</property>
</object>
</child>
</property>
</object>
</child>
<!-- Cameras -->
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="yes">Permitted Apps</property>
<property name="description" translatable="yes">The following sandboxed apps have been given permission to use cameras. Apps that are not sandboxed can use cameras without asking for permission.</property>
<child>
<object class="GtkListBox" id="camera_apps_list_box">
<property name="selection-mode">none</property>
<style>
<class name="boxed-list"/>
</style>
<object class="GtkStackPage">
<property name="name">content</property>
<property name="child">
<object class="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<property name="description" translatable="yes">Use of the camera allows applications to capture photos and video. Disabling the camera may cause some applications to not function properly.
<child type="placeholder">
<object class="GtkLabel">
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="label" translatable="yes">No sandboxed apps have asked for camera access</property>
<property name="wrap">true</property>
<property name="max-width-chars">50</property>
<style>
<class name="dim-label" />
</style>
Allow the applications below to use your camera.</property>
<child>
<object class="GtkListBox" id="camera_apps_list_box">
<property name="selection-mode">none</property>
<style>
<class name="boxed-list"/>
</style>
<child type="placeholder">
<object class="GtkLabel">
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="label" translatable="yes">No Applications Have Asked for Camera Access</property>
<property name="wrap">true</property>
<property name="max-width-chars">50</property>
<style>
<class name="dim-label" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</property>
</object>
</child>
</object>
</child>
</template>

View File

@@ -1,6 +1,6 @@
[Desktop Entry]
Name=Cameras
Comment=Restrict camera access
Name=Camera
Comment=Protect your pictures
Exec=gnome-control-center camera
# FIXME
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
@@ -11,5 +11,9 @@ NoDisplay=true
StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
OnlyShowIn=GNOME;Unity;
# Translators: Search terms to find the Cameras panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=camera;photos;video;webcam;lock;private;privacy;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-control-center
X-GNOME-Bugzilla-Component=privacy
X-GNOME-Bugzilla-Version=@VERSION@
# Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;identity;

View File

@@ -1,9 +1,15 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input: desktop + '.in.in',
output: desktop + '.in',
configuration: desktop_conf
)
i18n.merge_file(
type: 'desktop',
input: desktop + '.in',
input: desktop_in,
output: desktop,
po_dir: po_dir,
install: true,

View File

@@ -603,6 +603,96 @@ cc_color_calibrate_cancel (CcColorCalibrate *calibrate)
g_main_loop_quit (calibrate->loop);
}
static gboolean
cc_color_calibrate_move_and_resize_window (GtkWindow *window,
CdDevice *device,
GError **error)
{
g_autoptr(GListModel) monitors = NULL;
g_autoptr(GdkMonitor) monitor = NULL;
const gchar *xrandr_name;
gboolean ret = TRUE;
GdkRectangle rect;
GdkDisplay *display;
gint i;
gint monitor_num = -1;
gint num_monitors;
/* find the monitor num of the device output */
display = gdk_display_get_default ();
monitors = gdk_display_get_monitors (display);
num_monitors = g_list_model_get_n_items (monitors);
xrandr_name = cd_device_get_metadata_item (device, CD_DEVICE_METADATA_XRANDR_NAME);
for (i = 0; i < num_monitors; i++)
{
g_autoptr(GdkMonitor) m = NULL;
const gchar *plug_name;
m = g_list_model_get_item (monitors, i);
plug_name = gdk_monitor_get_model (m);
if (g_strcmp0 (plug_name, xrandr_name) == 0)
monitor_num = i;
}
if (monitor_num == -1)
{
ret = FALSE;
g_set_error (error,
CD_SESSION_ERROR,
CD_SESSION_ERROR_INTERNAL,
"failed to find output %s",
xrandr_name);
goto out;
}
/* move the window, and set it to the right size */
monitor = g_list_model_get_item (monitors, monitor_num);
gdk_monitor_get_geometry (monitor, &rect);
g_debug ("Setting window to %ix%i with size %ix%i",
rect.x, rect.y, rect.width, rect.height);
out:
return ret;
}
#if 0
static void
cc_color_calibrate_window_realize_cb (CcColorCalibrate *self)
{
GtkWidget *widget;
widget = GTK_WIDGET (gtk_builder_get_object (self->builder,
"dialog_calibrate"));
gtk_window_fullscreen (GTK_WINDOW (widget));
gtk_window_maximize (GTK_WINDOW (widget));
}
static gboolean
cc_color_calibrate_window_state_cb (CcColorCalibrate *calibrate,
GdkEvent *event)
{
gboolean ret;
g_autoptr(GError) error = NULL;
GdkEventWindowState *event_state = (GdkEventWindowState *) event;
GtkWindow *window;
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
"dialog_calibrate"));
/* check event */
if (event->type != GDK_WINDOW_STATE)
return TRUE;
if (event_state->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)
return TRUE;
/* resize to the correct screen */
ret = cc_color_calibrate_move_and_resize_window (window,
calibrate->device,
&error);
if (!ret)
g_warning ("Failed to resize window: %s", error->message);
return TRUE;
}
#endif
static void
cc_color_calibrate_button_done_cb (CcColorCalibrate *calibrate)
{
@@ -899,6 +989,14 @@ cc_color_calibrate_start (CcColorCalibrate *calibrate,
return TRUE;
}
static gboolean
cc_color_calibrate_delete_event_cb (CcColorCalibrate *calibrate)
{
/* do not destroy the window */
cc_color_calibrate_cancel (calibrate);
return TRUE;
}
static void
cc_color_calibrate_finalize (GObject *object)
{
@@ -981,6 +1079,19 @@ cc_color_calibrate_init (CcColorCalibrate *calibrate)
/* setup the specialist calibration window */
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
"dialog_calibrate"));
/*
g_signal_connect_object (window, "draw",
G_CALLBACK (cc_color_calibrate_alpha_window_draw), calibrate, G_CONNECT_SWAPPED);
g_signal_connect_object (window, "realize",
G_CALLBACK (cc_color_calibrate_window_realize_cb), calibrate, G_CONNECT_SWAPPED);
g_signal_connect_object (window, "window-state-event",
G_CALLBACK (cc_color_calibrate_window_state_cb), calibrate, G_CONNECT_SWAPPED);
g_signal_connect_object (window, "delete-event",
G_CALLBACK (cc_color_calibrate_delete_event_cb), calibrate, G_CONNECT_SWAPPED);
cc_color_calibrate_alpha_screen_changed_cb (calibrate);
g_signal_connect_object (window, "screen-changed",
G_CALLBACK (cc_color_calibrate_alpha_screen_changed_cb), calibrate, G_CONNECT_SWAPPED);
*/
calibrate->window = window;
}

View File

@@ -253,6 +253,7 @@ cc_color_device_clicked_expander_cb (CcColorDevice *color_device)
static void
cc_color_device_init (CcColorDevice *color_device)
{
GtkStyleContext *context;
GtkWidget *box;
/* description */
@@ -289,7 +290,8 @@ cc_color_device_init (CcColorDevice *color_device)
/* not calibrated */
color_device->widget_nocalib = gtk_label_new (_("Not calibrated"));
gtk_widget_add_css_class (color_device->widget_nocalib, "dim-label");
context = gtk_widget_get_style_context (color_device->widget_nocalib);
gtk_style_context_add_class (context, "dim-label");
gtk_widget_set_margin_end (color_device->widget_nocalib, 18);
gtk_box_append (GTK_BOX (box), color_device->widget_nocalib);

View File

@@ -1705,8 +1705,7 @@ static void
gcm_prefs_list_box_row_selected_cb (CcColorPanel *panel,
GtkListBoxRow *row)
{
if (!panel->toolbar_devices ||
gtk_widget_in_destruction (panel->toolbar_devices))
if (gtk_widget_in_destruction (panel->toolbar_devices))
return;
gcm_prefs_refresh_toolbar_buttons (panel);

View File

@@ -10,6 +10,10 @@ NoDisplay=true
StartupNotify=true
Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;HardwareSettings;X-GNOME-DevicesSettings;
OnlyShowIn=GNOME;Unity;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-control-center
X-GNOME-Bugzilla-Component=color
X-GNOME-Bugzilla-Version=@VERSION@
# Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=Color;ICC;Profile;Calibrate;Printer;Display;
# Notifications are emitted by gnome-settings-daemon

View File

@@ -1,9 +1,15 @@
panels_list += cappletname
desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
desktop_in = configure_file(
input: desktop + '.in.in',
output: desktop + '.in',
configuration: desktop_conf
)
i18n.merge_file(
type: 'desktop',
input: desktop + '.in',
input: desktop_in,
output: desktop,
po_dir: po_dir,
install: true,

View File

@@ -27,13 +27,13 @@
struct _CcHostnameEntry
{
AdwEntryRow parent;
GtkEntry parent;
GDBusProxy *hostnamed_proxy;
guint set_hostname_timeout_source_id;
};
G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, ADW_TYPE_ENTRY_ROW)
G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, GTK_TYPE_ENTRY)
#define SET_HOSTNAME_TIMEOUT 1
@@ -234,9 +234,7 @@ cc_hostname_entry_constructed (GObject *object)
else
gtk_editable_set_text (GTK_EDITABLE (self), "");
g_signal_connect (self, "apply", G_CALLBACK (text_changed_cb), NULL);
adw_entry_row_set_show_apply_button (ADW_ENTRY_ROW (self), TRUE);
g_signal_connect (self, "changed", G_CALLBACK (text_changed_cb), NULL);
}
static void

View File

@@ -19,13 +19,13 @@
#pragma once
#include <adwaita.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_HOSTNAME_ENTRY (cc_hostname_entry_get_type())
G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, AdwEntryRow)
G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, GtkEntry)
CcHostnameEntry *cc_hostname_entry_new (void);
gchar* cc_hostname_entry_get_hostname (CcHostnameEntry *entry);

View File

@@ -1,153 +0,0 @@
/* cc-illustrated-row.c
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 "cc-illustrated-row.h"
struct _CcIllustratedRow
{
CcVerticalRow parent;
GtkBox *picture_box;
GtkPicture *picture;
const gchar *resource_path;
GtkMediaStream *media_stream;
};
G_DEFINE_FINAL_TYPE (CcIllustratedRow, cc_illustrated_row, CC_TYPE_VERTICAL_ROW);
enum
{
PROP_0,
PROP_RESOURCE,
N_PROPS,
};
static GParamSpec *props[N_PROPS] = { NULL, };
static void
on_picture_leave_cb (CcIllustratedRow *self)
{
GtkMediaStream *stream = GTK_MEDIA_STREAM (gtk_picture_get_paintable (self->picture));
gtk_media_stream_set_loop (stream, FALSE);
gtk_media_stream_pause (stream);
}
static void
on_picture_hover_cb (CcIllustratedRow *self)
{
GtkMediaStream *stream = GTK_MEDIA_STREAM (gtk_picture_get_paintable (self->picture));
gtk_media_stream_set_loop (stream, TRUE);
gtk_media_stream_play (stream);
}
static void
cc_illustrated_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcIllustratedRow *self = CC_ILLUSTRATED_ROW (object);
switch (prop_id)
{
case PROP_RESOURCE:
g_value_set_string (value, self->resource_path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_illustrated_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcIllustratedRow *self = CC_ILLUSTRATED_ROW (object);
switch (prop_id)
{
case PROP_RESOURCE:
cc_illustrated_row_set_resource (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_illustrated_row_class_init (CcIllustratedRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_illustrated_row_get_property;
object_class->set_property = cc_illustrated_row_set_property;
props[PROP_RESOURCE] =
g_param_spec_string ("resource",
"Resource",
"Resource",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, N_PROPS, props);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-illustrated-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcIllustratedRow, picture);
gtk_widget_class_bind_template_child (widget_class, CcIllustratedRow, picture_box);
gtk_widget_class_bind_template_callback (widget_class, on_picture_hover_cb);
gtk_widget_class_bind_template_callback (widget_class, on_picture_leave_cb);
}
static void
cc_illustrated_row_init (CcIllustratedRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_widget_set_name (GTK_WIDGET (self), "illustrated-row");
gtk_widget_add_css_class (GTK_WIDGET (self), "illustrated-row");
}
void
cc_illustrated_row_set_resource (CcIllustratedRow *self,
const gchar *resource_path)
{
g_return_if_fail (CC_IS_ILLUSTRATED_ROW (self));
if (self->media_stream != NULL)
g_clear_object (&self->media_stream);
self->resource_path = resource_path;
self->media_stream = gtk_media_file_new_for_resource (resource_path);
gtk_picture_set_paintable (self->picture, GDK_PAINTABLE (self->media_stream));
gtk_widget_set_visible (GTK_WIDGET (self->picture_box),
resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESOURCE]);
}

View File

@@ -1,45 +0,0 @@
/* cc-illustrated-row.h
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 <adwaita.h>
#include "cc-vertical-row.h"
G_BEGIN_DECLS
#define CC_TYPE_ILLUSTRATED_ROW (cc_illustrated_row_get_type())
G_DECLARE_FINAL_TYPE (CcIllustratedRow, cc_illustrated_row, CC, ILLUSTRATED_ROW, CcVerticalRow)
struct _CcIllustratedRowClass
{
CcVerticalRowClass parent_class;
/*< private >*/
gpointer padding[4];
};
void cc_illustrated_row_set_resource (CcIllustratedRow *self,
const gchar *resource_path);
G_END_DECLS

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcIllustratedRow" parent="CcVerticalRow">
<child>
<object class="GtkEventControllerMotion">
<signal name="enter" handler="on_picture_hover_cb" object="CcIllustratedRow" swapped="yes"/>
<signal name="leave" handler="on_picture_leave_cb" object="CcIllustratedRow" swapped="yes"/>
</object>
</child>
<child type="content">
<object class="GtkBox" id="picture_box">
<property name="visible">False</property>
<property name="hexpand">True</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<style>
<class name="frame" />
<class name="background" />
</style>
<child>
<object class="GtkPicture" id="picture">
<property name="hexpand">True</property>
<property name="halign">center</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="height-request">128</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -61,14 +61,6 @@ enum {
static GParamSpec *properties[N_PROPS];
static void
update_checked_state (CcListRow *self)
{
gtk_accessible_update_state (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_STATE_CHECKED, self->switch_active,
-1);
}
static void
cc_list_row_switch_active_cb (CcListRow *self)
{
@@ -83,7 +75,6 @@ cc_list_row_switch_active_cb (CcListRow *self)
return;
self->switch_active = switch_active;
update_checked_state (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVE]);
}
@@ -142,7 +133,6 @@ cc_list_row_set_property (GObject *object,
gtk_switch_set_active (self->enable_switch,
g_value_get_boolean (value));
self->switch_active = g_value_get_boolean (value);
update_checked_state (self);
g_signal_handlers_unblock_by_func (self->enable_switch,
cc_list_row_switch_active_cb, self);
break;
@@ -238,8 +228,6 @@ cc_list_row_set_show_switch (CcListRow *self,
adw_action_row_set_activatable_widget (ADW_ACTION_ROW (self),
self->show_switch ? GTK_WIDGET (self->enable_switch) : NULL);
update_checked_state (self);
}
gboolean

View File

@@ -20,7 +20,6 @@
<object class="GtkSwitch" id="enable_switch">
<property name="visible">False</property>
<property name="valign">center</property>
<property name="can-focus">false</property>
<signal name="notify::active" handler="cc_list_row_switch_active_cb" swapped="yes"/>
</object>
</child>

View File

@@ -27,7 +27,6 @@
<child>
<object class="GtkLabel" id="title">
<property name="halign">start</property>
<property name="wrap">True</property>
<!-- Actual string set in code -->
<property name="label"></property>
<attributes>
@@ -38,7 +37,6 @@
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="wrap">True</property>
<property name="label" translatable="yes">Some settings must be unlocked before they can be changed.</property>
</object>
</child>
@@ -57,7 +55,6 @@
<object class="GtkLockButton" id="lock_button">
<property name="receives-default">True</property>
<property name="label" translatable="yes">Unlock…</property>
<property name="valign">GTK_ALIGN_CENTER</property>
</object>
</child>
</object>

View File

@@ -1,413 +0,0 @@
/* cc-split-row.c
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 "cc-split-row.h"
struct _CcSplitRow
{
CcVerticalRow parent;
GtkPicture *default_option_picture;
GtkPicture *alternative_option_picture;
GtkCheckButton *alternative_option_checkbutton;
GtkCheckButton *default_option_checkbutton;
const gchar *alternative_resource_path;
const gchar *default_resource_path;
gchar *alternative_option_title;
gchar *alternative_option_subtitle;
gchar *default_option_title;
gchar *default_option_subtitle;
gboolean use_default;
};
G_DEFINE_FINAL_TYPE (CcSplitRow, cc_split_row, CC_TYPE_VERTICAL_ROW);
enum
{
PROP_0,
PROP_USE_DEFAULT,
PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE,
PROP_ALTERNATIVE_OPTION_TITLE,
PROP_ALTERNATIVE_OPTION_SUBTITLE,
PROP_DEFAULT_ILLUSTRATION_RESOURCE,
PROP_DEFAULT_OPTION_TITLE,
PROP_DEFAULT_OPTION_SUBTITLE,
N_PROPS,
};
static GParamSpec *props[N_PROPS] = { NULL, };
static void
on_option_click_released_cb (GtkGestureClick *self,
gint n_press,
gdouble x,
gdouble y,
GtkCheckButton *check_button)
{
gtk_widget_activate (GTK_WIDGET (check_button));
}
static void
on_option_focus_leave_cb (GtkEventControllerMotion *controller,
GtkPicture *picture)
{
GtkMediaStream *stream;
GdkPaintable *paintable;
paintable = gtk_picture_get_paintable (GTK_PICTURE (picture));
if (!GTK_IS_MEDIA_STREAM (paintable))
return;
stream = GTK_MEDIA_STREAM (paintable);
gtk_media_stream_set_loop (stream, FALSE);
gtk_media_stream_pause (stream);
}
static void
on_option_focus_enter_cb (GtkEventControllerMotion *controller,
gdouble x,
gdouble y,
GtkPicture *picture)
{
GtkMediaStream *stream;
GdkPaintable *paintable;
paintable = gtk_picture_get_paintable (GTK_PICTURE (picture));
if (!GTK_IS_MEDIA_STREAM (paintable))
return;
stream = GTK_MEDIA_STREAM (paintable);
gtk_media_stream_set_loop (stream, TRUE);
gtk_media_stream_play (stream);
}
static void
on_checkbutton_toggled_cb (CcSplitRow *self)
{
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
}
static void
cc_split_row_dispose (GObject *object)
{
CcSplitRow *self = CC_SPLIT_ROW (object);
g_clear_pointer (&self->alternative_option_title, g_free);
g_clear_pointer (&self->alternative_option_subtitle, g_free);
g_clear_pointer (&self->default_option_title, g_free);
g_clear_pointer (&self->default_option_subtitle, g_free);
G_OBJECT_CLASS (cc_split_row_parent_class)->dispose (object);
}
static void
cc_split_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcSplitRow *self = CC_SPLIT_ROW (object);
switch (prop_id)
{
case PROP_USE_DEFAULT:
g_value_set_boolean (value, gtk_check_button_get_active (self->default_option_checkbutton));
break;
case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
g_value_set_string (value, cc_split_row_get_alternative_illustration_resource (self));
break;
case PROP_ALTERNATIVE_OPTION_TITLE:
g_value_set_string (value, cc_split_row_get_alternative_option_title (self));
break;
case PROP_ALTERNATIVE_OPTION_SUBTITLE:
g_value_set_string (value, cc_split_row_get_alternative_option_subtitle (self));
break;
case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
g_value_set_string (value, cc_split_row_get_default_illustration_resource (self));
break;
case PROP_DEFAULT_OPTION_TITLE:
g_value_set_string (value, cc_split_row_get_default_option_title (self));
break;
case PROP_DEFAULT_OPTION_SUBTITLE:
g_value_set_string (value, cc_split_row_get_default_option_subtitle (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_split_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcSplitRow *self = CC_SPLIT_ROW (object);
switch (prop_id)
{
case PROP_USE_DEFAULT:
cc_split_row_set_use_default (self, g_value_get_boolean (value));
break;
case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
cc_split_row_set_alternative_illustration_resource (self, g_value_get_string (value));
break;
case PROP_ALTERNATIVE_OPTION_TITLE:
cc_split_row_set_alternative_option_title (self, g_value_get_string (value));
break;
case PROP_ALTERNATIVE_OPTION_SUBTITLE:
cc_split_row_set_alternative_option_subtitle (self, g_value_get_string (value));
break;
case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
cc_split_row_set_default_illustration_resource (self, g_value_get_string (value));
break;
case PROP_DEFAULT_OPTION_TITLE:
cc_split_row_set_default_option_title (self, g_value_get_string (value));
break;
case PROP_DEFAULT_OPTION_SUBTITLE:
cc_split_row_set_default_option_subtitle (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_split_row_class_init (CcSplitRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = cc_split_row_dispose;
object_class->get_property = cc_split_row_get_property;
object_class->set_property = cc_split_row_set_property;
props[PROP_USE_DEFAULT] =
g_param_spec_boolean ("use-default",
"Use Default",
"Use Default",
TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE] =
g_param_spec_string ("alternative-illustration-resource",
"Alternative illustration resource",
"Alternative illustration resource",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_ALTERNATIVE_OPTION_TITLE] =
g_param_spec_string ("alternative-option-title",
"Alternative option title",
"Alternative option title",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_ALTERNATIVE_OPTION_SUBTITLE] =
g_param_spec_string ("alternative-option-subtitle",
"Alternative option subtitle",
"Alternative option subtitle",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_DEFAULT_ILLUSTRATION_RESOURCE] =
g_param_spec_string ("default-illustration-resource",
"Default illustration resource",
"Default illustration resource",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_DEFAULT_OPTION_TITLE] =
g_param_spec_string ("default-option-title",
"Default option title",
"Default option title",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_DEFAULT_OPTION_SUBTITLE] =
g_param_spec_string ("default-option-subtitle",
"Default option subtitle",
"Default option subtitle",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, N_PROPS, props);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-split-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_checkbutton);
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_picture);
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_checkbutton);
gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_picture);
gtk_widget_class_bind_template_callback (widget_class, on_checkbutton_toggled_cb);
gtk_widget_class_bind_template_callback (widget_class, on_option_click_released_cb);
gtk_widget_class_bind_template_callback (widget_class, on_option_focus_enter_cb);
gtk_widget_class_bind_template_callback (widget_class, on_option_focus_leave_cb);
}
static void
cc_split_row_init (CcSplitRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_widget_set_name (GTK_WIDGET (self), "split-row");
gtk_widget_add_css_class (GTK_WIDGET (self), "split-row");
}
const gchar *
cc_split_row_get_default_illustration_resource (CcSplitRow *self)
{
return self->default_resource_path;
}
void
cc_split_row_set_default_illustration_resource (CcSplitRow *self,
const gchar *resource_path)
{
g_autoptr(GtkMediaStream) media_file = NULL;
g_return_if_fail (CC_IS_SPLIT_ROW (self));
self->default_resource_path = resource_path;
media_file = gtk_media_file_new_for_resource (resource_path);
gtk_picture_set_paintable (self->default_option_picture, GDK_PAINTABLE (media_file));
gtk_widget_set_visible (GTK_WIDGET (self->default_option_picture),
resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_ILLUSTRATION_RESOURCE]);
}
const gchar *
cc_split_row_get_alternative_illustration_resource (CcSplitRow *self)
{
return self->alternative_resource_path;
}
void
cc_split_row_set_alternative_illustration_resource (CcSplitRow *self,
const gchar *resource_path)
{
g_autoptr(GtkMediaStream) media_file = NULL;
g_return_if_fail (CC_IS_SPLIT_ROW (self));
self->alternative_resource_path = resource_path;
media_file = gtk_media_file_new_for_resource (resource_path);
gtk_media_stream_set_loop (media_file, TRUE);
gtk_picture_set_paintable (self->alternative_option_picture, GDK_PAINTABLE (media_file));
gtk_widget_set_visible (GTK_WIDGET (self->alternative_option_picture),
resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE]);
}
void
cc_split_row_set_use_default (CcSplitRow *self,
gboolean use_default)
{
g_return_if_fail (CC_IS_SPLIT_ROW (self));
gtk_check_button_set_active (use_default ? self->default_option_checkbutton : self->alternative_option_checkbutton, TRUE);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
}
gboolean
cc_split_row_get_use_default (CcSplitRow *self)
{
return gtk_check_button_get_active (self->default_option_checkbutton);
}
const gchar *
cc_split_row_get_default_option_title (CcSplitRow *self)
{
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
return self->default_option_title;
}
void
cc_split_row_set_default_option_title (CcSplitRow *self,
const gchar *title)
{
g_return_if_fail (CC_IS_SPLIT_ROW (self));
if (g_set_str (&self->default_option_title, title))
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_TITLE]);
}
const gchar *
cc_split_row_get_default_option_subtitle (CcSplitRow *self)
{
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
return self->default_option_subtitle;
}
void
cc_split_row_set_default_option_subtitle (CcSplitRow *self,
const gchar *subtitle)
{
g_return_if_fail (CC_IS_SPLIT_ROW (self));
if (g_set_str (&self->default_option_subtitle, subtitle))
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_SUBTITLE]);
}
const gchar *
cc_split_row_get_alternative_option_title (CcSplitRow *self)
{
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
return self->alternative_option_title;
}
void
cc_split_row_set_alternative_option_title (CcSplitRow *self,
const gchar *title)
{
g_return_if_fail (CC_IS_SPLIT_ROW (self));
if (g_set_str (&self->alternative_option_title, title))
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_TITLE]);
}
const gchar *
cc_split_row_get_alternative_option_subtitle (CcSplitRow *self)
{
g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
return self->alternative_option_subtitle;
}
void
cc_split_row_set_alternative_option_subtitle (CcSplitRow *self,
const gchar *subtitle)
{
g_return_if_fail (CC_IS_SPLIT_ROW (self));
if (g_set_str (&self->alternative_option_subtitle, subtitle))
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_SUBTITLE]);
}

View File

@@ -1,74 +0,0 @@
/* cc-vertical-row.h
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 <adwaita.h>
#include "cc-vertical-row.h"
G_BEGIN_DECLS
#define CC_TYPE_SPLIT_ROW (cc_split_row_get_type())
G_DECLARE_FINAL_TYPE (CcSplitRow, cc_split_row, CC, SPLIT_ROW, CcVerticalRow)
struct _CcSplitRowClass
{
CcVerticalRowClass parent_class;
/*< private >*/
gpointer padding[4];
};
void cc_split_row_set_default_illustration_resource (CcSplitRow *self,
const gchar *resource_path);
const gchar *cc_split_row_get_default_illustration_resource (CcSplitRow *self);
void cc_split_row_set_alternative_illustration_resource (CcSplitRow *self,
const gchar *resource_path);
const gchar *cc_split_row_get_alternative_illustration_resource (CcSplitRow *self);
void cc_split_row_set_use_default (CcSplitRow *self,
gboolean use_default);
gboolean cc_split_row_get_use_default (CcSplitRow *self);
const gchar *cc_split_row_get_default_option_title (CcSplitRow *self);
void cc_split_row_set_default_option_title (CcSplitRow *self,
const gchar *title);
const gchar *cc_split_row_get_default_option_subtitle (CcSplitRow *self);
void cc_split_row_set_default_option_subtitle (CcSplitRow *self,
const gchar *subtitle);
const gchar *cc_split_row_get_alternative_option_title (CcSplitRow *self);
void cc_split_row_set_alternative_option_title (CcSplitRow *self,
const gchar *title);
const gchar *cc_split_row_get_alternative_option_subtitle (CcSplitRow *self);
void cc_split_row_set_alternative_option_subtitle (CcSplitRow *self,
const gchar *subtitle);
G_END_DECLS

View File

@@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcSplitRow" parent="CcVerticalRow">
<child type="content">
<object class="GtkBox">
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="spacing">24</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<!-- Default Option -->
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEventControllerMotion">
<signal name="enter" handler="on_option_focus_enter_cb" object="default_option_picture" swapped="no" />
<signal name="leave" handler="on_option_focus_leave_cb" object="default_option_picture" swapped="no" />
</object>
</child>
<child>
<object class="GtkGestureClick">
<signal name="released" handler="on_option_click_released_cb" object="default_option_checkbutton" swapped="no" />
</object>
</child>
<child>
<object class="AdwBin">
<style>
<class name="background"/>
<class name="frame"/>
</style>
<child>
<object class="GtkPicture" id="default_option_picture">
<property name="hexpand">True</property>
<property name="halign">center</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="height-request">128</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkCheckButton" id="default_option_checkbutton">
<property name="margin-start">6</property>
<property name="group">alternative_option_checkbutton</property>
<signal name="toggled" handler="on_checkbutton_toggled_cb" object="CcSplitRow" swapped="yes"/>
<property name="child">
<object class="GtkBox">
<property name="valign">center</property>
<property name="margin-start">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="xalign">0.0</property>
<binding name="label">
<lookup name="default-option-title">CcSplitRow</lookup>
</binding>
<style>
<class name="title" />
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="xalign">0.0</property>
<binding name="label">
<lookup name="default-option-subtitle">CcSplitRow</lookup>
</binding>
<style>
<class name="subtitle" />
</style>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<!-- Alternative Option -->
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEventControllerMotion">
<signal name="enter" handler="on_option_focus_enter_cb" object="alternative_option_picture" swapped="no" />
<signal name="leave" handler="on_option_focus_leave_cb" object="alternative_option_picture" swapped="no" />
</object>
</child>
<child>
<object class="GtkGestureClick">
<signal name="released" handler="on_option_click_released_cb" object="alternative_option_checkbutton" swapped="no" />
</object>
</child>
<child>
<object class="AdwBin">
<style>
<class name="background"/>
<class name="frame"/>
</style>
<child>
<object class="GtkPicture" id="alternative_option_picture">
<property name="hexpand">True</property>
<property name="halign">center</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="height-request">128</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkCheckButton" id="alternative_option_checkbutton">
<property name="margin-start">6</property>
<signal name="toggled" handler="on_checkbutton_toggled_cb" object="CcSplitRow" swapped="yes"/>
<property name="child">
<object class="GtkBox">
<property name="valign">center</property>
<property name="margin-start">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="xalign">0.0</property>
<binding name="label">
<lookup name="alternative-option-title">CcSplitRow</lookup>
</binding>
<style>
<class name="title" />
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="xalign">0.0</property>
<binding name="label">
<lookup name="alternative-option-subtitle">CcSplitRow</lookup>
</binding>
<style>
<class name="subtitle" />
</style>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -108,7 +108,6 @@ time_editor_time_changed_cb (CcTimeEditor *self)
{
g_assert (CC_IS_TIME_EDITOR (self));
time_editor_clock_changed_cb (self);
g_signal_emit (self, signals[TIME_CHANGED], 0);
}

View File

@@ -568,8 +568,6 @@ cc_time_entry_set_time (CcTimeEntry *self,
self->minute = CLAMP (minute, 0, 59);
cc_time_entry_set_am_pm (self, is_am_pm);
g_signal_emit (self, signals[TIME_CHANGED], 0);
time_entry_fill_time (self);
}

View File

@@ -145,23 +145,6 @@ cc_util_get_smart_date (GDateTime *date)
}
}
char *
cc_util_get_smart_date_time (GDateTime *date)
{
g_autofree gchar *date_str = NULL;
g_autofree gchar *smart_date = NULL;
if (date == NULL)
return NULL;
smart_date = cc_util_get_smart_date (date);
date_str = g_date_time_format (date, "\%X");
/* TRANSLATORS: This is the datetime format in the style of
"Aug 1, 10:10:10 PM", "Feb 24, 2013, 10:10:10 PM", "Today, 10:10:10 AM",
and "Yesterday, 10:10:10 AM" */
return g_strdup_printf (_("%1$s, %2$s"), smart_date, date_str);
}
/* Copied from src/plugins/properties/bacon-video-widget-properties.c
* in totem */
char *

View File

@@ -24,5 +24,4 @@
char * cc_util_normalize_casefold_and_unaccent (const char *str);
char * cc_util_get_smart_date (GDateTime *date);
char * cc_util_get_smart_date_time (GDateTime *date);
char * cc_util_time_to_string_text (gint64 msecs);

View File

@@ -1,606 +0,0 @@
/* cc-vertical-row.c
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 "cc-vertical-row.h"
typedef struct
{
AdwPreferencesRow parent;
GtkBox *content_box;
GtkBox *header;
GtkImage *image;
GtkBox *prefixes;
GtkLabel *subtitle;
GtkBox *suffixes;
GtkLabel *title;
GtkBox *title_box;
GtkWidget *previous_parent;
gboolean use_underline;
gint title_lines;
gint subtitle_lines;
GtkWidget *activatable_widget;
} CcVerticalRowPrivate;
static GtkBuildableIface *parent_buildable_iface;
static void cc_vertical_row_buildable_init (GtkBuildableIface *iface);
G_DEFINE_TYPE_WITH_CODE (CcVerticalRow, cc_vertical_row, ADW_TYPE_PREFERENCES_ROW,
G_ADD_PRIVATE (CcVerticalRow) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_vertical_row_buildable_init))
enum
{
PROP_0,
PROP_ICON_NAME,
PROP_ACTIVATABLE_WIDGET,
PROP_SUBTITLE,
PROP_USE_UNDERLINE,
PROP_TITLE_LINES,
PROP_SUBTITLE_LINES,
N_PROPS,
};
enum
{
SIGNAL_ACTIVATED,
SIGNAL_LAST_SIGNAL,
};
static GParamSpec *props[N_PROPS] = { NULL, };
static guint signals[SIGNAL_LAST_SIGNAL] = { 0, };
static void
row_activated_cb (CcVerticalRow *self,
GtkListBoxRow *row)
{
/* No need to use GTK_LIST_BOX_ROW() for a pointer comparison. */
if ((GtkListBoxRow *) self == row)
cc_vertical_row_activate (self);
}
static void
parent_cb (CcVerticalRow *self)
{
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self));
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
if (priv->previous_parent != NULL)
{
g_signal_handlers_disconnect_by_func (priv->previous_parent,
G_CALLBACK (row_activated_cb),
self);
priv->previous_parent = NULL;
}
if (parent == NULL || !GTK_IS_LIST_BOX (parent))
return;
priv->previous_parent = parent;
g_signal_connect_swapped (parent, "row-activated", G_CALLBACK (row_activated_cb), self);
}
static void
update_subtitle_visibility (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
gtk_widget_set_visible (GTK_WIDGET (priv->subtitle),
gtk_label_get_text (priv->subtitle) != NULL &&
g_strcmp0 (gtk_label_get_text (priv->subtitle), "") != 0);
}
static void
cc_vertical_row_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcVerticalRow *self = CC_VERTICAL_ROW (object);
switch (prop_id)
{
case PROP_ICON_NAME:
g_value_set_string (value, cc_vertical_row_get_icon_name (self));
break;
case PROP_ACTIVATABLE_WIDGET:
g_value_set_object (value, (GObject *) cc_vertical_row_get_activatable_widget (self));
break;
case PROP_SUBTITLE:
g_value_set_string (value, cc_vertical_row_get_subtitle (self));
break;
case PROP_SUBTITLE_LINES:
g_value_set_int (value, cc_vertical_row_get_subtitle_lines (self));
break;
case PROP_TITLE_LINES:
g_value_set_int (value, cc_vertical_row_get_title_lines (self));
break;
case PROP_USE_UNDERLINE:
g_value_set_boolean (value, cc_vertical_row_get_use_underline (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_vertical_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcVerticalRow *self = CC_VERTICAL_ROW (object);
switch (prop_id)
{
case PROP_ICON_NAME:
cc_vertical_row_set_icon_name (self, g_value_get_string (value));
break;
case PROP_ACTIVATABLE_WIDGET:
cc_vertical_row_set_activatable_widget (self, (GtkWidget*) g_value_get_object (value));
break;
case PROP_SUBTITLE:
cc_vertical_row_set_subtitle (self, g_value_get_string (value));
break;
case PROP_SUBTITLE_LINES:
cc_vertical_row_set_subtitle_lines (self, g_value_get_int (value));
break;
case PROP_TITLE_LINES:
cc_vertical_row_set_title_lines (self, g_value_get_int (value));
break;
case PROP_USE_UNDERLINE:
cc_vertical_row_set_use_underline (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_vertical_row_dispose (GObject *object)
{
CcVerticalRow *self = CC_VERTICAL_ROW (object);
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
if (priv->previous_parent != NULL) {
g_signal_handlers_disconnect_by_func (priv->previous_parent, G_CALLBACK (row_activated_cb), self);
priv->previous_parent = NULL;
}
cc_vertical_row_set_activatable_widget (self, NULL);
g_clear_pointer ((GtkWidget**)&priv->header, gtk_widget_unparent);
G_OBJECT_CLASS (cc_vertical_row_parent_class)->dispose (object);
}
static void
cc_vertical_row_class_init (CcVerticalRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->get_property = cc_vertical_row_get_property;
object_class->set_property = cc_vertical_row_set_property;
object_class->dispose = cc_vertical_row_dispose;
props[PROP_ICON_NAME] =
g_param_spec_string ("icon-name",
"Icon name",
"Icon name",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_ACTIVATABLE_WIDGET] =
g_param_spec_object ("activatable-widget",
"Activatable widget",
"The widget to be activated when the row is activated",
GTK_TYPE_WIDGET,
G_PARAM_READWRITE);
props[PROP_SUBTITLE] =
g_param_spec_string ("subtitle",
"Subtitle",
"Subtitle",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_USE_UNDERLINE] =
g_param_spec_boolean ("use-underline",
"Use underline",
"If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_TITLE_LINES] =
g_param_spec_int ("title-lines",
"Number of title lines",
"The desired number of title lines",
0, G_MAXINT,
1,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_SUBTITLE_LINES] =
g_param_spec_int ("subtitle-lines",
"Number of subtitle lines",
"The desired number of subtitle lines",
0, G_MAXINT,
1,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, N_PROPS, props);
signals[SIGNAL_ACTIVATED] =
g_signal_new ("activated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE,
0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-vertical-row.ui");
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, content_box);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, header);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, image);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, prefixes);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, subtitle);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, suffixes);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, title);
gtk_widget_class_bind_template_child_private (widget_class, CcVerticalRow, title_box);
}
static gboolean
string_is_not_empty (GBinding *binding,
const GValue *from_value,
GValue *to_value,
gpointer user_data)
{
const gchar *string = g_value_get_string (from_value);
g_value_set_boolean (to_value, string != NULL && g_strcmp0 (string, "") != 0);
return TRUE;
}
static void
cc_vertical_row_init (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
priv->title_lines = 1;
priv->subtitle_lines = 1;
gtk_widget_init_template (GTK_WIDGET (self));
g_object_bind_property_full (self, "title",
priv->title, "visible",
G_BINDING_SYNC_CREATE,
string_is_not_empty,
NULL, NULL, NULL);
update_subtitle_visibility (self);
g_signal_connect (self, "notify::parent", G_CALLBACK (parent_cb), NULL);
}
static void
cc_vertical_row_buildable_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const gchar *type)
{
CcVerticalRow *self = CC_VERTICAL_ROW (buildable);
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
if (!priv->header)
parent_buildable_iface->add_child (buildable, builder, child, type);
else if (type && strcmp (type, "prefix") == 0)
cc_vertical_row_add_prefix (self, GTK_WIDGET (child));
else if (type && strcmp (type, "content") == 0)
cc_vertical_row_add_content (self, GTK_WIDGET (child));
else if (!type && GTK_IS_WIDGET (child))
{
gtk_box_append (priv->suffixes, GTK_WIDGET (child));
gtk_widget_show (GTK_WIDGET (priv->suffixes));
}
else
parent_buildable_iface->add_child (buildable, builder, child, type);
}
static void
cc_vertical_row_buildable_init (GtkBuildableIface *iface)
{
parent_buildable_iface = g_type_interface_peek_parent (iface);
iface->add_child = cc_vertical_row_buildable_add_child;
}
const gchar *
cc_vertical_row_get_subtitle (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
return gtk_label_get_text (priv->subtitle);
}
void
cc_vertical_row_set_subtitle (CcVerticalRow *self,
const gchar *subtitle)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
if (g_strcmp0 (gtk_label_get_text (priv->subtitle), subtitle) == 0)
return;
gtk_label_set_text (priv->subtitle, subtitle);
gtk_widget_set_visible (GTK_WIDGET (priv->subtitle),
subtitle != NULL && g_strcmp0 (subtitle, "") != 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE]);
}
const gchar *
cc_vertical_row_get_icon_name (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
return gtk_image_get_icon_name (priv->image);
}
void
cc_vertical_row_set_icon_name (CcVerticalRow *self,
const gchar *icon_name)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
const gchar *old_icon_name;
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
old_icon_name = gtk_image_get_icon_name (priv->image);
if (g_strcmp0 (old_icon_name, icon_name) == 0)
return;
gtk_image_set_from_icon_name (priv->image, icon_name);
gtk_widget_set_visible (GTK_WIDGET (priv->image),
icon_name != NULL && g_strcmp0 (icon_name, "") != 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
}
GtkWidget *
cc_vertical_row_get_activatable_widget (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), NULL);
return priv->activatable_widget;
}
static void
activatable_widget_weak_notify (gpointer data,
GObject *where_the_object_was)
{
CcVerticalRow *self = CC_VERTICAL_ROW (data);
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
priv->activatable_widget = NULL;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
}
void
cc_vertical_row_set_activatable_widget (CcVerticalRow *self,
GtkWidget *widget)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
if (priv->activatable_widget == widget)
return;
if (priv->activatable_widget)
g_object_weak_unref (G_OBJECT (priv->activatable_widget),
activatable_widget_weak_notify,
self);
priv->activatable_widget = widget;
if (priv->activatable_widget != NULL) {
g_object_weak_ref (G_OBJECT (priv->activatable_widget),
activatable_widget_weak_notify,
self);
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE);
gtk_accessible_update_relation (GTK_ACCESSIBLE (priv->activatable_widget),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, priv->title, NULL,
GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, priv->subtitle, NULL,
-1);
}
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
}
gboolean
cc_vertical_row_get_use_underline (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), FALSE);
return priv->use_underline;
}
void
cc_vertical_row_set_use_underline (CcVerticalRow *self,
gboolean use_underline)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
use_underline = !!use_underline;
if (priv->use_underline == use_underline)
return;
priv->use_underline = use_underline;
adw_preferences_row_set_use_underline (ADW_PREFERENCES_ROW (self), priv->use_underline);
gtk_label_set_use_underline (priv->title, priv->use_underline);
gtk_label_set_use_underline (priv->subtitle, priv->use_underline);
gtk_label_set_mnemonic_widget (priv->title, GTK_WIDGET (self));
gtk_label_set_mnemonic_widget (priv->subtitle, GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]);
}
gint
cc_vertical_row_get_title_lines (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), 0);
return priv->title_lines;
}
void
cc_vertical_row_set_title_lines (CcVerticalRow *self,
gint title_lines)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (title_lines >= 0);
if (priv->title_lines == title_lines)
return;
priv->title_lines = title_lines;
gtk_label_set_lines (priv->title, title_lines);
gtk_label_set_ellipsize (priv->title, title_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE_LINES]);
}
gint
cc_vertical_row_get_subtitle_lines (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_val_if_fail (CC_IS_VERTICAL_ROW (self), 0);
return priv->subtitle_lines;
}
void
cc_vertical_row_set_subtitle_lines (CcVerticalRow *self,
gint subtitle_lines)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (subtitle_lines >= 0);
if (priv->subtitle_lines == subtitle_lines)
return;
priv->subtitle_lines = subtitle_lines;
gtk_label_set_lines (priv->subtitle, subtitle_lines);
gtk_label_set_ellipsize (priv->subtitle, subtitle_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE_LINES]);
}
void
cc_vertical_row_add_prefix (CcVerticalRow *self,
GtkWidget *widget)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (GTK_IS_WIDGET (self));
gtk_box_append (priv->prefixes, widget);
gtk_widget_show (GTK_WIDGET (priv->prefixes));
}
void
cc_vertical_row_add_content (CcVerticalRow *self,
GtkWidget *widget)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (GTK_IS_WIDGET (self));
/* HACK: the content box pushes the title too much to the top, so we
* need to compensate this here.
*/
gtk_widget_set_margin_top (GTK_WIDGET (priv->header), 12);
gtk_box_append (priv->content_box, widget);
gtk_widget_set_visible (GTK_WIDGET (priv->content_box), TRUE);
}
void
cc_vertical_row_activate (CcVerticalRow *self)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
if (priv->activatable_widget)
gtk_widget_mnemonic_activate (priv->activatable_widget, FALSE);
g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0);
}
void
cc_vertical_row_remove (CcVerticalRow *self,
GtkWidget *child)
{
CcVerticalRowPrivate *priv = cc_vertical_row_get_instance_private (self);
GtkWidget *parent;
g_return_if_fail (CC_IS_VERTICAL_ROW (self));
g_return_if_fail (GTK_IS_WIDGET (child));
parent = gtk_widget_get_parent (child);
if (parent == GTK_WIDGET (priv->prefixes))
gtk_box_remove (priv->prefixes, child);
else if (parent == GTK_WIDGET (priv->suffixes))
gtk_box_remove (priv->suffixes, child);
else if (parent == GTK_WIDGET (priv->content_box))
gtk_box_remove (priv->content_box, child);
else
g_warning ("%p is not a child of %p", child, self);
}

View File

@@ -1,75 +0,0 @@
/* cc-vertical-row.h
*
* Copyright 2018 Purism SPC
* 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
* 2023 Red Hat, Inc
*
* 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 <adwaita.h>
G_BEGIN_DECLS
#define CC_TYPE_VERTICAL_ROW (cc_vertical_row_get_type())
G_DECLARE_DERIVABLE_TYPE (CcVerticalRow, cc_vertical_row, CC, VERTICAL_ROW, AdwPreferencesRow)
struct _CcVerticalRowClass
{
AdwPreferencesRowClass parent_class;
/*< private >*/
gpointer padding[4];
};
const gchar *cc_vertical_row_get_subtitle (CcVerticalRow *self);
void cc_vertical_row_set_subtitle (CcVerticalRow *self,
const gchar *subtitle);
const gchar *cc_vertical_row_get_icon_name (CcVerticalRow *self);
void cc_vertical_row_set_icon_name (CcVerticalRow *self,
const gchar *icon_name);
GtkWidget *cc_vertical_row_get_activatable_widget (CcVerticalRow *self);
void cc_vertical_row_set_activatable_widget (CcVerticalRow *self,
GtkWidget *widget);
gboolean cc_vertical_row_get_use_underline (CcVerticalRow *self);
void cc_vertical_row_set_use_underline (CcVerticalRow *self,
gboolean use_underline);
gint cc_vertical_row_get_title_lines (CcVerticalRow *self);
void cc_vertical_row_set_title_lines (CcVerticalRow *self,
gint title_lines);
gint cc_vertical_row_get_subtitle_lines (CcVerticalRow *self);
void cc_vertical_row_set_subtitle_lines (CcVerticalRow *self,
gint subtitle_lines);
void cc_vertical_row_add_prefix (CcVerticalRow *self,
GtkWidget *widget);
void cc_vertical_row_add_content (CcVerticalRow *self,
GtkWidget *widget);
void cc_vertical_row_activate (CcVerticalRow *self);
void cc_vertical_row_remove (CcVerticalRow *self,
GtkWidget *child);
G_END_DECLS

View File

@@ -1,13 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/common">
<file preprocess="xml-stripblanks">cc-illustrated-row.ui</file>
<file preprocess="xml-stripblanks">cc-language-chooser.ui</file>
<file preprocess="xml-stripblanks">cc-language-row.ui</file>
<file preprocess="xml-stripblanks">cc-list-row.ui</file>
<file preprocess="xml-stripblanks">cc-time-editor.ui</file>
<file preprocess="xml-stripblanks">cc-permission-infobar.ui</file>
<file preprocess="xml-stripblanks">cc-split-row.ui</file>
<file preprocess="xml-stripblanks">cc-vertical-row.ui</file>
</gresource>
</gresources>

View File

@@ -25,14 +25,11 @@ common_sources += gnome.mkenums(
)
resource_data = files(
'cc-illustrated-row.ui',
'cc-language-chooser.ui',
'cc-language-row.ui',
'cc-list-row.ui',
'cc-time-editor.ui',
'cc-permission-infobar.ui',
'cc-split-row.ui',
'cc-vertical-row.ui',
)
common_sources += gnome.compile_resources(
@@ -66,14 +63,11 @@ libwidgets_dep = declare_dependency(
sources = common_sources + files(
'cc-common-language.c',
'cc-illustrated-row.c',
'cc-language-chooser.c',
'cc-language-row.c',
'cc-list-row.c',
'cc-time-editor.c',
'cc-permission-infobar.c',
'cc-split-row.c',
'cc-vertical-row.c',
'cc-util.c'
)

View File

@@ -20,20 +20,18 @@
*/
#include "config.h"
#include "cc-list-row.h"
#include "cc-time-editor.h"
#include "cc-datetime-panel.h"
#include "cc-datetime-resources.h"
#include <langinfo.h>
#include <sys/time.h>
#include "cc-tz-dialog.h"
#include "cc-timezone-map.h"
#include "timedated.h"
#include "date-endian.h"
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <gdesktop-enums.h>
#include "gdesktop-enums-types.h"
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
@@ -47,6 +45,12 @@
#define DEFAULT_TZ "Europe/London"
#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
enum {
CITY_COL_CITY_HUMAN_READABLE,
CITY_COL_ZONE,
CITY_NUM_COLS
};
#define DATETIME_PERMISSION "org.gnome.controlcenter.datetime.configure"
#define DATETIME_TZ_PERMISSION "org.freedesktop.timedate1.set-timezone"
#define LOCATION_SETTINGS "org.gnome.system.location"
@@ -64,6 +68,8 @@ struct _CcDateTimePanel
{
CcPanel parent_instance;
GtkWidget *map;
GList *toplevels;
TzLocation *current_location;
@@ -76,9 +82,12 @@ struct _CcDateTimePanel
GSettings *datetime_settings;
GSettings *filechooser_settings;
GDesktopClockFormat clock_format;
GtkFrame *aspectmap;
GtkWidget *auto_datetime_row;
GtkWidget *auto_timezone_row;
GtkWidget *auto_timezone_switch;
GtkListStore *city_liststore;
GtkTreeModelSort *city_modelsort;
GtkWidget *date_grid;
GtkWidget *datetime_button;
GtkWidget *datetime_dialog;
@@ -89,15 +98,14 @@ struct _CcDateTimePanel
GtkLockButton *lock_button;
GtkListBox *date_box;
GtkListBoxRow *day_row;
GtkSingleSelection *month_model;
GtkPopover *month_popover;
GtkListBoxRow *month_row;
AdwComboRow *month_row;
GtkListBoxRow *year_row;
GtkWidget *network_time_switch;
GtkWidget *time_editor;
GtkWidget *timezone_button;
GtkWidget *timezone_dialog;
GtkWidget *timezone_label;
GtkWidget *timezone_searchentry;
GtkWidget *year_spinbutton;
GnomeWallClock *clock_tracker;
@@ -105,8 +113,6 @@ struct _CcDateTimePanel
Timedate1 *dtm;
GCancellable *cancellable;
gboolean pending_ntp_state;
GPermission *permission;
GPermission *tz_permission;
GSettings *location_settings;
@@ -248,7 +254,7 @@ update_time (CcDateTimePanel *self)
}
self->month = g_date_time_get_month (self->date);
gtk_single_selection_set_selected (self->month_model, self->month - 1);
adw_combo_row_set_selected (self->month_row, self->month - 1);
gtk_label_set_text (GTK_LABEL (self->datetime_label), label);
}
@@ -305,10 +311,6 @@ set_using_ntp_cb (GObject *source,
/* TODO: display any error in a user friendly way */
g_warning ("Could not set system to use NTP: %s", error->message);
}
else
{
gtk_switch_set_state (GTK_SWITCH (self->network_time_switch), self->pending_ntp_state);
}
}
static void
@@ -329,10 +331,12 @@ queue_set_datetime (CcDateTimePanel *self)
}
static void
queue_set_ntp (CcDateTimePanel *self,
gboolean using_ntp)
queue_set_ntp (CcDateTimePanel *self)
{
self->pending_ntp_state = using_ntp;
gboolean using_ntp;
/* for now just do it */
using_ntp = gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
timedate1_call_set_ntp (self->dtm,
using_ntp,
TRUE,
@@ -377,6 +381,25 @@ change_date (CcDateTimePanel *self)
queue_set_datetime (self);
}
static gboolean
city_changed_cb (CcDateTimePanel *self,
GtkTreeModel *model,
GtkTreeIter *iter,
GtkEntryCompletion *completion)
{
GtkWidget *entry;
g_autofree gchar *zone = NULL;
gtk_tree_model_get (model, iter,
CITY_COL_ZONE, &zone, -1);
cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), zone);
entry = gtk_entry_completion_get_entry (completion);
gtk_editable_set_text (GTK_EDITABLE (entry), "");
return TRUE;
}
static char *
translated_city_name (TzLocation *loc)
{
@@ -407,8 +430,18 @@ translated_city_name (TzLocation *loc)
static void
update_timezone (CcDateTimePanel *self)
{
g_autofree gchar *bubble_text = NULL;
g_autofree gchar *city_country = NULL;
g_autofree gchar *label = NULL;
g_autofree gchar *time_label = NULL;
g_autofree gchar *utc_label = NULL;
g_autofree gchar *tz_desc = NULL;
gboolean use_ampm;
if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
use_ampm = TRUE;
else
use_ampm = FALSE;
city_country = translated_city_name (self->current_location);
@@ -418,6 +451,62 @@ update_timezone (CcDateTimePanel *self)
g_date_time_get_timezone_abbreviation (self->date),
city_country);
gtk_label_set_text (GTK_LABEL (self->timezone_label), label);
/* Translators: UTC here means the Coordinated Universal Time.
* %:::z will be replaced by the offset from UTC e.g. UTC+02 */
utc_label = g_date_time_format (self->date, _("UTC%:::z"));
if (use_ampm)
{
/* Translators: This is the time format used in 12-hour mode. */
time_label = g_date_time_format (self->date, _("%l:%M %p"));
}
else
{
/* Translators: This is the time format used in 24-hour mode. */
time_label = g_date_time_format (self->date, _("%R"));
}
/* Update the text bubble in the timezone map */
/* Translators: "timezone (utc shift)" */
tz_desc = g_strdup_printf (C_("timezone map", "%s (%s)"),
g_date_time_get_timezone_abbreviation (self->date),
utc_label);
bubble_text = g_strdup_printf ("<b>%s</b>\n"
"<small>%s</small>\n"
"<b>%s</b>",
tz_desc,
city_country,
time_label);
cc_timezone_map_set_bubble_text (CC_TIMEZONE_MAP (self->map), bubble_text);
}
static void
location_changed_cb (CcDateTimePanel *self,
TzLocation *location)
{
g_autoptr(GDateTime) old_date = NULL;
g_autoptr(GTimeZone) timezone = NULL;
g_debug ("location changed to %s/%s", location->country, location->zone);
self->current_location = location;
timezone = g_time_zone_new_identifier (location->zone);
if (!timezone)
{
g_warning ("Could not find timezone \"%s\", using UTC instead", location->zone);
timezone = g_time_zone_new_utc ();
}
old_date = self->date;
self->date = g_date_time_to_timezone (old_date, timezone);
cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
g_date_time_get_hour (self->date),
g_date_time_get_minute (self->date));
update_timezone (self);
queue_set_timezone (self);
}
static void
@@ -428,16 +517,37 @@ get_initial_timezone (CcDateTimePanel *self)
timezone = timedate1_get_timezone (self->dtm);
if (timezone == NULL ||
!cc_tz_dialog_set_tz (CC_TZ_DIALOG (self->timezone_dialog), timezone))
!cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), timezone))
{
g_warning ("Timezone '%s' is unhandled, setting %s as default", timezone ? timezone : "(null)", DEFAULT_TZ);
cc_tz_dialog_set_tz (CC_TZ_DIALOG (self->timezone_dialog), DEFAULT_TZ);
cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), DEFAULT_TZ);
}
self->current_location = cc_tz_dialog_get_selected_location (CC_TZ_DIALOG (self->timezone_dialog));
self->current_location = cc_timezone_map_get_location (CC_TIMEZONE_MAP (self->map));
update_timezone (self);
}
static void
load_cities (TzLocation *loc,
GtkListStore *city_store)
{
g_autofree gchar *human_readable = NULL;
human_readable = translated_city_name (loc);
gtk_list_store_insert_with_values (city_store, NULL, 0,
CITY_COL_CITY_HUMAN_READABLE, human_readable,
CITY_COL_ZONE, loc->zone,
-1);
}
static void
load_regions_model (GtkListStore *cities)
{
g_autoptr(TzDB) db = NULL;
db = tz_load_db ();
g_ptr_array_foreach (db->locations, (GFunc) load_cities, cities);
}
static void
day_changed (CcDateTimePanel *panel)
{
@@ -468,29 +578,20 @@ month_year_changed (CcDateTimePanel *self)
}
static void
on_date_box_row_activated_cb (CcDateTimePanel *self,
GtkListBoxRow *row)
on_month_row_selected_changed_cb (AdwComboRow *month_row,
GParamSpec *pspec,
CcDateTimePanel *self)
{
g_assert (CC_IS_DATE_TIME_PANEL (self));
if (row == self->month_row)
gtk_popover_popup (self->month_popover);
}
static void
on_month_selection_changed_cb (CcDateTimePanel *self)
{
guint i;
unsigned int i;
g_assert (CC_IS_DATE_TIME_PANEL (self));
g_assert (ADW_IS_COMBO_ROW (month_row));
i = gtk_single_selection_get_selected (self->month_model);
i = adw_combo_row_get_selected (month_row);
g_assert (i >= 0 && i < 12);
self->month = i + 1;
month_year_changed (self);
gtk_popover_popdown (self->month_popover);
}
static void
@@ -504,10 +605,9 @@ on_clock_changed (CcDateTimePanel *panel,
}
static gboolean
change_ntp (CcDateTimePanel *self,
gboolean state)
change_ntp (CcDateTimePanel *self)
{
queue_set_ntp (self, state);
queue_set_ntp (self);
/* The new state will be visible once we see the reply. */
return TRUE;
@@ -523,7 +623,7 @@ on_ntp_changed (CcDateTimePanel *self)
g_signal_handlers_block_by_func (self->network_time_switch, change_ntp, self);
g_object_set (self->network_time_switch,
"active", ntp_on,
"state", ntp_on,
NULL);
g_signal_handlers_unblock_by_func (self->network_time_switch, change_ntp, self);
@@ -587,7 +687,9 @@ on_can_ntp_changed (CcDateTimePanel *self)
static void
on_timezone_changed (CcDateTimePanel *self)
{
g_signal_handlers_block_by_func (self->map, location_changed_cb, self);
get_initial_timezone (self);
g_signal_handlers_unblock_by_func (self->map, location_changed_cb, self);
}
static void
@@ -682,15 +784,6 @@ bind_switch_to_row (CcDateTimePanel *self,
NULL, self, NULL);
}
static void
panel_tz_selection_changed_cb (CcDateTimePanel *self)
{
g_assert (CC_IS_DATE_TIME_PANEL (self));
self->current_location = cc_tz_dialog_get_selected_location (CC_TZ_DIALOG (self->timezone_dialog));
queue_set_timezone (self);
}
static void
list_box_row_activated (CcDateTimePanel *self,
GtkListBoxRow *row)
@@ -727,6 +820,24 @@ time_changed_cb (CcDateTimePanel *self,
queue_set_datetime (self);
}
static void
setup_timezone_dialog (CcDateTimePanel *self)
{
g_autoptr(GtkEntryCompletion) completion = NULL;
/* set up timezone map */
self->map = (GtkWidget *) cc_timezone_map_new ();
gtk_frame_set_child (self->aspectmap, self->map);
/* Create the completion object */
completion = gtk_entry_completion_new ();
gtk_entry_set_completion (GTK_ENTRY (self->timezone_searchentry), completion);
gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (self->city_modelsort));
gtk_entry_completion_set_text_column (completion, CITY_COL_CITY_HUMAN_READABLE);
}
static void
setup_datetime_dialog (CcDateTimePanel *self)
{
@@ -742,9 +853,6 @@ setup_datetime_dialog (CcDateTimePanel *self)
".gnome-control-center-datetime-setup-time>label {\n"
" font-size: 250%;\n"
"}\n"
"gridview.month-grid > child {\n"
" background: transparent;\n"
"}\n"
".gnome-control-center-datetime-setup-time>spinbutton>entry {\n"
" padding: 8px 13px;\n"
"}", -1);
@@ -774,7 +882,7 @@ setup_datetime_dialog (CcDateTimePanel *self)
/* Month */
self->month = g_date_time_get_month (self->date);
gtk_single_selection_set_selected (self->month_model, self->month - 1);
adw_combo_row_set_selected (self->month_row, self->month - 1);
}
static int
@@ -832,15 +940,14 @@ cc_date_time_panel_class_init (CcDateTimePanelClass *klass)
panel_class->get_help_uri = cc_date_time_panel_get_help_uri;
g_type_ensure (CC_TYPE_LIST_ROW);
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/datetime/cc-datetime-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, aspectmap);
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, city_liststore);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, city_modelsort);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_box);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_button);
gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_dialog);
@@ -849,24 +956,21 @@ cc_date_time_panel_class_init (CcDateTimePanelClass *klass)
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, 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_button);
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, timezone_searchentry);
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, on_month_row_selected_changed_cb);
bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
@@ -926,7 +1030,7 @@ cc_date_time_panel_init (CcDateTimePanel *self)
self->toplevels = g_list_append (self->toplevels, self->datetime_dialog);
self->toplevels = g_list_append (self->toplevels, self->timezone_dialog);
/* setup_timezone_dialog (self); */
setup_timezone_dialog (self);
setup_datetime_dialog (self);
/* set up network time switch */
@@ -966,10 +1070,21 @@ cc_date_time_panel_init (CcDateTimePanel *self)
update_time (self);
load_regions_model (GTK_LIST_STORE (self->city_liststore));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->city_modelsort), CITY_COL_CITY_HUMAN_READABLE,
GTK_SORT_ASCENDING);
/* After the initial setup, so we can be sure that
* the model is filled up */
get_initial_timezone (self);
g_signal_connect_object (gtk_entry_get_completion (GTK_ENTRY (self->timezone_searchentry)),
"match-selected", G_CALLBACK (city_changed_cb), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->map, "location-changed",
G_CALLBACK (location_changed_cb), self, G_CONNECT_SWAPPED);
/* Watch changes of timedated remote service properties */
g_signal_connect_object (self->dtm, "g-properties-changed",
G_CALLBACK (on_timedated_properties_changed), self, G_CONNECT_SWAPPED);

View File

@@ -1,10 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="CcTzDialog" id="timezone_dialog">
<signal name="tz-selected" handler="panel_tz_selection_changed_cb" swapped="yes"/>
<object class="GtkListStore" id="city_liststore">
<columns>
<!-- column-name city-human-readable -->
<column type="gchararray"/>
<!-- column-name zone -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkTreeModelSort" id="city_modelsort">
<property name="model">city_liststore</property>
</object>
<object class="GtkDialog" id="datetime_dialog">
<property name="title" translatable="yes">Date &amp; Time</property>
<property name="modal">True</property>
@@ -34,7 +40,6 @@
<object class="GtkListBox" id="date_box">
<property name="width-request">320</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="on_date_box_row_activated_cb" swapped="yes"/>
<style>
<class name="boxed-list"/>
</style>
@@ -57,28 +62,27 @@
<!-- Month row -->
<child>
<object class="CcListRow" id="month_row">
<object class="AdwComboRow" id="month_row">
<property name="title" translatable="yes">Month</property>
<binding name="secondary-label">
<lookup name="string" type="GtkStringObject">
<lookup name="selected-item">month_model</lookup>
</lookup>
</binding>
<child type="suffix">
<object class="GtkBox">
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="icon-name">pan-down-symbolic</property>
</object>
</child>
<child>
<object class="GtkPopover" id="month_popover">
<property name="child">month_grid</property>
</object>
</child>
<signal name="notify::selected" handler="on_month_row_selected_changed_cb" object="CcDateTimePanel" swapped="no" />
<property name="model">
<object class="GtkStringList">
<items>
<item translatable="yes">January</item>
<item translatable="yes">February</item>
<item translatable="yes">March</item>
<item translatable="yes">April</item>
<item translatable="yes">May</item>
<item translatable="yes">June</item>
<item translatable="yes">July</item>
<item translatable="yes">August</item>
<item translatable="yes">September</item>
<item translatable="yes">October</item>
<item translatable="yes">November</item>
<item translatable="yes">December</item>
</items>
</object>
</child>
</property>
</object>
</child>
@@ -105,6 +109,44 @@
</object>
</child>
</object>
<object class="GtkDialog" id="timezone_dialog">
<property name="title" translatable="yes">Time Zone</property>
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="use_header_bar">1</property>
<property name="hide-on-close">True</property>
<child internal-child="headerbar">
<object class="GtkHeaderBar" id="dialog_header_bar">
<property name="show-title-buttons">True</property>
<child type="title">
<object class="GtkEntry" id="timezone_searchentry">
<property name="halign">center</property>
<property name="margin_start">5</property>
<property name="margin_end">5</property>
<property name="width_chars">40</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<property name="placeholder_text" translatable="yes">Search for a city</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="dialog_vbox7">
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkFrame" id="aspectmap">
<property name="margin_start">5</property>
<property name="margin_end">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
</object>
</child>
</object>
</child>
</object>
<template class="CcDateTimePanel" parent="CcPanel">
<child type="titlebar-end">
@@ -205,7 +247,7 @@
<signal name="notify::selected-item" handler="change_clock_settings" object="CcDateTimePanel" swapped="no"/>
<property name="model">
<object class="AdwEnumListModel">
<property name="enum-type">GDesktopClockFormat</property>
<property name="enum_type">GDesktopClockFormat</property>
</object>
</property>
<property name="expression">
@@ -218,49 +260,4 @@
</object>
</child>
</template>
<object class="GtkGridView" id="month_grid">
<property name="halign">start</property>
<property name="margin-start">3</property>
<property name="margin-end">3</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<property name="orientation">horizontal</property>
<property name="max-columns">6</property>
<property name="min-columns">6</property>
<property name="enable-rubberband">False</property>
<style>
<class name="month-grid"/>
</style>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/org/gnome/control-center/datetime/cc-month-row.ui</property>
</object>
</property>
<property name="model">
<object class="GtkSingleSelection" id="month_model">
<property name="autoselect">False</property>
<signal name="selection-changed" handler="on_month_selection_changed_cb" swapped="yes"/>
<property name="model">
<object class="GtkStringList">
<items>
<item translatable="yes">January</item>
<item translatable="yes">February</item>
<item translatable="yes">March</item>
<item translatable="yes">April</item>
<item translatable="yes">May</item>
<item translatable="yes">June</item>
<item translatable="yes">July</item>
<item translatable="yes">August</item>
<item translatable="yes">September</item>
<item translatable="yes">October</item>
<item translatable="yes">November</item>
<item translatable="yes">December</item>
</items>
</object>
</property>
</object>
</property>
</object>
</interface>

View File

@@ -1,55 +0,0 @@
<interface>
<template class="GtkListItem">
<property name="activatable">False</property>
<property name="child">
<object class="GtkBox">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<!-- Month name -->
<child>
<object class="GtkLabel">
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="width-request">96</property>
<style>
<class name="title"/>
</style>
<binding name="label">
<lookup name="string" type="GtkStringObject">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<!-- Check Image -->
<child>
<object class="GtkImage" id="select_image">
<property name="visible" bind-source="GtkListItem" bind-property="selected" bind-flags="sync-create" />
<property name="icon-name">object-select-symbolic</property>
</object>
</child>
<!-- Placeholder too keep check image space intact -->
<child>
<object class="AdwBin" id="image_placeholder">
<property name="visible" bind-source="select_image" bind-flags="sync-create|invert-boolean" />
</object>
</child>
</object>
</property>
</template>
<object class="GtkSizeGroup">
<property name="mode">both</property>
<widgets>
<widget name="select_image"/>
<widget name="image_placeholder"/>
</widgets>
</object>
</interface>

View File

@@ -0,0 +1,577 @@
/*
* Copyright (C) 2010 Intel, Inc
*
* Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
* Written by Evan Dandrea <evand@ubuntu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Thomas Wood <thomas.wood@intel.com>
*
*/
#include "cc-timezone-map.h"
#include <math.h>
#include <string.h>
#include "tz.h"
#define PIN_HOT_POINT_X 8
#define PIN_HOT_POINT_Y 15
#define DATETIME_RESOURCE_PATH "/org/gnome/control-center/datetime"
typedef struct
{
gdouble offset;
guchar red;
guchar green;
guchar blue;
guchar alpha;
} CcTimezoneMapOffset;
struct _CcTimezoneMap
{
GtkWidget parent_instance;
GdkTexture *orig_background;
GdkTexture *orig_background_dim;
GdkTexture *background;
GdkTexture *color_map;
GdkTexture *pin;
gdouble selected_offset;
TzDB *tzdb;
TzLocation *location;
gchar *bubble_text;
};
G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
enum
{
LOCATION_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static GdkTexture *
texture_from_resource (const gchar *resource_path,
GError **error)
{
g_autofree gchar *full_path = g_strdup_printf ("resource://%s", resource_path);
g_autoptr(GFile) file = g_file_new_for_uri (full_path);
g_autoptr(GdkTexture) texture = gdk_texture_new_from_file (file, error);
return g_steal_pointer (&texture);
}
static void
cc_timezone_map_dispose (GObject *object)
{
CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
g_clear_object (&self->color_map);
g_clear_object (&self->orig_background);
g_clear_object (&self->orig_background_dim);
g_clear_object (&self->background);
g_clear_object (&self->pin);
g_clear_pointer (&self->bubble_text, g_free);
G_OBJECT_CLASS (cc_timezone_map_parent_class)->dispose (object);
}
static void
cc_timezone_map_finalize (GObject *object)
{
CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
g_clear_pointer (&self->tzdb, tz_db_free);
G_OBJECT_CLASS (cc_timezone_map_parent_class)->finalize (object);
}
/* GtkWidget functions */
static void
cc_timezone_map_measure (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum,
gint *natural,
gint *minimum_baseline,
gint *natural_baseline)
{
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
gint size;
switch (orientation)
{
case GTK_ORIENTATION_HORIZONTAL:
size = gdk_texture_get_width (map->orig_background);
break;
case GTK_ORIENTATION_VERTICAL:
size = gdk_texture_get_height (map->orig_background);
break;
}
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
cc_timezone_map_size_allocate (GtkWidget *widget,
gint width,
gint height,
gint baseline)
{
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
GdkTexture *texture;
if (!gtk_widget_is_sensitive (widget))
texture = map->orig_background_dim;
else
texture = map->orig_background;
g_clear_object (&map->background);
map->background = g_object_ref (texture);
GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->size_allocate (widget,
width,
height,
baseline);
}
static gdouble
convert_longitude_to_x (gdouble longitude, gint map_width)
{
const gdouble xdeg_offset = -6;
gdouble x;
x = (map_width * (180.0 + longitude) / 360.0)
+ (map_width * xdeg_offset / 180.0);
return x;
}
static gdouble
radians (gdouble degrees)
{
return (degrees / 360.0) * G_PI * 2;
}
static gdouble
convert_latitude_to_y (gdouble latitude, gdouble map_height)
{
gdouble bottom_lat = -59;
gdouble top_lat = 81;
gdouble top_per, y, full_range, top_offset, map_range;
top_per = top_lat / 180.0;
y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
full_range = 4.6068250867599998;
top_offset = full_range * top_per;
map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
y = fabs (y - top_offset);
y = y / map_range;
y = y * map_height;
return y;
}
static void
draw_text_bubble (CcTimezoneMap *map,
GtkSnapshot *snapshot,
gint width,
gint height,
gdouble pointx,
gdouble pointy)
{
static const double corner_radius = 9.0;
static const double margin_top = 12.0;
static const double margin_bottom = 12.0;
static const double margin_left = 24.0;
static const double margin_right = 24.0;
GskRoundedRect rounded_rect;
PangoRectangle text_rect;
PangoLayout *layout;
GdkRGBA rgba;
double x;
double y;
double bubble_width;
double bubble_height;
if (!map->bubble_text)
return;
layout = gtk_widget_create_pango_layout (GTK_WIDGET (map), NULL);
/* Layout the text */
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
pango_layout_set_spacing (layout, 3);
pango_layout_set_markup (layout, map->bubble_text, -1);
pango_layout_get_pixel_extents (layout, NULL, &text_rect);
/* Calculate the bubble size based on the text layout size */
bubble_width = text_rect.width + margin_left + margin_right;
bubble_height = text_rect.height + margin_top + margin_bottom;
if (pointx < width / 2)
x = pointx + 25;
else
x = pointx - bubble_width - 25;
y = pointy - bubble_height / 2;
/* Make sure it fits in the visible area */
x = CLAMP (x, 0, width - bubble_width);
y = CLAMP (y, 0, height - bubble_height);
gtk_snapshot_save (snapshot);
gsk_rounded_rect_init (&rounded_rect,
&GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height),
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
&GRAPHENE_SIZE_INIT (corner_radius, corner_radius));
gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect);
rgba = (GdkRGBA) {
.red = 0.2,
.green = 0.2,
.blue = 0.2,
.alpha = 0.7,
};
gtk_snapshot_append_color (snapshot,
&rgba,
&GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height));
rgba = (GdkRGBA) {
.red = 1.0,
.green = 1.0,
.blue = 1.0,
.alpha = 1.0,
};
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + margin_left, y + margin_top));
gtk_snapshot_append_layout (snapshot, layout, &rgba);
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
g_object_unref (layout);
}
static void
cc_timezone_map_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
g_autoptr(GdkTexture) orig_highlight = NULL;
g_autofree gchar *file = NULL;
g_autoptr(GError) err = NULL;
gdouble pointx, pointy;
gint width, height;
char buf[16];
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
/* paint background */
gtk_snapshot_append_texture (snapshot,
map->background,
&GRAPHENE_RECT_INIT (0, 0, width, height));
/* paint highlight */
if (gtk_widget_is_sensitive (widget))
{
file = g_strdup_printf (DATETIME_RESOURCE_PATH "/timezone_%s.png",
g_ascii_formatd (buf, sizeof (buf),
"%g", map->selected_offset));
}
else
{
file = g_strdup_printf (DATETIME_RESOURCE_PATH "/timezone_%s_dim.png",
g_ascii_formatd (buf, sizeof (buf),
"%g", map->selected_offset));
}
orig_highlight = texture_from_resource (file, &err);
if (!orig_highlight)
{
g_warning ("Could not load highlight: %s",
(err) ? err->message : "Unknown Error");
}
else
{
gtk_snapshot_append_texture (snapshot,
orig_highlight,
&GRAPHENE_RECT_INIT (0, 0, width, height));
}
if (map->location)
{
pointx = convert_longitude_to_x (map->location->longitude, width);
pointy = convert_latitude_to_y (map->location->latitude, height);
pointx = CLAMP (floor (pointx), 0, width);
pointy = CLAMP (floor (pointy), 0, height);
draw_text_bubble (map, snapshot, width, height, pointx, pointy);
if (map->pin)
{
gtk_snapshot_append_texture (snapshot,
map->pin,
&GRAPHENE_RECT_INIT (pointx - PIN_HOT_POINT_X,
pointy - PIN_HOT_POINT_Y,
gdk_texture_get_width (map->pin),
gdk_texture_get_height (map->pin)));
}
}
}
static void
update_cursor (GtkWidget *widget)
{
const gchar *cursor_name = NULL;
if (!gtk_widget_get_realized (widget))
return;
if (gtk_widget_is_sensitive (widget))
cursor_name = "pointer";
gtk_widget_set_cursor_from_name (widget, cursor_name);
}
static void
cc_timezone_map_state_flags_changed (GtkWidget *widget,
GtkStateFlags prev_state)
{
update_cursor (widget);
if (GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed)
GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed (widget, prev_state);
}
static void
cc_timezone_map_class_init (CcTimezoneMapClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = cc_timezone_map_dispose;
object_class->finalize = cc_timezone_map_finalize;
widget_class->measure = cc_timezone_map_measure;
widget_class->size_allocate = cc_timezone_map_size_allocate;
widget_class->snapshot = cc_timezone_map_snapshot;
widget_class->state_flags_changed = cc_timezone_map_state_flags_changed;
signals[LOCATION_CHANGED] = g_signal_new ("location-changed",
CC_TYPE_TIMEZONE_MAP,
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
}
static gint
sort_locations (TzLocation *a,
TzLocation *b)
{
if (a->dist > b->dist)
return 1;
if (a->dist < b->dist)
return -1;
return 0;
}
static void
set_location (CcTimezoneMap *map,
TzLocation *location)
{
g_autoptr(TzInfo) info = NULL;
map->location = location;
info = tz_info_from_location (map->location);
map->selected_offset = tz_location_get_base_utc_offset (map->location)
/ (60.0*60.0);
gtk_widget_queue_draw (GTK_WIDGET (map));
g_signal_emit (map, signals[LOCATION_CHANGED], 0, map->location);
}
static gboolean
map_clicked_cb (GtkGestureClick *self,
gint n_press,
gdouble x,
gdouble y,
CcTimezoneMap *map)
{
const GPtrArray *array;
gint width, height;
GList *distances = NULL;
gint i;
/* work out the coordinates */
array = tz_get_locations (map->tzdb);
width = gtk_widget_get_width (GTK_WIDGET (map));
height = gtk_widget_get_height (GTK_WIDGET (map));
for (i = 0; i < array->len; i++)
{
gdouble pointx, pointy, dx, dy;
TzLocation *loc = array->pdata[i];
pointx = convert_longitude_to_x (loc->longitude, width);
pointy = convert_latitude_to_y (loc->latitude, height);
dx = pointx - x;
dy = pointy - y;
loc->dist = dx * dx + dy * dy;
distances = g_list_prepend (distances, loc);
}
distances = g_list_sort (distances, (GCompareFunc) sort_locations);
set_location (map, (TzLocation*) distances->data);
g_list_free (distances);
return TRUE;
}
static void
cc_timezone_map_init (CcTimezoneMap *map)
{
GtkGesture *click_gesture;
GError *err = NULL;
map->orig_background = texture_from_resource (DATETIME_RESOURCE_PATH "/bg.png", &err);
if (!map->orig_background)
{
g_warning ("Could not load background image: %s",
(err) ? err->message : "Unknown error");
g_clear_error (&err);
}
map->orig_background_dim = texture_from_resource (DATETIME_RESOURCE_PATH "/bg_dim.png", &err);
if (!map->orig_background_dim)
{
g_warning ("Could not load background image: %s",
(err) ? err->message : "Unknown error");
g_clear_error (&err);
}
map->color_map = texture_from_resource (DATETIME_RESOURCE_PATH "/cc.png", &err);
if (!map->color_map)
{
g_warning ("Could not load background image: %s",
(err) ? err->message : "Unknown error");
g_clear_error (&err);
}
map->pin = texture_from_resource (DATETIME_RESOURCE_PATH "/pin.png", &err);
if (!map->pin)
{
g_warning ("Could not load pin icon: %s",
(err) ? err->message : "Unknown error");
g_clear_error (&err);
}
map->tzdb = tz_load_db ();
click_gesture = gtk_gesture_click_new ();
g_signal_connect (click_gesture, "pressed", G_CALLBACK (map_clicked_cb), map);
gtk_widget_add_controller (GTK_WIDGET (map), GTK_EVENT_CONTROLLER (click_gesture));
}
CcTimezoneMap *
cc_timezone_map_new (void)
{
return g_object_new (CC_TYPE_TIMEZONE_MAP, NULL);
}
gboolean
cc_timezone_map_set_timezone (CcTimezoneMap *map,
const gchar *timezone)
{
GPtrArray *locations;
guint i;
g_autofree gchar *real_tz = NULL;
gboolean ret;
real_tz = tz_info_get_clean_name (map->tzdb, timezone);
locations = tz_get_locations (map->tzdb);
ret = FALSE;
for (i = 0; i < locations->len; i++)
{
TzLocation *loc = locations->pdata[i];
if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
{
set_location (map, loc);
ret = TRUE;
break;
}
}
if (ret)
gtk_widget_queue_draw (GTK_WIDGET (map));
return ret;
}
void
cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
const gchar *text)
{
g_free (map->bubble_text);
map->bubble_text = g_strdup (text);
gtk_widget_queue_draw (GTK_WIDGET (map));
}
TzLocation *
cc_timezone_map_get_location (CcTimezoneMap *map)
{
return map->location;
}

View File

@@ -1,6 +1,5 @@
/* cc-firmware-security-boot-dialog.h
*
* Copyright (C) 2021 Red Hat, Inc
/*
* Copyright (C) 2010 Intel, Inc
*
* 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
@@ -15,23 +14,26 @@
* 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: Kate Hsuan <hpa@redhat.com>
* Author: Thomas Wood <thomas.wood@intel.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
#include "cc-firmware-security-utils.h"
#include "tz.h"
G_BEGIN_DECLS
#define CC_TYPE_FIRMWARE_SECURITY_BOOT_DIALOG (cc_firmware_security_boot_dialog_get_type ())
G_DECLARE_FINAL_TYPE (CcFirmwareSecurityBootDialog, cc_firmware_security_boot_dialog,
CC, FIRMWARE_SECURITY_BOOT_DIALOG, GtkDialog)
#define CC_TYPE_TIMEZONE_MAP (cc_timezone_map_get_type ())
G_DECLARE_FINAL_TYPE (CcTimezoneMap, cc_timezone_map, CC, TIMEZONE_MAP, GtkWidget)
GtkWidget *cc_firmware_security_boot_dialog_new (SecureBootState secure_boot_state);
CcTimezoneMap *cc_timezone_map_new (void);
gboolean cc_timezone_map_set_timezone (CcTimezoneMap *map,
const gchar *timezone);
void cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
const gchar *text);
TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);
G_END_DECLS

View File

@@ -1,327 +0,0 @@
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* cc-tz-dialog.c
*
* Copyright 2022 Purism SPC
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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/>.
*
* Author(s):
* Mohammed Sadiq <sadiq@sadiqpk.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "cc-tz-dialog"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define _GNU_SOURCE
#include <string.h>
#include <glib/gi18n.h>
#include "cc-tz-dialog.h"
#include "tz.h"
struct _CcTzDialog
{
AdwWindow parent_instance;
GtkSearchEntry *location_entry;
GtkStack *main_stack;
AdwStatusPage *empty_page;
GtkScrolledWindow *tz_page;
GtkListView *tz_view;
TzDB *tz_db;
GListStore *tz_store;
GtkFilterListModel *tz_filtered_model;
GtkNoSelection *tz_selection_model;
CcTzItem *selected_item;
};
G_DEFINE_TYPE (CcTzDialog, cc_tz_dialog, ADW_TYPE_WINDOW)
enum {
TZ_SELECTED,
N_SIGNALS
};
static guint signals[N_SIGNALS];
static gboolean
match_tz_item (CcTzItem *item,
CcTzDialog *self)
{
g_auto(GStrv) strv = NULL;
g_autofree char *country = NULL;
g_autofree char *name = NULL;
g_autofree char *zone = NULL;
const char *search_terms;
g_assert (CC_IS_TZ_ITEM (item));
g_assert (CC_IS_TZ_DIALOG (self));
search_terms = gtk_editable_get_text (GTK_EDITABLE (self->location_entry));
if (!search_terms || !*search_terms)
return TRUE;
g_object_get (item,
"country", &country,
"name", &name,
"zone", &zone,
NULL);
if (!name || !zone || !country)
return FALSE;
/* Search for each word separated by spaces */
strv = g_strsplit (search_terms, " ", 0);
/*
* List the item only if the value contain each word.
* ie, for a search "as kol" it will match "Asia/Kolkata"
* not "Asia/Karachi"
*/
for (guint i = 0; strv[i]; i++)
{
const char *str = strv[i];
if (!str || !*str)
continue;
if (!strcasestr (name, str) &&
!strcasestr (zone, str) &&
!strcasestr (country, str))
return FALSE;
}
return TRUE;
}
static void
load_tz (CcTzDialog *self)
{
GPtrArray *locations;
g_assert (CC_IS_TZ_DIALOG (self));
self->tz_db = tz_load_db ();
g_assert (self->tz_db);
locations = tz_get_locations (self->tz_db);
g_assert (locations);
for (guint i = 0; i < locations->len; i++)
{
g_autoptr(CcTzItem) item = NULL;
TzLocation *location;
location = locations->pdata[i];
item = cc_tz_item_new (location);
g_list_store_append (self->tz_store, item);
}
}
static void
tz_selection_model_changed_cb (CcTzDialog *self)
{
guint n_items;
g_assert (CC_IS_TZ_DIALOG (self));
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->tz_selection_model));
if (n_items)
gtk_stack_set_visible_child (self->main_stack, GTK_WIDGET (self->tz_page));
else
gtk_stack_set_visible_child (self->main_stack, GTK_WIDGET (self->empty_page));
}
static void
tz_dialog_search_changed_cb (CcTzDialog *self)
{
GtkFilter *filter;
g_assert (CC_IS_TZ_DIALOG (self));
filter = gtk_filter_list_model_get_filter (self->tz_filtered_model);
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static void
tz_dialog_row_activated_cb (CcTzDialog *self,
guint position)
{
GListModel *model;
g_assert (CC_IS_TZ_DIALOG (self));
g_clear_object (&self->selected_item);
model = G_LIST_MODEL (self->tz_selection_model);
self->selected_item = g_list_model_get_item (model, position);
gtk_window_close (GTK_WINDOW (self));
g_signal_emit (self, signals[TZ_SELECTED], 0);
}
static void
cc_tz_dialog_map (GtkWidget *widget)
{
CcTzDialog *self = (CcTzDialog *)widget;
gtk_editable_set_text (GTK_EDITABLE (self->location_entry), "");
gtk_widget_grab_focus (GTK_WIDGET (self->location_entry));
GTK_WIDGET_CLASS (cc_tz_dialog_parent_class)->map (widget);
}
static void
cc_tz_dialog_finalize (GObject *object)
{
CcTzDialog *self = (CcTzDialog *)object;
g_clear_object (&self->tz_store);
g_clear_pointer (&self->tz_db, tz_db_free);
G_OBJECT_CLASS (cc_tz_dialog_parent_class)->finalize (object);
}
static void
cc_tz_dialog_class_init (CcTzDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = cc_tz_dialog_finalize;
widget_class->map = cc_tz_dialog_map;
signals[TZ_SELECTED] =
g_signal_new ("tz-selected",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/control-center/"
"datetime/cc-tz-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, location_entry);
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, main_stack);
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, empty_page);
gtk_widget_class_bind_template_child (widget_class, CcTzDialog, tz_page);
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_row_activated_cb);
}
static void
cc_tz_dialog_init (CcTzDialog *self)
{
GtkSortListModel *tz_sorted_model;
GtkExpression *expression;
GtkSorter *sorter;
GtkFilter *filter;
gtk_widget_init_template (GTK_WIDGET (self));
self->tz_store = g_list_store_new (CC_TYPE_TZ_ITEM);
load_tz (self);
/* Sort items by name */
expression = gtk_property_expression_new (CC_TYPE_TZ_ITEM, NULL, "name");
sorter = GTK_SORTER (gtk_string_sorter_new (expression));
tz_sorted_model = gtk_sort_list_model_new (G_LIST_MODEL (self->tz_store), sorter);
filter = (GtkFilter *)gtk_custom_filter_new ((GtkCustomFilterFunc) match_tz_item, self, NULL);
self->tz_filtered_model = gtk_filter_list_model_new (G_LIST_MODEL (tz_sorted_model), filter);
self->tz_selection_model = gtk_no_selection_new (G_LIST_MODEL (self->tz_filtered_model));
g_signal_connect_object (self->tz_selection_model, "items-changed",
G_CALLBACK (tz_selection_model_changed_cb),
self, G_CONNECT_SWAPPED);
tz_selection_model_changed_cb (self);
gtk_list_view_set_model (self->tz_view, GTK_SELECTION_MODEL (self->tz_selection_model));
}
GtkWidget *
cc_tz_dialog_new (void)
{
return g_object_new (CC_TYPE_TZ_DIALOG, NULL);
}
gboolean
cc_tz_dialog_set_tz (CcTzDialog *self,
const char *timezone)
{
g_autofree gchar *tz = NULL;
guint n_items;
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), FALSE);
g_return_val_if_fail (timezone && *timezone, FALSE);
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->tz_store));
tz = tz_info_get_clean_name (self->tz_db, timezone);
for (guint i = 0; i < n_items; i++)
{
g_autoptr(CcTzItem) item = NULL;
TzLocation *loc;
item = g_list_model_get_item (G_LIST_MODEL (self->tz_store), i);
loc = cc_tz_item_get_location (item);
if (g_strcmp0 (loc->zone, tz ? tz : timezone) == 0)
{
g_set_object (&self->selected_item, item);
return TRUE;
}
}
return FALSE;
}
CcTzItem *
cc_tz_dialog_get_selected_tz (CcTzDialog *self)
{
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), NULL);
return self->selected_item;
}
TzLocation *
cc_tz_dialog_get_selected_location (CcTzDialog *self)
{
g_return_val_if_fail (CC_IS_TZ_DIALOG (self), NULL);
if (!self->selected_item)
return NULL;
return cc_tz_item_get_location (self->selected_item);
}

View File

@@ -1,19 +0,0 @@
#pragma once
#include <adwaita.h>
#include "cc-tz-item.h"
G_BEGIN_DECLS
#define CC_TYPE_TZ_DIALOG (cc_tz_dialog_get_type ())
G_DECLARE_FINAL_TYPE (CcTzDialog, cc_tz_dialog, CC, TZ_DIALOG, AdwWindow)
GtkWidget *cc_tz_dialog_new (void);
gboolean cc_tz_dialog_set_tz (CcTzDialog *self,
const char *timezone);
CcTzItem *cc_tz_dialog_get_selected_tz (CcTzDialog *self);
TzLocation *cc_tz_dialog_get_selected_location (CcTzDialog *self);
G_END_DECLS

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcTzDialog" parent="AdwWindow">
<property name="modal">True</property>
<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">300</property>
<property name="default-height">540</property>
<property name="content">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwHeaderBar">
<property name="show-start-title-buttons">True</property>
<property name="show-end-title-buttons">True</property>
</object>
</child>
<!-- SearchBar -->
<child>
<object class="GtkSearchEntry" id="location_entry">
<property name="halign">center</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="width-chars">24</property>
<signal name="search-changed" handler="tz_dialog_search_changed_cb" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkStack" id="main_stack">
<property name="vexpand">True</property>
<child>
<object class="AdwStatusPage" id="empty_page">
<property name="margin-top">18</property>
<property name="title" translatable="yes">No Results</property>
<property name="icon-name">system-search-symbolic</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="tz_page">
<property name="hscrollbar-policy">never</property>
<property name="vexpand">True</property>
<child>
<object class="AdwClampScrollable">
<child>
<object class="GtkListView" id="tz_view">
<property name="show-separators">True</property>
<property name="single-click-activate">True</property>
<signal name="activate" handler="tz_dialog_row_activated_cb" swapped="yes"/>
<style>
/* fixme: 'boxed-list' gives nice rounded borders, but we can't use
* it here as it works only with GtkListBox, not with GtkListView */
<class name="frame"/>
</style>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/org/gnome/control-center/datetime/cc-tz-row.ui</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</template>
</interface>

View File

@@ -1,285 +0,0 @@
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright 2022 Purism SPC
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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/>.
*
* Author(s):
* Mohammed Sadiq <sadiq@sadiqpk.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "cc-tz-item"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib/gi18n.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-languages.h>
#include <libgnome-desktop/gnome-wall-clock.h>
#include "cc-tz-item.h"
#define DEFAULT_TZ "Europe/London"
#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
struct _CcTzItem
{
GObject parent_instance;
GSettings *desktop_settings;
GTimeZone *tz;
GnomeWallClock *wall_clock;
TzLocation *tz_location;
TzInfo *tz_info;
char *name;
char *country;
char *time;
char *offset; /* eg: UTC+530 */
char *zone;
};
G_DEFINE_TYPE (CcTzItem, cc_tz_item, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_COUNTRY,
PROP_NAME,
PROP_OFFSET,
PROP_TIME,
PROP_ZONE,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
/* Adapted from cc-datetime-panel.c */
static void
generate_city_name (CcTzItem *self,
TzLocation *loc)
{
g_auto(GStrv) split_translated = NULL;
gint length;
/* Load the translation for it */
self->zone = g_strdup (dgettext (GETTEXT_PACKAGE_TIMEZONES, loc->zone));
g_strdelimit (self->zone, "_", ' ');
split_translated = g_regex_split_simple ("[\\x{2044}\\x{2215}\\x{29f8}\\x{ff0f}/]",
self->zone,
0, 0);
length = g_strv_length (split_translated);
self->country = gnome_get_country_from_code (loc->country, NULL);
self->name = g_strdup (split_translated[length-1]);
}
static const char *
tz_item_get_time (CcTzItem *self)
{
g_autoptr(GDateTime) now = NULL;
GDesktopClockFormat format;
g_assert (CC_IS_TZ_ITEM (self));
if (self->time)
return self->time;
now = g_date_time_new_now (self->tz);
format = g_settings_get_enum (self->desktop_settings, "clock-format");
self->time = gnome_wall_clock_string_for_datetime (self->wall_clock, now, format, TRUE, FALSE, FALSE);
return self->time;
}
static void
tz_item_clock_changed_cb (CcTzItem *self)
{
gboolean had_time;
g_assert (CC_IS_TZ_ITEM (self));
had_time = !!self->time;
/* Clear the time, so that it'll be re-created when asked for one */
g_clear_pointer (&self->time, g_free);
if (had_time)
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TIME]);
}
static void
cc_tz_item_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcTzItem *self = (CcTzItem *)object;
switch (prop_id)
{
case PROP_COUNTRY:
g_value_set_string (value, self->country);
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_OFFSET:
g_value_set_string (value, self->offset);
break;
case PROP_TIME:
g_value_set_string (value, tz_item_get_time (self));
break;
case PROP_ZONE:
g_value_set_string (value, self->zone);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cc_tz_item_finalize (GObject *object)
{
CcTzItem *self = (CcTzItem *)object;
g_clear_object (&self->desktop_settings);
g_clear_object (&self->wall_clock);
g_clear_pointer (&self->tz, g_time_zone_unref);
g_clear_pointer (&self->tz_info, tz_info_free);
g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->country, g_free);
g_clear_pointer (&self->time, g_free);
g_clear_pointer (&self->offset, g_free);
g_clear_pointer (&self->zone, g_free);
G_OBJECT_CLASS (cc_tz_item_parent_class)->finalize (object);
}
static void
cc_tz_item_class_init (CcTzItemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = cc_tz_item_get_property;
object_class->finalize = cc_tz_item_finalize;
properties[PROP_COUNTRY] =
g_param_spec_string ("country",
"Timezone Country",
"Timezone Country",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_NAME] =
g_param_spec_string ("name",
"Timezone Name",
"Timezone Name",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_OFFSET] =
g_param_spec_string ("offset",
"Timezone offset",
"Timezone offset",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_TIME] =
g_param_spec_string ("time",
"Timezone time",
"Timezone time",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_ZONE] =
g_param_spec_string ("zone",
"Timezone zone",
"Timezone zone",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
cc_tz_item_init (CcTzItem *self)
{
self->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
self->wall_clock = gnome_wall_clock_new ();
g_signal_connect_object (self->wall_clock, "notify::clock",
G_CALLBACK (tz_item_clock_changed_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->desktop_settings, "changed::clock-format",
G_CALLBACK (tz_item_clock_changed_cb),
self,
G_CONNECT_SWAPPED);
}
CcTzItem *
cc_tz_item_new (TzLocation *location)
{
CcTzItem *self;
GString *offset;
g_return_val_if_fail (location, NULL);
self = g_object_new (CC_TYPE_TZ_ITEM, NULL);
self->tz_location = location;
self->tz_info = tz_info_from_location (location);
generate_city_name (self, location);
self->tz = g_time_zone_new_offset (self->tz_info->utc_offset);
offset = g_string_new (g_time_zone_get_identifier (self->tz));
/* Strip the seconds, eg: +05:30:00 -> +05:30 */
g_string_set_size (offset, offset->len - 3);
/* eg: +05:30 -> +0530*/
g_string_replace (offset, ":", "", 0);
/* If the timezone is UTC remove the time, which will always be [+]0000 */
if (g_str_has_suffix (offset->str, "0000"))
g_string_set_size (offset, 0);
/* eg: +0530 -> UTC+0530 */
g_string_prepend (offset, "UTC");
self->offset = g_string_free (offset, FALSE);
return self;
}
TzLocation *
cc_tz_item_get_location (CcTzItem *self)
{
g_return_val_if_fail (CC_IS_TZ_ITEM (self), NULL);
return self->tz_location;
}

View File

@@ -1,40 +0,0 @@
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright 2022 Purism SPC
* Copyright 2022 Mohammed Sadiq <sadiq@sadiqpk.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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/>.
*
* Author(s):
* Mohammed Sadiq <sadiq@sadiqpk.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <glib-object.h>
#include "tz.h"
G_BEGIN_DECLS
#define CC_TYPE_TZ_ITEM (cc_tz_item_get_type ())
G_DECLARE_FINAL_TYPE (CcTzItem, cc_tz_item, CC, TZ_ITEM, GObject)
CcTzItem *cc_tz_item_new (TzLocation *location);
TzLocation *cc_tz_item_get_location (CcTzItem *self);
G_END_DECLS

View File

@@ -1,129 +0,0 @@
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkGrid">
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">6</property>
<property name="column-spacing">6</property>
<!-- Location -->
<child>
<object class="GtkLabel">
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<style>
<class name="title"/>
</style>
<binding name="label">
<lookup name="name" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<!-- Country -->
<child>
<object class="GtkLabel">
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<style>
<class name="heading"/>
</style>
<binding name="label">
<lookup name="country" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">3</property>
<style>
<class name="caption"/>
<class name="dim-label"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="column-span">2</property>
</layout>
<!-- Zone Name -->
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="zone" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<!-- Zone Name -->
<child>
<object class="GtkLabel">
<property name="margin-start">3</property>
<property name="margin-end">3</property>
<property name="label">•</property>
</object>
</child>
<!-- Offset from GMT -->
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="offset" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</child>
<!-- Current time for the given timezone -->
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="halign">end</property>
<attributes>
<attribute name="font-features" value="tnum"/>
</attributes>
<style>
<class name="dim-label"/>
</style>
<binding name="label">
<lookup name="time" type="CcTzItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<layout>
<property name="column">2</property>
<property name="row">0</property>
<property name="row-span">2</property>
</layout>
</object>
</child>
</object>
</property>
</template>
</interface>

BIN
panels/datetime/data/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
panels/datetime/data/cc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

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