Compare commits

...

422 Commits

Author SHA1 Message Date
Philip Withnall 7c615a46b9 Merge branch 'hide-private-structs' into 'main'
build: Hide private structs from generated GIR files

See merge request pwithnall/malcontent!163
2023-12-20 11:04:46 +00:00
Philip Withnall 8ca426f631 build: Hide private structs from generated GIR files
Otherwise the fields in `MctAppFilter` become visible to introspected
languages, which was not the intention.

Spotted in
https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/65.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2023-12-20 11:02:43 +00:00
Philip Withnall de7a645548 Merge branch 'sathieu-main-patch-63945' into 'main'
Add AppInfo support to malcontent-client check-app-filter

See merge request pwithnall/malcontent!157
2023-12-07 10:10:53 +00:00
Mathieu Parent cdaa32ae4e Add AppInfo support to malcontent-client check-app-filter 2023-12-07 10:10:53 +00:00
Philip Withnall a7e6f0e973 Merge branch 'fix-appdata' into 'main'
data: Update appdata

See merge request pwithnall/malcontent!162
2023-11-21 09:42:49 +00:00
Sabri Ünal 6c561cd93c data: Update appdata
- Update the donation URL.
- Add the cvs-browser URL.

These URLs are visible on Flathub and GNOME Software.

For more information: https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-url"
2023-11-20 04:18:08 +03:00
Philip Withnall 4508c2ca1d Merge branch 'l10n-sv' into 'main'
Update Swedish translation

See merge request pwithnall/malcontent!161
2023-11-13 12:04:01 +00:00
Anders Jonsson 8d7b560795 Update Swedish translation 2023-11-11 14:11:07 +01:00
Philip Withnall 5bb3c24b08 Merge branch 'main' into 'main'
update ru.po

See merge request pwithnall/malcontent!160
2023-11-01 15:08:46 +00:00
Ser82-png 086b0ede78 update ru.po 2023-10-29 01:04:15 +10:00
Philip Withnall b3e6666fe3 Merge branch 'cs-update' into 'main'
Update Czech translation

See merge request pwithnall/malcontent!159
2023-10-24 10:04:15 +00:00
AsciiWolf c11596e3da Update Czech translation 2023-10-23 23:04:48 +02:00
Philip Withnall c764487abf Merge branch '53-carousel-focus' into 'main'
ui: Add explicit focus outline to carousel items

Closes #53

See merge request pwithnall/malcontent!156
2023-10-13 13:58:45 +00:00
Philip Withnall 51bd3a668d ui: Add explicit focus outline to carousel items
Since they’re custom widgets, they need custom CSS to define a focus
outline, and can’t rely on GTK providing it for them.

Ideally we’d be using the same `$focus_border_color` as GTK does, and
adjusting it for dark and high-contrast themes, but GTK doesn’t export
that colour so we have to work around it.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #53
2023-10-13 14:51:25 +01:00
Philip Withnall cbad81565e Merge branch '31-app-list-search' into 'main'
restrict-applications-dialog: Add support for searching the app list

Closes #31

See merge request pwithnall/malcontent!155
2023-10-13 12:31:20 +00:00
Philip Withnall 73d8343a3e restrict-applications-dialog: Add support for searching the app list
This is a type-ahead search which filters the app list by app name.

It’s always visible because search is a very obvious interaction the
user might want to do to find an app in the app list. That’s why
`GtkSearchBar` is not being used here.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #31
2023-10-13 13:24:37 +01:00
Philip Withnall 69253a2b2c build: Post-release version bump
We’re about to add new API, so bump the version number in preparation.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2023-10-13 11:34:29 +01:00
Philip Withnall 4a1cc8a830 user-controls: Fix a minor string leak
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2023-10-13 11:32:13 +01:00
Philip Withnall a58c660dca restrict-applications-selector: Add more spacing around placeholder label
This makes it look nicer.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2023-10-13 11:25:48 +01:00
Philip Withnall 13c8a88e17 restrict-applications-selector: Fix display of placeholder
The `GtkListBox` already correctly works out when to show/hide the
placeholder; we don’t need to do that ourselves. It actually breaks
things if we hide the placeholder, since `GtkListBox` then doesn’t
re-show it.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2023-10-13 11:24:50 +01:00
Philip Withnall 537d4bf791 restrict-applications-selector: Move GListStore to UI file
This simplifies the code a little and will allow binding to it in an
upcoming commit.

It introduces no functional changes.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #31
2023-10-13 11:23:31 +01:00
Philip Withnall d4951a333f Merge branch '56-string-tweak' into 'main'
user-controls: Tweak a string to improve understandability

Closes #56

See merge request pwithnall/malcontent!154
2023-10-12 13:39:46 +00:00
Philip Withnall f763d71cd2 user-controls: Tweak a string to improve understandability
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #56
2023-10-12 11:48:30 +01:00
Philip Withnall 2f67afec78 Merge branch 'update_pt_BR' into 'main'
Update pt_BR translation

See merge request pwithnall/malcontent!153
2023-07-20 12:33:22 +00:00
Matheus Polkorny b4c6e9d8ef Update pt_BR translation 2023-07-07 23:34:31 +00:00
Philip Withnall 0979e60567
0.11.1
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2023-03-16 13:16:02 +00:00
Philip Withnall bcb33bced1 Merge branch 'update-tr' into 'main'
doc: Add Turkish Translation

See merge request pwithnall/malcontent!152
2023-03-09 09:54:31 +00:00
Sabri Unal 828c5b5973 doc: Add Turkish Translation 2023-03-09 09:54:30 +00:00
Philip Withnall 062231804a Merge branch 'wip/jtojnar/meson_postinstall' into 'main'
build: Switch to Meson’s gnome.post_install function

See merge request pwithnall/malcontent!148
2022-12-30 16:57:12 +00:00
Jan Tojnar 4d234c01dd build: Switch to Meson’s gnome.post_install function
Instead of using a custom post install script.
This drops the GTK 3 dependency.

Required bumping minimum Meson version to 0.59
for the `update_desktop_database` kwarg.

https://mesonbuild.com/Gnome-module.html#gnomepost_install
2022-12-30 16:35:55 +00:00
Jan Tojnar 6c96a5e7b6 build: Bump Meson dependency to 0.59.0
Required for switching to `gnome.post_install()` function
with `update_desktop_database` kwarg.

Even newer version is available in bullseye-backports in Debian
so it should probably be fine.
2022-12-30 16:35:55 +00:00
Philip Withnall 54ebc3739e ci: Add missing dependencies
`libdbus-1-dev` is needed for the interfaces dir from `dbus-1.pc`, and
`desktop-file-utils` is needed for `update-desktop-database`.

These are needed due to updating Debian Unstable.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-12-30 16:35:15 +00:00
Philip Withnall 8c2a1dd73b Merge branch 'main' into 'main'
Update Hindi (hi) translation

See merge request pwithnall/malcontent!151
2022-11-29 11:29:51 +00:00
Hemish 3d1ec3047f Update Hindi (hi) translation 2022-11-29 13:07:23 +05:30
Philip Withnall 327173ba11 Merge branch 'hun-20220922' into 'main'
Update Hungarian translation

See merge request pwithnall/malcontent!150
2022-10-10 11:56:49 +00:00
Philip Withnall afb3f9630c Merge branch 'main' into 'main'
po: add Georgian translation

See merge request pwithnall/malcontent!149
2022-10-10 11:55:41 +00:00
Balázs Úr c577543af8 Update Hungarian translation 2022-09-22 21:55:47 +00:00
NorwayFun af4cd80fd5 add Georgian translation 2022-09-14 07:50:37 +00:00
NorwayFun 2ef945255c add Georgian 2022-09-14 07:50:08 +00:00
Georges Basile Stavracas Neto 741bc8a2b0 Merge branch 'gbsneto/release-0-11-0' into 'main'
0.11.0

See merge request pwithnall/malcontent!147
2022-08-12 15:10:26 +00:00
Georges Basile Stavracas Neto 810c16bbf1 0.11.0 2022-08-12 12:06:34 -03:00
Georges Basile Stavracas Neto e1c5b8a4fe Merge branch '52-focusable' into 'main'
restrict-applications-selector: Make rows not focusable

Closes #52

See merge request pwithnall/malcontent!146
2022-08-12 14:58:06 +00:00
Philip Withnall 950abf2e44 user-controls: Mark rows as not focusable
Only the controls inside them should be focusable. This saves having to
press the tab key twice as much as needed.

The row to open the restrict applications dialogue remains focusable, as
it doesn’t contain an interactive widget. It’s essentially one big
button.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #52
2022-07-25 23:53:24 +02:00
Philip Withnall 2e72916afb restrict-applications-selector: Make rows not focusable
The toggle switches remain focusable, but the rows should not be
focusable. Otherwise tabbing through the list involves two tabs per row.

The screen reader continues to work correctly with this MR applied: when
tabbing to a new switch, it reads out the label from the row, plus the
switch state.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #52
2022-07-25 23:53:24 +02:00
Philip Withnall 2f64f3865e Merge branch 'piotrdrag/fix-string' into 'main'
main: Restore previous whitespace in string

See merge request pwithnall/malcontent!145
2022-07-24 18:55:29 +00:00
Piotr Drąg 8416b0f263 main: Restore previous whitespace in string
So that we don’t change the string for no reason,
invalidating all existing translations.
2022-07-24 15:47:45 +02:00
Georges Basile Stavracas Neto a859e22e26 Merge branch 'wip/wjt/more-gtk4' into 'main'
Fix some build system leftovers from the GTK 4 port

See merge request pwithnall/malcontent!144
2022-07-22 12:22:04 +00:00
Will Thompson 8eba2f2ef3 Prepare for 0.11.0 release 2022-07-22 11:26:28 +01:00
Will Thompson ffba5dab43 libmalcontent-ui: Bump API version
An app which currently depends on malcontent-ui-0.pc or
MalcontentUi-0.gir will fail to compile or run, respectively, aganist
the GTK 4-ified version.

Bump the API version, which is used in both those names. This will also
(I think) allow the two versions of libmalcontent-ui to be
parallel-installed.
2022-07-22 11:13:33 +01:00
Will Thompson 922ae096be libmalcontent-ui: Fix includes for GIR
The libmalcontent-ui API exposes types from GTK 4 (not 3) and
libadwaita.
2022-07-22 11:12:47 +01:00
Will Thompson 1c7fe694fa Don't depend on gtk+-3.0 if xmllint is found
When validating the .ui files, we need to determine the path to GTK 4's
relaxng schema. Previously this was erroneously looked up in the prefix
of GTK 3, which malcontent otherwise doesn't depend on.

Define the GTK dependency once, and use that variable everywhere.
2022-07-22 11:09:35 +01:00
Georges Basile Stavracas Neto 2da5d5597e Merge branch 'gbsneto/gtk4' into 'main'
GTK4

See merge request pwithnall/malcontent!141
2022-07-20 22:27:51 +00:00
Georges Basile Stavracas Neto fe785d357d user-controls: Remove AdwPreferencesPage
AdwPreferencesPage is intended to be used as the first widget
inside page. It has an AdwClamp and a scrolled window to handle
just that.

Putting it in the MctUserControls widget is undesired, because
it introduces an oddly positioned scrolled window in the parental
controls page of Initial Setup, and if we ever reintroduce this
widgetry in Settings, it would suffer from the same problem.

Remove AdwPreferencesPage from MctUserControls, and replace it
with a vertical box. Add an AdwPreferencesPage in malcontent-controls
to compensate for that.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 9a35a09e24 malcontent-control: Update copyright headers
Append myself as the author of the files I've meaninfully changed.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto e8e9231d89 libmalcontent-ui: Cleanup CSS
Use named colors, and reimplement the disabled slider with a CSS
grayscale filter.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 61141a6670 restrict-applications-selector: Center-align app list
Simply expanding this list is enough to let the AdwClamp of
the parent AdwPreferencesGroup center it.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto d204944ae2 main: Improve visuals of loading label
Replace the manual scaling of the font size by a proper style
class, and center-align it vertically.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto a4ac1d644d user-selector: Purge items after listing users
The first call to act_user_manager_list_users() may lazily load
and notify the 'is-loaded' property, in which case we end up
indirectly recursing into reload_users(). Because we recurse
*after* purging carousel items, the same user is added twice:
once in the leaf recursion call, and once again in the call that
notified the 'is-loaded' property.

A simple workaround to this is purging carousel items after the
call to act_user_manager_list_users().
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto b5e516bea0 user-controls: Don't set popover direction
Let GTK handle that as it sees fit.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto e5ecc02488 user-controls: Remove OARS widgetry size group
We don't actually want the menu button to have the same size
of the popover, since the popover can grow pretty wide.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto b25a4e2119 carousel: Simplify arrow handling
The CSS-based animation is incompatible with the layout machinery
of GTK4, and we can't easily reintroduce it without another major
surgery in the carousel code, so just drop it for now.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 15172723dd carousel: Use revealer to calculate arrow offset
Now that the inner GtkStack has margins, it has an odd offset from
what we would expect. A better widget to use is the GtkRevealer,
which must cover the entire allocation, and therefore will always
produce the expected x offset.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 4887ded149 carousel: Replace size-allocate callback by a layout manager
GTK4 has no size-allocate signal anymore, but we can use a custom
layout manager to produce the same effect.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 3656cffcc0 carousel: Cleanup overlays
There are overlays inside overlays and that is not playing well
with event delivery - the main box is eating away clicks from the
userlist avatars.

Remove all that, and the extra overlays, and just leave one simple
overlay handling the whole widgetry.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 1d20fc50c9 carousel: Improve carousel box
This makes the carousel look more like what it used to.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto cd7d6a3845 carousel: Reindent file
No functional changes, just reindent the file.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto a9290f86b9 main: Make unlock button a pill
And set the 'suggested-action' style class too. This makes the
button more inline with modern GNOME HIG.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 486183a017 carousel: Move margins to inner stack 2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 0134e5d875 main: Remove has-default from buttons
This property is read-only in GTK4.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 8a8fe7b346 restrict-applications-dialog: Use close-request
Instead of delete-event. Pretty straightforward, 1:1 port to this
new signal.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 977b82f681 main: Remove can-default 2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto adaea91a4c carousel: Remove pass-through from overlay children
It doesn't exist anymore.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 3e1c14bda3 project: Port to GtkStack API changes 2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 6cd201166b main: Remove use-popover property from GtkMenuButton
It doesn't exist anymore.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 58fc4e0a5b main: Reimplement primary menu accellerator as a shortcut
In GTK4, the replacement to accelerators like this are shortcut
controllers.

Add a global shortcut controller to the primary menu button, and
bind it to F10.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 6fc250d5cf main: Adapt to GtkHeaderBar API changes 2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto dc1f68c7bc application: Port to gtk_show_uri_full()
A pretty straightfoward port, and most importantly, this function
actually exists in GTK4 :)
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto b71b83f348 carousel: Port MctCarousel to GTK4
Make it an AdwBin subclass. Purge all GtkContainer usage, and expose
GTK4-inspired API to add items to the carousel, and also to control
the internal GtkRevealer.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 0fca70768a carousel: Make MctCarouselItem subclass GtkButton
And add a setter to its internal child.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto e088443645 carousel: use double to translate coordinates
That's what GTK4 expects now.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 03ecb2dcb2 user-controls: Use GtkPopoverMenu API to set menu model
Pretty trivial replacement, since 'oars_popover' already is a
GtkPopoverMenu.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 6cb361efb9 user-image: Port to AdwAvatar
This simultaneously allows us to remove a lot of code, and make
Malcontent more consistent with the rest of the system.

Port MctUserImage to use an AdwAvatar internally. Make it inherit
AdwBin since it has a single child now.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto d4f219b71e user-controls: Use GtkRoot API to get toplevel
In practice, widgets that implement GtkRoot represent what
toplevel widgets used to. Use that instead.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 8c170d11a2 project: Port GdkScreen to GdkDisplay
API looks about the same, just switching to 'display'.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 6ee8b77b95 user-controls: Remove unused variable 2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto c39ffd45fc project: Remove unnecessary usage of gtk_widget_show()
Now that widgets are visible by default, no need to show them
after creating them. Also revove gtk_widget_show_all() which
doesn't exist in GTK4.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto bb0865eb23 project: Use gtk_window_present() to present windows
Instead of gtk_widget_show(). In practice, it's exactly the same,
but it'll make follow-up patches cleaner.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 360c5b0271 restrict-applications-selector: Adapt to GtkImage API changes
This was supposed to be a project-wide commit, but actually only
MctRestrictApplicationsDialog had APIs to be updated. MctUseImage
will undergo a major surgery soon, so it's left out.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 8560ca0677 project: Simplify buttons
GtkButton has an 'icon-name' property that greatly simplifies
setting up buttons. GtkMenuButton has a new 'always-show-arrow'
property that also allows us to simplify some code.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto c9f8bb22f6 restrict-applications-selector: Adapt to AdwActionRow
This greatly reduces the code size. GtkBin is no more, and
AdwActionRow has specific API to add suffix widgets.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 631df4f1a5 project: Adapt to GtkBox API changes
GtkBox provides a different API surface, such as gtk_box_append()
and gtk_box_prepend(), so switch to that.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 2d9b408a32 user-controls: Inherit from AdwBin
GtkBin is no more, but libadwaita has a nice 1:1 replacement which
is AdwBin.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto e322d8cd98 Hdy → Adw
This simply changes namespaces. Fortunately, no further widgetry
changes will be necessary - all the widgets and APIs seem to have
an exact match in libadwaita.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto d142554ed3 malcontent-control: Replace border-width by margins
The 'border-width' property does not exist in GTK4 anymore, so
replace it with margin-* and in one case just remove it entirely.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto a8484b9c07 project: Port to GTK4 accessibility framework
This was simple, since few widgets have accessibility properties
manually set. The 'static' role doesn't exist anymore, and GtkLabel
handles everything for us, so we can just drop it.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 262d6a6e7a project: Remove most can-focus properties
In GTK4, can-focus usage is much more specific to widget subclasses,
and in almost all cases it's not necessary to set it.

Remove it everywhere, except in one case where it still needs to be
manually set to False.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto 5bec6e8fdc project: Remove all visible=True properties
Start the GTK4 port by cleaning up all visible=True properties,
since widgets are visible by default on GTK4.
2022-07-20 19:23:12 -03:00
Georges Basile Stavracas Neto c31640fa12 build: Switch to GTK4 and libadwaita
Switch the build system to GTK4 and libadwaita, instead of GTK3
and libhandy.

This commit breaks the build.
2022-07-20 19:23:12 -03:00
Christopher Davis 52b4b490f3 dockerfile: Add libhandy as a dependency
Though it's unlikely Debian will have a version
new enough for us, it's still useful to have this an
advance. The meson subproject will work in cases where
we don't have a new enough version of libhandy.
2022-07-20 19:23:12 -03:00
Christopher Davis d11e609543 dependencies: Add libhandy as a subproject
Allows for building on systems that don't ship libhandy
or a version of libhandy that's new enough.
2022-07-20 19:23:12 -03:00
Christopher Davis 554b390cd4 main.ui: Use HdyStatusPage for status pages
We now have a nice pre-built widget for status pages
with an icon, title, description, and children.
We should take advantage of that instead of manually
setting up each status page.
2022-07-20 19:23:12 -03:00
Christopher Davis 73c1d7f3fe restrict-applications-selector: Hide placeholder when list isn't empty
Prevents a broken bottom border radius on the list.
2022-07-20 19:23:12 -03:00
Christopher Davis 9ed46ae597 restrict-applications-selector: Use HdyActionRow
Implements click-to-activate for rows in the dialog.
2022-07-20 19:23:12 -03:00
Christopher Davis c68058f0f3 restrict-applications: Use HdyPreferencesWindow
HdyPreferencesWindow provides a neat API we can use for
windows like this.
2022-07-20 19:23:12 -03:00
Christopher Davis 358cad3a24 user-controls: Use HdyPreferencesPage and HdyActionRow API
This allows us to get styling consistent with
HdyPreferencesWindow and similar content across GNOME.

Part of a consistency push for GNOME 40
2022-07-20 19:23:12 -03:00
Philip Withnall 598fab96a9 Merge branch 'fix-it-help' into 'main'
po: Fix markup error in Italian translation of the help

See merge request pwithnall/malcontent!143
2022-07-15 12:18:48 +00:00
Philip Withnall 766603676c po: Fix markup error in Italian translation of the help
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-07-15 13:16:29 +01:00
Christopher Davis d80ed10592 malcontent-control: Use HdyWindow and HdyHeaderBar 2022-07-13 12:00:33 -03:00
Philip Withnall f11d91da3a Merge branch 'gbsneto/appstream' into 'main'
libmalcontent-ui: Port to libappstream

Closes #51

See merge request pwithnall/malcontent!142
2022-07-13 14:29:08 +00:00
Georges Basile Stavracas Neto 25486a1df9 libmalcontent-ui: Port to libappstream
Depend on libappstream-dev, and include appstream.h instead of
appstream-glib.h.

We can depend on a new enough version of libappstream that all the
content rating symbols we need are available, which means that
`gs-content-rating.[ch]` can be dropped entirely.

Turns out no code changes are needed other than that.

Fixes: #51
2022-07-13 15:26:12 +01:00
Philip Withnall 0bbdb242a0 build: Bump Meson dependency to 0.57.0
This means we can depend on fix 42ba8efaf2 in Meson, which fixes use of
`volatile` in the default templates used by `gnome.mkenums_simple()`.
This fixes compiler warnings with recent compilers, which are promoted
to errors due to `-Werror`.

Meson 0.57.0 is available in bullseye-backports in Debian, which means
it’s available basically everywhere now.

Bumping the dependency required fixing a few deprecations in the
`meson.build` files.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-07-13 15:26:11 +01:00
Philip Withnall a732fd418d Merge branch 'main' into 'main'
update ru.po

See merge request pwithnall/malcontent!140
2022-06-20 09:43:56 +00:00
Ser82-png cae9044b92 update ru.po 2022-06-19 20:36:14 +10:00
Philip Withnall 40933baef2 Merge branch 'main' into 'main'
Update Russian translation

See merge request pwithnall/malcontent!139
2022-06-06 10:43:13 +00:00
Ser82-png c6581c49cd Update Russian translation 2022-06-05 11:43:28 +10:00
Philip Withnall 9d1e8ac3c5 0.10.5
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-05-31 13:56:40 +01:00
Philip Withnall 26961a0614 Merge branch 'main' into 'main'
Update Chinese (Taiwan) translation file.

See merge request pwithnall/malcontent!138
2022-05-31 12:52:16 +00:00
Freddy Cheng 788c13d827 Update Chinese (Taiwan) translation file. 2022-05-30 19:36:36 +00:00
Philip Withnall 0baa23ab44 Merge branch 'main' into 'main'
Update tr.po

See merge request pwithnall/malcontent!137
2022-05-19 13:51:20 +00:00
libre ajans 88a7c57fb0 Update tr.po 2022-05-19 13:42:32 +00:00
Philip Withnall 1a0b3e5d4b Merge branch 'polkornyipt-main-patch-69406' into 'main'
Update pt_BR.po

See merge request pwithnall/malcontent!136
2022-04-13 15:07:35 +00:00
Matheus Polkorny c36b5b268e Update pt_BR.po 2022-04-13 15:07:35 +00:00
Philip Withnall 0e89f39e89 Merge branch 'main' into 'main'
Add German help translation

See merge request pwithnall/malcontent!135
2022-03-21 13:15:26 +00:00
Tim Sabsch 069fe74e9c Add German help translation 2022-03-21 14:03:01 +01:00
Philip Withnall f8a7d0e372 Merge branch 'albanobattistella-main-patch-74286' into 'main'
Update it.po

See merge request pwithnall/malcontent!134
2022-03-14 11:47:22 +00:00
albanobattistella dbdc0d3f16 Update it.po 2022-03-12 15:13:38 +00:00
Philip Withnall d9bcc0537b 0.10.4
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-03-09 17:17:48 +00:00
Philip Withnall e1adf705cb help: Fix incorrect quoting in Italian .po file
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-03-09 17:17:48 +00:00
Philip Withnall 7259dab831 subproject: Bump libglib-testing to 0.1.1 for Meson fixes
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-03-09 17:07:23 +00:00
Philip Withnall 4b6e1521a6 Merge branch 'main' into 'main'
help: Add Italian help translation

See merge request pwithnall/malcontent!133
2022-01-17 13:38:47 +00:00
albanobattistella e1920eb287 help: Add Italian help translation 2022-01-17 13:36:46 +00:00
Philip Withnall db48b73b6e Merge branch 'fix-build-with-meson-0-61' into 'main'
Remove superfluous arguments to i18n.merge_file

See merge request pwithnall/malcontent!132
2022-01-17 13:29:09 +00:00
Heiko Becker f433aaf8c8 Remove superfluous arguments to i18n.merge_file
It fixes the build with meson 0.61.0. The positional argument was
ignored in the past, became a warning in meson 0.60 and a hard error
starting with 0.61.0.
2022-01-13 09:50:05 +01:00
Philip Withnall 88757a149c Merge branch 'albanobattistella-main-patch-66771' into 'main'
Update it.po

See merge request pwithnall/malcontent!129
2022-01-06 12:49:23 +00:00
albanobattistella aa61f7d8bd Update it.po 2022-01-06 12:31:41 +00:00
Philip Withnall 37e834e340 Merge branch 'main' into 'main'
Update German proof-read translation from https://l10n.gnome.org/vertimus/malcontent/main/po/de/

See merge request pwithnall/malcontent!128
2021-11-30 23:11:26 +00:00
Christian K 4332e90e8a Update German proof-read translation from https://l10n.gnome.org/vertimus/malcontent/main/po/de/ 2021-11-30 20:59:55 +00:00
Philip Withnall df0ab419dc Merge branch 'main' into 'main'
Update Catalan translation

See merge request pwithnall/malcontent!127
2021-11-11 10:22:52 +00:00
Jordi Mas b2a514cb25 Update Catalan translation 2021-11-10 18:15:18 +01:00
Philip Withnall 9dd47e5abc 0.10.3
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-11-01 11:10:05 +00:00
Philip Withnall dcf7265f55 Merge branch 'fix-focus' into 'main'
malcontent-control: Focus controls rather than user selector

See merge request pwithnall/malcontent!126
2021-10-12 14:08:58 +00:00
Philip Withnall ec7fa2529b libmalcontent-ui: Improve keynav between listboxes
Fix using the up and down keys to change the keyboard focus between rows
between the listboxes. Previously, keynav would fail at the bottom of
the first listbox, and at the top of the second.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-10-07 16:22:51 +01:00
Philip Withnall 98ebfaa20e malcontent-control: Focus controls rather than user selector
When showing the controls, focus them first rather than the user
selector. The correct user is probably already selected.

This has the added benefit of not drawing attention to the ugly focus
rectangle on the user selector.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-10-07 16:22:51 +01:00
Philip Withnall b311cbd2bf Merge branch 'fix-array-length' into 'main'
malcontent-control: Fix an unterminated option entry array

See merge request pwithnall/malcontent!125
2021-10-07 13:44:17 +00:00
Philip Withnall 6115ebf119 malcontent-control: Fix an unterminated option entry array
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-10-07 14:43:02 +01:00
Philip Withnall 6b45db7b1b Merge branch 'asciiwolf-l10n' into 'main'
Update Czech translation

See merge request pwithnall/malcontent!124
2021-10-04 10:32:38 +00:00
AsciiWolf a90a67013b Update Czech translation 2021-10-02 00:36:34 +02:00
Philip Withnall f0d330ccd7 Merge branch 'asciiwolf-l10n' into 'main'
Add Czech translation

See merge request pwithnall/malcontent!123
2021-10-01 08:51:00 +00:00
Philip Withnall 9d020326bf Merge branch 'asciiwolf-main-patch-62608' into 'main'
malcontent-control: Add <compulsory_for_desktop> to the AppData file

Closes #44

See merge request pwithnall/malcontent!122
2021-10-01 08:49:49 +00:00
AsciiWolf f123f52005 Add Czech translation 2021-10-01 00:24:52 +02:00
AsciiWolf ac9b8bea67 malcontent-control: Add <compulsory_for_desktop> to the AppData file 2021-09-30 22:06:08 +00:00
Philip Withnall 33b0692896 0.10.2
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-09-17 12:48:32 +01:00
Philip Withnall a22a8fdaf3 Merge branch 'master-to-main' into 'main'
ci: Rename master to main branch

See merge request pwithnall/malcontent!121
2021-09-17 11:40:10 +00:00
Philip Withnall de353089de ci: Rename master to main branch
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-09-17 12:39:17 +01:00
Philip Withnall 16982f4914 Merge branch 'wip/hadess/hide-icon-by-default' into 'master'
malcontent-control: Hide application in GNOME

See merge request pwithnall/malcontent!119
2021-09-06 14:41:45 +00:00
Philip Withnall 41980463ad Merge branch 'master' into 'master'
Update Indonesian translation of UI & help

See merge request pwithnall/malcontent!120
2021-09-06 13:23:45 +00:00
Andika Triwidada 4538cfeba3 Update Indonesian translation of UI & help 2021-09-06 13:23:45 +00:00
Bastien Nocera 6d0ee2b7ab malcontent-control: Hide application in GNOME
The parental controls application is instead accessed through the user
accounts GNOME Settings panel.
2021-08-26 17:00:42 +02:00
Philip Withnall 11f9288ef0 Merge branch 'subprojects-update' into 'master'
ci: Limit depth of clone of subprojects

See merge request pwithnall/malcontent!118
2021-03-22 17:55:58 +00:00
Philip Withnall 1b09aca666 ci: Limit depth of clone of subprojects
This saves bandwidth and CI image size.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-03-22 17:54:42 +00:00
Philip Withnall a0ec9f1f2f build: Post-release version bump to 0.11.0
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-03-22 17:49:24 +00:00
Philip Withnall 7a877f611a Merge branch 'l10n/it' into 'master'
l10n: update Italian translation

See merge request pwithnall/malcontent!117
2021-03-17 14:19:44 +00:00
Milo Casagrande 32c2709fb1 l10n: update Italian translation
Signed-off-by: Milo Casagrande <milo@milo.name>
2021-03-17 14:31:24 +01:00
Philip Withnall e0fac33638 0.10.1
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-03-11 14:14:16 +00:00
Philip Withnall 04fbddbfa7 Merge branch 'drop-eos-link' into 'master'
libmalcontent-ui: Drop handling of eos-link desktop files

See merge request pwithnall/malcontent!116
2021-03-11 13:52:41 +00:00
Philip Withnall af3a8b33db libmalcontent-ui: Drop handling of eos-link desktop files
They are being dropped in Endless OS, and would have been filtered out
by the fact they’re not flatpaks anyway.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-03-11 13:50:53 +00:00
Philip Withnall ff8ec54b22 Merge branch '32-sort-on-name' into 'master'
libmalcontent-ui: Sort apps on the visible name

Closes #32

See merge request pwithnall/malcontent!115
2021-02-26 18:20:48 +00:00
Will Thompson fc047e6e67 libmalcontent-ui: Sort apps on the visible name
Previously, we sorted apps based on their display name, but
(confusingly) displayed their name. This leads to inconsistencies like
Rhythmbox being sorted (in French) as "Lecteur de musique Rhythmbox"
which places it between Krita and LibreOffice, but displayed as
"Rhythmbox".

Fixes #32
2021-02-25 14:12:20 +00:00
Philip Withnall b067a84266 Merge branch 'piotrdrag/pl-update-201220' into 'master'
Update Polish translation 201220

See merge request pwithnall/malcontent!113
2020-12-21 14:24:52 +00:00
Piotr Drąg c76c2346dc Update Polish translation 2020-12-20 13:34:13 +01:00
Philip Withnall 515a96fab4 Merge branch 'l10n-sv' into 'master'
Update Swedish translation

See merge request pwithnall/malcontent!112
2020-12-18 10:02:57 +00:00
Anders Jonsson e2644f8ed2 Update Swedish translation 2020-12-17 18:56:33 +01:00
Philip Withnall b35be5bd8d 0.10.0
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-12-09 16:53:16 +00:00
Philip Withnall f73fb35207 Merge branch 'system-repo-permissions' into 'master'
accounts-service: Allow installation to the system repo by default

See merge request pwithnall/malcontent!111
2020-12-09 16:23:16 +00:00
Philip Withnall cc195235ac Merge branch '15-padding-again' into 'master'
ui: Increase spacing between labels and buttons to 18px

Closes #15

See merge request pwithnall/malcontent!110
2020-12-09 16:23:02 +00:00
Philip Withnall b4a74b0fa4 accounts-service: Allow installation to the system repo by default
Note that this permissions check only concerns parental controls. If the
system flatpak polkit policy disallows installation to the system repo
(or requires an administrator password for it), this setting cannot
override that.

The default was previously to disallow installation, because the flatpak
polkit policy was previously overridden by these settings. How parental
controls are checked in flatpak has evolved since then, though.

See: https://github.com/flatpak/flatpak/issues/3995

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-12-09 16:08:52 +00:00
Philip Withnall ebad35703b ui: Increase spacing between labels and buttons to 18px
Was previously 12px, but the buttons are slightly logically separate
from the labels, so it should be 18px according to
https://developer.gnome.org/hig/stable/visual-layout.html.en.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #15
2020-12-09 15:53:31 +00:00
Philip Withnall c2c25a14aa Merge branch 'uk_update5' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!109
2020-12-09 09:17:54 +00:00
Yuri Chornoivan 63e2ec7809 Update Ukrainian translation 2020-12-09 09:03:57 +02:00
Philip Withnall d0153db94a Merge branch 'uk_update4' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!108
2020-12-08 20:29:15 +00:00
Yuri Chornoivan badd856534 Update Ukrainian translation 2020-12-08 22:22:21 +02:00
Philip Withnall d352fe2550 Merge branch '25-initial-screen' into 'master'
malcontent-control: Change wording on no-other-users page

Closes #25

See merge request pwithnall/malcontent!90
2020-12-08 16:37:04 +00:00
Philip Withnall 9335565fe3 malcontent-control: Change wording on no-other-users page
Clarify that a standard user account has to be created, and then
parental controls enabled for it — and that clicking the button will
open the control centre.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #25
Helps: #26
2020-12-08 16:35:07 +00:00
Philip Withnall 045ed2ec02 Merge branch '13-terminology' into 'master'
Resolve "Consider terminology of ‘parental controls’"

Closes #13

See merge request pwithnall/malcontent!99
2020-12-08 12:18:14 +00:00
Philip Withnall 351a7811e5 Merge branch 'appstream-glib-dep' into 'master'
Bump appstream-glib dep and update content rating code

See merge request pwithnall/malcontent!100
2020-12-08 12:18:09 +00:00
Philip Withnall 854ea21fb4 Merge branch 'csm-guidance' into 'master'
malcontent-control: Add link to guidance on how to set parental controls

See merge request pwithnall/malcontent!103
2020-12-08 12:18:07 +00:00
Philip Withnall 8a8405fc4e Merge branch 'use-case-docs' into 'master'
docs: Add a development principles section to the README

See merge request pwithnall/malcontent!104
2020-12-08 12:17:52 +00:00
Philip Withnall 2010898947 malcontent-control: Add link to guidance on how to set parental controls
Try and nudge parents/carers towards the best practice for how to set
parental controls on a user, by linking them to appropriate external
content from people who know what they’re talking about.

This external content can vary in the translations so that parents are
pointed to appropriate localised guidelines. In the UK, for example,
this may be
https://www.nspcc.org.uk/keeping-children-safe/online-safety/.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-12-04 11:58:06 +00:00
Philip Withnall 01e861f317 Merge branch 'uk_update3' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!107
2020-11-22 17:55:28 +00:00
Yuri Chornoivan e50c0c58d6 Update Ukrainian translation 2020-11-22 17:55:28 +00:00
Philip Withnall 34c774addc Merge branch '30-drop-user-repos' into 'master'
malcontent-control: Drop ‘Restrict Application Installation for Others’

Closes #30

See merge request pwithnall/malcontent!105
2020-11-21 22:37:28 +00:00
Philip Withnall 60a46fb623 Merge branch 'patch-1' into 'master'
Update Danish translation

See merge request pwithnall/malcontent!106
2020-11-18 09:38:58 +00:00
scootergrisen b71424a4e2 Update Danish translation 2020-11-18 09:38:58 +00:00
Philip Withnall cd36d90091 malcontent-control: Drop ‘Restrict Application Installation for Others’
This simplifies the UI, as nobody really understood the difference
between ‘Restrict Application Installation’ and ‘Restrict Application
Installation for Others’. Now there’s just a ‘Restrict Application
Installation’ checkbox, which controls application installation in the
home and system flatpak repos.

The underlying app-filter representation in libmalcontent still supports
restricting installation to them separately, but the UI will always set
them to the same value.

There is a suggestion that we may want to support user repos again in
future iff the user has added a remote to their user repo. However,
figuring that out for other users (which is what the admin would have to
do when setting this all up) starts to get tricky with permissions for
reading other users’ home directories. Skip that for the moment — we can
reconsider adding that option in future if someone argues a case for it.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #30
2020-11-15 17:31:21 +00:00
Philip Withnall 07ee189e2c docs: Add a development principles section to the README
This documents some development principles which should be borne in mind
when working on new malcontent features.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-11-05 11:37:11 +00:00
Philip Withnall 8e65091fc2 Merge branch 'app-filter-unchanged' into 'master'
user-controls: Only save the app filter if it’s changed

See merge request pwithnall/malcontent!102
2020-11-04 09:50:05 +00:00
Philip Withnall cac7ba414c user-controls: Only save the app filter if it’s changed
This prevents a polkit authentication prompt popping up unexpectedly if,
for example, a non-privileged user has opened and immediately closed
malcontent-control.

Spotted by Andre Moreira Magalhaes.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-11-03 17:49:00 +00:00
Philip Withnall ecd541b2e9 libmalcontent: Add mct_app_filter_equal() comparison method
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-11-03 17:49:00 +00:00
Philip Withnall a045e9fc51 Merge branch 'ui-load-saved-app-filter' into 'master'
Fix partial loss of parental controls settings when partially updating them

See merge request pwithnall/malcontent!101
2020-11-02 13:31:08 +00:00
Philip Withnall ecfb3035d5 libmalcontent-ui: Load restricted apps and OARS when loading app filter
While the label for the OARS pseudo-combobox was updated when loading a
user’s app filter, the internal state (`self->selected_age`) was not.
Similarly, the set of restricted apps wasn’t loaded until the restricted
apps dialog was opened.

This caused problems when loading a user’s parental controls and then
editing a control which *wasn’t* restricted apps or the OARS level. The
resulting app filter would be built using default values for those two
controls, overwriting and losing their previous values when it was
saved.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-29 19:22:13 +00:00
Philip Withnall e7588a2333 libmalcontent-ui: Sync switches with app filter when loading selector
Since the changes to avoid reloading the app list entirely when loading
an app filter (commit 9d4639cf49), the switch states haven’t been set
properly when loading a new app filter, since the app rows already
exist, and the switch states were only set on creation.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-29 19:20:14 +00:00
Philip Withnall fc5432205c gs-content-rating: Backport OARS/CSM mapping changes from appstream-glib
This is a backport of commit f742cc3cf2428 from appstream-glib:

    as-content-rating: Align the OARS/CSM mappings of sex-*

    Align the OARS/CSM mappings of sex-homosexuality and sex-themes, as the
    two are identical apart from discriminating on sexual orientation.

    This is a follow-up to commit 01e9ee8113a8ad.

    Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-29 15:13:09 +00:00
Philip Withnall 1371e1c819 libmalcontent-ui: Bump appstream-glib dependency to ≥ 0.7.15
This allows some (but not all) of the fallback code to be dropped.
appstream-glib 0.7.17 is available on all versions of Fedora and Debian
which malcontent is packaged for:
 • https://packages.debian.org/search?suite=bullseye&searchon=names&keywords=appstream-glibhttps://src.fedoraproject.org/rpms/libappstream-glib

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-29 15:10:00 +00:00
Philip Withnall f791ded58f docs: Document terminology used in the project
This is to be referred to by developers when working on the project, and
documents the decisions behind the terminology used.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #13
2020-10-28 17:01:44 +00:00
Philip Withnall ac2ed2c21a docs: Tidy up wording in DOAP file
We’re standardising on ‘parental controls’ as terminology, and moving
away from explicitly referring to ‘children’.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #13
2020-10-28 16:35:18 +00:00
Philip Withnall d31d021896 help: Clarify that parental controls can be used in other situations
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #13
2020-10-28 16:34:42 +00:00
Philip Withnall e1cd202ad5 Merge branch '4-manpage' into 'master'
Resolve "Add manpage docs for malcontent-client monitor, set and oars-section commands"

Closes #4

See merge request pwithnall/malcontent!98
2020-10-27 18:28:31 +00:00
Philip Withnall c40d5ff9b4 malcontent-client: Add newer subcommands and examples to man page
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #4
2020-10-27 18:26:51 +00:00
Philip Withnall 194fef286e malcontent-client: Update support URI in man page
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #4
2020-10-27 18:26:32 +00:00
Philip Withnall adbf176186 Merge branch 'piotrdrag/pl-update-201025' into 'master'
Update Polish translation 201025

See merge request pwithnall/malcontent!96
2020-10-26 09:55:39 +00:00
Piotr Drąg cbf0586fe8 Update Polish translation 2020-10-25 09:26:13 +01:00
Philip Withnall 540c337ae1 Merge branch '19-select-user' into 'master'
Resolve "Add command line option to malcontent-control to pre-select a user"

Closes #19

See merge request pwithnall/malcontent!95
2020-10-22 13:38:22 +00:00
Philip Withnall b6a0b14cdd Merge branch '28-empty-app-list' into 'master'
Fix several issues with the app list in the restrict applications dialogue

Closes #28 and #18

See merge request pwithnall/malcontent!92
2020-10-20 18:14:18 +00:00
Philip Withnall 93b88af0c1 libmalcontent-ui: Reload the app list when it changes on the system
This will no longer destroy in-progress user input.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #18
2020-10-20 19:13:01 +01:00
Philip Withnall e1b5bcd324 libmalcontent-ui: Load the app list when constructing the apps selector
Rather than waiting until an app filter is set on the application
selector, load the app list immediately at construction time. This is
now possible because it can be diffed easily when the app filter is set.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #28
2020-10-20 19:13:01 +01:00
Philip Withnall 9d4639cf49 libmalcontent-ui: Cache and diff the app list when rebuilding it
Instead of removing all the entries in the list store when the set of
installed apps is updated, diff the old and new lists so that removed
apps can be selectively removed from the list store, and added apps can
be selectively added.

This means that we can (in subsequent commits) reload the app list less
conservatively, as doing so will no longer remove in-progress user
modifications to the set of blocked apps. Modifications are still only
saved when the restrict applications dialogue is closed.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #18, #28
2020-10-20 19:13:01 +01:00
Philip Withnall 60754b6745 build: Bump version for new release series
This will allow g-c-c to check for version 0.10 at compile time.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-20 12:41:05 +01:00
Philip Withnall db54baf9d6 malcontent-control: Add a --user command line argument
This is handled on the primary instance, and causes the tab to be
switched to show the given username (if possible).

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #19
2020-10-19 17:55:47 +01:00
Philip Withnall 5efc773bda malcontent-control: Add API to select users by username
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-19 17:54:37 +01:00
Philip Withnall 887b8c9b9b Merge branch 'piotrdrag/pl-update-201018' into 'master'
Update Polish translation 201018

See merge request pwithnall/malcontent!94
2020-10-19 09:39:41 +00:00
Philip Withnall 03f207965b Merge branch 'uk_update3' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!93
2020-10-19 09:39:23 +00:00
Piotr Drąg 4e9c95e3fe Update Polish translation 2020-10-18 13:15:20 +02:00
Yuri Chornoivan faa0fa94d8 Update Ukrainian translation 2020-10-17 16:57:43 +03:00
Philip Withnall 1d5da7c094 libmalcontent-ui: Adjust the app list sort to be more stable
This doesn’t achieve anything by itself, but makes some upcoming commits
to diff the new/old app lists work properly.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Helps: #18, #28
2020-10-15 16:40:10 +01:00
Philip Withnall d01f063c39 libmalcontent-ui: Add g_autolist() to simplify memory management
This introduces no functional changes.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-15 15:09:11 +01:00
Philip Withnall 792a069736 Merge branch 'string-rationalisation' into 'master'
libmalcontent: Rationalise a couple of translatable strings

See merge request pwithnall/malcontent!91
2020-10-15 13:56:12 +00:00
Philip Withnall ee290a21e6 libmalcontent: Rationalise a couple of translatable strings
Following on from commit b5b1ac2, change a couple of other strings to be
the same to reduce the number of translatable strings. These strings are
unlikely to ever be seen by the user, so it’s not an issue that they’re
becoming a little less specific.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-10-15 14:54:46 +01:00
Philip Withnall ba5dccfde0 Merge branch 'wip/tolerate-no-accountsservice' into 'master'
manager: Return MCT_MANAGER_ERROR_DISABLED if no accountsservice

Closes #27

See merge request pwithnall/malcontent!89
2020-10-15 13:52:45 +00:00
Simon McVittie b5b1ac26a2 manager: Make an error message less specific
Philip Withnall pointed out that if mct_manager_get_session_limits()
fails with G_DBUS_ERROR_ACCESS_DENIED or
org.freedesktop.Accounts.Error.PermissionDenied, the error message
will wrongly refer to app filter data. Make it more generally applicable.

Signed-off-by: Simon McVittie <smcv@debian.org>
2020-10-15 09:05:56 +01:00
Simon McVittie 1abce3eb91 manager: Return MCT_MANAGER_ERROR_DISABLED if no accountsservice
In distributions that package shared libraries and daemons separately,
it's possible to have the shared library (because it's required to run
something like Flatpak) but not the accountsservice daemon or its
malcontent extension (because the administrator of this particular
installation has no interest in parental controls, and their choice of
desktop environment is such that nothing else depends on accountsservice
either). This minimizes the memory and disk space cost of enabling the
libmalcontent feature in Flatpak for those who do not need it, while
keeping it available for those that do.

Treat this the same as if accountsservice is available but the
malcontent extension is not: fail open, by returning
MCT_MANAGER_ERROR_DISABLED.

Resolves: https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/27
Bug-Debian: https://bugs.debian.org/972145
Signed-off-by: Simon McVittie <smcv@debian.org>
2020-10-15 09:04:13 +01:00
Philip Withnall 5c0a7bf056 Merge branch 's1' into 'master'
Add Danish translation

See merge request pwithnall/malcontent!88
2020-10-12 11:13:39 +00:00
scootergrisen fe5deabdf4 Add Danish translation 2020-10-11 23:00:16 +02:00
Philip Withnall dbe726fb5e Merge branch 'master' into 'master'
l10n-sv

See merge request pwithnall/malcontent!87
2020-09-14 14:28:02 +00:00
Anders Jonsson 2c37e217b4 Add Swedish help translation 2020-09-14 16:10:12 +02:00
Anders Jonsson 40373ee255 Update Swedish translation 2020-09-14 16:00:39 +02:00
Philip Withnall f9d283ac83 Merge branch 'l10n-it' into 'master'
l10n: Update Italian translation

See merge request pwithnall/malcontent!86
2020-09-14 08:29:16 +00:00
Milo Casagrande bda8b88bbc l10n: Update Italian translation
Signed-off-by: Milo Casagrande <milo@milo.name>
2020-09-14 09:56:01 +02:00
Philip Withnall bbe53b521f Merge branch 'uk_update2' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!85
2020-09-10 08:55:31 +00:00
Yuri Chornoivan aca7f0aeab Update Ukrainian translation 2020-09-10 09:35:18 +03:00
Philip Withnall f592d0e36c Merge branch 'appstream-validation' into 'master'
Fix strict appdata validation

Closes #23

See merge request pwithnall/malcontent!84
2020-09-08 12:04:08 +00:00
Philip Withnall 8789d8980b malcontent-control: Add descriptive paragraphs to appdata releases
This fixes strict validation.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #23
2020-09-08 12:52:17 +01:00
Philip Withnall b25110beab malcontent-control: Add a screenshot to the appdata
This fixes a problem with strict validation.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #23
2020-09-08 12:51:53 +01:00
Philip Withnall bf9bf5e8ba 0.9.0
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-09-03 12:03:51 +01:00
Philip Withnall bb427946f9 Merge branch 'master' into 'master'
Update Spanish translation

See merge request pwithnall/malcontent!83
2020-09-01 12:08:35 +00:00
Adolfo Jayme Barrientos 26661fa64b Update Spanish translation 2020-08-22 09:42:06 -05:00
Philip Withnall 61c6becfcd Merge branch 'subproject-depth' into 'master'
subprojects: Limit depth when cloning

See merge request pwithnall/malcontent!82
2020-07-22 13:57:56 +00:00
Philip Withnall a6601a934b subprojects: Limit depth when cloning
This reduces the bandwidth requirements of subprojects a little.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-07-21 12:43:24 +01:00
Philip Withnall 97e6205900 Merge branch 'ci-revamp' into 'master'
ci: Use pre-built Docker images for CI builds

See merge request pwithnall/malcontent!81
2020-07-21 11:10:25 +00:00
Philip Withnall e6f82a4a86 ci: Use pre-built Docker images for CI builds
Rather than updating the packages on a generic Debian Unstable image
every time a CI build happens, pre-build the image and pre-download all
the dependencies.

This should speed the CI runs up; they currently take about 4 minutes.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-07-21 11:58:51 +01:00
Philip Withnall 9161baf0cd Merge branch 'patch-1' into 'master'
Update Brazilian Portuguese translation

See merge request pwithnall/malcontent!80
2020-07-21 10:10:26 +00:00
Rafael Fontenelle 9dd477df9e Update Brazilian Portuguese translation 2020-07-18 11:26:19 -03:00
Philip Withnall ab75b35d91 Merge branch 'subprojects-again' into 'master'
build: Re-add libglib-testing subproject

See merge request pwithnall/malcontent!79
2020-07-07 14:32:14 +00:00
Philip Withnall 81964dec1f build: Re-add libglib-testing subproject
This time, add it as a wrap module rather than a git submodule. They’re
easier to manage, and integrate better with Meson.

The subproject has to be re-added so that malcontent can be built on
Debian Stable and Fedora 31 for the gnome-software CI. See
https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/487.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-07-07 15:29:11 +01:00
Philip Withnall 7d9c32aa9a Merge branch 'source_root' into 'master'
build: Use meson.current_source_dir() instead of source_root()

See merge request pwithnall/malcontent!78
2020-07-06 10:02:50 +00:00
Philip Withnall d085c7f585 build: Use meson.current_source_dir() instead of source_root()
The latter doesn’t work well when building as a subproject — it
explicitly refers to the parent project root.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-07-06 10:59:45 +01:00
Philip Withnall c4853f0f02 Merge branch 'codespell' into 'master'
all: Fix various typos and incorrect terminology

See merge request pwithnall/malcontent!77
2020-06-18 16:39:53 +00:00
Philip Withnall 363bd53e7d Merge branch 'privileged_group' into 'master'
Add option to tweak privileged group in polkit rules

Closes #22

See merge request pwithnall/malcontent!76
2020-06-18 13:12:39 +00:00
Philip Withnall 73d7c5e113 all: Fix various typos and incorrect terminology
Done using:
```
codespell \
    --builtin clear,rare,usage \
    --skip './po/*' --skip './help/*/*.po' --skip './.git/*' --skip './NEWS*' \
    --write-changes .
```
and then some manual checking and editing.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-06-18 13:51:35 +01:00
Sergey Shatunov ffb1279301
Use sudo group in debian ci build
Signed-off-by: Sergey Shatunov <me@prok.pw>
2020-06-18 03:39:01 +07:00
Sergey Shatunov 0114e4d965
Add option to tweak privileged group in polkit rules
Signed-off-by: Sergey Shatunov <me@prok.pw>
2020-06-18 03:35:36 +07:00
Philip Withnall ce26ca909c Merge branch 'piotrdrag/pl-update-200614' into 'master'
Update Polish translation 200614

See merge request pwithnall/malcontent!75
2020-06-17 17:42:22 +00:00
Piotr Drąg b200d8a4a8 Update Polish translation 2020-06-14 13:50:00 +02:00
Philip Withnall ae9ea66095 Merge branch 'uk_update' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!74
2020-06-10 18:04:29 +00:00
Yuri Chornoivan 01279055cc Update Ukrainian translation 2020-06-10 20:39:52 +03:00
Philip Withnall 63f59aee71 Merge branch 'translations' into 'master'
po: Update translations from downstream in Endless

See merge request pwithnall/malcontent!73
2020-06-10 11:40:18 +00:00
Philip Withnall 46aaefeffc po: Update translations from downstream in Endless
We’ll drop the Transifex translation machinery downstream after this, so
this is the last time the translations will be synced.

I have not verified any of these translations, but am upstreaming them
on the premise that some strings are better than no strings.

This commit was produced by:
 1. `ninja malcontent-update-po`
 2. Copy in po files from downstream
 3. `ninja malcontent-update-po` again
 4. Manually drop header-only changes
 5. Manually drop changes to `translator-credits`
 6. Manually drop some conflicted strings from `id.po` (prefer the
    upstream versions)
 7. Manually merge headers

There are no more `help/` translations to upstream.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-06-10 12:37:21 +01:00
Philip Withnall 93b5fa3ea2 po: Update po files
This is simply the result of
```
ninja malcontent-update-po
```

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-06-10 12:36:55 +01:00
Philip Withnall f97b9e0c64 Merge branch 'inclusive-terminology' into 'master'
tree-wide: Replace usages of whitelist/blacklist

See merge request pwithnall/malcontent!72
2020-06-10 08:55:23 +00:00
Matthew Leeds 15e8a74b21 tree-wide: Replace usages of whitelist/blacklist
Replace usages of the terms whitelist and blacklist with the more
inclusive and more precise terms allowlist and blocklist, which are
actually also more consistent with parts of the codebase, e.g.
mct_app_filter_is_content_type_allowed().

The only API break here is in libmalcontent/app-filter.h but the
relevant API is not used anywhere else in Endless OS beyond this repo,
nor to my knowledge in any other distribution. Also, per the README,
this project's API is not stable, so now is a good time to make this
change.
2020-06-09 15:35:21 -07:00
Philip Withnall c6fd3c0ad3 Merge branch 'oars-csm-update' into 'master'
gs-content-rating: Backport OARS/CSM mapping changes from appstream-glib

Closes #21

See merge request pwithnall/malcontent!71
2020-06-09 10:10:45 +00:00
Philip Withnall 2d4e8e0012 gs-content-rating: Backport OARS/CSM mapping changes from appstream-glib
This is a backport of commit 01e9ee8113 from appstream-glib:

    as-content-rating: Lower the OARS/CSM mapping of sex-homosexuality/intense

    This rationalises it with the OARS/CSM mapping of
    sex-themes/intense, and with many western societal norms. It is
    against the laws and morals of various western countries to discriminate
    on sexual orientation, so the mappings for sex-homosexuality/intense and
    sex-themes/intense should be the same.

    The mappings for the other values of sex-homosexuality and sex-themes
    remain different, as their descriptions aren’t as comparable (for
    example, for `mild`, the descriptions are “Indirect references to
    homosexuality” vs “Provocative references or descriptions”).

    The sex-homosexuality ratings category does need to continue to exist,
    though, as it’s illegal in some countries to *not* discriminate on
    sexual orientation. Those countries can provide and maintain their own
    OARS/age mappings.

    See https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/21.
    This issue is now being solved in appstream-glib as the content rating
    code has been moved there so it can be shared between malcontent and
    gnome-software.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/21
2020-06-09 11:07:54 +01:00
Philip Withnall 14f0284a60 Merge branch 'content-rating-rationalisation' into 'master'
Use appstream-glib implementation of content rating systems

Closes #7

See merge request pwithnall/malcontent!70
2020-06-09 09:06:22 +00:00
Philip Withnall 52399e8d58 libmalcontent-ui: Use appstream-glib code for content rating systems
If a suitably new version of appstream-glib is available, use its
implementation of content rating systems (see
https://github.com/hughsie/appstream-glib/pull/364), rather than our
forked one.

This adds a dependency on libappstream-glib, but no particular version.

Eventually, our copy of `gs-content-rating.[ch]` can be dropped.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #7
2020-05-21 16:25:21 +01:00
Philip Withnall 12c1718782 libmalcontent-ui: Fix inconsistencies in OARS → CSM mappings
This incorporates the following commits from gnome-software:
 • 4db48ef429501d86a45e87eaf8dd97e59dea0d58
 • a62b57a60f886a61c30f17b08277c1b826068a9d
 • 617f0de4f109efe319de36cbc42076e667578eda

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-21 16:14:09 +01:00
Philip Withnall 2a87b85fe1 libmalcontent-ui: Add an explicit array length argument to a function
This aligns the copy of the API here with what’s being proposed in
appstream-glib (https://github.com/hughsie/appstream-glib/pull/364). In
a few commits’ time, this copy will be deprecated.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-21 16:03:46 +01:00
Philip Withnall 150d303d39 fixup! libmalcontent-ui: Update content rating formatting code 2020-05-21 16:02:40 +01:00
Philip Withnall 9064babe6f fixup! libmalcontent-ui: Update content rating formatting code 2020-05-21 16:01:10 +01:00
Philip Withnall 6174eebd55 libmalcontent-ui: Drop an unused content rating function
This drops a load of translatable strings which aren’t used in
malcontent.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-21 12:34:46 +01:00
Philip Withnall a27f96517f libmalcontent-ui: Choose rating system by territory rather than language
This incorporates commit ed981f1d26f9a2c086eeccdee2909959de64f908 from
gnome-software, which ensures that content rating systems are chosen by
territory rather than language.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-21 12:31:41 +01:00
Philip Withnall 396dd3c039 libmalcontent-ui: Update content rating formatting code
This incorporates commit 7d00c4d84b2a47dd815dc88da1a82dc54800d4b6 from
gnome-software, which allows the ESRB strings to be localised.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-21 12:30:05 +01:00
Philip Withnall 77b8704cb4 Merge branch 'ui-tweaks' into 'master'
Two small UI tweaks

See merge request pwithnall/malcontent!69
2020-05-01 15:52:54 +00:00
Philip Withnall 9b3dedd9ed malcontent-control: Centre the user controls
This causes the controls on the main window to be centred at their full
width (when there’s enough window width to do so), rather than expanding
to fill the entire window.

It’s not currently possible with GTK+3 to easily set a maximum width
(of, say, 600px) to the column, without writing a custom widget (like
`HdyColumn` does).

From a suggestion by Nick Richards
(https://www.nedrichards.com/2020/04/endless-3.8.0-beta-1-trip-report/).

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-01 16:11:39 +01:00
Philip Withnall c835bcdc9a user-controls: Make whole ‘Restrict Applications’ row activatable
Previously, just the button at the end was activatable, but making the
whole row activatable makes it an easier hit target.

From a suggestion by Nick Richards
(https://www.nedrichards.com/2020/04/endless-3.8.0-beta-1-trip-report/).

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-05-01 15:20:09 +01:00
Philip Withnall 659d22ba34 0.8.0
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-28 14:07:37 +01:00
Philip Withnall 785c5d25cc Merge branch 'wip/jtojnar/meson-cleanups' into 'master'
Various meson cleanups

See merge request pwithnall/malcontent!50
2020-04-28 13:00:25 +00:00
Jan Tojnar 38c1170bda tests: Respect pamlibdir in installed tests
The build allows configuring pam module installation path but then it did
not respect it in installed tests.
2020-04-28 13:57:29 +01:00
Philip Withnall 01bf39cdc6 Merge branch 'i18n-lib' into 'master'
Fix translation of libmalcontent-ui

See merge request pwithnall/malcontent!68
2020-04-27 13:21:43 +00:00
Philip Withnall f856d46571 libmalcontent-ui: Explicitly state translation domains in UI files
This means the strings are always translated using the correct domain,
regardless of which program libmalcontent-ui is used in.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-27 12:11:39 +01:00
Philip Withnall 28d496926d libmalcontent: Add a constructor to bind the translation domain
This ensures that the translation domain is loaded for malcontent as
soon as the library is loaded.

The same is not needed for libmalcontent-ui, because it always causes
libmalcontent to be loaded.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-27 12:10:58 +01:00
Philip Withnall 3556813c55 libmalcontent-ui: Use library i18n functions
Rather than application i18n functions and `#include`s. This ensures
that the correct translation domain is used.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-27 11:55:10 +01:00
Philip Withnall 0d31a38855 Merge branch 'add-help-pt_BR' into 'master'
Add Brazilian Portuguese translation

See merge request pwithnall/malcontent!67
2020-04-27 10:40:11 +00:00
Rafael Fontenelle c98924480f Add Brazilian Portuguese translation 2020-04-24 14:19:14 -03:00
Philip Withnall 8b0f0ac23a Merge branch 'patch-1' into 'master'
Update Brazilian Portuguese translation

See merge request pwithnall/malcontent!66
2020-04-21 10:21:14 +00:00
Rafael Fontenelle 0155a10031 Update Brazilian Portuguese translation 2020-04-21 02:20:12 +00:00
Philip Withnall 110d80be70 Merge branch 'translator-comments' into 'master'
Add translator comments for about dialog strings

See merge request pwithnall/malcontent!65
2020-04-20 13:08:13 +00:00
Will Thompson a626236f59 Add translator comments for about dialog strings
When ordering commercial translations, at least one translator
translated these literally, eg "Sitio web de mal gusto" and
"créditos-de-traductor".

It's likely that translators familiar with GNOME would not make this
mistake, but let's be explicit anyway.
2020-04-20 13:47:22 +01:00
Philip Withnall e225ba8e96 Merge branch 'import-zh_TW' into 'master'
Import zh_TW translation from Endless

See merge request pwithnall/malcontent!64
2020-04-20 10:39:27 +00:00
Will Thompson b713180b59 Import zh_TW translation from Endless
These translations are taken from the eos3.7 branch of
gnome-control-center. I apparently missed these when importing the last
batch in 39bdde5, I think due to the empty zh_TW.po file generated by
`ninja malcontent-update-po` being in some broken encoding that polib
can't read. I tried a different approach here:

- Copy the file from gnome-control-center
- `ninja malcontent-update-po`
- Manually remove fuzzy and obsolete translations
- `ninja malcontent-update-po`
2020-04-17 23:18:24 +01:00
Philip Withnall ffbe93d91e Merge branch 'import-endless-translations' into 'master'
Import translations from Endless

See merge request pwithnall/malcontent!63
2020-04-16 09:31:08 +00:00
Philip Withnall 2c0eea4ce5 Merge branch 'no-more-subprojects' into 'master'
Remove use of libglib-testing subproject

See merge request pwithnall/malcontent!3
2020-04-15 14:31:45 +00:00
Philip Withnall d85126da9d build: Stop building libglib-testing as a subproject
Just add it as a dependency instead. It’s a lot less painful (git
submodules are still a pain to use; and `git evtag` doesn’t work well
with them); and libglib-testing has just done a 0.1.0 release which we
can depend on.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-15 15:03:39 +01:00
Philip Withnall d374ea676f ci: Switch from Fedora to Debian for CI
Debian Unstable now has libglib-testing packaged, which can be used to
avoid having to build it as a submodule. Otherwise, building on Debian
should be largely equivalent to building on Fedora.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: !3
2020-04-15 15:02:33 +01:00
Will Thompson 39bdde59d6 Import translations from Endless
Much of this code previously lived in Endless's fork of
gnome-control-center, and so many strings had previously been translated
there. I imported a bunch of them from
https://github.com/endlessm/gnome-control-center/tree/eos3.7 as follows:

    cp ~/src/endlessm/gnome-control-center/po/LINGUAS po
    ninja -C _build/ meson-malcontent-update-po
    for x in po/*.po; do
        t3k copy ~/src/endlessm/gnome-control-center/$x $x
    done
    ninja -C _build/ meson-malcontent-update-po

Then manually reviewed the output from t3k to exclude languages where
only trivial translations such as "Help" were copied.

Many of these translations are for OARS rating descriptions, which are
actually originally from gnome-software, and were imported into our
gnome-control-center in a similar way. I have long been sad that these
strings were not present in some common shared library; hooray! now they
are.

[t3k]: https://gitlab.gnome.org/wjt/translate-o-tron-3000/
2020-04-15 13:57:55 +01:00
Philip Withnall 7813a3c40f Merge branch 'piotrdrag/malcontent-piotrdrag/pl-update-200412' 2020-04-14 14:37:07 +01:00
Piotr Drąg 6bc4383cce Add Polish help translation 2020-04-14 14:36:28 +01:00
Piotr Drąg f731994dc3 Update Polish translation 2020-04-14 14:35:50 +01:00
Philip Withnall 0a86c5ba93 Merge branch 'master' into 'master'
Added Indonesian help translation

See merge request pwithnall/malcontent!62
2020-04-14 13:31:12 +00:00
Andika Triwidada 19e9be56e3 Added Indonesian help translation 2020-04-14 13:31:12 +00:00
Philip Withnall 980f035ea9 Merge branch 'builder-problems' into 'master'
user-controls: Add a fallback bus connection

See merge request pwithnall/malcontent!60
2020-04-07 13:27:23 +00:00
Philip Withnall 28992ac7f3 user-controls: Add a fallback bus connection
This is a hack to allow `MctUserControls` to be used from `GtkBuilder`
templates, where it’s not possible to pass construct-only properties in
to the `MctUserControls` constructor. It’s not feasible to make
`MctUserControls:dbus-connection` not construct-only, because it gets
used to construct an `MctManager` which then subscribes to various
signals.

So for the cases where `MctUserControls` is used from a builder
template, the code has to connect to the system bus manually, which is
possibly (though unlikely) a blocking operation.

This fixes a critical warning when enabling parental controls in
gnome-initial-setup.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-07 12:52:15 +01:00
Philip Withnall 6f09483b4c libmalcontent: Clarify nullability of MctManager:connection
It’s not.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-07 12:52:15 +01:00
Philip Withnall b79e6c3589 Merge branch 'piotrdrag/pl-update-200405' into 'master'
Update Polish translation 200405

See merge request pwithnall/malcontent!56
2020-04-07 11:51:51 +00:00
Philip Withnall 784d8f495e Merge branch 'update_uk' into 'master'
Update Ukrainian translation + docs translation

See merge request pwithnall/malcontent!57
2020-04-07 11:51:42 +00:00
Yuri Chornoivan 4c6d77ff6d Update Ukrainian translation + docs translation 2020-04-07 09:06:54 +03:00
Philip Withnall 78d553bafd Merge branch 'meson-warnings' into 'master'
meson: bump minimum version to 0.50.0

See merge request pwithnall/malcontent!59
2020-04-06 13:46:25 +00:00
Philip Withnall fb176f8039 Merge branch 'header-bar' into 'master'
malcontent-control: Add a header bar and primary menu

See merge request pwithnall/malcontent!58
2020-04-06 13:33:41 +00:00
Will Thompson c7041f362a meson: bump minimum version to 0.50.0
WARNING: Project specifies a minimum meson_version '>= 0.49.0' but
    uses features which were added in newer versions:
     * 0.50.0: {'install arg in configure_file'}
2020-04-06 14:32:22 +01:00
Philip Withnall 99736b3f6c malcontent-control: Add a header bar and primary menu
This makes it easier to access the help and about dialogue, and brings
the application in line with the [GNOME
HIG](https://developer.gnome.org/hig/stable/header-bars.html.en).

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-06 12:38:11 +01:00
Jan Tojnar 0d60138e0a
build: Only update post-install caches when they exist
When building without UI, there are no icon or desktop files so there is no need to run the commands to refresh the caches.

It would be even nicer to move the postinstall script to the malcontent-control subdirectory but it really applies to the installation output of the whole project, not just the malcontent-control part.
2020-04-05 10:52:05 +02:00
Jan Tojnar 697fd56f38
build: Remove schema generation
We do not have any GSettings schemas.
2020-04-05 10:52:05 +02:00
Piotr Drąg 367a83eaff Update Polish translation 2020-04-05 10:48:26 +02:00
Philip Withnall 8a764cc0cd Merge branch 'introspection-error-fix' into 'master'
libmalcontent: Add enum types to fix introspection of MctManagerError

See merge request pwithnall/malcontent!55
2020-04-03 23:39:20 +00:00
Philip Withnall aaca135199 libmalcontent: Add enum types to fix introspection of MctManagerError
Without a GType for the error enum, g-ir-scanner fails to properly
associate it with the error quark function, and (for example) error code
matching in JS doesn’t work.

This adds the enum types in a new public header file.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-04 00:37:26 +01:00
Philip Withnall 2d7e38aa74 Merge branch 'help' into 'master'
Add user manual/documentation

See merge request pwithnall/malcontent!51
2020-04-03 14:28:39 +00:00
Philip Withnall e03bb128b8 malcontent-control: Add an action to launch the help
Also add actions for `app.about` and `app.quit`, for completeness.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-03 15:08:47 +01:00
Philip Withnall b683ef7e37 help: Add a basic user manual for malcontent-control
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-04-03 15:08:47 +01:00
Philip Withnall 2591a20beb Merge branch 'uk_update' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!54
2020-04-02 09:00:23 +00:00
Yuri Chornoivan f8df997db7 Update Ukrainian translation 2020-04-02 09:21:04 +03:00
Philip Withnall 9997311537 Merge branch 'master' into 'master'
Added Indonesian translation

See merge request pwithnall/malcontent!53
2020-03-31 13:00:45 +00:00
Andika Triwidada 9f001159db Added Indonesian translation 2020-03-31 13:00:45 +00:00
Philip Withnall 942007f275 Merge branch 'piotrdrag/pl-update-200329' into 'master'
Update Polish translation 200329

See merge request pwithnall/malcontent!52
2020-03-30 22:19:13 +00:00
Piotr Drąg 0e4b953606 Update Polish translation 2020-03-29 12:41:16 +02:00
Philip Withnall 2e8a07d58c 0.7.0
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-24 11:23:01 +00:00
Philip Withnall 5054ba2bfb Merge branch '16-libraries-as-features' into 'master'
build: Add -Dui option to Meson

Closes #16

See merge request pwithnall/malcontent!38
2020-03-24 11:09:56 +00:00
Philip Withnall d8602bcd0b Merge branch 'refactor-bus' into 'master'
malcontent-control: Refactor bus initialisation

See merge request pwithnall/malcontent!49
2020-03-24 11:08:54 +00:00
Philip Withnall 435515d9da Merge branch 'parental-controls-enabled' into 'master'
app-filter: Add mct_app_filter_is_enabled() API

See merge request pwithnall/malcontent!47
2020-03-24 11:08:33 +00:00
Philip Withnall 04705c079a session-limits: Add mct_session_limits_is_enabled() API
This is a high-level API to indicate whether parental controls are
‘enabled’ for the given user. It’s a mirror of
`mct_app_filter_is_enabled()`, and exposes the existing
`time_limit_enabled_out` argument of
`mct_session_limits_check_time_remaining()` more conveniently.

Includes tests.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-24 11:06:16 +00:00
Philip Withnall f106319fdd app-filter: Add mct_app_filter_is_enabled() API
This is a high-level API to indicate whether parental controls are
‘enabled’ for the given user. Specifically, whether any of the
properties of the `MctAppFilter` differ from their default value.

Includes tests.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-24 11:06:16 +00:00
Philip Withnall faa0b9a3eb app-filter: Factor out a helper function
This introduces no functional changes, but will make an upcoming change
a little simpler.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-24 11:06:16 +00:00
Philip Withnall 9fbcef0fb8 libmalcontent: Add a clarifying comment about nullability
This introduces no functional changes.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-24 11:06:16 +00:00
Philip Withnall f917f6e79a malcontent-control: Refactor bus initialisation
Get the system bus higher up in the application, so the same system bus
connection can be shared between different parts of the application if
needed in future.

This also means the synchronous I/O needed to connect to the bus is done
before the application UI is shown, which prevents it unnecessarily
blocking initialisation of the `MctUserControls` widget.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-23 14:43:22 +00:00
Philip Withnall 5f170ab5fe Merge branch 'piotrdrag/update-potfiles-200320' into 'master'
Update POTFILES.in 200320

See merge request pwithnall/malcontent!48
2020-03-20 17:24:49 +00:00
Piotr Drąg 8b880748ef Update POTFILES.in 2020-03-20 18:09:33 +01:00
Philip Withnall 743529a82f Merge branch 'data-serialisation' into 'master'
Support data serialisation and deserialisation

See merge request pwithnall/malcontent!45
2020-03-19 09:44:31 +00:00
Philip Withnall 6ba767029f session-limits: Add serialize and deserialize methods
See the previous commit; this is the same, but for session limits.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-19 09:42:25 +00:00
Philip Withnall cba851fc27 app-filter: Add serialize and deserialize methods
Add methods to serialise and deserialise the app filter, and use them to
replace the code in `MctManager` which was previously doing this. This
exposes the variant format for the app filter in the API (although the
format is described as ‘opaque’) so that user code can log it or store
it separately.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-18 10:40:27 +00:00
Philip Withnall a617365bba Merge branch 'papercuts' into 'master'
Fix papercuts when editing parental controls of current user

See merge request pwithnall/malcontent!46
2020-03-18 10:00:41 +00:00
Philip Withnall 4481cf1271 malcontent-control: Imply all app-filter polkit permissions
When unlocking malcontent-control while running as an unprivileged user
to edit *that* user’s parental controls, the `ChangeOwn` and `ReadOwn`
privileges should also be granted.

Otherwise a second polkit authorisation dialogue is popped up after
editing any of the parental controls, to get permission to save the
changes.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-17 17:31:53 +00:00
Philip Withnall cbc9b93348 malcontent-control: Tweak polkit label wording
When malcontent-control is run as an unprivileged user (i.e. a child)
the fact that the unlock wording refers to ‘other users’ is a little
confusing, since the purpose of running malcontent-control was likely to
edit the parental controls for *this* user.

Adjust the wording to make this a little clearer.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-17 17:30:49 +00:00
Philip Withnall 6125cc3a85 build: Add an option to build against libmalcontent from the system
Rather than building it again; this is the second half of resolving the
dependency cycle from the previous commit.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #16
2020-03-16 18:31:57 +00:00
Philip Withnall fda2fbd330 build: Add -Dui option to Meson
This allows the UI components (libmalcontent-ui and malcontent-control)
to be disabled in the build so that a dependency cycle with flatpak can
be avoided (by building malcontent twice, once with `-Dui=disabled` and
then again with `-Dui=enabled`).

The dependency graph is:
  malcontent-control → libmalcontent-ui → flatpak → libmalcontent
which becomes cyclic if libmalcontent-ui and libmalcontent can only be
built at the same time.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #16
2020-03-16 18:31:57 +00:00
Philip Withnall bd173218e6 Merge branch 'glib-testing-system' into 'master'
Use libglib-testing submodule only as fallback

See merge request pwithnall/malcontent!40
2020-03-16 18:14:41 +00:00
Philip Withnall 8b95a655a8 Merge branch 'oars-button-direction' into 'master'
user-controls: Make OARS drop down open to the right

See merge request pwithnall/malcontent!43
2020-03-16 17:11:22 +00:00
Philip Withnall 8166044e6e Merge branch 'locale-change' into 'master'
Fix updating the UI when a user’s locale changes

See merge request pwithnall/malcontent!44
2020-03-16 12:19:01 +00:00
Philip Withnall bf0eaea612 user-controls: Update when the ActUser changes
When the user object changes one of its properties (for example, the
user’s locale might change if the administrator is editing a user in
g-c-c while viewing their parental controls in malcontent-control),
update the UI.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-16 12:11:45 +00:00
Philip Withnall 4698ad88a0 user-controls: Update OARS menu entries before choosing an updated one
If the user’s locale changes, we need to update the set of entries in
the OARS menu before selecting a new one and updating the label.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-16 12:10:11 +00:00
Matthew Leeds 87db73178f user-controls: Make OARS drop down open to the right
On laptops which have a 1366 by 768 display, in gnome-initial-setup the
OARS dropdown is cut off by the edge of the screen. Only the first
couple entries are visible. So make it open to the right instead, where
more room is available.
2020-03-13 11:32:11 -07:00
Philip Withnall e9c2f3d054 Merge branch 'readme-licensing' into 'master'
docs: Update license information in README and meson.build

See merge request pwithnall/malcontent!42
2020-03-10 14:16:01 +00:00
Philip Withnall 12c320d43a docs: Update license information in README and meson.build
Some of the files in `malcontent-control` are GPL-2.0+.

Use the latest SPDX identifiers in the machine-readable data in
meson.build, but use the deprecated ‘+’ form in the README since it’s a
little more human friendly.

See https://spdx.org/licenses/.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-10 14:12:25 +00:00
Philip Withnall 1064221a9c Merge branch 'patch-1' into 'master'
Fix typo in malcontent-client.8

See merge request pwithnall/malcontent!41
2020-03-09 18:24:34 +00:00
Laurent Bigonville a05d3e8b8f Fix the NAME section of malcontent-client.8
This fix the debian lintian "manpage-has-bad-whatis-entry" warning
2020-03-07 11:21:08 +00:00
Laurent Bigonville ed794f58c9 Fix typo in malcontent-client.8 2020-03-07 09:53:01 +00:00
Jan Tojnar fc4efbef74
Use libglib-testing submodule only as fallback
Eventually, we will only use the one from system but until then both variants should work.
2020-03-06 20:41:21 +01:00
Philip Withnall 991d002a4e Merge branch 'piotrdrag/pl-translation-200306' into 'master'
Add Polish translation

See merge request pwithnall/malcontent!39
2020-03-06 17:00:30 +00:00
Piotr Drąg 90680f1552 Add Polish translation 2020-03-06 17:47:06 +01:00
Philip Withnall 8f82a7b05c Merge branch '16-dependencies' into 'master'
Drop a few unnecessary dependencies

See merge request pwithnall/malcontent!37
2020-03-02 16:28:35 +00:00
Philip Withnall b4c5ca22f2 malcontent-control: Drop unused flatpak dependency
Note that it’s still transitively required through libmalcontent-ui.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-02 15:58:25 +00:00
Philip Withnall 2cc56e1441 user-controls: Drop unused flatpak include
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-03-02 15:58:10 +00:00
Philip Withnall 18926be3ae Merge branch 'uk-update' into 'master'
Update Ukrainian translation

See merge request pwithnall/malcontent!35
2020-03-02 10:30:30 +00:00
Yuri Chornoivan f624fc277e Update Ukrainian translation 2020-03-02 10:30:30 +00:00
Philip Withnall 15e3e7a407 0.6.0
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-27 15:19:00 +00:00
Philip Withnall 240c5e1c69 Merge branch '11-more-ui-tweaks' into 'master'
More small UI tweaks

Closes #11

See merge request pwithnall/malcontent!34
2020-02-27 13:06:59 +00:00
Philip Withnall 82ecf17079 user-controls: Left-align the OARS drop-down text
Make it look more and more like a combo box. This widget really should
have been a combo box to begin with. We’re eventually going to end up
re-implementing a combo box from first principles at this rate.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-26 11:00:41 +00:00
Philip Withnall 3f3e86bcbb user-controls: More minor wording tweaks
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-26 11:00:28 +00:00
Philip Withnall 1d46f55be4 restrict-applications-dialog: Remove the Save button
Add a close button instead, as the dialogue is instant-apply.

See https://developer.gnome.org/hig/stable/dialogs.html.en#instant-and-explicit-apply

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-26 11:00:12 +00:00
Philip Withnall 8bde311b9c Merge branch '11-ui-improvements' into 'master'
Tweak user controls UI

Closes #11

See merge request pwithnall/malcontent!25
2020-02-26 09:17:21 +00:00
Philip Withnall 8c7815e33c restrict-applications-dialog: Allow introduction label to wrap
Rather than ellipsising, allow it to wrap. Also ensure it’s
left-aligned.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-26 09:15:19 +00:00
Philip Withnall 7a7c26bcbf Merge branch 'parent-account' into 'master'
accounts-service: Add AccountInfo interface

See merge request pwithnall/malcontent!26
2020-02-25 13:14:08 +00:00
Philip Withnall 372d51a491 accounts-service: Add AccountInfo interface
This will store information about the user which is related to parental
controls. Currently, that’s just a boolean indicating that the user is a
parent, and hence that their account should be presented differently in
UIs.

See: https://gitlab.gnome.org/GNOME/gnome-initial-setup/issues/94

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-25 13:10:35 +00:00
Philip Withnall 2d43ac38ec libmalcontent-ui: Restyle ‘restricts’ switches in yellow
This has fewer ‘error’ connotations than red. See
https://gitlab.freedesktop.org/pwithnall/malcontent/issues/11#note_419124.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:49:29 +00:00
Philip Withnall 3db3a42e8d user-controls: Line wrap labels rather than ellipsising
The labels are too long to fit on a single line, given the default width
of the user controls widget, so allow them to wrap onto multiple lines
rather than unhelpfully ellipsising.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 008b75edd1 user-controls: Add a drop-down arrow next to the OARS age selector
To make it more obvious that it triggers a drop-down menu. Potentially,
this should be a `GtkComboBox` rather than reinventing the wheel using a
`GtkMenuButton` — but that’s a change for another day.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 7ad804835a user-controls: Rename OARS widget variables to be more descriptive
This doesn’t introduce any functional changes.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 5a1bfb842a user-controls: Include user display name in the description labels
This clarifies that the settings apply to that user.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall dee4d92ea9 restrict-applications-dialog: Invert controls to be restrictive
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 8753109e80 user-controls: Tweak the wording of the ‘application suitability’ label
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 516e3936eb user-controls: Relabel ‘allow installation’ as ‘restrict installation’
This is part of a move to make all the controls restrictive, rather than
permissive.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall f956fab427 user-controls: Tweak the wording of the ‘restrict applications’ label
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 8e4fa643d3 user-controls: Relabel ‘allow web browsers’ as ‘restrict web browsers’
This is part of a move to make all the controls restrictive, rather than
permissive.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 8027351f58 carousel: Lower CSS priority
Otherwise an application won’t be able to override the CSS installed by
libmalcontent-ui if this is ever moved into libmalcontent-ui.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-25 12:25:40 +00:00
Philip Withnall b9a2b7a6a7 user-controls: Add CSS to support styling switches as ‘restrictive’
This will be used in upcoming commits to mark switches as restricting
something when they’re active, rather than allowing something. Their
background will be red, rather than blue.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 12:25:40 +00:00
Philip Withnall 67ca6806e6 user-controls: Add separators between rows
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 10:31:38 +00:00
Philip Withnall ef6fc0a7f5 user-controls: Fix icon for ‘Restrict Applications’ button
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 10:31:24 +00:00
Philip Withnall 98395185e3 user-controls: Add full stops to end of control descriptions
They are sentences.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #11
2020-02-25 10:31:24 +00:00
Philip Withnall 5cff42e4d2 Merge branch 'linguas' into 'master'
po: Order LINGUAS alphabetically

See merge request pwithnall/malcontent!33
2020-02-25 10:17:50 +00:00
Philip Withnall 967d9f1bd0 po: Order LINGUAS alphabetically
This will make it a bit easier to maintain in future.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-25 10:15:15 +00:00
Philip Withnall da7b4b1be4 Merge branch 'add-pt_BR' into 'master'
Add Brazilian Portuguese translation

See merge request pwithnall/malcontent!32
2020-02-25 10:14:36 +00:00
Rafael Fontenelle 2572973153 Add Brazilian Portuguese translation 2020-02-24 19:46:09 -03:00
Philip Withnall 4e90d5c66a Merge branch 'fix-locale-dir' into 'master'
build: Fix definition of PACKAGE_LOCALE_DIR

See merge request pwithnall/malcontent!31
2020-02-21 09:48:36 +00:00
Philip Withnall 77beea2dfe build: Fix definition of PACKAGE_LOCALE_DIR
It was causing translations to be looked for in the wrong place.

Also hard-code `GETTEXT_PACKAGE` since it’s basically API now.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-21 09:45:47 +00:00
Philip Withnall 69bb421d18 Merge branch 'uk-add' into 'master'
Add Ukrainian translation

See merge request pwithnall/malcontent!30
2020-02-21 09:34:46 +00:00
Yuri Chornoivan 9080af21e3 Add Ukrainian translation 2020-02-21 09:34:46 +00:00
Philip Withnall f6fbccd10d Merge branch 'translatable-files' into 'master'
po: Add some missing files to POTFILES.in

See merge request pwithnall/malcontent!29
2020-02-19 16:25:05 +00:00
Philip Withnall ad07277e21 po: Add some missing files to POTFILES.in
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-19 16:22:57 +00:00
Philip Withnall b311727c43 Merge branch '9-icon' into 'master'
malcontent-control: Add scalable and symbolic icons

Closes #9

See merge request pwithnall/malcontent!28
2020-02-19 14:01:29 +00:00
Philip Withnall eef28da339 build: Add post-install script to update caches
Update the desktop, schema and icon caches.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Helps: #9
2020-02-19 13:58:09 +00:00
Philip Withnall b4eab1a7c0 malcontent-control: Add scalable and symbolic icons
Drawn by Jakub Steiner. Thanks!

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #9
2020-02-19 13:46:03 +00:00
Philip Withnall 48b9839d04 Merge branch 'warning-fixes' into 'master'
user-selector: Fix some const-to-non-const cast warnings

See merge request pwithnall/malcontent!27
2020-02-19 13:40:51 +00:00
Philip Withnall 8da1088e9b user-selector: Fix some const-to-non-const cast warnings
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-18 12:08:42 +00:00
Philip Withnall cb27d75645 Release version 0.5.0
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-14 14:47:13 +00:00
Philip Withnall 33167e7767 Merge branch 'user-controls-without-user' into 'master'
Allow user controls to be used for not-yet-existing users

See merge request pwithnall/malcontent!24
2020-02-14 12:16:56 +00:00
Philip Withnall 1c033f82df user-controls: Allow widgets to be used without an `ActUser`
Allow the user controls widget to be used for user accounts which don’t
currently exist. This is necessary for using them in
gnome-initial-setup.

See the big new documentation comment at the top of the widget for
details of how the new semantics work.

This adds API, but does not break existing API.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-14 12:00:57 +00:00
Philip Withnall fc9ba76331 user-controls: Add some missing includes to the header
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall e4fbb570af user-controls: Add some missing documentation comments
The annotations in these fix some GIR warnings.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall 7dfd03907d user-controls: Split out app filter construction into a new method
This means that calling code can extract the app filter manually rather
than having to rely on the `MctUserControls` to save it. This will be
useful in a few commits’ time when support is added for using
`MctUserControls` for not-yet-created users.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall e3f923b294 user-controls: Don’t clear filter if updating it is a no-op
If `self->user == NULL`, don’t clear the app filter, as that leaves us
in a worse-off position than before.

Rename the method to make it clearer that it queries the filter from the
user.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall 3519ac2dc1 user-controls: Tweak the API of an internal helper function
Make it take a `MctUserControls` rather than a member of it. This
introduces no functional changes, but will make some upcoming
refactoring easier.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall 608444891f user-controls: Modernise GObject property code
This introduces no functional changes, but does make the code work
better with `-Wswitch-enum`.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall 0f2c8d6601 restrict-applications-selector: Drop unnecessary include
Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall 6b45ad9f76 restrict-applications-dialog: Drop accountsservice dependency
Instead of taking an `ActUser` as a property of the
`MctRestrictApplicationsDialog`, take the display name which we would
have queried from it.

This will allow the restrict applications dialog to be used in
situations where an `ActUser` isn’t available, such as when setting the
parental controls for a yet-to-be-created user.

This breaks the `MctRestrictApplicationsDialog` API, but the previous
API hadn’t yet been released.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall acf402dcc5 restrict-applications-dialog: Allow :user to be set at any point
It doesn’t actually need to be construct-only.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
Philip Withnall b98ec83e66 libmalcontent-ui: Add GIR dependency on libmalcontent
This was missing and causing some problems with GIR compilation for the
UI library.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-02-06 12:52:06 +00:00
150 changed files with 45094 additions and 2959 deletions

View File

@ -1,13 +1,3 @@
image: fedora:30
before_script:
- dnf install -y meson pkgconf-pkg-config gtk-doc
libxml2-devel dbus-daemon
glib2-devel dbus-devel gobject-introspection-devel
gettext-devel polkit-devel polkit-gnome git
lcov pam-devel gtk3-devel accountsservice-devel flatpak-devel
- export LANG=C.UTF-8
stages: stages:
- build - build
- deploy - deploy
@ -16,23 +6,53 @@ cache:
paths: paths:
- _ccache/ - _ccache/
fedora: variables:
stage: build DEBIAN_IMAGE: "registry.freedesktop.org/pwithnall/malcontent/debian-unstable:v4"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
G_MESSAGES_DEBUG: all
MESON_COMMON_OPTIONS: "--buildtype debug --wrap-mode=nodownload"
.only-default:
only:
- branches
except: except:
- tags - tags
.build:
extends: .only-default
before_script:
- cp -r $HOME/subprojects/* subprojects/
debian:
extends: .build
image: $DEBIAN_IMAGE
stage: build
variables:
CFLAGS: "-coverage -ftest-coverage -fprofile-arcs"
script: script:
- git submodule update --init - meson ${MESON_COMMON_OPTIONS}
- meson --buildtype debug --werror -Db_coverage=true -Ddocumentation=true _build . --werror
- meson test -C _build -Db_coverage=true
# FIXME: lcov doesn't support gcc9 yet: -Dinstalled_tests=true
# https://github.com/linux-test-project/lcov/issues/58 -Dprivileged_group=sudo
- ninja -C _build coverage || true _build
- ninja -C _build
- mkdir -p _coverage
- lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --initial --output-file "_coverage/${CI_JOB_NAME}-baseline.lcov"
- .gitlab-ci/run-tests.sh
- lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --output-file "_coverage/${CI_JOB_NAME}.lcov"
- bash -x ./.gitlab-ci/coverage-docker.sh
coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/'
artifacts: artifacts:
when: always reports:
junit: "_build/${CI_JOB_NAME}-report.xml"
name: "malcontent-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" name: "malcontent-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
when: always
paths: paths:
- "_build/config.h"
- "_build/meson-logs" - "_build/meson-logs"
- "_build/${CI_JOB_NAME}-report.xml"
- "_coverage"
# FIXME: Run gtkdoc-check when we can. See: # FIXME: Run gtkdoc-check when we can. See:
# https://github.com/mesonbuild/meson/issues/3580 # https://github.com/mesonbuild/meson/issues/3580
@ -40,10 +60,9 @@ fedora:
pages: pages:
stage: deploy stage: deploy
only: only:
- master - main
script: script:
- mkdir -p public/ - mv _coverage/ public/
- mv _build/meson-logs/coveragereport/ public/coverage/
artifacts: artifacts:
paths: paths:
- public - public

23
.gitlab-ci/README.md Normal file
View File

@ -0,0 +1,23 @@
# CI support stuff
## Docker image
GitLab CI jobs run in a Docker image, defined here. To update that image
(perhaps to install some more packages):
1. Edit `.gitlab-ci/Dockerfile` with the changes you want
1. Run `.gitlab-ci/run-docker.sh build --base=debian-unstable --base-version=1` to
build the new image (bump the version from the latest listed for that `base`
on https://gitlab.freedesktop.org/pwithnall/malcontent/container_registry)
1. Run `.gitlab-ci/run-docker.sh push --base=debian-unstable --base-version=1` to
upload the new image to the GNOME GitLab Docker registry
* If this is the first time you're doing this, you'll need to log into the
registry
* If you use 2-factor authentication on your GNOME GitLab account, you'll
need to [create a personal access token][pat] and use that rather than
your normal password — the token should have `read_registry` and
`write_registry` permissions
1. Edit `.gitlab-ci.yml` (in the root of this repository) to use your new
image
[pat]: https://gitlab.freedesktop.org/profile/personal_access_tokens

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -e
git clone --depth 1 --no-tags https://gitlab.freedesktop.org/pwithnall/malcontent.git
meson subprojects download --sourcedir malcontent
rm malcontent/subprojects/*.wrap
mv malcontent/subprojects/ .
rm -rf malcontent

29
.gitlab-ci/coverage-docker.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
set -e
for path in _coverage/*.lcov; do
# Remove coverage from generated code in the build directory
lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/_build/*' -o "$(pwd)/${path}"
# Remove any coverage from system files
lcov --config-file .gitlab-ci/lcovrc -e "${path}" "$(pwd)/*" -o "$(pwd)/${path}"
done
genhtml \
--ignore-errors=source \
--config-file .gitlab-ci/lcovrc \
_coverage/*.lcov \
-o _coverage/coverage
cd _coverage
rm -f ./*.lcov
cat >index.html <<EOL
<html>
<body>
<ul>
<li><a href="coverage/index.html">Coverage</a></li>
</ul>
</body>
</html>
EOL

View File

@ -0,0 +1,45 @@
FROM debian:unstable
RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \
desktop-file-utils \
gettext \
git \
gtk-doc-tools \
lcov \
libadwaita-1-dev \
libaccountsservice-dev \
libappstream-dev \
libdbus-1-dev \
libflatpak-dev \
libgirepository1.0-dev \
libglib2.0-dev \
libglib-testing-0-dev \
libgtk-4-dev \
libpam0g-dev \
libpolkit-gobject-1-dev \
libxml2-utils \
locales \
meson \
pkg-config \
policykit-1 \
python3-pip \
&& rm -rf /usr/share/doc/* /usr/share/man/*
# Locale for our build
RUN locale-gen C.UTF-8 && /usr/sbin/update-locale LANG=C.UTF-8
ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8
RUN pip3 install meson==0.59.4
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
COPY cache-subprojects.sh .
RUN ./cache-subprojects.sh
ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8

13
.gitlab-ci/lcovrc Normal file
View File

@ -0,0 +1,13 @@
# lcov and genhtml configuration
# See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php
# Always enable branch coverage
lcov_branch_coverage = 1
# Exclude precondition assertions, as we can never reasonably get full branch
# coverage of them, as they should never normally fail.
# See https://github.com/linux-test-project/lcov/issues/44
lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_
# Similarly for unreachable assertions.
lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached

115
.gitlab-ci/meson-junit-report.py Executable file
View File

@ -0,0 +1,115 @@
#!/usr/bin/env python3
# Turns a Meson testlog.json file into a JUnit XML report
#
# Copyright 2019 GNOME Foundation
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Emmanuele Bassi
import argparse
import datetime
import json
import os
import sys
import xml.etree.ElementTree as ET
aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default='Unknown')
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='main')
aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
default=sys.stdout)
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r', encoding='UTF-8'),
default=sys.stdin)
args = aparser.parse_args()
outfile = args.output
testsuites = ET.Element('testsuites')
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
testsuites.set('package', args.project_name)
testsuites.set('timestamp', datetime.datetime.utcnow().isoformat())
suites = {}
for line in args.infile:
data = json.loads(line)
(full_suite, unit_name) = data['name'].split(' / ')
try:
(project_name, suite_name) = full_suite.split(':')
except ValueError:
project_name = full_suite
suite_name = full_suite
duration = data['duration']
return_code = data['returncode']
log = data['stdout']
log_stderr = data.get('stderr', '')
unit = {
'suite': suite_name,
'name': unit_name,
'duration': duration,
'returncode': return_code,
'stdout': log,
'stderr': log_stderr,
}
units = suites.setdefault(suite_name, [])
units.append(unit)
for name, units in suites.items():
print('Processing suite {} (units: {})'.format(name, len(units)))
def if_failed(unit):
if unit['returncode'] != 0:
return True
return False
def if_succeded(unit):
if unit['returncode'] == 0:
return True
return False
successes = list(filter(if_succeded, units))
failures = list(filter(if_failed, units))
print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures)))
testsuite = ET.SubElement(testsuites, 'testsuite')
testsuite.set('name', '{}/{}'.format(args.project_name, name))
testsuite.set('tests', str(len(units)))
testsuite.set('errors', str(len(failures)))
testsuite.set('failures', str(len(failures)))
for unit in successes:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
for unit in failures:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
failure = ET.SubElement(testcase, 'failure')
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
failure.set('name', unit['name'])
failure.set('type', 'error')
failure.text = unit['stdout'] + '\n' + unit['stderr']
output = ET.tostring(testsuites, encoding='unicode')
outfile.write(output)

132
.gitlab-ci/run-docker.sh Executable file
View File

@ -0,0 +1,132 @@
#!/bin/bash
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read -r "$1" <<< "${BASH_REMATCH[1]}"
else
read -r "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
SUDO_CMD="sudo"
if docker -v |& grep -q podman; then
# Using podman
SUDO_CMD=""
# Docker is actually implemented by podman, and its OCI output
# is incompatible with some of the dockerd instances on GitLab
# CI runners.
export BUILDAH_FORMAT=docker
fi
set -e
base=""
base_version=""
build=0
run=0
push=0
list=0
print_help=0
no_login=0
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z "${base}" ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z "${base_version}" ]; then
base_version="latest"
else
base_version="v$base_version"
fi
TAG="registry.freedesktop.org/pwithnall/malcontent/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
$SUDO_CMD docker build \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
if [ $push == 1 ]; then
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
if [ $no_login == 0 ]; then
$SUDO_CMD docker login registry.freedesktop.org
fi
$SUDO_CMD docker push $TAG
exit $?
fi
if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
$SUDO_CMD docker run \
--rm \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \
bash
exit $?
fi

29
.gitlab-ci/run-tests.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
set +e
case "$1" in
--log-file)
log_file="$2"
shift
shift
;;
*)
log_file="_build/meson-logs/testlog.json"
esac
meson test \
-C _build \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--no-suite flaky \
"$@"
exit_code=$?
python3 .gitlab-ci/meson-junit-report.py \
--project-name=malcontent \
--job-id "${CI_JOB_NAME}" \
--output "_build/${CI_JOB_NAME}-report.xml" \
"${log_file}"
exit $exit_code

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "subprojects/libglib-testing"]
path = subprojects/libglib-testing
url = https://gitlab.gnome.org/pwithnall/libglib-testing.git

61
COPYING-DOCS Normal file
View File

@ -0,0 +1,61 @@
Attribution-ShareAlike 3.0 Unported
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License.
"Creative Commons Compatible License" means a license that is listed at http://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License.
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
to Distribute and Publicly Perform Adaptations.
For the avoidance of doubt:
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and,
Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License.
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested.
You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.

22
HACKING.md Normal file
View File

@ -0,0 +1,22 @@
Terminology
-----------
The main terminology used in malcontent is parental controls, which are
implemented by administrators and enforced on child users.
The feature applies to a range of other carer/caree relationships, though, where
the caree user might need to be protected from doing things on the computer
which arent suitable for them.
The terminology parental controls is used consistently, despite not all
situations actually involving a parent or child, because thats how most users
will find the functionality.
To remain as inclusive as possible, there are some rules about which terminology
to use:
- Use parental controls to refer to the overall feature
- Refer to administrators or administrator accounts rather than parents
- Refer to child users in general contexts, but refer to particular user
accounts using their full name — dont mention child in that case
Reference: https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/13

417
NEWS
View File

@ -1,3 +1,420 @@
Overview of changes in malcontent 0.11.1
========================================
* Bugs fixed:
- !147 0.11.0
- !148 build: Switch to Mesons gnome.post_install function
- !149 po: add Georgian translation
- !150 Update Hungarian translation
- !151 Update Hindi (hi) translation
- !152 doc: Add Turkish Translation
* Translation updates:
- Georgian (NorwayFun)
- Hindi (Hemish)
- Hungarian (Balázs Úr)
- Turkish (Sabri Unal)
Overview of changes in malcontent 0.11.0
========================================
* libmalcontent-ui, and the malcontent-control application, now use
libappstream rather than appstream-glib. (#51)
* libmalcontent-ui, and the malcontent-control application, now use GTK 4 and
libadwaita rather than GTK+ 3. (!141)
* As a result of these changes, the pkg-config name has been bumped to
libmalcontent-ui-1, and the gobject-introspection name to MalcontentUi-1.
* Improve keyboard navigation of the malcontent-control application. (#52)
* Translation updates:
- Italian
- Russian
Overview of changes in malcontent 0.10.5
========================================
* Bugs fixed:
- !134 Update it.po
- !135 Add German help translation
- !136 Update pt_BR.po
- !137 Update tr.po
- !138 Update Chinese (Taiwan) translation file.
* Translation updates:
- Chinese (Taiwan)
- Italian
- Portuguese (Brazil)
- Turkish
Overview of changes in malcontent 0.10.4
========================================
* Bugs fixed:
- !127 Update Catalan translation
- !128 Update German proof-read translation from https://l10n.gnome.org/vertimus/malcontent/main/po/de/
- !129 Update it.po
- !132 Remove superfluous arguments to i18n.merge_file
- !133 help: Add Italian help translation
* Translation updates:
- Catalan
- German
- Italian
Overview of changes in malcontent 0.10.3
========================================
* Bugs fixed:
- #44 Do not make malcontent-control user uninstallable using gui
- !123 Add Czech translation
- !124 Update Czech translation
- !125 malcontent-control: Fix an unterminated option entry array
- !126 malcontent-control: Focus controls rather than user selector
* Translation updates:
- Czech
Overview of changes in malcontent 0.10.2
========================================
* Hide the launcher for malcontent-control from gnome-shell if using the GNOME
desktop; find it via gnome-control-center instead (!119)
* Bugs fixed:
- !118 ci: Limit depth of clone of subprojects
- !119 malcontent-control: Hide application in GNOME
- !121 ci: Rename master to main branch
* Translation updates:
- Indonesian
- Italian
Overview of changes in malcontent 0.10.1
========================================
* Bugs fixed:
- #32 App sort key does not match displayed name
- !112 Update Swedish translation
- !113 Update Polish translation 201220
- !116 libmalcontent-ui: Drop handling of eos-link desktop files
* Translation updates:
- Polish
- Swedish
Overview of changes in malcontent 0.10.0
========================================
* Improve support for systems without accountsservice (#27)
* Fix some data loss-causing state synchronisation problems (#18, #28)
* Hide support for flatpak user repositories, as they are typically not
configured on systems (#30)
* Bugs fixed:
- #4 Add manpage docs for malcontent-client monitor, set and oars-section commands
- #13 Consider terminology of parental controls
- #15 Improving padding/spacing in malcontent-control UI
- #18 Reload Restrict Apps list when installed apps change on system
- #19 Add command line option to malcontent-control to pre-select a user
- #23 appdata not validating
- #25 Parental controls app empty state is misleading
- #27 Fails closed if accountsservice isn't available on the bus
- #28 Restrict Applications dialogue is empty if MctUserControls is created with empty app filter
- #30 Restrict App Installation tickboxes are confusing
- !85 Update Ukrainian translation
- !86 l10n: Update Italian translation
- !87 l10n-sv
- !88 Add Danish translation
- !91 libmalcontent: Rationalise a couple of translatable strings
- !92 Fix several issues with the app list in the restrict applications dialogue
- !93 Update Ukrainian translation
- !94 Update Polish translation 201018
- !96 Update Polish translation 201025
- !100 Bump appstream-glib dep and update content rating code
- !101 Fix partial loss of parental controls settings when partially updating them
- !102 user-controls: Only save the app filter if its changed
- !103 malcontent-control: Add link to guidance on how to set parental controls
- !104 docs: Add a development principles section to the README
- !106 Update Danish translation
- !107 Update Ukrainian translation
- !108 Update Ukrainian translation
- !109 Update Ukrainian translation
- !111 accounts-service: Allow installation to the system repo by default
* Translation updates:
- Danish
- Italian
- Polish
- Swedish
- Ukrainian
Overview of changes in malcontent 0.9.0
=======================================
* Use appstream-glib code for content rating systems if available — this
adds a dependency on appstream-glib, but no particular version (see #7)
* Rename three APIs in `app-filter.h` to avoid discriminatory language:
- `mct_app_filter_builder_blacklist_path` → `…_blocklist_path`
- `…_blacklist_flatpak_ref` → `…_blocklist_flatpak_ref`
- `…_blacklist_content_type` → `…_blocklist_content_type`
This is an API break. (See !72)
* Add a `privileged_group` configure option to set the name of the system
sudo group — it might be `sudo` or `wheel` (thanks to Sergey Shatunov; see #22)
* Bugs fixed:
- #7 Lift GNOME Software content rating implementation into appstream-glib, and fix it
- #21 No references to homosexuality
- #22 Polkit rules should use wheel group instead of sudo
- !69 Two small UI tweaks
- !72 tree-wide: Replace usages of whitelist/blacklist
- !73 po: Update translations from downstream in Endless
- !74 Update Ukrainian translation
- !75 Update Polish translation 200614
- !77 all: Fix various typos and incorrect terminology
- !78 build: Use meson.current_source_dir() instead of source_root()
- !79 build: Re-add libglib-testing subproject
- !80 Update Brazilian Portuguese translation
- !81 ci: Use pre-built Docker images for CI builds
- !82 subprojects: Limit depth when cloning
- !83 Update Spanish translation
* Translation updates:
- Afrikaans
- Arabic
- Bangla
- Basque
- Bokmål, Norwegian
- Bulgarian
- Catalan
- Catalan — valencia.UTF-8
- Chinese (Taiwan)
- Croatian
- Czech
- Danish
- Dutch
- Esperanto
- Finnish
- French
- Friulian
- Gaelic
- Galician
- German
- Greek, Modern (1453-)
- Hebrew
- Hindi
- Hungarian
- Indonesian
- Italian
- Kazakh
- Korean
- Latvian
- Lithuanian
- Malay
- Malayalam
- Occitan (post 1500)
- Panjabi
- Persian
- Polish
- Portuguese
- Portuguese (Brazil)
- Romanian
- Russian
- Serbian
- Serbian — latin.UTF-8
- Slovak
- Slovenian
- Spanish
- Swedish
- Thai
- Turkish
- Ukrainian
- Vietnamese
Overview of changes in malcontent 0.8.0
=======================================
* Add user manual (!51)
* Add a header bar and primary menu to the main UI (!58)
* Bump Meson dependency to 0.50.0 (!59)
* Fix translation of libmalcontent-ui widgets when used in other applications (!68)
* Bugs fixed:
- !3 Remove use of libglib-testing subproject
- !50 Various meson cleanups
- !51 Add user manual/documentation
- !52 Update Polish translation 200329
- !53 Added Indonesian translation
- !54 Update Ukrainian translation
- !55 libmalcontent: Add enum types to fix introspection of MctManagerError
- !56 Update Polish translation 200405
- !57 Update Ukrainian translation + docs translation
- !58 malcontent-control: Add a header bar and primary menu
- !59 meson: bump minimum version to 0.50.0
- !60 user-controls: Add a fallback bus connection
- !62 Added Indonesian help translation
- !63 Import translations from Endless
- !64 Import zh_TW translation from Endless
- !65 Add translator comments for about dialog strings
- !66 Update Brazilian Portuguese translation
- !67 Add Brazilian Portuguese translation
- !68 Fix translation of libmalcontent-ui
* Translation updates:
- Afrikaans
- Arabic
- Bangla
- Basque
- Bokmål, Norwegian
- Bulgarian
- Catalan
- Catalan — valencia.UTF-8
- Chinese (Taiwan)
- Croatian
- Czech
- Danish
- Dutch
- Esperanto
- Finnish
- French
- Friulian
- Gaelic
- Galician
- German
- Greek, Modern (1453-)
- Hebrew
- Hindi
- Hungarian
- Indonesian
- Italian
- Kazakh
- Korean
- Latvian
- Lithuanian
- Malay
- Malayalam
- Occitan (post 1500)
- Panjabi
- Persian
- Polish
- Portuguese
- Portuguese (Brazil)
- Romanian
- Russian
- Serbian
- Serbian — latin.UTF-8
- Slovak
- Slovenian
- Spanish
- Swedish
- Thai
- Turkish
- Ukrainian
- Vietnamese
Overview of changes in malcontent 0.7.0
=======================================
* Add `-Dui` configure option to help work around circular dependency with
flatpak (#16)
* Add data serialization and deserialization methods for app filters and
session limits (!45)
* Add mct_app_filter_is_enabled() and mct_session_limits_is_enabled() APIs
for determining whether filtering/limits are enabled at a high level (!47)
* Bugs fixed:
- #16 Circular dependency on flatpak
- !35 Update Ukrainian translation
- !37 Drop a few unnecessary dependencies
- !39 Add Polish translation
- !40 Use libglib-testing submodule only as fallback
- !41 Fix typo in malcontent-client.8
- !42 docs: Update license information in README and meson.build
- !43 user-controls: Make OARS drop down open to the right
- !44 Fix updating the UI when a users locale changes
- !45 Support data serialisation and deserialisation
- !46 Fix papercuts when editing parental controls of current user
- !47 app-filter: Add mct_app_filter_is_enabled() API
- !48 Update POTFILES.in 200320
- !49 malcontent-control: Refactor bus initialisation
* Translation updates:
- Polish
- Ukrainian
Overview of changes in malcontent 0.6.0
=======================================
* Add icon for `malcontent-control` (thanks Jakub Steiner) (#9)
* Redesign `malcontent-control` UI in response to design feedback (#11)
* Add `AccountInfo` interface for metadata on parent accounts (!26)
* Fix translation of the UI (!31)
* Bugs fixed:
- #9 Add icon for malcontent-control
- #11 User controls UI tweaks
- !26 accounts-service: Add AccountInfo interface
- !27 user-selector: Fix some const-to-non-const cast warnings
- !29 po: Add some missing files to POTFILES.in
- !30 Add Ukrainian translation
- !31 build: Fix definition of PACKAGE_LOCALE_DIR
- !32 Add Brazilian Portuguese translation
- !33 po: Order LINGUAS alphabetically
- !34 More small UI tweaks
* Translation updates:
- Portuguese (Brazil)
- Ukrainian
Overview of changes in malcontent 0.5.0
=======================================
* Add libmalcontent-ui library for parental controls widgets
* Add malcontent-control parental controls app
* Add initial support for session limits (but more needs to be done)
* Rename some of the commands for `malcontent-client` and rename some C APIs
(but with compatibility defines)
* Bugs fixed:
- #6 Align GLib dependency requirements
- !16 docs: Improve documentation of "app-filter-changed" signal
- !18 build: Port meson-make-symlink script to Python
- !19 Add session limits support and PAM module
- !20 Initial version of parental controls app
- !21 build: Fix default value of pamlibdir
- !22 Iterate on UI of parental controls app
- !23 Split widgets into separate library
- !24 Allow user controls to be used for not-yet-existing users
Overview of changes in malcontent 0.4.0 Overview of changes in malcontent 0.4.0
======================================= =======================================

View File

@ -52,6 +52,32 @@ AppArmor or SELinux. However, its correct use by applications should provide
enough of an obstacle to prevent users easily or accidentally having access to enough of an obstacle to prevent users easily or accidentally having access to
content which they shouldnt. content which they shouldnt.
Development principles
---
malcontent exists to make it easier for parents to responsibly set limits on
what their children can do on the computer (similarly, for other carer/caree
relationships). It should provide guidance on, and nudge parents towards,
following the best practice for discussing, choosing and setting restrictions on
their childs computer use.
Restrictions should be supported which allow giving children access to material
which is appropriate to their age/stage of development, but which can restrict
access to other material so they are not overwhelmed with too many, or too
complex, ideas for their stage of development. Similarly, restrictions should be
supported to control unsupervised communication with unknown people online, as
being coerced or bullied is one of the more common harms for children online.
Best practices should be research and evidence-based, and supported by large
international or national childrens organisations or charities. They may change
over time.
malcontent is a tool to help with a social problem. In the hands of a bad
parent, it can be used to do bad things. Features in malcontent should be
designed with that in mind, such that if they are used maliciously, they should
not give the parent radically more power over their child than they would have
had without malcontent.
Example usage Example usage
--- ---
@ -61,7 +87,7 @@ set parental controls policies for users.
``` ```
$ # This sets the parental controls policy for user philip to allow no \\ $ # This sets the parental controls policy for user philip to allow no \\
installation of apps with anything more than none for realistic violence, \\ installation of apps with anything more than none for realistic violence, \\
and to blacklist running the org.freedesktop.Bustle flatpak: and to blocklist running the org.freedesktop.Bustle flatpak:
$ malcontent-client set philip \\ $ malcontent-client set philip \\
violence-realistic=none \\ violence-realistic=none \\
app/org.freedesktop.Bustle/x86_64/stable app/org.freedesktop.Bustle/x86_64/stable
@ -89,19 +115,23 @@ Dependencies
------------ ------------
* accounts-service * accounts-service
* appstream
* dbus-daemon * dbus-daemon
* flatpak * flatpak
* gio-2.0 ≥ 2.60 * gio-2.0 ≥ 2.60
* gio-unix-2.0 ≥ 2.60 * gio-unix-2.0 ≥ 2.60
* glib-2.0 ≥ 2.60 * glib-2.0 ≥ 2.60
* gobject-2.0 ≥ 2.60 * gobject-2.0 ≥ 2.60
* gtk+-3.0 * gtk4
* libadwaita
* polkit-gobject-1 * polkit-gobject-1
Licensing Licensing
--------- ---------
All code in this project is licensed under LGPL-2.1+. See COPYING for more details. All code in the libraries in this project is licensed under LGPL-2.1+. Code in the
`malcontent-control` application is licensed under GPL-2.0+. See `COPYING` and the
copyright headers in individual files for more details.
Bugs Bugs
---- ----

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.endlessm.ParentalControls.AccountInfo">
<annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
<annotation name="org.freedesktop.Accounts.Authentication.ChangeOwn"
value="com.endlessm.ParentalControls.AccountInfo.ChangeOwn"/>
<annotation name="org.freedesktop.Accounts.Authentication.ReadOwn"
value="com.endlessm.ParentalControls.AccountInfo.ReadOwn"/>
<annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
value="com.endlessm.ParentalControls.AccountInfo.ChangeAny"/>
<annotation name="org.freedesktop.Accounts.Authentication.ReadAny"
value="com.endlessm.ParentalControls.AccountInfo.ReadAny"/>
<!--
IsParent:
Whether this user is a parent on the system. All parents must be
administrators, but not all administrators must be parents.
This is intended to allow parent accounts to be rendered differently in
the user interface. It must not be used to make authentication
decisions — use polkit for that.
The value of this property must be treated as `false` if the user is not
an administrator.
-->
<property name="IsParent" type="b" access="readwrite">
<annotation name="org.freedesktop.Accounts.DefaultValue" value="false"/>
</property>
</interface>
</node>

View File

@ -24,8 +24,8 @@
The string list contains flatpak application IDs (containing at least one The string list contains flatpak application IDs (containing at least one
dot and no leading slash) and absolute binary paths (containing a leading dot and no leading slash) and absolute binary paths (containing a leading
slash). The boolean value indicates whether this is a whitelist (true) or slash). The boolean value indicates whether this is an allowlist (true)
blacklist (false). or blocklist (false).
--> -->
<property name="AppFilter" type="(bas)" access="readwrite"> <property name="AppFilter" type="(bas)" access="readwrite">
<annotation name="org.freedesktop.Accounts.DefaultValue" <annotation name="org.freedesktop.Accounts.DefaultValue"
@ -69,7 +69,7 @@
installation can proceed. installation can proceed.
If this is false, the user is not allowed to install any apps or runtimes If this is false, the user is not allowed to install any apps or runtimes
to their flatpak user repository. to their flatpak user repository due to parental controls.
--> -->
<property name="AllowUserInstallation" type="b" access="readwrite"> <property name="AllowUserInstallation" type="b" access="readwrite">
<annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/> <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
@ -80,14 +80,15 @@
Whether this user is allowed to install to the flatpak system repository. Whether this user is allowed to install to the flatpak system repository.
If this is true, and if the polkit check for allowing app installation If this is true, and if the polkit check for allowing app installation
succeeds, and if the OarsFilter does not restrict this app, app succeeds (i.e. the user is an administrator or an administrator has given
permission), and if the OarsFilter does not restrict this app, app
installation can proceed. installation can proceed.
If this is false, the user is not allowed to install any apps or runtimes If this is false, the user is not allowed to install any apps or runtimes
to the flatpak system repository. to the flatpak system repository due to parental controls.
--> -->
<property name="AllowSystemInstallation" type="b" access="readwrite"> <property name="AllowSystemInstallation" type="b" access="readwrite">
<annotation name="org.freedesktop.Accounts.DefaultValue" value="false"/> <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
</property> </property>
</interface> </interface>
</node> </node>

View File

@ -79,4 +79,44 @@
<allow_active>auth_admin_keep</allow_active> <allow_active>auth_admin_keep</allow_active>
</defaults> </defaults>
</action> </action>
<action id="com.endlessm.ParentalControls.AccountInfo.ChangeOwn">
<description>Change your own account info</description>
<message>Authentication is required to change your account info.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="com.endlessm.ParentalControls.AccountInfo.ReadOwn">
<description>Read your own account info</description>
<message>Authentication is required to read your account info.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="com.endlessm.ParentalControls.AccountInfo.ChangeAny">
<description>Change another users account info</description>
<message>Authentication is required to change another users account info.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="com.endlessm.ParentalControls.AccountInfo.ReadAny">
<description>Read another users account info</description>
<message>Authentication is required to read another users account info.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
</policyconfig> </policyconfig>

View File

@ -27,7 +27,7 @@ polkit.addRule(function(action, subject) {
action.id == "com.endlessm.ParentalControls.SessionLimits.ReadOwn" || action.id == "com.endlessm.ParentalControls.SessionLimits.ReadOwn" ||
action.id == "com.endlessm.ParentalControls.SessionLimits.ReadAny") && action.id == "com.endlessm.ParentalControls.SessionLimits.ReadAny") &&
subject.active && subject.local && subject.active && subject.local &&
subject.isInGroup("sudo")) { subject.isInGroup("@PRIVILEGED_GROUP@")) {
return polkit.Result.YES; return polkit.Result.YES;
} }

View File

@ -1,4 +1,4 @@
i18n.merge_file('com.endlessm.ParentalControls.policy', i18n.merge_file(
input: 'com.endlessm.ParentalControls.policy.in', input: 'com.endlessm.ParentalControls.policy.in',
output: 'com.endlessm.ParentalControls.policy', output: 'com.endlessm.ParentalControls.policy',
po_dir: po_dir, po_dir: po_dir,
@ -7,6 +7,7 @@ i18n.merge_file('com.endlessm.ParentalControls.policy',
) )
dbus_interfaces = [ dbus_interfaces = [
'com.endlessm.ParentalControls.AccountInfo',
'com.endlessm.ParentalControls.AppFilter', 'com.endlessm.ParentalControls.AppFilter',
'com.endlessm.ParentalControls.SessionLimits', 'com.endlessm.ParentalControls.SessionLimits',
] ]
@ -20,5 +21,11 @@ foreach dbus_interface: dbus_interfaces
join_paths(accountsserviceinterfacesdir, filename)) join_paths(accountsserviceinterfacesdir, filename))
endforeach endforeach
install_data('com.endlessm.ParentalControls.rules', polkit_conf = configuration_data()
install_dir: join_paths(get_option('datadir'), 'polkit-1', 'rules.d')) polkit_conf.set('PRIVILEGED_GROUP', get_option('privileged_group'))
configure_file(
input: 'com.endlessm.ParentalControls.rules.in',
output: 'com.endlessm.ParentalControls.rules',
configuration: polkit_conf,
install_dir: join_paths(get_option('datadir'), 'polkit-1', 'rules.d')
)

View File

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="creating-a-child-user">
<info>
<link type="guide" xref="index#setup"/>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
<desc>Creating a child user on the computer.</desc>
</info>
<title>Creating a Child User</title>
<p>Parental controls can only be applied to non-administrator accounts. Such
an account may have been created when the computer was initially set up.
If not, a new child user may be created from the <app>Parental
Controls</app> application if no child users already exist; and otherwise
may be created from the <app>Control Center</app>.</p>
<p>To create a new child user, see <link type="guide" xref="help:gnome-help/user-add">Add a new user account</link>.
As soon as the new user is created, it will appear in the <app>Parental
Controls</app> window so that its parental controls settings can be
configured.</p>
</page>

21
help/C/index.page Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="guide" id="index">
<info>
<revision pkgversion="0.7.0" version="0.1" date="2020-03-27" status="final"/>
<credit type="author copyright">
<name>Philip Withnall</name>
<email>withnall@endlessm.com</email>
<years>2020</years>
</credit>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
</info>
<title>Parental Controls Help</title>
<section id="setup" style="2column">
<title>Introduction &amp; Setup</title>
</section>
<section id="controls" style="2column">
<title>Controls to Apply</title>
</section>
</page>

23
help/C/internet.page Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="internet">
<info>
<link type="guide" xref="index#controls"/>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
<desc>Restricting a child users access to the internet.</desc>
</info>
<title>Restricting Access to the Internet</title>
<p>You can restrict a users access to the internet. This will prevent them
using a web browser, but it will not prevent them using the internet (in
potentially more limited forms) through other applications. For example,
it will not prevent access to e-mail accounts using <app>Evolution</app>,
and it will not prevent software updates being downloaded and applied.</p>
<p>To restrict a users access to the internet:</p>
<steps>
<item><p>Open the <app>Parental Controls</app> application.</p></item>
<item><p>Select the user in the tabs at the top.</p></item>
<item><p>Enable the <gui style="checkbox">Restrict Web Browsers</gui> checkbox.</p></item>
</steps>
</page>

30
help/C/introduction.page Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="introduction">
<info>
<link type="guide" xref="index#setup"/>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
<desc>Overview of parental controls, the <app>Parental Controls</app>
application and its use in other situations where access restrictions are
needed on a user.</desc>
<link type="seealso" xref="creating-a-child-user"/>
</info>
<title>Introduction to Parental Controls</title>
<p>Parental controls are a way to restrict what non-administrator accounts can
do on the computer, with the aim of allowing parents to restrict what their
children can do when using the computer unsupervised or under limited
supervision.</p>
<p>This functionality can be used in other situations ­ such as other
carer/caree relationships but is labelled as parental controls so that
its easy to find, as thats what most people will be looking for.</p>
<p>The parental controls for any user can be queried and set using the
<app>Parental Controls</app> application. This lists the non-administrator
accounts in tabs along its top bar, and shows their current parental
controls settings below. Changes to the parental controls apply immediately.</p>
<p>Restrictions on using the computer can only be applied to non-administrator
accounts. The parental controls settings for a user can only be changed by
an administrator, although the administrator can do so from the users
account by entering their password when prompted by the <app>Parental
Controls</app> application.</p>
</page>

6
help/C/legal.xml Normal file
View File

@ -0,0 +1,6 @@
<license xmlns="http://projectmallard.org/1.0/"
href="http://creativecommons.org/licenses/by-sa/3.0/">
<p>This work is licensed under a
<link href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
Attribution-ShareAlike 3.0 Unported License</link>.</p>
</license>

View File

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="restricting-applications">
<info>
<link type="guide" xref="index#controls"/>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
<desc>Restricting a child user from running already-installed applications.</desc>
</info>
<title>Restricting Access to Installed Applications</title>
<p>You can prevent a user from running specific applications which are already
installed on the computer. This could be useful if other users need those
applications but they are not appropriate for a child.</p>
<p>When installing additional software, you should consider whether that needs
to be restricted for some users — newly installed software is usable by all
users by default.</p>
<p>To restrict a users access to a specific application:</p>
<steps>
<item><p>Open the <app>Parental Controls</app> application.</p></item>
<item><p>Select the user in the tabs at the top.</p></item>
<item><p>Press the <gui style="button">Restrict Applications</gui> button.</p></item>
<item><p>Enable the switch in the row for each application you would like to restrict the user from accessing.</p></item>
<item><p>Close the <gui>Restrict Applications</gui> window.</p></item>
</steps>
<p>Restricting access to specific applications is often used in conjunction
with <link xref="software-installation"/> to prevent a user from installing
additional software which has not been vetted.</p>
</page>

View File

@ -0,0 +1,66 @@
<?xml version="1.0"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="software-installation">
<info>
<link type="guide" xref="index#controls"/>
<include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
<desc>Restricting the software a child user can install, or preventing them installing additional software entirely.</desc>
</info>
<title>Restricting Software Installation</title>
<p>You can prevent a user from installing additional software on the system.
They will still be able to search for new software to install, but will need
an administrator to authorize the installation when they try to install an
application. This applies whether they are trying to install the application
system-wide (for all users) or just for themselves.</p>
<p>Additionally, you can restrict which software a user can browse or search
for in the <app>Software</app> catalog by age categories.</p>
<p>To prevent a user from running an application which has already been
installed, see <link xref="restricting-applications"/>.</p>
<section id="installation">
<title>Preventing Software Installation</title>
<p>To prevent a user from installing additional software:</p>
<steps>
<item><p>Open the <app>Parental Controls</app> application.</p></item>
<item><p>Select the user in the tabs at the top.</p></item>
<item><p>Enable the <gui style="checkbox">Restrict Application Installation</gui> checkbox.</p></item>
</steps>
</section>
<section id="oars">
<title>Restricting Software Installation by Age</title>
<p>Applications in the <app>Software</app> catalog have information about
content they contain which might be inappropriate for some ages — for
example, various forms of violence, unmoderated chat with other people on
the internet, or the possibility of spending money.</p>
<p>For each application, this information is summarized as the minimum age
child it is typically suitable to be used by — for example, “suitable for
ages 7+”. These age ratings are presented in region-specific schemes which
can be compared with the ratings schemes used for films and games.</p>
<p>The applications shown to a user in the <app>Software</app> catalog can
be filtered by their age suitability. Applications which are not suitable
for the user will be hidden, and will not be installable by that user.
They will be installable by other users (if their age suitability is set
high enough).</p>
<p>To filter the applications seen by a user in the <app>Software</app>
catalog to only those suitable for a certain age:</p>
<steps>
<item><p>Open the <app>Parental Controls</app> application.</p></item>
<item><p>Select the user in the tabs at the top.</p></item>
<item><p>In the <gui>Application Suitability</gui> list, select the age which applications should be suitable for.</p></item>
</steps>
<note style="important">
<p>The users actual age is not stored, so the <gui>Application Suitability</gui>
is not automatically updated over time as the child grows older. You
must periodically re-assess the appropriate <gui>Application Suitability</gui>
for each user.</p>
</note>
</section>
</page>

13
help/LINGUAS Normal file
View File

@ -0,0 +1,13 @@
# please keep this list sorted alphabetically
da
de
es
hu
id
it
pl
pt_BR
ru
sv
tr
uk

457
help/da/da.po Normal file
View File

@ -0,0 +1,457 @@
# Danish translation for malcontent.
# Copyright (C) 2020 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# scootergrisen, 2020.
# scootergrisen: oversættelsen er ikke afprøvet
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-10-11 03:28+0000\n"
"PO-Revision-Date: 2020-11-18 00:00+0200\n"
"Last-Translator: scootergrisen\n"
"Language-Team: Danish\n"
"Language: da\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "scootergrisen <>, 2020"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Oprettelse af en barnebruger på computeren."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Oprettelse af en barnebruger"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Forældrestyring kan kun anvendes på konti som ikke er administrator. En "
"sådan konto kan være blevet oprettet, første gang computeren blev opsat. Er "
"det ikke tilfældet, så kan der oprettes en ny barnebruger i programmet "
"<app>Forældrestyring</app>, hvis der ikke allerede findes en barnebruger, "
"ellers kan den oprettes i <app>Kontrolpanel</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Se <link type=\"guide\" xref=\"help:gnome-"
"help/user-add\">Tilføj en ny brugerkonto</link>, for at oprette en ny barnebruger. Den nye bruger vises i "
"vinduet <app>Forældrestyring</app>, så snart den er oprettet, så dens "
"forældrestyringsindstillinger kan konfigureres."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Hjælp til Forældrestyring"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Introduktion og opsætning"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Styring som kan anvendes"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Begrænsning af en barnebrugers adgang til internettet."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Begrænsning af adgang til internettet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Du kan begrænse en brugers adgang til internettet. Det forhindrer dem i at "
"bruge en webbrowser, men det forhindrer dem ikke i at bruge internettet (i "
"potentielt mere begrænset form) gennem andre programmer. Det vil f.eks. "
"ikke forhindre adgang til e-mailkonti med <app>Evolution</app> og det "
"forhindrer ikke softwareopdateringer i at blive downloadet og installeret."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Sådan begrænses en brugers adgang til internettet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:27 C/software-installation.page:64
msgid "Open the <app>Parental Controls</app> application."
msgstr "Åbn programmet <app>Forældrestyring</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:28 C/software-installation.page:65
msgid "Select the user in the tabs at the top."
msgstr "Vælg brugeren i fanebladene øverst."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Aktivér afkrydsningsboksen <gui style=\"checkbox\">Begræns webbrowsere</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls and the <app>Parental Controls</app> "
"application."
msgstr "Overblik over forældrestyring og programmet <app>Forældrestyring</app>."
#. (itstool) path: page/title
#: C/introduction.page:10
msgid "Introduction to Parental Controls"
msgstr "Introduktion til Forældrestyring"
#. (itstool) path: page/p
#: C/introduction.page:12
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Forældrestyring er et måde til at begrænse, hvad konti, som ikke er "
"administrator, kan gøre på computeren med det mål at give forældre mulighed "
"for at begrænse, hvad deres børn kan, når de bruger computeren uden opsyn "
"eller under begrænset opsyn."
# scootergrisen: fra gennemlæsning: det skal nok ikke forstås som en plejesituation som på et plejehjem, men som et forhold mellem dem, der bestemmer, og dem der bliver bestemt over
# scootergrisen: fra gennemlæsning: Prøv med: såsom andre forhold mellem myndige og umyndige
#. (itstool) path: page/p
#: C/introduction.page:16
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find."
msgstr ""
"Funktionaliteten kan bruges i andre situationer ­ såsom et andet forhold mellem "
"plejer og plejede men kaldes forældrestyring for at det skal være let at finde."
#. (itstool) path: page/p
#: C/introduction.page:19
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Forældrestyringen kan for alle brugere forespørges og indstilles med "
"programmet <app>Forældrestyring</app>. Det viser de konti, som ikke er "
"administrator, i faneblade langs den øverste linje og viser deres nuværende "
"forældrestyringsindstillinger nedenfor. Ændringer til forældrestyringen "
"anvendes straks."
#. (itstool) path: page/p
#: C/introduction.page:23
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Begrænsninger i at bruge computeren kan kun anvendes på konti som ikke er "
"administrator. Forældrestyringsindstillingerne til en bruger kan kun ændres "
"af en administrator, dog kan administratoren gøre det fra brugerens konto "
"ved at indtaste deres adgangskode når de bliver spurgt om det i programmet "
"<app>Forældrestyring</app>."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr ""
"Creative Commons Kreditering-Deling på samme vilkår 3.0 Ikke porteret-licens"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Værket er licenseret under en <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr ""
"Begrænsning af en barnebruger i at køre programmer som allerede er "
"installeret."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Begrænsning af adgang til installerede programmer"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Du kan forhindre en bruger i at køre bestemte programmer som allerede er "
"installeret på computeren. Det kan være nyttigt hvis andre brugere har brug "
"for de programmet men de ikke er egnet til et barn."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Når der installeres yderligere software bør du overveje om det skal "
"begrænses til nogle brugere — nyligt "
"installeret software kan bruges af alle brugere som standard."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Sådan begrænses en brugers adgang til et bestemt program:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Tryk på knappen <gui style=\"button\">Begræns programmer</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Aktivér kontakten i rækken ved de programmer du vil begrænse brugeren i at få "
"adgang til."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Luk vinduet <gui>Begræns programmer</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Begrænsning af adgang til bestemte programmer bruges ofte sammen med <link "
"xref=\"software-installation\"/> for at forhindre en bruger i at installere "
"yderligere software som ikke er blevet undersøgt."
# scootergrisen: her er både "Restricting" og "preventing" brugt
# scootergrisen: så måske de ikke begge skal være samme ord
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Begrænsning af den software en barnebruger kan installere eller helt forhindre "
"dem i at installere yderligere software."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Begrænsning af softwareinstallation"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software, either for the "
"entire system, or just for themselves. They will still be able to search for "
"new software to install, but will need an administrator to authorize the "
"installation when they try to install an application."
msgstr ""
"Du kan forhindre en bruger i at installere yderligere software, enten for "
"hele systemet eller blot sig selv. De vil stadigvæk være i stand til at søge "
"efter ny software der skal installeres, men en administrator skal godkende "
"installationen når de forsøger at installere et program."
#. (itstool) path: page/p
#: C/software-installation.page:16
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Derudover kan du begrænse, hvilken software en bruger kan gennemse eller søge "
"efter i <app>Software</app>-kataloget efter aldersgruppekategorier."
#. (itstool) path: page/p
#: C/software-installation.page:19
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"For at forhindre en bruger i at køre et program som allerede er blevet "
"installeret, se <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:23
msgid "Preventing Software Installation"
msgstr "Forhindring af softwareinstallation"
#. (itstool) path: section/p
#: C/software-installation.page:25
msgid "To prevent a user from installing additional software:"
msgstr "Sådan forhindres en bruger i at installere yderligere software:"
#. (itstool) path: item/p
#: C/software-installation.page:29
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Aktivér afkrydsningsboksen <gui style=\"checkbox\">Begræns "
"programinstallation</gui>."
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Or enable the <gui style=\"checkbox\">Restrict Application Installation for "
"Others</gui> checkbox."
msgstr ""
"Eller aktivér afkrydsningsboksen <gui style=\"checkbox\">Begræns "
"programinstallation for andre</gui>."
#. (itstool) path: section/p
#: C/software-installation.page:33
msgid ""
"The <gui style=\"checkbox\">Restrict Application Installation for Others</"
"gui> checkbox allows the user to install additional software for themselves, "
"but prevents that software from being made available to other users. It "
"could be used, for example, if there were two child users, one of whom is "
"mature enough to be allowed to install additional software, but the other "
"isnt — enabling <gui style=\"checkbox\">Restrict Application Installation "
"for Others</gui> would prevent the more mature child from installing "
"applications which are inappropriate for the other child and making them "
"available to the other child."
msgstr ""
"Afkrydsningsboksen <gui style=\"checkbox\">Begræns programinstallation for "
"andre</gui> giver brugeren mulighed for at installere yderligere software "
"til sig selv, men forhindrer softwaren i at blive gjort tilgængelig for andre "
"brugere. Det kan f.eks. bruges, hvis der er to barnebrugere, hvoraf en af dem "
"er moden nok til at få tilladelse til at installere yderligere software, men "
"den anden ikke er — hvis <gui style=\"checkbox\">Begræns programinstallation "
"for andre</gui> tillades vil det forhindre det modne barn i at installere "
"programmer, som kan være uegnet for det andet barn og gøre dem tilgængelige "
"for det andet barn."
#. (itstool) path: section/title
#: C/software-installation.page:45
msgid "Restricting Software Installation by Age"
msgstr "Begrænsning af softwareinstallation efter aldersgruppe"
# scootergrisen: find god oversættelse af "unmoderated"
#. (itstool) path: section/p
#: C/software-installation.page:47
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Programmer i <app>Software</app>-kataloget har information om deres indhold "
"som kan være uegnet til nogle aldersgrupper — f.eks. diverse former for "
"vold, umodereret chat med andre personer på internettet eller muligheden for "
"at bruge penge."
# scootergrisen: find ud af hvordan "suitable for ages 7+" er oversat andet sted
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Informationen er opsummeret i hvert program som den laveste alder for børn "
"det typisk er egnet for at blive brugt af — f.eks. “suitable for ages 7+”. "
"Disse aldersvurderinger præsenteres i områdespecifikke modeller som kan "
"sammenlignes med de vurderingsmodeller som bruges til film og spil."
# scootergrisen: tjek "age suitability". Findes to gange
#. (itstool) path: section/p
#: C/software-installation.page:55
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"De programmer, som vises til en bruger i <app>Software</app>-kataloget, kan "
"filtreres efter den aldersgruppe, de er egnet til. Programmer, som ikke er "
"egnet til brugeren, skjules og kan ikke installeres af den bruger. De kan "
"installeres af andre brugere (hvis aldersgruppen de er egnet til er "
"indstillet højt nok)."
#. (itstool) path: section/p
#: C/software-installation.page:61
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Sådan filtreres de programmer en bruger kan se i "
"<app>Software</app>-kataloget til dem der kun er egnet til en bestemt "
"aldersgruppe:"
#. (itstool) path: item/p
#: C/software-installation.page:66
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Vælg den aldersgruppe som programmerne "
"skal være egnet til i listen <gui>Programegnethed</gui>."
#. (itstool) path: note/p
#: C/software-installation.page:70
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Brugerens rigtige alder gemmes ikke, så <gui>Programegnethed</gui> opdateres "
"ikke automatisk efterhånden som barnet bliver ældre. Du skal periodisk "
"revurdere den passende <gui>Programegnethed</gui> til hver bruger."

362
help/de/de.po Normal file
View File

@ -0,0 +1,362 @@
# German translation for malcontent.
# Copyright (C) 2021 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Christian Kirbach <Christian.Kirbach@gmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent main\n"
"POT-Creation-Date: 2021-12-29 15:34+0000\n"
"PO-Revision-Date: 2021-12-31 13:36+0100\n"
"Last-Translator: Tim Sabsch <tim@sabsch.com>\n"
"Language-Team: German <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Christian Kirbach <christian.kirbach@gmail.com>, 2021."
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "So legen Sie ein Kinderkonto auf dem Rechner an."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Ein Kinderkonto anlegen"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Die Kindersicherung kann für alle Konten außer Administrator-Konten "
"eingerichtet werden. Ein solches Konto wurde vermutlich bei der "
"Ersteinrichtung des Rechners angelegt. Falls nicht, können Sie ein neues "
"Kinderkonto in der Anwendung <app>Kindersicherung</app> anlegen, und "
"alternativ in den <app>Einstellungen</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Folgen Sie den Anweisungen <link type=\"guide\" xref=\"help:gnome-help/user-"
"add\">Ein neues Benutzerkonto anlegen</link>, um ein neues Kinderkonto "
"anzulegen. Sobald der neue Benutzer angelegt wurde, erscheint er im Fenster "
"von <app>Kindersicherung</app>. Die Einrichtung der Kindersicherung wird "
"dort durchgeführt."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Hilfe zur Kindersicherung"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Einführung und Einrichtung"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr ""
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Den Internet-Zugang eines Kinderkontos einschränken."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Den Zugriff auf das Internet einschränken"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "So schränken Sie den Internet-Zugang eines Kinderkontos ein:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Öffnen Sie die Anwendung <app>Kindersicherung</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Wählen Sie den Benutzer oben in den Reitern."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Aktivieren Sie das Ankreuzfeld <gui style=\"checkbox\">Web-Browser "
"einschränken</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Einführung in die Kindersicherung"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Dieses Werk wird unter einer <_:link-1/> verbreitet."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr ""
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Den Zugriff auf installierte Anwendungen einschränken"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Sie können Benutzer daran hindern, bestimmte Anwendungen auszuführen, die "
"auf dem Rechner installiert sind. Dies ist nützlich, wenn andere Benutzer "
"die Anwendungen benötigen, diese aber nicht für Kinder geeignet sind."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Wenn Sie weitere Software installieren, sollten Sie berücksichtigen, ob sie "
"für einige Benutzer eingeschränkt werden muss. Neu installierte Software ist "
"standardmäßig für alle Benutzer nutzbar."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr ""
"So schränken Sie den Zugriff eines Benutzers auf bestimmte Anwendungen ein:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr ""
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr ""
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Software-Installation einschränken"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr ""
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr ""
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""

455
help/es/es.po Normal file
View File

@ -0,0 +1,455 @@
# Spanish translations for malcontent.
# Copyright © 2020 the malcontent authors.
# This file is distributed under the same license as the malcontent package.
# Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-04-24 15:30+0000\n"
"PO-Revision-Date: 2020-08-22 09:41-0500\n"
"Last-Translator: Adolfo Jayme Barrientos <fitojb@ubuntu.com>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.1\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2020"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Crear una cuenta infantil en el equipo."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Crear una cuenta infantil"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Los controles parentales pueden aplicarse únicamente a las cuentas no "
"administrativas. Puede que se haya creado una cuenta de este tipo al momento "
"de la configuración inicial del equipo. Si no es así, es posible crear una "
"cuenta infantil nueva desde la aplicación <app>Controles parentales</app> o "
"mediante la <app>Configuración</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Para crear una cuenta infantil, consulte <link type=\"guide\" xref=\"help:"
"gnome-help/user-add\">Añadir una cuenta de usuario nueva</link>. Tan pronto "
"como haya creado la cuenta nueva, esta figurará en la ventana de "
"<app>Controles parentales</app> para que puedan definirse sus "
"configuraciones de control parental."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Ayuda sobre los controles parentales"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Introducción y configuración"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Controles para aplicar"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Restringir el acceso a Internet por parte de un menor"
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Restringir el acceso a Internet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Es posible restringir el acceso de un usuario a Internet. Esto le impedirá "
"utilizar un navegador web, pero no restringirá la conexión a Internet de "
"otras aplicaciones. Por ejemplo, no impedirá el acceso a las cuentas de "
"correo electrónico mediante <app>Evolution</app>, ni impedirá la descarga y "
"aplicación de actualizaciones de software."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Para restringir el acceso de un usuario a Internet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:27 C/software-installation.page:64
msgid "Open the <app>Parental Controls</app> application."
msgstr "Abra la aplicación <app>Controles parentales</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:28 C/software-installation.page:65
msgid "Select the user in the tabs at the top."
msgstr "En las pestañas de la parte superior, seleccione la cuenta deseada."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Active la casilla <gui style=\"checkbox\">Restringir navegadores web</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls and the <app>Parental Controls</app> "
"application."
msgstr ""
"Visión de conjunto de los controles parentales y la aplicación "
"<app>Controles parentales</app>."
#. (itstool) path: page/title
#: C/introduction.page:10
msgid "Introduction to Parental Controls"
msgstr "Introducción al control parental"
#. (itstool) path: page/p
#: C/introduction.page:12
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Los controles parentales representan una manera de restringir lo que las "
"cuentas no administrativas pueden efectuar en el equipo, con el objetivo de "
"permitir que los padres restrinjan las acciones de sus hijos al utilizar el "
"equipo sin supervisión o bajo supervisión limitada."
#. (itstool) path: page/p
#: C/introduction.page:16
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find."
msgstr ""
"Esta funcionalidad puede ser de utilidad en otras situaciones —como las "
"relaciones entre cuidadores y tutelados—, pero se denomina «controles "
"parentales» para facilitar su localización."
#. (itstool) path: page/p
#: C/introduction.page:19
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"La aplicación <app>Controles parentales</app> permite realizar consultas "
"sobre cualquier cuenta y definir controles por cada una. La aplicación "
"enumera todas las cuentas no administrativas en forma de pestañas en la "
"barra superior de la ventana, y por debajo muestra los controles definidos "
"actualmente. Las modificaciones a los controles parentales surten efecto de "
"inmediato."
#. (itstool) path: page/p
#: C/introduction.page:23
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Solo se puede aplicar restricciones de uso del equipo sobre cuentas no "
"administrativas. Únicamente los administradores pueden establecer las "
"configuraciones de controles parentales para una cuenta determinada. Es "
"posible hacer esto sin salir de la cuenta; basta con proporcionar la "
"contraseña administrativa cuando <app>Controles parentales</app> la solicite."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr ""
"Licencia genérica Creative Commons 3.0 de atribución e igual compartición"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Esta obra está disponible en virtud de la <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Restringir a los menores el uso de aplicaciones ya instaladas."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Restringir el acceso a las aplicaciones instaladas"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Puede impedir que una cuenta ejecute determinadas aplicaciones instaladas en "
"el equipo. Esto puede ser útil si hay otros usuarios que necesitan estas "
"aplicaciones, pese a ser inadecuadas para un menor."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Tras instalar software adicional, es recomendable que considere si hace "
"falta restringírselo a determinados usuarios, dado que, de manera "
"predeterminada, todos los usuarios pueden utilizarlo."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Para restringir el acceso de una cuenta a una aplicación concreta:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Pulse el botón <gui style=\"button\">Restringir aplicaciones</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Active el interruptor en la fila de cada aplicación que quiera restringir."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Cierre la ventana <gui>Restringir aplicaciones</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"La restricción de acceso a aplicaciones determinadas se emplea a menudo "
"junto con <link xref=\"software-installation\"/> para evitar que se instale "
"software sin que usted lo examine."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Restringir el software que un menor puede instalar, o bien evitar que "
"instalen software adicional por completo."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Restringir la instalación de software"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software, either for the "
"entire system, or just for themselves. They will still be able to search for "
"new software to install, but will need an administrator to authorize the "
"installation when they try to install an application."
msgstr ""
"Puede impedir que un usuario instale software adicional, bien para todo el "
"sistema, bien para sí mismo. Todavía será capaz de buscar software nuevo "
"para instalar, pero si intenta instalarlo deberá contar con la ayuda de un "
"administrador para que este lo autorice."
#. (itstool) path: page/p
#: C/software-installation.page:16
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Además, si se sirve de las categorías por edades en <app>Software</app>, "
"puede restringir qué software se podrá explorar en su catálogo."
#. (itstool) path: page/p
#: C/software-installation.page:19
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Para evitar que un usuario ejecute una aplicación previamente instalada, "
"consulte <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:23
msgid "Preventing Software Installation"
msgstr "Evitar la instalación de software"
#. (itstool) path: section/p
#: C/software-installation.page:25
msgid "To prevent a user from installing additional software:"
msgstr ""
"Siga este procedimiento para impedir la instalación de software adicional:"
#. (itstool) path: item/p
#: C/software-installation.page:29
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Active la casilla <gui style=\"checkbox\">Restringir instalación de "
"aplicaciones</gui>."
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Or enable the <gui style=\"checkbox\">Restrict Application Installation for "
"Others</gui> checkbox."
msgstr ""
"O bien, active la casilla <gui style=\"checkbox\">Restringir instalación de "
"aplicaciones para los otros</gui>."
#. (itstool) path: section/p
#: C/software-installation.page:33
msgid ""
"The <gui style=\"checkbox\">Restrict Application Installation for Others</"
"gui> checkbox allows the user to install additional software for themselves, "
"but prevents that software from being made available to other users. It "
"could be used, for example, if there were two child users, one of whom is "
"mature enough to be allowed to install additional software, but the other "
"isnt — enabling <gui style=\"checkbox\">Restrict Application Installation "
"for Others</gui> would prevent the more mature child from installing "
"applications which are inappropriate for the other child and making them "
"available to the other child."
msgstr ""
"La casilla <gui style=\"checkbox\">Restringir instalación de aplicaciones a "
"los otros</gui> permite la instalación de software adicional para uno mismo, "
"pero restringe su disponibilidad a las demás cuentas. Se puede sacar "
"provecho de esta función, por ejemplo, si tiene dos menores, de los cuales "
"solo uno es lo suficientemente maduro para permitírsele la instalación de "
"software; activar <gui style=\"checkbox\">Restringir instalación de "
"aplicaciones a los otros</gui> impedirá que el menor más maduro instale "
"aplicaciones inapropiadas para el otro niño."
#. (itstool) path: section/title
#: C/software-installation.page:45
msgid "Restricting Software Installation by Age"
msgstr "Restringir la instalación de software por edades"
#. (itstool) path: section/p
#: C/software-installation.page:47
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Las aplicaciones que se incluyen en el catálogo de <app>Software</app> "
"incluyen información relativa al contenido que poseen y la aptitud de este "
"según la edad, notando detalles como: diversas formas de violencia, chat no "
"moderado con otras personas a través de internet, o la posibilidad de gastar "
"dinero."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"En cada aplicación, esta información se condensa como la edad mínima en la "
"que se considera adecuado que un menor la utilice; por ejemplo, «de 7 años "
"en adelante». Estas clasificaciones se presentan de conformidad con ciertos "
"esquemas regionales, comparables con los que se utilizan para clasificar "
"películas y juegos."
#. (itstool) path: section/p
#: C/software-installation.page:55
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Las aplicaciones que <app>Software</app> muestra a cada usuario se pueden "
"filtrar por adecuación a la edad. Aquellas aplicaciones que no sean "
"adecuadas para una cuenta se ocultarán del catálogo y no se podrán instalar. "
"Otros usuarios las podrán instalar (si es que su clasificación de edad lo "
"permite)."
#. (itstool) path: section/p
#: C/software-installation.page:61
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Para filtrar las aplicaciones que un usuario ve en el catálogo de "
"<app>Software</app> y que se muestren solo las adecuadas para una "
"determinada edad:"
#. (itstool) path: item/p
#: C/software-installation.page:66
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"En la lista <gui>Idoneidad de aplicaciones</gui>, seleccione la edad deseada."
#. (itstool) path: note/p
#: C/software-installation.page:70
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Como no se almacena la edad del usuario, la <gui>idoneidad de aplicaciones</"
"gui> no se actualiza automáticamente a medida que crece el menor. Debe "
"revalorar periódicamente el nivel adecuado de <gui>Idoneidad de "
"aplicaciones</gui> para cada una de las cuentas."

441
help/hu/hu.po Normal file
View File

@ -0,0 +1,441 @@
# Hungarian translation for malcontent.
# Copyright (C) 2022 Free Software Foundation, Inc.
# This file is distributed under the same license as the malcontent package.
#
# Balázs Úr <ur.balazs at fsf dot hu>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: malcontent main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pwithnall/malcontent/"
"issues\n"
"POT-Creation-Date: 2022-09-21 15:25+0000\n"
"PO-Revision-Date: 2022-09-22 23:43+0200\n"
"Last-Translator: Balázs Úr <ur.balazs at fsf dot hu>\n"
"Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 19.12.3\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Úr Balázs <ur dot balazs at fsf dot hu>, 2022."
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Gyermekfelhasználó létrehozása a számítógépen."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Gyermekfelhasználó létrehozása"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"A szülői felügyelet csak a nem rendszergazdai fiókokra alkalmazható. Ilyen "
"fiókot esetleg a számítógép kezdeti beállításakor hozhattak létre. Ha nem, "
"akkor új gyermekfelhasználó hozható létre a <app>Szülői felügyelet</app> "
"alkalmazásból, ha még nem létezik gyermekfelhasználó, egyébként pedig a "
"<app>Vezérlőközpont</app> alkalmazásból hozható létre."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Új gyermekfelhasználó létrehozásához nézze meg az <link type=\"guide\" xref="
"\"help:gnome-help/user-add\">Új felhasználói fiók hozzáadása</link> "
"fejezetet. Amint az új felhasználó létrejött, megjelenik a <app>Szülői "
"felügyelet</app> ablakban, így a szülői felügyeleti beállításai "
"konfigurálhatók."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Szülői felügyelet súgó"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Bevezetés és beállítás"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Alkalmazandó szabályozások"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Egy gyermekfelhasználó internet-hozzáférésének korlátozása."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Internet-hozzáférés korlátozása"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Korlátozhatja egy felhasználó internet-hozzáférését. Ez megakadályozza őt a "
"webböngésző használatában, de nem akadályozza meg abban, hogy az internetet "
"(esetleg korlátozottabb formában) más alkalmazásokon keresztül használja. "
"Például nem akadályozza meg az e-mail fiókokhoz való hozzáférést az "
"<app>Evolution</app> használatával, és nem akadályozza meg a "
"szoftverfrissítések letöltését és alkalmazását."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Egy felhasználó internet-hozzáférésének korlátozásához:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Nyissa meg a <app>Szülői felügyelet</app> alkalmazást."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Válassza ki a felhasználót a fenti lapokon."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Jelölje be a <gui style=\"checkbox\">Webböngészők korlátozása</gui> "
"jelölőnégyzetet."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"A szülői felügyelet áttekintése, a <app>Szülői felügyelet</app> alkalmazás "
"és annak használata olyan egyéb helyzetekben, amikor egy felhasználó "
"hozzáférésének korlátozásai szükségesek."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Bevezetés a szülői felügyeletbe"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"A szülői felügyelet segítségével korlátozható, hogy a nem rendszergazdai "
"fiókok mit tehetnek a számítógépen, azzal a céllal, hogy a szülők "
"korlátozhassák, hogy mit tehetnek a gyermekeik, amikor felügyelet nélkül "
"vagy korlátozott felügyelet mellett használják a számítógépet."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Ez a funkció más helyzetekben is használható például egyéb gondozó-"
"gondozott kapcsolatokban , de „szülői felügyelet” címkével van ellátva, "
"hogy könnyen megtalálható legyen, mivel a legtöbb ember ezt keresi."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"A szülői felügyelet bármely felhasználóhoz lekérdezhető és beállítható a "
"<app>Szülői felügyelet</app> alkalmazás használatával. Ez a felső sávjában "
"lévő lapokon felsorolja a nem rendszergazdai fiókokat, és alatta megjeleníti "
"az aktuális szülői felügyeleti beállításokat. A szülői felügyelet "
"változtatásai azonnal érvénybe lépnek."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"A számítógép használatára vonatkozó korlátozások csak a nem rendszergazdai "
"fiókokra alkalmazhatók. Egy felhasználó szülői felügyeleti beállításait csak "
"egy rendszergazda változtathatja meg, bár a rendszergazda ezt a felhasználó "
"fiókjából is megteheti a jelszavának megadásával, amikor a <app>Szülői "
"felügyelet</app> alkalmazás erre kéri."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Nevezd meg! - Így add tovább! 3.0 átíratlan licenc"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Ez a mű a <_:link-1/> szerint licencelt."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr ""
"Egy gyermekfelhasználó korlátozása a már telepített alkalmazások "
"futtatásában."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "A telepített alkalmazásokhoz való hozzáférés korlátozása"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Megakadályozhatja, hogy egy felhasználó a számítógépre már telepített "
"bizonyos alkalmazásokat futtasson. Ez akkor lehet hasznos, ha más "
"felhasználóknak szükségük van ezekre az alkalmazásokra, de egy gyermek "
"számára nem megfelelőek."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"További szoftverek telepítésekor meg kell fontolnia, hogy nem kell-e "
"korlátozni azokat egyes felhasználók számára, ugyanis az újonnan telepített "
"szoftverek alapértelmezetten minden felhasználó számára használhatóak."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr ""
"Egy felhasználó adott alkalmazáshoz való hozzáférésének korlátozásához:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr ""
"Nyomja meg az <gui style=\"button\">Alkalmazások korlátozása</gui> gombot."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Kapcsolja be a kapcsolót minden olyan alkalmazás sorában, amelyhez a "
"felhasználó hozzáférését korlátozni szeretné."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Zárja be az <gui>Alkalmazások korlátozása</gui> ablakot."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Bizonyos alkalmazásokhoz való hozzáférés korlátozását gyakran használják a "
"<link xref=\"software-installation\"/> korlátozással együtt, hogy "
"megakadályozzanak egy felhasználót a további, nem ellenőrzött szoftverek "
"telepítésében."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Egy gyermekfelhasználó által telepíthető szoftverek korlátozása, vagy "
"további szoftverek telepítésének teljes megakadályozása."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Szoftvertelepítés korlátozása"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Megakadályozhat egy felhasználót abban, hogy további szoftvereket telepítsen "
"a rendszerre. A felhasználó továbbra is kereshet új telepítendő szoftvert, "
"de rendszergazdára lesz szüksége a telepítés felhatalmazásához, amikor "
"megpróbál telepíteni egy alkalmazást. Ez arra is vonatkozik, hogy az "
"alkalmazást rendszerszinten (minden felhasználónak) vagy csak saját magának "
"próbálja telepíteni."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Ezenkívül azt is korlátozhatja az életkor kategória alapján, hogy egy "
"felhasználó milyen szoftvereket böngészhet vagy kereshet a <app>Szoftver</"
"app> katalógusában."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Annak megakadályozásához, hogy egy felhasználó egy már telepített "
"alkalmazást futtasson, nézze meg az <link xref=\"restricting-applications\"/"
"> fejezetet."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Szoftvertelepítés megakadályozása"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
"Annak megakadályozásához, hogy a felhasználó további szoftvereket telepítsen:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Jelölje be az <gui style=\"checkbox\">Alkalmazástelepítés korlátozása</gui> "
"jelölőnégyzetet."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Szoftvertelepítés korlátozása életkor alapján"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"A <app>Szoftver</app> katalógusában található alkalmazások információval "
"rendelkeznek az általuk tartalmazott tartalommal kapcsolatban, hogy melyek "
"lehetnek bizonyos korosztályok számára nem megfelelőek például az erőszak "
"különböző formái, moderálatlan csevegés az interneten más emberekkel, vagy a "
"pénzköltés lehetősége."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Minden egyes alkalmazás esetében ez az információ összefoglalja, hogy az "
"adott alkalmazás jellemzően legalább milyen korú gyermek számára alkalmas "
"például „7 év felettiek számára alkalmas”. Ezek a korhatár-besorolások régió-"
"specifikus sémákban jelennek meg, amelyek összehasonlíthatók a filmek és "
"játékok esetében használt besorolási sémákkal."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"A <app>Szoftver</app> katalógusában egy felhasználó számára megjelenített "
"alkalmazások szűrhetők az életkori alkalmasságuk alapján. A felhasználó "
"számára nem megfelelő alkalmazások el lesznek rejtve, és nem lesznek "
"telepíthetők az adott felhasználó számára. Más felhasználók számára "
"telepíthetők lesznek (ha az életkori alkalmasságuk elég magasra van állítva)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"A <app>Szoftver</app> katalógusában egy felhasználó által látott "
"alkalmazások szűréséhez, hogy csak egy bizonyos korosztály számára legyenek "
"alkalmasak:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Az <gui>Alkalmazás alkalmassága</gui> listából válassza ki azt az életkort, "
"amelyre az alkalmazásoknak alkalmasnak kell lenniük."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"A felhasználó tényleges életkora nem kerül tárolásra, így az <gui>Alkalmazás "
"alkalmassága</gui> nem frissül automatikusan az idő múlásával, ahogy a "
"gyermek idősebbé válik. Rendszeresen újra kell értékelnie a megfelelő "
"<gui>Alkalmazás alkalmassága</gui> értéket minden egyes felhasználónál."

424
help/id/id.po Normal file
View File

@ -0,0 +1,424 @@
# Indonesian translation for malcontent.
# Copyright (C) 2020 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Andika Triwidada <andika@gmail.com>, 2020, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-12-18 15:14+0000\n"
"PO-Revision-Date: 2021-08-30 18:26+0700\n"
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.4.3\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Andika Triwidada <andika@gmail.com>, 2020, 2021."
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Membuat pengguna anak pada komputer."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Membuat Pengguna Anak"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Pengawasan orang tua hanya dapat diterapkan untuk akun non-administrator. "
"Akun tersebut mungkin telah dibuat saat komputer awalnya diatur. Jika tidak, "
"pengguna anak baru dapat dibuat dari aplikasi <app>Pengawasan Orang Tua</"
"app> jika tidak ada pengguna anak yang sudah ada; dan sebaliknya dapat "
"dibuat dari <app>Pusat Kontrol</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Untuk membuat pengguna anak baru, lihat <link type=\"guide\" xref=\"help:"
"gnome-help/user-add\">Menambahkan akun pengguna baru</link>. Segera setelah "
"pengguna baru dibuat, itu akan muncul di jendela <app>Pengawasan Orang Tua</"
"app> sehingga pengaturan pengawasan orang tua dapat dikonfigurasi."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Bantuan Pengawasan Orang Tua"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Pendahuluan &amp; Penyiapan"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Pengawasan yang Diterapkan"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Membatasi akses pengguna anak ke Internet."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Membatasi Akses ke Internet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Anda dapat membatasi akses pengguna ke internet. Ini akan mencegah mereka "
"menggunakan peramban web, tetapi tidak akan mencegah mereka menggunakan "
"internet (dalam bentuk yang berpotensi lebih terbatas) melalui aplikasi "
"lain. Sebagai contoh, itu tidak akan mencegah akses ke akun surel "
"menggunakan <app>Evolution</app>, dan tidak akan mencegah pembaruan "
"perangkat lunak yang diunduh dan diterapkan."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Untuk membatasi akses pengguna ke internet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Buka aplikasi <app>Pengawasan Orang Tua</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Pilih pengguna di tab di bagian atas."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Fungsikan kotak centang <gui style=\"checkbox\">Batasi Peramban Web</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Ikhtisar pengawasan orang tua, aplikasi <app>Pengawasan Orang Tua</app>, dan "
"penggunaannya dalam situasi lain dimana pembatasan akses diperlukan pada "
"seorang pengguna."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Pengenalan untuk Pengawasan Orang Tua"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Pengawasan orang tua adalah cara untuk membatasi apa yang dapat dilakukan "
"oleh akun non-administrator pada komputer, dengan tujuan memperbolehkan "
"orangtua membatasi apa yang dapat dilakukan anak mereka saat menggunakan "
"komputer tanpa pengawasan atau di bawah supervisi yang terbatas."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Fungsi ini dapat digunakan dalam situasi lain seperti hubungan perawat/"
"terrawat lainnya tetapi diberi label sebagai 'pengawasan orang tua' "
"sehingga mudah ditemukan, karena itulah yang kebanyakan orang akan cari."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Pengawasan orang tua untuk setiap pengguna dapat ditanyakan dan diatur "
"menggunakan aplikasi <app>Pengawasan Orang Tua</app>. Ini mencantumkan akun "
"non-administrator di tab di sepanjang bilah atasnya, dan menunjukkan setelan "
"pengawasan orang tua mereka saat ini di bawah. Perubahan pada pengawasan "
"orang tua akan segera berlaku."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Pembatasan penggunaan komputer hanya dapat diterapkan pada akun non-"
"administrator. Setelan pengawasan orang tua untuk pengguna hanya dapat "
"diubah oleh administrator, meskipun administrator dapat melakukannya dari "
"akun pengguna dengan memasukkan kata sandi saat diminta oleh aplikasi "
"<app>Pengawasan Orang Tua</app> ."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Karya ini dilisensikan di bawah <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Membatasi pengguna anak dari menjalankan aplikasi yang sudah diinstal."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Membatasi Akses ke Aplikasi yang Terinstal"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Anda dapat mencegah pengguna menjalankan aplikasi tertentu yang telah "
"diinstal di komputer. Hal ini dapat berguna jika pengguna lain membutuhkan "
"aplikasi tersebut tetapi mereka tidak sesuai untuk anak."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Ketika menginstal perangkat lunak tambahan, Anda harus mempertimbangkan "
"apakah yang perlu dibatasi untuk beberapa pengguna — perangkat lunak yang "
"baru diinstal dapat dipakai oleh semua pengguna secara baku."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Untuk membatasi akses pengguna ke aplikasi tertentu:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Tekan tombol <gui style=\"button\">Batasi Aplikasi</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Fungsikan saklar di baris untuk setiap aplikasi yang Anda ingin membatasi "
"pengguna dari mengaksesnya."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Tutup jendela <gui>Batasi Aplikasi</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Membatasi akses ke aplikasi tertentu sering digunakan dalam hubungannya "
"dengan <link xref=\"software-installation\"/> untuk mencegah pengguna dari "
"menginstal perangkat lunak tambahan yang belum diperiksa."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Membatasi perangkat lunak yang dapat dipasang pengguna anak, atau mencegah "
"mereka menginstal perangkat lunak tambahan sepenuhnya."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Membatasi Instalasi Perangkat Lunak"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Anda dapat mencegah pengguna dari memasang perangkat lunak tambahan, baik "
"untuk seluruh sistem, atau hanya untuk diri mereka sendiri. Mereka masih "
"akan dapat mencari perangkat lunak baru untuk dipasang, tetapi akan "
"memerlukan administrator untuk mengesahkan instalasi ketika mereka mencoba "
"untuk memasang aplikasi."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Selain itu, Anda dapat membatasi perangkat lunak yang dapat ditelusuri atau "
"dicari oleh pengguna di katalog <app>Perangkat Lunak</app> berdasarkan "
"kategori usia."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Untuk mencegah pengguna menjalankan aplikasi yang sudah terinstal, lihat "
"<link xref=\"restricting-applications\"/> ."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Mencegah Instalasi Perangkat Lunak"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr "Untuk mencegah pengguna menginstal perangkat lunak tambahan:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Fungsikan kotak centang <gui style=\"checkbox\">Batasi Pemasangan Aplikasi</"
"gui>."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Membatasi Instalasi Perangkat Lunak berdasarkan Umur"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Aplikasi dalam katalog <app>Perangkat Lunak</app> memiliki informasi tentang "
"konten yang mereka kandung yang mungkin tidak pantas untuk usia tertentu — "
"misalnya, berbagai bentuk kekerasan, obrolan tanpa moderator dengan orang "
"lain di internet, atau kemungkinan membelanjakan uang."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Untuk setiap aplikasi, informasi ini diringkas sebagai yang biasanya cocok "
"untuk digunakan oleh usia minimum anak berapa — misalnya, \"cocok untuk usia "
"7+\". Peringkat usia ini disajikan dalam skema spesifik wilayah yang dapat "
"dibandingkan dengan skema penilaian yang digunakan untuk film dan permainan."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Aplikasi yang ditampilkan kepada pengguna di katalog <app>Perangkat Lunak</"
"app> dapat difilter menurut kesesuaian usia mereka. Aplikasi yang tidak "
"cocok untuk pengguna akan disembunyikan, dan tidak akan dapat diinstal oleh "
"pengguna tersebut. Mereka akan dapat diinstal oleh pengguna lain (jika "
"kesesuaian usia mereka ditetapkan cukup tinggi)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Untuk menyaring aplikasi yang dilihat oleh pengguna dalam katalog "
"<app>Perangkat Lunak</app> agar hanya yang cocok untuk usia tertentu:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Dalam daftar <gui>Kesesuaian Aplikasi</gui>, pilih usia mana aplikasi mesti "
"cocok."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Usia pengguna yang sebenarnya tidak disimpan, sehingga <gui>Kesesuaian "
"Aplikasi</gui> tidak diperbarui secara otomatis dari waktu saat anak tumbuh "
"lebih tua. Anda harus secara berkala menilai kembali <gui>Kesesuaian "
"Aplikasi</gui> yang sesuai untuk setiap pengguna."

450
help/it/it.po Normal file
View File

@ -0,0 +1,450 @@
# Italian translations for malcontent.
# Copyright © 2020 the malcontent authors.
# This file is distributed under the same license as the malcontent package.
# Albano Battistella <albano_battistella@hotmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-04-24 15:30+0000\n"
"PO-Revision-Date: 2022-01-07 15:41+0100\n"
"Last-Translator: Albano Battistella <albano_battistella@hotmail.com>\n"
"Language-Team: Italian\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.1\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Albano Battistella <albano_battistella@hotmail.com>, 2022."
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Creazione di un account per bambini sul computer."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Creazione un Account per Bambini"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Il controllo parentale può essere applicato solo agli account non-amministratore."
"Al momento potrebbe essere stato creato un account di questo tipo "
"dalla configurazione iniziale del computer. In caso contrario, è possibile creare un "
"nuovo account per bambino dall'applicazione <app>Controllo Parentale</app> o "
"tramite le <app>Impostazioni</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Per creare un nuovo utente per bambino, vedere <link type =\"guide\" xref=\"help:gnome-help/"
"user-add\">Aggiungi un nuovo account utente</link>. Non appena il nuovo utente sarà "
"creato, apparirà nella finestra <app>Controllo Parentale</app> in modo che "
"le sue impostazioni di controllo parentale possano essere configurate."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Aiuto sui controlli parentali"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Introduzione e configurazione"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Controlli da applicare"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Limitare l'accesso a Internet da parte di un minore"
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Limitare l'accesso a Internet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"È possibile limitare l'accesso di un utente a Internet. Questo gli impedirà "
"di usare un browser web, ma non limiterà la connessione a Internet (in forma limitata) di "
"altre applicazioni. Ad esempio, non impedirà l'accesso agli account di "
"e-mail utilizzando <app>Evolution</app>, né impedirà il download ed "
"applicazione di aggiornamenti software."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Per limitare l'accesso di un utente a Internet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:27 C/software-installation.page:64
msgid "Open the <app>Parental Controls</app> application."
msgstr "Apri l'app <app>Controllo Parentale</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:28 C/software-installation.page:65
msgid "Select the user in the tabs at the top."
msgstr "Nelle schede in alto, seleziona l'account desiderato."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Seleziona la casella <gui style=\"checkbox\">Limita i browser web</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls and the <app>Parental Controls</app> "
"application."
msgstr ""
"Panoramica del controllo parentale e dell'applicazione "
"<app>Controllo Parentale</app>."
#. (itstool) path: page/title
#: C/introduction.page:10
msgid "Introduction to Parental Controls"
msgstr "Introduzione al Controllo Parentale"
#. (itstool) path: page/p
#: C/introduction.page:12
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Il controllo parentale è un modo per limitare ciò che gli account non-amministratore possono "
"fare al computer, con l'obiettivo di consentire ai genitori di limitare ciò che i loro "
"bambini possono fare quando usano il computer senza sorveglianza o sotto una supervisione "
"limitata."
#. (itstool) path: page/p
#: C/introduction.page:16
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find."
msgstr ""
"Questa funzionalità può essere utilizzata in altre situazioni, ad esempio per altri tutori/"
"relazioni di carriera - ma è etichettato comecontrollo parentale in modo che sia "
"facile da trovare."
#. (itstool) path: page/p
#: C/introduction.page:19
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"L'applicazione <app>Controllo Parentale</app> consente le query "
"a qualsiasi titolo e definisce i controlli per ciascuno. L'applicazione "
"elenca tutti gli account non-amministratore sotto forma di schede nella "
"barra superiore della finestra e sotto mostra i controlli definiti "
"attualmente. Le modifiche al controllo parentale hanno effetto immediato."
#. (itstool) path: page/p
#: C/introduction.page:23
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Le restrizioni sull'uso dei computer possono essere applicate solo agli account "
"non-amministratore. Le impostazioni del controllo parentale per un utente possono "
"essere modificate solo da un amministratore, anche se l'amministratore può farlo dall'utente "
"account inserendo la password quando richiesto dall'applicazione "
"<app>Controllo Parentale</app>."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Quest'opera è sotto licenza <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Limita l'utilizzo di applicazioni già installate ai minori."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Limita l'accesso alle applicazioni installate"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Puoi impedire ad un utente di eseguire applicazioni specifiche che sono già "
"installate nel computer. Questo potrebbe essere utile se altri utenti hanno bisogno "
"di queste applicazioni ma che non siano appropriate per un bambino."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Durante l'installazione di software aggiuntivo, è necessario considerare se sia necessario "
"limitarlo per alcuni utenti: il software appena installato è utilizzabile da tutti gli "
"utenti per impostazione predefinita."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Per limitare l'accesso di un utente a un'applicazione specifica:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Premi il pulsante <gui style=\"button\">Limita Applicazioni</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Attiva l'interruttore nella riga per ogni app che desideri limitare."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Chiudi la finestra <gui>Limita Applicazioni</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Spesso viene utilizzata la limitazione dell'accesso a determinate applicazioni "
"Con <link xref=\"software-installation\"/> per evitare che venga installato "
"software senza che sia stato verificato."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Limita il software che un minore può installare o impediscigli di "
"installare completamente software aggiuntivo."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Limitare Installazione di Software"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software, either for the "
"entire system, or just for themselves. They will still be able to search for "
"new software to install, but will need an administrator to authorize the "
"installation when they try to install an application."
msgstr ""
"Puoi impedire ad un utente di installare software aggiuntivo, sia per l'intero "
"sistema, sia per te stesso. Sarà ancora in grado di cercare nuovo software "
"da installare, ma se proverà ad installarlo dovrà avere l'aiuto di un "
"amministratore per l'autorizzazione."
#. (itstool) path: page/p
#: C/software-installation.page:16
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Inoltre, se utilizzi le categorie di età in <app>Software</app>, "
"puoi limitare quale software può essere sfogliato nel tuo catalogo."
#. (itstool) path: page/p
#: C/software-installation.page:19
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Per impedire a un utente di eseguire un'applicazione precedentemente installata, "
"vedere <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:23
msgid "Preventing Software Installation"
msgstr "Evitare l'installazione di software"
#. (itstool) path: section/p
#: C/software-installation.page:25
msgid "To prevent a user from installing additional software:"
msgstr ""
"Seguire questa procedura per impedire l'installazione di software aggiuntivo:"
#. (itstool) path: item/p
#: C/software-installation.page:29
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Selezionare la casella <gui style=\"checkbox\">Limita l'installazione di "
"Applicazioni</gui>."
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Or enable the <gui style=\"checkbox\">Restrict Application Installation for "
"Others</gui> checkbox."
msgstr ""
"Oppure, seleziona la casella <gui style=\"checkbox\">Limita l'installazione di "
"applicazioni per gli altri</gui>."
#. (itstool) path: section/p
#: C/software-installation.page:33
msgid ""
"The <gui style=\"checkbox\">Restrict Application Installation for Others</"
"gui> checkbox allows the user to install additional software for themselves, "
"but prevents that software from being made available to other users. It "
"could be used, for exampcheckboxle, if there were two child users, one of whom is "
"mature enough to be allowed to install additional software, but the other "
"isnt — enabling <gui style=\"\">Restrict Application Installation "
"for Others</gui> would prevent the more mature child from installing "
"applications which are inappropriate for the other child and making them "
"available to the other child."
msgstr ""
"La casella <gui style=\"checkbox\">Limita l'installazione di applicazioni "
"ad altri</gui> consente l'installazione di software aggiuntivo per se stessi, "
"ma ne limita la disponibilità agli altri account. Potrebbe essere usato "
"approfittando di questa funzione, ad esempio, se hai due minorenni, di cui "
"solo uno è abbastanza maturo da potersi installare software "
"abilitando <gui style=\"checkbox\">Limita l'installazione di "
"applicazioni ad altri</gui> impedirà al minore più maturo di installare "
"applicazioni inadeguate per l'altro bambino."
#. (itstool) path: section/title
#: C/software-installation.page:45
msgid "Restricting Software Installation by Age"
msgstr "Limitare l'installazione del software in base all'età"
#. (itstool) path: section/p
#: C/software-installation.page:47
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Le applicazioni incluse nel catalogo di <app>Software</app> "
"includono informazioni riguardanti il contenuto che possiedono e la sua idoneità "
"secondo l'età, annotando dettagli come: varie forme di violenza, chat non "
"moderate con altre persone tramite internet, o la capacità di spendere "
"soldi."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"In ogni applicazione, questa informazione è condensata come l'età minima "
"che è ritenuta appropriata per un minore utilizzarla; ad esempio,“7 anni o +“. "
"Queste classificazioni sono presentate in conformità con alcuni "
"schemi regionali, paragonabili a quelli utilizzati per classificare "
"film e giochi."
#. (itstool) path: section/p
#: C/software-installation.page:55
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Le applicazioni <app>Software</app> mostrate a ciascun utente possono essere "
"filtrate per adeguatezza all'età. Le applicazioni non adatte per un account "
"verranno nascoste dal catalogo e non potranno essere installate. "
"Altri utenti potranno installarle (se la loro fascia d'età è tale che lo si permetta)."
#. (itstool) path: section/p
#: C/software-installation.page:61
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Per filtrare le applicazioni che vede un utente nel catalogo "
"<app>Software</app> e che solo quelli appropriati vengono mostrati per una "
"certa età:"
#. (itstool) path: item/p
#: C/software-installation.page:66
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Nella lista <gui>Idoneità dell'applicazione</gui>, selezionare l'età desiderata."
#. (itstool) path: note/p
#: C/software-installation.page:70
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Poiché l'età dell'utente non viene memorizzata, l' <gui>Idoneità dell'applicazione</"
"gui> non viene aggiornata automaticamente man mano che il minore cresce. Si dovrebbe "
"rivalutare periodicamente il livello appropriato di <gui>Idoneità dell'applicazione</"
"gui> per ciascuno degli account."

17
help/meson.build Normal file
View File

@ -0,0 +1,17 @@
help_media = [
]
help_files = [
'creating-a-child-user.page',
'index.page',
'internet.page',
'introduction.page',
'legal.xml',
'restricting-applications.page',
'software-installation.page',
]
gnome.yelp(meson.project_name(),
sources: help_files,
media: help_media,
symlink_media: true,
)

437
help/pl/pl.po Normal file
View File

@ -0,0 +1,437 @@
# Polish translation for malcontent help.
# Copyright © 2020 the malcontent authors.
# This file is distributed under the same license as the malcontent help.
# Piotr Drąg <piotrdrag@gmail.com>, 2020.
# Aviary.pl <community-poland@mozilla.org>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent-help\n"
"POT-Creation-Date: 2020-12-18 15:14+0000\n"
"PO-Revision-Date: 2020-12-20 13:22+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr ""
"Piotr Drąg <piotrdrag@gmail.com>, 2020\n"
"Aviary.pl <community-poland@mozilla.org>, 2020"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Tworzenie konta dziecka na komputerze."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Tworzenie konta dziecka"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Kontrola rodzicielska może zostać zastosowana tylko na kontach niebędących "
"administratorami. Takie konto można utworzyć podczas początkowej "
"konfiguracji komputera. Jeśli nie zostało wtedy utworzone, to można to "
"zrobić w programie <app>Kontrola rodzicielska</app>, jeśli żadne konto "
"dziecka jeszcze nie istnieje. W przeciwnym wypadku można je utworzyć "
"w programie <app>Ustawienia</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"<link type=\"guide\" xref=\"help:gnome-help/user-add\">Dokumentacja "
"środowiska</link> zawiera informacje o tym, jak utworzyć nowe konto "
"użytkownika. Po utworzeniu pojawi się ono w oknie programu <app>Kontrola "
"rodzicielska</app>, gdzie można skonfigurować jego ustawienia kontroli "
"rodzicielskiej."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Kontrola rodzicielska"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Wprowadzenie i konfiguracja"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Ograniczenia do zastosowania"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Ograniczanie dostępu konta dziecka do Internetu."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Ograniczanie dostępu do Internetu"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Można ograniczyć użytkownikowi dostęp do Internetu. Uniemożliwi im to "
"używanie przeglądarki internetowej, ale nie uniemożliwi im korzystania "
"z Internetu (w potencjalnie bardziej ograniczonej formie) za pomocą innych "
"programów. Na przykład nie uniemożliwi dostępu do kont e-mail za pomocą "
"programu <app>Evolution</app> oraz nie zatrzyma pobierania i instalowania "
"aktualizacji oprogramowania."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Aby ograniczyć dostęp użytkownika do Internetu:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Otwórz program <app>Kontrola rodzicielska</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Wybierz użytkownika z kart na górze."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Zaznacz pole <gui style=\"checkbox\">Ograniczanie przeglądarek "
"internetowych</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Przegląd kontroli rodzicielskiej, programu <app>Kontrola rodzicielska</app> "
"i jego użycia w innych sytuacjach, w których potrzebne są ograniczenia "
"dostępu użytkownika."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Wprowadzenie do kontroli rodzicielskiej"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Kontrola rodzicielska to sposób na ograniczanie tego, co nieadministracyjne "
"konta mogą robić na komputerze, którego celem jest umożliwienie rodzicom "
"ograniczania, co ich dzieci mogą robić w czasie korzystania z komputera bez "
"nadzoru lub z minimalnym nadzorem."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Ta funkcjonalność może być używana w innych sytuacjach — takich jak inne "
"relacje opiekuńcze — ale nazywa się „kontrola rodzicielska”, aby można ją "
"było łatwo znaleźć, jako że większość osób będzie szukać tego terminu."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Za pomocą programu <app>Kontrola rodzicielska</app> można sprawdzać "
"i ustawiać kontrolę rodzicielską dla każdego konta. Zawiera on listę kont "
"niebędących administratorami w kartach na górnym pasku i ich obecne "
"ustawienia kontroli rodzicielskiej poniżej. Zmiany kontroli rodzicielskiej "
"są uwzględniane od razu."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Ograniczenia korzystania z komputera można stosować tylko na kontach "
"nieadministracyjnych. Ustawienia kontroli rodzicielskiej użytkownika mogą "
"być zmieniane tylko przez administratora, ale administrator może robić to "
"z konta użytkownika wpisując swoje hasło, kiedy program <app>Kontrola "
"rodzicielska</app> o nie poprosi."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Na warunkach licencji <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr ""
"Ograniczanie kontu dziecka możliwości uruchamiania już zainstalowanych "
"programów."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Ograniczanie dostępu do zainstalowanych programów"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Można uniemożliwić użytkownikowi uruchamianie określonych programów, które "
"są już zainstalowane na komputerze. Może to być przydatne, jeśli pozostali "
"użytkownicy potrzebują tych programów, ale nie są one odpowiednie dla "
"dziecka."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Podczas instalowania dodatkowego oprogramowania należy rozważyć, czy musi "
"ono być ograniczone dla części użytkowników — nowo zainstalowane "
"oprogramowanie domyślnie może być używane przez wszystkich użytkowników."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Aby ograniczyć dostęp użytkownika do danego programu:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Kliknij przycisk <gui style=\"button\">Ograniczanie programów</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Kliknij przełącznik w rzędzie każdego programu, do którego użytkownik ma "
"mieć ograniczony dostęp."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Zamknij okno <gui>Ograniczanie programów</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Ograniczanie dostępu do określonych programów jest często używane "
"jednocześnie z funkcją <link xref=\"software-installation\"/>, aby "
"uniemożliwić użytkownikowi instalowanie dodatkowego oprogramowania, które "
"nie zostało jeszcze zatwierdzone."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Ograniczanie oprogramowania, które dziecko może instalować lub całkowite "
"uniemożliwianie im instalowania dodatkowego oprogramowania."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Ograniczanie instalacji oprogramowania"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Można uniemożliwić użytkownikowi instalowanie dodatkowego oprogramowania na "
"komputerze. Nadal będzie on mógł wyszukiwać nowe oprogramowanie, ale do jego "
"zainstalowania będzie potrzebował upoważnienia administratora. Ma to "
"zastosowanie niezależnie od tego, czy użytkownik próbuje zainstalować "
"program w systemie (dla wszystkich użytkowników) czy tylko dla siebie."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Dodatkowe można ograniczyć, które oprogramowanie użytkownik może przeglądać "
"i wyszukiwać w katalogu <app>Menedżera oprogramowania</app> według kategorii "
"wiekowych."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"<link xref=\"restricting-applications\"/> zawiera informacje o tym, jak "
"uniemożliwić użytkownikowi uruchamianie już zainstalowanego programu."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Uniemożliwianie instalacji oprogramowania"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
"Aby uniemożliwić użytkownikowi instalowanie dodatkowego oprogramowania:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Zaznacz pole <gui style=\"checkbox\">Ograniczanie instalacji programów</gui>."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Ograniczanie instalacji oprogramowania według wieku"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Programy w katalogu <app>Menedżera oprogramowania</app> mają informacje "
"o zawieranej treści, która może być nieodpowiednia dla osób w pewnym wieku — "
"na przykład różne formy przemocy, niemoderowany czat z innymi osobami "
"w Internecie lub możliwość wydawania pieniędzy."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Dla każdego programu ta informacja jest podsumowana jako minimalny wiek "
"dziecka, w jakim zazwyczaj jest odpowiedni — na przykład „odpowiednie dla "
"dzieci siedmioletnich i starszych”. Te oceny wiekowe są przestawiane "
"w formie dla danego regionu, które można porównywać z ocenami używanymi dla "
"filmów i gier."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Programy wyświetlane użytkownikowi w katalogu <app>Menedżera oprogramowania</"
"app> mogą być filtrowane według ich kategorii wiekowych. Programy "
"nieodpowiednie dla użytkownika będą ukryte i nie będzie on mógł ich "
"instalować. Pozostali użytkownicy będą mogli je instalować (jeśli ich "
"kategoria wiekowa jest ustawiona odpowiednio wysoko)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Aby odfiltrować nieodpowiednie programy widoczne dla użytkownika w katalogu "
"<app>Menedżera oprogramowania</app>:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Na liście <gui>Odpowiedniość programów</gui> wybierz wiek, dla którego "
"programy powinny być odpowiednie."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Rzeczywisty wiek użytkownika nie jest przechowywany, więc opcja "
"<gui>Odpowiedniość programów</gui> nie jest automatycznie aktualizowana wraz "
"z upływem czasu i dorastania dziecka. Należy okresowo sprawdzać, czy opcja "
"<gui>Odpowiedniość programów</gui> jest właściwie ustawiona dla każdego "
"użytkownika."

455
help/pt_BR/pt_BR.po Normal file
View File

@ -0,0 +1,455 @@
# Brazilian Portuguese translation for malcontent.
# Copyright (C) 2020 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Rafael Fontenelle <rafaelff@gnome.org>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-04-24 15:30+0000\n"
"PO-Revision-Date: 2020-04-24 09:11-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"X-Generator: Gtranslator 3.36.0\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Rafael Fontenelle <rafaelff@gnome.org>, 2020"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Criando um usuário filho no computador."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Criando um usuário filho"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Os controles dos pais podem ser aplicados apenas a contas de não "
"administrador. Essa conta pode ter sido criada quando o computador foi "
"configurado inicialmente. Caso contrário, um novo usuário filho poderá ser "
"criado a partir do aplicativo <app>Controle parental</app> se nenhum usuário "
"filho já existir; e, caso contrário, pode ser criado no <app>Controle "
"parental</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Para criar um novo usuário filho, consulte <link type=\"guide\" xref=\"help:"
"gnome-help/user-add\">Adicionando uma nova conta de usuário</link>. Assim "
"que o novo usuário for criado, ele aparecerá na janela do <app>Controle "
"parental</app> para que suas configurações de controle parental possam ser "
"definidas."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Ajuda do Controle parental"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Introdução &amp; configuração"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Controles para aplicar"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Restringindo o acesso do usuário filho à Internet."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Restringindo acesso à Internet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Você pode restringir o acesso de um usuário à Internet. Isso os impedirá de "
"usar um navegador web, mas não os impedirá de usar a Internet (em formas "
"potencialmente mais limitadas) por meio de outros aplicativos. Por exemplo, "
"não impedirá o acesso a contas de e-mail usando o <app>Evolution</app>, nem "
"impedirá o download e aplicação de atualizações de software."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Para restringir o acesso de um usuário à Internet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:27 C/software-installation.page:64
msgid "Open the <app>Parental Controls</app> application."
msgstr "Abra o aplicativo <app>Controle parental</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:28 C/software-installation.page:65
msgid "Select the user in the tabs at the top."
msgstr "Selecione o usuário nas abas no topo."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Habilite a caixa de seleção <gui style=\"checkbox\">Restringir navegadores "
"web</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls and the <app>Parental Controls</app> "
"application."
msgstr ""
"Visão geral dos controles parentais e o aplicativo <app>Controle parental</"
"app>."
#. (itstool) path: page/title
#: C/introduction.page:10
msgid "Introduction to Parental Controls"
msgstr "Introdução ao Controle parental"
#. (itstool) path: page/p
#: C/introduction.page:12
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"O controle parental é uma maneira de restringir o que as contas não-"
"administradoras podem fazer no computador, com o objetivo de permitir que os "
"pais restrinjam o que seus filhos podem fazer ao usar o computador sem "
"supervisão ou sob supervisão limitada."
#. (itstool) path: page/p
#: C/introduction.page:16
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find."
msgstr ""
"Essa funcionalidade pode ser usada em outras situações, como outras relações "
"de tutor/tutelado, mas é rotulada como “controle parental”, para facilitar a "
"localização."
#. (itstool) path: page/p
#: C/introduction.page:19
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"O controle parental para qualquer usuário pode ser consultado e definido "
"usando o aplicativo <app>Controle parental</app>. Isso lista as contas de "
"não administrador nas abas na barra superior e mostra as configurações "
"atuais do controle parental abaixo. Alterações no controle parental se "
"aplicam imediatamente."
#. (itstool) path: page/p
#: C/introduction.page:23
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Restrições ao uso do computador podem ser aplicadas apenas a contas de não "
"administrador. As configurações de controle parental de um usuário só podem "
"ser alteradas por um administrador, embora o administrador possa fazer isso "
"da conta do usuário digitando sua senha quando solicitado pelo aplicativo "
"<app>Controle parental</app>."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Atribuição Compartilhada Igual 3.0 Não Adaptada"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Essa obra está licenciada sob uma licença <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Restringindo um usuário filho de executar aplicativos já instalados."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Restringindo o acesso aos aplicativos instalados"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Você pode impedir que um usuário execute aplicativos específicos que já "
"estão instalados no computador. Isso pode ser útil se outros usuários "
"precisarem desses aplicativos, mas não forem apropriados para uma criança."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Ao instalar software adicional, considere se isso precisa ser restrito para "
"alguns usuários — o software recém-instalado é utilizável por todos os "
"usuários por padrão.­­"
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Para restringir o acesso de um usuário a um aplicativo específico:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Pressione o botão <gui style=\"button\">Restringir aplicativos</gui>. "
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Habilite a opção na linha de cada aplicativo que você gostaria de restringir "
"o acesso do usuário."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Feche a janela <gui>Restringir aplicativos</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"A restrição de acesso a aplicativos específicos é frequentemente usada em "
"conjunto com <link xref=\"software-installation\"/> para impedir que um "
"usuário instale um software adicional que ainda não foi verificado."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Restringindo o software que um usuário filho pode instalar ou impedindo-o de "
"instalar completamente software adicional."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Restringindo instalação de software"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software, either for the "
"entire system, or just for themselves. They will still be able to search for "
"new software to install, but will need an administrator to authorize the "
"installation when they try to install an application."
msgstr ""
"Você pode impedir que um usuário instale software adicional, seja para todo "
"o sistema ou apenas para si. Eles ainda poderão procurar um novo software "
"para instalar, mas precisarão de um administrador para autorizar a "
"instalação quando tentarem instalar um aplicativo."
#. (itstool) path: page/p
#: C/software-installation.page:16
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Além disso, você pode restringir o software que um usuário pode procurar ou "
"procurar no catálogo <app>Software</app> por categorias de idade."
#. (itstool) path: page/p
#: C/software-installation.page:19
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Para impedir que um usuário execute um aplicativo que já foi instalado, "
"consulte <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:23
msgid "Preventing Software Installation"
msgstr "Impedindo a instalação do software"
#. (itstool) path: section/p
#: C/software-installation.page:25
msgid "To prevent a user from installing additional software:"
msgstr "Para impedir que um usuário instale software adicional:"
#. (itstool) path: item/p
#: C/software-installation.page:29
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Marque a caixa de seleção <gui style=\"checkbox\">Restringir instalação de "
"aplicativo</gui>."
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Or enable the <gui style=\"checkbox\">Restrict Application Installation for "
"Others</gui> checkbox."
msgstr ""
"Ou habilite a caixa de seleção <gui style=\"checkbox\">Restringir instalação "
"de aplicativo para outros</gui>."
#. (itstool) path: section/p
#: C/software-installation.page:33
msgid ""
"The <gui style=\"checkbox\">Restrict Application Installation for Others</"
"gui> checkbox allows the user to install additional software for themselves, "
"but prevents that software from being made available to other users. It "
"could be used, for example, if there were two child users, one of whom is "
"mature enough to be allowed to install additional software, but the other "
"isnt — enabling <gui style=\"checkbox\">Restrict Application Installation "
"for Others</gui> would prevent the more mature child from installing "
"applications which are inappropriate for the other child and making them "
"available to the other child."
msgstr ""
"A caixa de seleção <gui style=\"checkbox\">Restringir instalação de "
"aplicativo para outros</gui> permite ao usuário instalar software adicional "
"para eles mesmos, mas impede que esse software seja disponibilizado para "
"outros usuários. Poderia ser usado, por exemplo, se houvesse dois usuários "
"filhos, um deles maduro o suficiente para poder instalar software adicional, "
"mas o outro não — habilitando <gui style=\"checkbox\">Restringir a "
"instalação de aplicativo para outros</gui> impediria a criança mais madura "
"de instalar aplicativos inadequados para a outra criança e disponibilizá-los "
"para a outra criança."
#. (itstool) path: section/title
#: C/software-installation.page:45
msgid "Restricting Software Installation by Age"
msgstr "Restringindo instalação de software por idade"
#. (itstool) path: section/p
#: C/software-installation.page:47
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Os aplicativos no catálogo <app> Software </app> contêm informações sobre o "
"conteúdo que podem ser inadequadas por algumas idades — por exemplo, várias "
"formas de violência, bate-papo moderado com outras pessoas na Internet ou a "
"possibilidade de gastar dinheiro."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Para cada aplicativo, essas informações são resumidas como a criança com "
"idade mínima em que normalmente é adequada para ser usada por — por exemplo, "
"“adequada para idades acima de 7 anos”. Essas classificações etárias são "
"apresentadas em esquemas de região específica que podem ser comparados com "
"os esquemas de classificação usados para filmes e jogos."
#. (itstool) path: section/p
#: C/software-installation.page:55
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Os aplicativos mostrados a um usuário no catálogo <app>Software</app> podem "
"ser filtrados de acordo com a sua idade. Os aplicativos que não são "
"adequados para o usuário serão ocultados e não serão instaláveis por esse "
"usuário. Eles serão instaláveis por outros usuários (se a adequação à idade "
"for alta o suficiente)."
#. (itstool) path: section/p
#: C/software-installation.page:61
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Para filtrar os aplicativos vistos por um usuário no catálogo <app>Software</"
"app> apenas para aqueles adequados para uma certa idade:"
#. (itstool) path: item/p
#: C/software-installation.page:66
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"Na lista <gui>Adequação do aplicativo</gui>, selecione a idade para a qual "
"os aplicativos devem ser adequados."
#. (itstool) path: note/p
#: C/software-installation.page:70
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"A idade real do usuário não é armazenada, portanto, a <gui>Adequação do "
"aplicativo</gui> não é atualizada automaticamente ao longo do tempo à medida "
"que a criança cresce. Você deve reavaliar periodicamente a <gui>Adequação do "
"aplicativo</gui> para cada usuário."

435
help/ru/ru.po Normal file
View File

@ -0,0 +1,435 @@
# Russian translation for malcontent.
# Copyright (C) 2022 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Sergej A. <sw@atrus.ru>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent main\n"
"POT-Creation-Date: 2022-06-04 15:25+0000\n"
"PO-Revision-Date: 2022-06-05 11:41+1000\n"
"Last-Translator: Ser82-png <sw@atrus.ru>\n"
"Language-Team: Russian <gnome-cyr@gnome.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.3\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Ser82-png <sw@atrus.ru>, 2022"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Создание записи пользователя-ребёнка на компьютере."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Создание записи пользователя-ребёнка"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Родительский контроль можно применять только к учётным записям без "
"административных прав. Такая учётная запись могла быть создана при "
"первоначальной настройке системы. Если этого не было сделано, можно создать "
"новую детскую учётную запись с помощью приложения <app>Родительский "
"контроль</app>. Кроме того, такую учётную запись можно создать с помощью "
"<app>Центра управления</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Чтобы создать нового пользователя ребёнка, смотрите <link type=\"guide\" "
"xref=\"help:gnome-help/user-add\">Добавление новой учётной записи "
"пользователя</link>. Как только новый пользователь будет создан, он появится "
"в окне <app>Родительский контроль</app>, чтобы можно было для него настроить "
"параметры родительского контроля."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Справка по родительскому контролю"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Введение &amp; Настройка"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Средства контроля, которые можно применить"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Ограничение доступа ребёнка к интернету."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Ограничение доступа к интернету"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Вы можете ограничить доступ пользователя к интернету. Этим способом можно "
"запретить пользователю использовать веб-браузер, но доступ к сети интернет "
"будет сохранён (в потенциально более ограниченной форме) с помощью других "
"приложений. Например, пользователь будет иметь доступ к учётным записям "
"электронной почты с помощью <app>Evolution</app>, а также не будет "
"ограничений для загрузки и обновления программного обеспечения."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Чтобы ограничить доступ пользователя к интернету:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Откройте приложение <app>Родительский контроль</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Выберите пользователя во вкладках верхней части окна."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"Установите флажок <gui style=\"checkbox\">Ограничить доступ к Веб-браузерам</"
"gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Обзор родительского контроля, приложения <app>Родительский контроль</app> и "
"его использования в различных ситуациях, когда необходимо ограничить доступ "
"для пользователя."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Введение в родительский контроль"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Родительский контроль — это способ ограничить перечень возможных действий на "
"компьютере пользователям не имеющим учётных записей администратора. Целью "
"является ограничение родителями действий детей при работе на компьютере, "
"находящихся без присмотра или под ограниченным присмотром."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Эту функцию также можно использовать и в других ситуациях, например, в "
"отношениях «сиделка/пациент», но она помечена как «родительский контроль» "
"только для удобства поиска, поскольку именно это будут искать большинство "
"пользователей."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Для любого пользователя можно просмотреть и установить родительский контроль "
"с помощью приложения <app>Родительский контроль</app>. В окне программы на "
"вкладках вдоль верхней панели перечислены учётные записи без прав "
"администратора, а ниже показаны их текущие настройки родительского контроля. "
"Изменения в родительском контроле вступают в силу немедленно."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Ограничения на использование компьютера могут применяться только к учётным "
"записям без прав администратора. Настройки родительского контроля для "
"пользователя может изменить только администратор, хотя он может сделать это "
"из учётной записи пользователя, введя свой пароль при запросе приложения "
"<app>Родительский контроль</app>."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Данная работа находится под лицензией <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Запретить ребёнку запускать уже установленные приложения."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Ограничение доступа к установленным приложениям"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Вы можете запретить пользователю запускать определённые приложения, уже "
"установленные на компьютере. Это может быть полезно, если эти приложения "
"необходимы другим пользователям, но не подходят для ребёнка."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"При установке дополнительного программного обеспечения вам следует "
"учитывать, нужно ли ограничивать доступ для некоторых пользователей — новое "
"установленное программное обеспечение по умолчанию может использоваться "
"всеми пользователями."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Чтобы ограничить доступ пользователя к определенному приложению:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr ""
"Нажмите кнопку <gui style=\"button\">Ограничить доступ к приложениям</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Измените положение переключателя в строке для каждого приложения, к которому "
"вы хотите ограничить доступ пользователя."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Закройте окно <gui>Ограничить доступ к приложениям</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Ограничение доступа к определённым приложениям часто используется в "
"сочетании с <link xref=\"software-installation\"/>, чтобы запретить "
"пользователю устанавливать непроверенное программное обеспечение."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Ограничение перечная программного обеспечения, которое ребёнок может "
"установить, или полный запрет на его установку."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Ограничения на установку программного обеспечения по возрасту"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Вы можете запретить пользователям устанавливать дополнительное программное "
"обеспечение. Хотя они по-прежнему смогут искать программное обеспечение для "
"установки, но при попытке установить приложение им потребуется разрешение "
"администратора. Это не зависит от того, пытаются ли установить приложение в "
"масштабах всей системы (для всех пользователей) или только для себя."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Кроме того, вы можете ограничить по возрастному критерию, какое программное "
"обеспечение пользователь может просматривать или искать в <app>Центре "
"приложений</app>."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Чтобы запретить пользователю запускать уже установленное приложение, "
"смотрите раздел <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Предотвращение установки программного обеспечения"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
"Чтобы запретить пользователю устанавливать дополнительное программное "
"обеспечение:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Установите флажок <gui style=\"checkbox\">Ограничить установку приложений</"
"gui>."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Ограничения на установку программного обеспечения по возрасту"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"В описании к приложениям из каталога <app>Центра приложений</app> содержатся "
"сведения, которые могут быть неприемлемыми для определённых возрастных групп "
"— например, различные формы насилия, неограниченные возможности по общению с "
"другими людьми в интернете или возможность расходовать деньги."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Для каждого приложения в этих сведениях содержится информация о минимальном "
"возрасте ребенка, с которого его можно допустить к использованию данного "
"приложения. Например, «подходит для возраста 7+». Эти возрастные оценки "
"представлены в виде специфических для региона схем, сопоставимых со схемами "
"рейтингов для фильмов и видеоигр."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Приложения, показанные в каталоге <app>Центра приложений</app>, могут быть "
"отфильтрованы по возрастным критериям. Приложения, которые не подходят для "
"конкретного пользователя, будут скрыты и не смогут быть установлены. Но для "
"других пользователей они будут доступны (если пользователи будут "
"соответствовать установленным возрастным критериям)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Чтобы отфильтровать приложения, представленные пользователю в каталоге "
"<app>Центра приложений</app>, по возрастному критерию:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"В списке <gui>Пригодность приложений</gui> выберите возраст, для которого "
"должны быть подходящими приложения."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Возраст пользователя в системе не сохраняется, поэтому <gui>Пригодность "
"приложений</gui> по мере взросления ребёнка автоматически не обновляется. Вы "
"должны периодически пересматривать соответствующую для каждого пользователя "
"<gui>Пригодность приложений</gui>."

455
help/sv/sv.po Normal file
View File

@ -0,0 +1,455 @@
# Swedish translation for malcontent.
# Copyright (C) 2020 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-12-08 15:28+0000\n"
"PO-Revision-Date: 2020-12-17 18:25+0100\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.2\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Anders Jonsson <anders.jonsson@norsjovallen.se>"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Skapa en barnanvändare på datorn."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Skapa en barnanvändare"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Föräldrakontroller kan endast tillämpas på konton som inte är "
"administratörer. Ett sådant konto kan ha skapats när datorn ursprungligen "
"konfigurerades. Om inte så kan en ny barnanvändare skapas från programmet "
"<app>Föräldrakontroller</app> om det inte redan finns några barnanvändare. "
"Annars kan de skapas från <app>Kontrollpanel</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"För att skapa en ny barnanvändare, se <link type=\"guide\" xref=\"help:gnome-"
"help/user-add\">Lägg till ett nytt användarkonto</link>. Så snart användaren "
"har skapats kommer den dyka upp i <app>Föräldrakontroller</app>-fönstret så "
"att dess inställningar för föräldrakontroll kan konfigureras."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Hjälp för Föräldrakontroller"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Introduktion &amp; konfiguration"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Kontroller att tillämpa"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Begränsa en barnanvändares åtkomst till internet."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Begränsa åtkomst till internet"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Du kan begränsa en användares åtkomst till internet. Detta kommer att "
"förhindra dem från att använda en webbläsare, men det kommer inte att hindra "
"dem från att använda internet (potentiellt i mer begränsade former) genom "
"andra program. Det kommer till exempel inte förhindra åtkomst till e-"
"postkonton genom <app>Evolution</app>, och kommer inte förhindra att "
"programvaruuppdateringar hämtas och tillämpas."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "För att begränsa en användares åtkomst till internet:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Öppna programmet <app>Föräldrakontroller</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Välj användaren i flikarna högst upp."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr "Aktivera kryssrutan <gui style=\"checkbox\">Begränsa webbläsare</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Översikt över föräldrakontroller, programmet <app>Föräldrakontroller</app> "
"och dess användning i andra situationer där åtkomstbegränsningar behövs för "
"en användare."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Introduktion till Föräldrakontroller"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Föräldrakontroller är ett sätt att begränsa vad icke-administratörskonton "
"kan göra på datorn, med målet att låta föräldrar begränsa vad deras barn kan "
"göra när de använder datorn utan översikt eller med begränsad översikt."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Denna funktionalitet kan användas i andra situationer som i andra "
"relationer där ena parten har ansvar för den andra men kallas "
"”föräldrakontroller” för att vara lätt att hitta, då det är vad de flesta "
"kommer att söka efter."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Föräldrakontrollerna för alla användare kan efterfrågas och ställas in med "
"programmet <app>Föräldrakontroller</app>. Detta listar icke-"
"administratörskontona i flikar i en rad högst upp, och visar deras aktuella "
"inställningar för föräldrakontroller nedanför. Ändringar till "
"föräldrakontrollerna tillämpas omedelbart."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Begränsningar på användning av datorn kan endast ställas in för konton som "
"inte är administratörer. Inställningarna för föräldrakontroller för en "
"användare kan endast ändras av en administratör, även om administratören kan "
"göra det från användarens konto genom att ange sitt lösenord då programmet "
"<app>Föräldrakontroller</app> efterfrågar det."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Erkännande-DelaLika 3.0 Unported"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Detta verk licensieras under licensen <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Begränsa en barnanvändare från att köra redan installerade program."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Begränsa åtkomst till installerade program"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Du kan förhindra en användare från att köra specifika program som redan "
"finns installerade på datorn. Detta kan vara användbart om andra användare "
"behöver de programmen men de inte är lämpliga för barn."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"När du installerar ytterligare programvara bör du överväga om den behöver "
"begränsas för vissa användare — programvara som installeras kan som standard "
"användas av alla användare."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "För att begränsa en användares åtkomst till ett specifikt program:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "Tryck på knappen <gui style=\"button\">Begränsa program</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Aktivera växelknappen i raden för varje program som du vill begränsa "
"användaren från att komma åt."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Stäng fönstret <gui>Begränsa program</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Att begränsa åtkomst till vissa program används ofta tillsammans med <link "
"xref=\"software-installation\"/> för att förhindra en användare från att "
"installera ytterligare programvara som inte har granskats."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Begränsa vilken programvara som en barnanvändare kan installera, eller "
"förhindra dem helt från att installera ytterligare programvara."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Begränsa installation av programvara"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Du kan förhindra en användare från att installera ytterligare programvara på "
"systemet. De kommer fortfarande kunna söka efter ny programvara att "
"installera, men kommer behöva att en administratör godkänner installationen "
"när de försöker installera ett program. Detta gäller oavsett om de försöker "
"installera programmet systemomfattande (för alla användare) eller bara för "
"sig själva."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Du kan dessutom begränsa vilken programvara en användare kan bläddra bland "
"eller söka efter i katalogen för <app>Programvara</app> enligt "
"ålderskategorier."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"För att förhindra en användare från att köra ett program som redan har "
"installerats, se <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Förhindra installation av programvara"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
"För att förhindra en användare från att installera ytterligare programvara:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Aktivera kryssrutan <gui style=\"checkbox\">Begränsa installation av "
"program</gui>."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Begränsning av programvaruinstallation enligt ålder"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"Program i katalogen för <app>Programvara</app> har information om innehåll "
"de har som kan vara olämpligt för vissa åldrar — exempelvis olika sorters "
"våld, oövervakad chatt med andra personer över internet, eller möjligheten "
"att spendera pengar."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"För varje program sammanfattas denna information som den lägsta åldern på "
"ett barn som det lämpligen kan användas av — exempelvis ”Lämpligt för åldrar "
"7+”. Dessa åldersgränser presenteras i regionsspecifika klassifikationer som "
"kan jämföras med klassifikationerna som används för film och spel."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Programmen som visas för en användare i katalogen för <app>Programvara</app> "
"kan filtreras enligt deras lämplighetsålder. Program som inte är lämpliga "
"för användaren kommer att döljas, och kommer inte kunna installeras av den "
"användaren. De kan installeras av andra användare (om deras lämplighetsålder "
"är satt tillräckligt högt)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"För att filtrera programmen som en användare ser i katalogen för "
"<app>Programvara</app> till att bara vara de som är lämpliga för en viss "
"ålder:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"I listan <gui>Lämplighet för program</gui>, välj åldern som programmen ska "
"vara lämpliga för."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Användarens faktiska ålder lagras inte, så <gui>Lämplighet för program</gui> "
"uppdateras inte automatiskt då barnet blir äldre. Du måste periodiskt "
"utvärdera den rätta <gui>Lämplighet för program</gui> för varje användare på "
"nytt."
#~ msgid ""
#~ "Or enable the <gui style=\"checkbox\">Restrict Application Installation "
#~ "for Others</gui> checkbox."
#~ msgstr ""
#~ "Eller aktivera kryssrutan <gui style=\"checkbox\">Begränsa installation "
#~ "av program åt andra</gui>."
#~ msgid ""
#~ "The <gui style=\"checkbox\">Restrict Application Installation for Others</"
#~ "gui> checkbox allows the user to install additional software for "
#~ "themselves, but prevents that software from being made available to other "
#~ "users. It could be used, for example, if there were two child users, one "
#~ "of whom is mature enough to be allowed to install additional software, "
#~ "but the other isnt — enabling <gui style=\"checkbox\">Restrict "
#~ "Application Installation for Others</gui> would prevent the more mature "
#~ "child from installing applications which are inappropriate for the other "
#~ "child and making them available to the other child."
#~ msgstr ""
#~ "Kryssrutan <gui style=\"checkbox\">Begränsa installation av program åt "
#~ "andra</gui> låter användaren installera ytterligare programvara åt sig "
#~ "själv, men förhindrar den programvaran från att bli tillgänglig för andra "
#~ "användare. Det kan till exempel användas om det finns två barnanvändare, "
#~ "en som är mogen nog för att tillåtas installera ytterligare programvara, "
#~ "och en som inte är det — att aktivera <gui style=\"checkbox\">Begränsa "
#~ "installation av program åt andra</gui> skulle förhindra det mognare "
#~ "barnet från att installera program som är olämpliga så att de blir "
#~ "tillgängliga för det andra barnet."

427
help/tr/tr.po Normal file
View File

@ -0,0 +1,427 @@
# Turkish translation for malcontent.
# Copyright (C) 2023 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
#
# Sabri Ünal <libreajans@gmail.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent main\n"
"POT-Creation-Date: 2023-03-08 15:25+0000\n"
"PO-Revision-Date: 2023-03-09 03:38+0300\n"
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
"Language-Team: Turkish <tr@li.org>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.1.1\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Sabri Ünal <libreajans@gmail.com>, 2023."
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Bilgisayarda çocuk kullanıcı oluşturmak."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Çocuk Kullanıcı Oluşturmak"
# Control Center için ayarlar çevirisini kullanıyoruz. Burada eski adı kullanılmış.
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Ebeveyn denetimleri yalnızca yönetici olmayan hesaplara uygulanabilir. Bu "
"tip hesap, bilgisayar ilk kurulduğunda oluşturulmuş olabilir. Değilse, hiç "
"çocuk kullanıcı yoksa, <app>Ebeveyn Denetimleri</app> uygulamasından yeni "
"çocuk kullanıcı oluşturulabilir; aksi halde <app>Ayarlar</app>ʼdan "
"oluşturulabilir."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Yeni çocuk kullanıcı oluşturmak için <link type=\"guide\" xref=\"help:gnome-"
"help/user-add\">Yeni kullanıcı hesabı ekle</link>ʼye bakın. Yeni kullanıcı "
"oluşturulunca, ebeveyn denetimleri ayarlarının yapılandırılabilmesi için "
"<app>Ebeveyn Denetimleri</app> penceresi görünecektir."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Ebeveyn Denetimleri Yardım"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Giriş ve Kurulum"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Uygulanacak Denetimler"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Çocuk kullanıcının internete erişimini kısıtlamak."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "İnternet Erişimini Kısıtlama"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Kullanıcının internete erişimini kısıtlayabilirsiniz. Bu, web tarayıcısı "
"kullanmalarını engelleyecektir, ancak diğer uygulamalar aracılığıyla "
"(muhtemelen daha sınırlı biçimlerde) interneti kullanmalarını "
"engellemeyecektir. Örneğin, <app>Evolution</app> kullanarak e-posta "
"hesaplarına erişimi engellemez ve yazılım güncellemelerinin indirilip "
"uygulanmasını engellemez."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Kullanıcının internet erişimini kısıtlamak için:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "<app>Ebeveyn Denetimleri</app> uygulamasınıın."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Üstteki sekmelerde kullanıcıyı seçin."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr ""
"<gui style=\"checkbox\">Web Tarayıcılarını Kısıtla</gui> onay kutusunu "
"etkinleştirin."
#. (itstool) path: info/desc
#: C/introduction.page:6
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Ebeveyn denetimlerine, <app>Ebeveyn Denetimleri</app> uygulamasına ve "
"kullanıcı için erişim kısıtlamalarının gereksinildiği diğer durumlarda "
"kullanımına genel bakış."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Ebeveyn Denetimleriʼne Giriş"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Ebeveyn denetimleri, bilgisayarda yönetici hesabı olmayan hesapların ne "
"yapabileceğini sınırlamanın bir yoludur. Amacı, ebeveynlerin çocukları "
"bilgisayarı gözetimsiz veya sınırlı gözetim altında kullandıklarında ne "
"yapabileceklerini sınırlamalarını sağlamaktır."
#. (itstool) path: page/p
#: C/introduction.page:18
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Bu işlevsellik diğer bakıcı/bakılan ilişkileri gibi diğer durumlarda da "
"kullanılabilir, ancak çoğu insanın ebeveyn denetimleri olarak arayacağı "
"varsayılarak, bulması kolay olsun diye bu şekilde adlandırılmıştır."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Herhangi bir kullanıcı için ebeveyn denetimleri, <app>Ebeveyn Denetimleri</"
"app> uygulaması kullanılarak sorgulanabilir ve ayarlanabilir. Bu, yönetici "
"olmayan hesapları üst çubuğundaki sekmelerde listeler ve altında geçerli "
"ebeveyn denetimleri ayarlarını gösterir. Ebeveyn denetimlerinde yapılan "
"değişiklikler hemen uygulanır."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Bilgisayar kullanımıyla ilgili kısıtlamalar yalnızca yönetici olmayan "
"hesaplara uygulanabilir. Bir kullanıcının ebeveyn denetimleri ayarları "
"yalnızca bir yönetici tarafından değiştirilebilir, ancak yönetici "
"<app>Ebeveyn Denetimleri</app> uygulaması tarafından istendiğinde parolasını "
"girerek kullanıcının hesabından bunu yapabilir."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Bu çalışma <_:link-1/> altında lisanslanmıştır."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr ""
"Çocuk kullanıcının zaten kurulmuş uygulamaları çalıştırmasını kısıtlama."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Kurulu Uygulamalara Erişimi Kısıtlama"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Kullanıcının zaten bilgisayarda kurulu olan belirli uygulamaları "
"çalıştırmasını engelleyebilirsiniz. Bu, diğer kullanıcıların bu uygulamalara "
"ihtiyacı varsa ancak çocuk için uygun değilse faydalı olabilir."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"Ek yazılım kurarken, bunun bazı kullanıcılar için kısıtlanması gerekip "
"gerekmediğini değerlendirmelisiniz. Yeni kurulan yazılımlar öntanımlı olarak "
"tüm kullanıcılar tarafından kullanılabilir."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr "Bir kullanıcının belirli bir uygulamaya erişimini kısıtlamak için:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr "<gui style=\"button\">Uygulamaları Kısıtla</gui> düğmesine basın."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Kullanıcının erişimini kısıtlamak istediğiniz her uygulamanın anahtarını "
"etkinleştirin."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "<gui style=\"button\">Uygulamaları Kısıtla</gui> benceresini kapatın."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Belirli uygulamalara erişimin kısıtlanması, kullanıcının incelenmemiş ek "
"yazılımlar kurmasını önlemek için genellikle <link xref=\"software-"
"installation\"/> ile birlikte kullanılır."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Çocuk kullanıcının kurabileceği yazılımı kısıtlamak ya da ek yazılım "
"kurmasını tamamen engellemek."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Yazılım Kurulumunu Kısıtlama"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Kullanıcının sisteme ek yazılım kurmasını engelleyebilirsiniz. Yine de "
"kurulum için yeni yazılım arayabilecekler, ancak uygulama kurmaya "
"çalıştıklarında kurulumu yetkilendirmek için yöneticiye ihtiyaçları olacak. "
"Bu, uygulamayı sistem geneline (tüm kullanıcılar için) ya da yalnızca "
"kendileri için kurmaya çalışsalar da geçerlidir."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Ayrıca, kullanıcının <app>Yazılımlar</app> kataloğunda hangi yazılımlara göz "
"atabileceğini ya da arayabileceğini yaş kategorilerine göre "
"sınırlayabilirsiniz."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Bir kullanıcının zaten kurulu bir uygulamayı çalıştırmasını engellemek için "
"bkz. <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Yazılım Kurulumunu Engelleme"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr "Kullanıcının ek yazılım kurmasını engellemek için:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"<gui style=\"checkbox\">Uygulama Kurulumunu Kısıtla</gui> onay kutusunu "
"etkinleştirin."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Yazılım Kurulumunu Yaşa Göre Kısıtlama"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"<app>Yazılımlar</app> kataloğundaki uygulamalar, kimi yaş grupları için "
"uygun olmayabilecek içerikleri hakkında bilgiler içerir - örneğin, çeşitli "
"şiddet türleri, internet üzerinden diğer kişilerle denetlenmeyen sohbet, ya "
"da para harcama olasılığı gibi."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Her uygulama için, bu bilgi genellikle kullanımı için uygun en düşük yaş "
"grubu olarak özetlenir - örneğin, \"7 yaş ve üzeri için uygun\". Bu yaş "
"derecelendirmeleri, filmler ve oyunlar için kullanılan derecelendirme "
"şemaları ile karşılaştırılabilen bölgesel şemalarda sunulur."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"<app>Yazılımlar</app> kataloğunda kullanıcıya gösterilen uygulamalar, yaş "
"uygunluğuna göre süzülerek gösterilebilir. Kullanıcı için uygun olmayan "
"uygulamalar gizlenir ve kullanıcı tarafından kurulamaz. Bu uygulamalar, yaş "
"uygunluğu yeterince yüksek olan diğer kullanıcılarca kurulabilir."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Kullanıcının <app>Yazılımlar</app> kataloğunda gördüğü uygulamaları yalnızca "
"belirli yaşa uygun olacak şekilde süzmek için:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"<gui>Uygulama Uygunluğu</gui> listesinde, uygulamaların hangi yaş için uygun "
"olduğunu seçin."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Kullanıcının gerçek yaşı depolanmadığı için, <gui>Uygulama Uygunluğu</gui> "
"çocuk büyüdükçe zamanla kendiliğinden güncellenmez. <gui>Uygulama Uygunluğu</"
"gui> her kullanıcı için düzenli olarak yeniden belirlenmelidir."

474
help/uk/uk.po Normal file
View File

@ -0,0 +1,474 @@
# Ukrainian translation for malcontent.
# Copyright (C) 2020 malcontent's COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
#
# Yuri Chornoivan <yurchor@ukr.net>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: malcontent master\n"
"POT-Creation-Date: 2020-12-08 15:28+0000\n"
"PO-Revision-Date: 2020-12-08 22:19+0200\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Lokalize 20.11.70\n"
#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
msgctxt "_"
msgid "translator-credits"
msgstr "Юрій Чорноіван <yurchor@ukr.net>, 2020"
#. (itstool) path: info/desc
#: C/creating-a-child-user.page:6
msgid "Creating a child user on the computer."
msgstr "Створення запису користувача-дитини на комп'ютері."
#. (itstool) path: page/title
#: C/creating-a-child-user.page:9
msgid "Creating a Child User"
msgstr "Створення запису користувача-дитини"
#. (itstool) path: page/p
#: C/creating-a-child-user.page:11
msgid ""
"Parental controls can only be applied to non-administrator accounts. Such an "
"account may have been created when the computer was initially set up. If "
"not, a new child user may be created from the <app>Parental Controls</app> "
"application if no child users already exist; and otherwise may be created "
"from the <app>Control Center</app>."
msgstr ""
"Батьківський контроль можна застосовувати лише до облікових записів без "
"адміністративних прав. Такий обліковий запис могло бути створено під час "
"початкового налаштовування системи. Якщо цього не було зроблено, можна "
"створити новий дитячий обліковий запис за допомогою програми "
"<app>Батьківський контроль</app>. Крім того, такий обліковий запис можна "
"створити за допомогою <app>Центру керування</app>."
#. (itstool) path: page/p
#: C/creating-a-child-user.page:17
msgid ""
"To create a new child user, see <link type=\"guide\" xref=\"help:gnome-help/"
"user-add\">Add a new user account</link>. As soon as the new user is "
"created, it will appear in the <app>Parental Controls</app> window so that "
"its parental controls settings can be configured."
msgstr ""
"Щоб створити дитячий обліковий запис, ознайомтеся із розділом довідки <link "
"type=\"guide\" xref=\"help:gnome-help/user-add\">Додавання нового облікового "
"запису користувача</link>. Щойно запис нового користувача буде створено, "
"його буде показано у вікні програми <app>Батьківський контроль</app>, отже, "
"ви зможете налаштувати параметри батьківського контролю."
#. (itstool) path: credit/name
#: C/index.page:6
msgid "Philip Withnall"
msgstr "Philip Withnall"
#. (itstool) path: credit/years
#: C/index.page:8
msgid "2020"
msgstr "2020"
#. (itstool) path: page/title
#: C/index.page:12
msgid "Parental Controls Help"
msgstr "Допомога у батьківському контролі"
#. (itstool) path: section/title
#: C/index.page:15
msgid "Introduction &amp; Setup"
msgstr "Вступ і налаштування"
#. (itstool) path: section/title
#: C/index.page:19
msgid "Controls to Apply"
msgstr "Засоби контролю, які можна застосувати"
#. (itstool) path: info/desc
#: C/internet.page:6
msgid "Restricting a child users access to the internet."
msgstr "Обмеження доступу дитячого облікового запису до інтернету."
#. (itstool) path: page/title
#: C/internet.page:9
msgid "Restricting Access to the Internet"
msgstr "Обмеження доступу до інтернету"
#. (itstool) path: page/p
#: C/internet.page:11
msgid ""
"You can restrict a users access to the internet. This will prevent them "
"using a web browser, but it will not prevent them using the internet (in "
"potentially more limited forms) through other applications. For example, it "
"will not prevent access to e-mail accounts using <app>Evolution</app>, and "
"it will not prevent software updates being downloaded and applied."
msgstr ""
"Ви можете обмежити доступ користувача до інтернету. Таким чином можна "
"заборонити користувачу користуватися браузером, але користувач збереже "
"доступ до інтернету (у потенційно обмеженішій формі) за допомогою інших "
"програм. Наприклад, користувач матиме доступ до облікових записів "
"електронної пошти за допомогою <app>Evolution</app>. Заборона також не "
"стосуватиметься отримання і застосування оновлень програмного забезпечення."
#. (itstool) path: page/p
#: C/internet.page:17
msgid "To restrict a users access to the internet:"
msgstr "Щоб обмежити доступ користувача до інтернету, виконайте такі дії:"
#. (itstool) path: item/p
#: C/internet.page:19 C/restricting-applications.page:20
#: C/software-installation.page:28 C/software-installation.page:54
msgid "Open the <app>Parental Controls</app> application."
msgstr "Відкрийте вікно програми <app>Батьківський контроль</app>."
#. (itstool) path: item/p
#: C/internet.page:20 C/restricting-applications.page:21
#: C/software-installation.page:29 C/software-installation.page:55
msgid "Select the user in the tabs at the top."
msgstr "Виберіть користувача у вкладках верхньої частини вікна."
#. (itstool) path: item/p
#: C/internet.page:21
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Web Browsers</gui> checkbox."
msgstr "Позначте пункт <gui style=\"checkbox\">Обмежити браузери</gui>."
#. (itstool) path: info/desc
#: C/introduction.page:6
#| msgid ""
#| "Overview of parental controls and the <app>Parental Controls</app> "
#| "application."
msgid ""
"Overview of parental controls, the <app>Parental Controls</app> application "
"and its use in other situations where access restrictions are needed on a "
"user."
msgstr ""
"Огляд батьківського контролю, програми <app>Батьківський контроль</app> та її"
" використання у інших ситуаціях, коли потрібне обмеження доступу для"
" користувача."
#. (itstool) path: page/title
#: C/introduction.page:12
msgid "Introduction to Parental Controls"
msgstr "Вступ до «Батьківського контролю»"
#. (itstool) path: page/p
#: C/introduction.page:14
msgid ""
"Parental controls are a way to restrict what non-administrator accounts can "
"do on the computer, with the aim of allowing parents to restrict what their "
"children can do when using the computer unsupervised or under limited "
"supervision."
msgstr ""
"Батьківський контроль — спосіб обмежити діапазон дій, які зможуть виконувати "
"користувачі неадміністративних облікових записів на комп'ютері. Метою є "
"уможливлення обмеження батьками дій, які можуть вчиняти на комп'ютері діти "
"без нагляду або із обмеженим наглядом."
#. (itstool) path: page/p
#: C/introduction.page:18
#| msgid ""
#| "This functionality can be used in other situations ­ such as other carer/"
#| "caree relationships but is labelled as parental controls so that its "
#| "easy to find."
msgid ""
"This functionality can be used in other situations ­ such as other carer/"
"caree relationships but is labelled as parental controls so that its "
"easy to find, as thats what most people will be looking for."
msgstr ""
"Цими функціональними можливостями можна скористатися і в інших ситуаціях — "
"зокрема у ситуаціях із стосунками доглядач-пацієнт, — ми назвали це "
"«батьківський контроль» лише для зручності пошуку, оскільки саме це шукають"
" більшість наших користувачів."
#. (itstool) path: page/p
#: C/introduction.page:21
msgid ""
"The parental controls for any user can be queried and set using the "
"<app>Parental Controls</app> application. This lists the non-administrator "
"accounts in tabs along its top bar, and shows their current parental "
"controls settings below. Changes to the parental controls apply immediately."
msgstr ""
"Переглянути і встановити батьківський контроль для будь-якого користувача "
"можна за допомогою програми <app>Батьківський контроль</app>. У вікні "
"програми буде показано список неадміністративних облікових записів уздовж "
"верхньої панелі, а також параметри поточного батьківського контролю на "
"панелі під списком. Зміни у батьківському контролі буде застосовано негайно."
#. (itstool) path: page/p
#: C/introduction.page:25
msgid ""
"Restrictions on using the computer can only be applied to non-administrator "
"accounts. The parental controls settings for a user can only be changed by "
"an administrator, although the administrator can do so from the users "
"account by entering their password when prompted by the <app>Parental "
"Controls</app> application."
msgstr ""
"Обмеження у користуванні комп'ютером можна запроваджувати лише для облікових "
"записів, які не є адміністративними. Параметри батьківського контролю для "
"користувача може бути змінено лише адміністратором, хоча адміністратор може "
"зробити це з облікового запису користувача, якщо введе пароль, коли про "
"нього запитає програма <app>Батьківський контроль</app>."
#. (itstool) path: p/link
#: C/legal.xml:4
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported License"
msgstr "Creative Commons Attribution-ShareAlike 3.0 Unported License"
#. (itstool) path: license/p
#: C/legal.xml:3
msgid "This work is licensed under a <_:link-1/>."
msgstr "Ця робота розповсюджується за умов дотримання <_:link-1/>."
#. (itstool) path: info/desc
#: C/restricting-applications.page:6
msgid "Restricting a child user from running already-installed applications."
msgstr "Обмеження запуску з дитячого облікового вже встановлених програм."
#. (itstool) path: page/title
#: C/restricting-applications.page:9
msgid "Restricting Access to Installed Applications"
msgstr "Обмеження доступу до встановлених програм"
#. (itstool) path: page/p
#: C/restricting-applications.page:11
msgid ""
"You can prevent a user from running specific applications which are already "
"installed on the computer. This could be useful if other users need those "
"applications but they are not appropriate for a child."
msgstr ""
"Ви можете заборонити користувачу запускати певні програми, які вже "
"встановлено на комп'ютері. Це може бути корисним, якщо ці програми потрібні "
"іншим користувачам, але є непридатними для користування дитиною."
#. (itstool) path: page/p
#: C/restricting-applications.page:14
msgid ""
"When installing additional software, you should consider whether that needs "
"to be restricted for some users — newly installed software is usable by all "
"users by default."
msgstr ""
"При встановленні додаткового програмного забезпечення вам слід зважати на "
"те, чи слід обмежувати доступ до нього для інших користувачів — типово, усе "
"нововстановлене програмне забезпечення є доступним для усіх користувачів "
"комп'ютера."
#. (itstool) path: page/p
#: C/restricting-applications.page:18
msgid "To restrict a users access to a specific application:"
msgstr ""
"Щоб обмежити доступ користувача до певної програми, виконайте такі дії:"
#. (itstool) path: item/p
#: C/restricting-applications.page:22
msgid "Press the <gui style=\"button\">Restrict Applications</gui> button."
msgstr ""
"Натисніть кнопку <gui style=\"button\">Обмеження доступу до програм</gui>."
#. (itstool) path: item/p
#: C/restricting-applications.page:23
msgid ""
"Enable the switch in the row for each application you would like to restrict "
"the user from accessing."
msgstr ""
"Увімкніть перемикач у рядку для кожної з програм, доступ до якої ви хочете "
"обмежити."
#. (itstool) path: item/p
#: C/restricting-applications.page:24
msgid "Close the <gui>Restrict Applications</gui> window."
msgstr "Закрийте вікно <gui>Обмеження доступу до програм</gui>."
#. (itstool) path: page/p
#: C/restricting-applications.page:27
msgid ""
"Restricting access to specific applications is often used in conjunction "
"with <link xref=\"software-installation\"/> to prevent a user from "
"installing additional software which has not been vetted."
msgstr ""
"Обмеження доступу до певної програми часто використовується у поєднанні із "
"<link xref=\"software-installation\"/> для запобігання встановленню "
"користувачем додаткового програмного забезпечення, доступ до якого не "
"обмежено."
#. (itstool) path: info/desc
#: C/software-installation.page:6
msgid ""
"Restricting the software a child user can install, or preventing them "
"installing additional software entirely."
msgstr ""
"Обмеження можливостей зі встановлення програмного забезпечення власником "
"дитячого облікового запису або повна заборона встановлення програмного "
"забезпечення для дитячого облікового запису."
#. (itstool) path: page/title
#: C/software-installation.page:9
msgid "Restricting Software Installation"
msgstr "Обмеження встановлення програмного забезпечення"
#. (itstool) path: page/p
#: C/software-installation.page:11
msgid ""
"You can prevent a user from installing additional software on the system. "
"They will still be able to search for new software to install, but will need "
"an administrator to authorize the installation when they try to install an "
"application. This applies whether they are trying to install the application "
"system-wide (for all users) or just for themselves."
msgstr ""
"Ви можете заборонити користувачеві встановлювати додаткове програмне "
"забезпечення. Користувачі зможуть виконувати пошук нового програмного "
"забезпечення для встановлення, але потребуватимуть пароля адміністратора для "
"уповноваження на встановлення. Запит щодо пароля буде показано, коли "
"користувач спробує встановити програму. Це стосується ситуацій, коли "
"користувачі намагаються встановити програму на загальносистемному рівні (для "
"усіх користувачів) або лише для себе."
#. (itstool) path: page/p
#: C/software-installation.page:17
msgid ""
"Additionally, you can restrict which software a user can browse or search "
"for in the <app>Software</app> catalog by age categories."
msgstr ""
"Крім того, ви можете обмежити перелік програмного забезпечення, яке зможе "
"бачити або шукати користувач у каталозі програми <app>Програмне "
"забезпечення</app>, за віковими категоріями."
#. (itstool) path: page/p
#: C/software-installation.page:20
msgid ""
"To prevent a user from running an application which has already been "
"installed, see <link xref=\"restricting-applications\"/>."
msgstr ""
"Щоб заборонити користувачу запускати програму, яку вже встановлено, "
"ознайомтеся із вмістом розділу <link xref=\"restricting-applications\"/>."
#. (itstool) path: section/title
#: C/software-installation.page:24
msgid "Preventing Software Installation"
msgstr "Заборона встановлення програмного забезпечення"
#. (itstool) path: section/p
#: C/software-installation.page:26
msgid "To prevent a user from installing additional software:"
msgstr ""
"Щоб заборонити користувачеві встановлення додаткового програмного "
"забезпечення:"
#. (itstool) path: item/p
#: C/software-installation.page:30
msgid ""
"Enable the <gui style=\"checkbox\">Restrict Application Installation</gui> "
"checkbox."
msgstr ""
"Позначте пункт <gui style=\"checkbox\">Обмежити встановлення програм</gui>."
#. (itstool) path: section/title
#: C/software-installation.page:35
msgid "Restricting Software Installation by Age"
msgstr "Обмеження встановлення програмного забезпечення за віком"
#. (itstool) path: section/p
#: C/software-installation.page:37
msgid ""
"Applications in the <app>Software</app> catalog have information about "
"content they contain which might be inappropriate for some ages — for "
"example, various forms of violence, unmoderated chat with other people on "
"the internet, or the possibility of spending money."
msgstr ""
"У пакунках програми з каталогу програми <app>Програмне забезпечення</app> "
"містяться відомості щодо вмісту пакунків, який може бути неприйнятним для "
"певних вікових груп. Наприклад, у програмах можуть бути посилання на різні "
"форми насильства, необмежені можливості спілкування зі сторонніми особами у "
"інтернеті або можливості з витрачання грошей."
#. (itstool) path: section/p
#: C/software-installation.page:41
msgid ""
"For each application, this information is summarized as the minimum age "
"child it is typically suitable to be used by — for example, “suitable for "
"ages 7+”. These age ratings are presented in region-specific schemes which "
"can be compared with the ratings schemes used for films and games."
msgstr ""
"Для кожної програми у цих відомостях щодо програми містяться дані щодо "
"мінімального віку дітей, з якого їх можна допускати до користування "
"програмою, наприклад, «придатна для віку 7+». Ці оцінки віку представлено у "
"вигляді специфічних для регіону схем, які можна порівняти із схемами "
"рейтингів для фільмів та відеоігор."
#. (itstool) path: section/p
#: C/software-installation.page:45
msgid ""
"The applications shown to a user in the <app>Software</app> catalog can be "
"filtered by their age suitability. Applications which are not suitable for "
"the user will be hidden, and will not be installable by that user. They will "
"be installable by other users (if their age suitability is set high enough)."
msgstr ""
"Програми, які буде показано користувачеві у каталозі <app>Програмне "
"забезпечення</app>, можна фільтрувати за придатністю для вікових груп. "
"Програми, які є непридатними для користувача, буде приховано — користувач не "
"зможе їх встановити. Їх зможуть встановлювати інші користувачі (якщо їхній "
"вік є відповідним до вікової категорії програм)."
#. (itstool) path: section/p
#: C/software-installation.page:51
msgid ""
"To filter the applications seen by a user in the <app>Software</app> catalog "
"to only those suitable for a certain age:"
msgstr ""
"Щоб налаштувати фільтрування програм, пункти яких буде показано "
"користувачеві у програмі <app>Програмне забезпечення</app> лише програмами, "
"які рекомендовано для певного вікового діапазону, виконайте такі дії:"
#. (itstool) path: item/p
#: C/software-installation.page:56
msgid ""
"In the <gui>Application Suitability</gui> list, select the age which "
"applications should be suitable for."
msgstr ""
"У списку <gui>Придатність програм</gui> виберіть вік, для якого мають бути "
"придатними програми."
#. (itstool) path: note/p
#: C/software-installation.page:60
msgid ""
"The users actual age is not stored, so the <gui>Application Suitability</"
"gui> is not automatically updated over time as the child grows older. You "
"must periodically re-assess the appropriate <gui>Application Suitability</"
"gui> for each user."
msgstr ""
"Програма не зберігає дані щодо віку користувача, тому список "
"<gui>Придатність програм</gui> не оновлюється автоматично з дорослішанням "
"дитини. Вам слід час від часу оновлювати дані списку <gui>Придатність "
"програм</gui> для кожного користувача."
#~ msgid ""
#~ "Or enable the <gui style=\"checkbox\">Restrict Application Installation "
#~ "for Others</gui> checkbox."
#~ msgstr ""
#~ "Або позначте пункт <gui style=\"checkbox\">Обмежити встановлення програм "
#~ "для інших</gui>."
#~ msgid ""
#~ "The <gui style=\"checkbox\">Restrict Application Installation for Others</"
#~ "gui> checkbox allows the user to install additional software for "
#~ "themselves, but prevents that software from being made available to other "
#~ "users. It could be used, for example, if there were two child users, one "
#~ "of whom is mature enough to be allowed to install additional software, "
#~ "but the other isnt — enabling <gui style=\"checkbox\">Restrict "
#~ "Application Installation for Others</gui> would prevent the more mature "
#~ "child from installing applications which are inappropriate for the other "
#~ "child and making them available to the other child."
#~ msgstr ""
#~ "За допомогою пункту <gui style=\"checkbox\">Обмежити встановлення програм "
#~ "для інших</gui> можна дозволити користувачеві встановлювати додаткове "
#~ "програмне забезпечення для себе, але заборонити доступ до встановленого "
#~ "програмного забезпечення для інших користувачів. Цим можна скористатися, "
#~ "наприклад, якщо у вас двоє дітей, з яких одна дитина достатньо доросла, "
#~ "щоб дозволити їй встановлювати додаткові програми, але інша є надто "
#~ "малою. Позначення пункту <gui style=\"checkbox\">Обмежити встановлення "
#~ "програм для інших</gui> заборонить старшій дитині встановлювати програми, "
#~ "доступ до яких для молодшої дитини слід обмежити."

View File

@ -1,968 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015-2016 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <string.h>
#include "gs-content-rating.h"
const gchar *
gs_content_rating_system_to_str (GsContentRatingSystem system)
{
if (system == GS_CONTENT_RATING_SYSTEM_INCAA)
return "INCAA";
if (system == GS_CONTENT_RATING_SYSTEM_ACB)
return "ACB";
if (system == GS_CONTENT_RATING_SYSTEM_DJCTQ)
return "DJCTQ";
if (system == GS_CONTENT_RATING_SYSTEM_GSRR)
return "GSRR";
if (system == GS_CONTENT_RATING_SYSTEM_PEGI)
return "PEGI";
if (system == GS_CONTENT_RATING_SYSTEM_KAVI)
return "KAVI";
if (system == GS_CONTENT_RATING_SYSTEM_USK)
return "USK";
if (system == GS_CONTENT_RATING_SYSTEM_ESRA)
return "ESRA";
if (system == GS_CONTENT_RATING_SYSTEM_CERO)
return "CERO";
if (system == GS_CONTENT_RATING_SYSTEM_OFLCNZ)
return "OFLCNZ";
if (system == GS_CONTENT_RATING_SYSTEM_RUSSIA)
return "RUSSIA";
if (system == GS_CONTENT_RATING_SYSTEM_MDA)
return "MDA";
if (system == GS_CONTENT_RATING_SYSTEM_GRAC)
return "GRAC";
if (system == GS_CONTENT_RATING_SYSTEM_ESRB)
return "ESRB";
if (system == GS_CONTENT_RATING_SYSTEM_IARC)
return "IARC";
return NULL;
}
const gchar *
gs_content_rating_key_value_to_str (const gchar *id, MctAppFilterOarsValue value)
{
guint i;
const struct {
const gchar *id;
MctAppFilterOarsValue value;
const gchar *desc;
} tab[] = {
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No cartoon violence") },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Cartoon characters in unsafe situations") },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Cartoon characters in aggressive conflict") },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic violence involving cartoon characters") },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No fantasy violence") },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Characters in unsafe situations easily distinguishable from reality") },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Characters in aggressive conflict easily distinguishable from reality") },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic violence easily distinguishable from reality") },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No realistic violence") },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Mildly realistic characters in unsafe situations") },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Depictions of realistic characters in aggressive conflict") },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic violence involving realistic characters") },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No bloodshed") },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Unrealistic bloodshed") },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Realistic bloodshed") },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Depictions of bloodshed and the mutilation of body parts") },
{ "violence-sexual", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No sexual violence") },
{ "violence-sexual", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Rape or other violent sexual behavior") },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to alcohol") },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("References to alcoholic beverages") },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Use of alcoholic beverages") },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to illicit drugs") },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("References to illicit drugs") },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Use of illicit drugs") },
{ "drugs-tobacco", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("References to tobacco products") },
{ "drugs-tobacco", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Use of tobacco products") },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No nudity of any sort") },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Brief artistic nudity") },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Prolonged nudity") },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references or depictions of sexual nature") },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Provocative references or depictions") },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Sexual references or depictions") },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic sexual behavior") },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No profanity of any kind") },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Mild or infrequent use of profanity") },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Moderate use of profanity") },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Strong or frequent use of profanity") },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No inappropriate humor") },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Slapstick humor") },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Vulgar or bathroom humor") },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Mature or sexual humor") },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No discriminatory language of any kind") },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Negativity towards a specific group of people") },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Discrimination designed to cause emotional harm") },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Explicit discrimination based on gender, sexuality, race or religion") },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No advertising of any kind") },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Product placement") },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Explicit references to specific brands or trademarked products") },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Users are encouraged to purchase specific real-world items") },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No gambling of any kind") },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Gambling on random events using tokens or credits") },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Gambling using “play” money") },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Gambling using real money") },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No ability to spend money") },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_MILD, /* v1.1 */
/* TRANSLATORS: content rating description */
_("Users are encouraged to donate real money") },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Ability to spend real money in-game") },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No way to chat with other users") },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("User-to-user game interactions without chat functionality") },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Moderated chat functionality between users") },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Uncontrolled chat functionality between users") },
{ "social-audio", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No way to talk with other users") },
{ "social-audio", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Uncontrolled audio or video chat functionality between users") },
{ "social-contacts", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No sharing of social network usernames or email addresses") },
{ "social-contacts", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Sharing social network usernames or email addresses") },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No sharing of user information with 3rd parties") },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_MILD, /* v1.1 */
/* TRANSLATORS: content rating description */
_("Checking for the latest application version") },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_MODERATE, /* v1.1 */
/* TRANSLATORS: content rating description */
_("Sharing diagnostic data that does not let others identify the user") },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Sharing information that lets others identify the user") },
{ "social-location", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No sharing of physical location to other users") },
{ "social-location", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Sharing physical location to other users") },
/* v1.1 */
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to homosexuality") },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Indirect references to homosexuality") },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Kissing between people of the same gender") },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic sexual behavior between people of the same gender") },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to prostitution") },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Indirect references to prostitution") },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Direct references to prostitution") },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic depictions of the act of prostitution") },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to adultery") },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Indirect references to adultery") },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Direct references to adultery") },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic depictions of the act of adultery") },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No sexualized characters") },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Scantily clad human characters") },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Overtly sexualized human characters") },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to desecration") },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Depictions or references to historical desecration") },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Depictions of modern-day human desecration") },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic depictions of modern-day desecration") },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No visible dead human remains") },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Visible dead human remains") },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Dead human remains that are exposed to the elements") },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic depictions of desecration of human bodies") },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_NONE,
/* TRANSLATORS: content rating description */
_("No references to slavery") },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_MILD,
/* TRANSLATORS: content rating description */
_("Depictions or references to historical slavery") },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_MODERATE,
/* TRANSLATORS: content rating description */
_("Depictions of modern-day slavery") },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_INTENSE,
/* TRANSLATORS: content rating description */
_("Graphic depictions of modern-day slavery") },
{ NULL, 0, NULL } };
for (i = 0; tab[i].id != NULL; i++) {
if (g_strcmp0 (tab[i].id, id) == 0 && tab[i].value == value)
return tab[i].desc;
}
return NULL;
}
/* data obtained from https://en.wikipedia.org/wiki/Video_game_rating_system */
const gchar *
gs_utils_content_rating_age_to_str (GsContentRatingSystem system, guint age)
{
if (system == GS_CONTENT_RATING_SYSTEM_INCAA) {
if (age >= 18)
return "+18";
if (age >= 13)
return "+13";
return "ATP";
}
if (system == GS_CONTENT_RATING_SYSTEM_ACB) {
if (age >= 18)
return "R18+";
if (age >= 15)
return "MA15+";
return "PG";
}
if (system == GS_CONTENT_RATING_SYSTEM_DJCTQ) {
if (age >= 18)
return "18";
if (age >= 16)
return "16";
if (age >= 14)
return "14";
if (age >= 12)
return "12";
if (age >= 10)
return "10";
return "L";
}
if (system == GS_CONTENT_RATING_SYSTEM_GSRR) {
if (age >= 18)
return "限制";
if (age >= 15)
return "輔15";
if (age >= 12)
return "輔12";
if (age >= 6)
return "保護";
return "普通";
}
if (system == GS_CONTENT_RATING_SYSTEM_PEGI) {
if (age >= 18)
return "18";
if (age >= 16)
return "16";
if (age >= 12)
return "12";
if (age >= 7)
return "7";
if (age >= 3)
return "3";
return NULL;
}
if (system == GS_CONTENT_RATING_SYSTEM_KAVI) {
if (age >= 18)
return "18+";
if (age >= 16)
return "16+";
if (age >= 12)
return "12+";
if (age >= 7)
return "7+";
if (age >= 3)
return "3+";
return NULL;
}
if (system == GS_CONTENT_RATING_SYSTEM_USK) {
if (age >= 18)
return "18";
if (age >= 16)
return "16";
if (age >= 12)
return "12";
if (age >= 6)
return "6";
return "0";
}
/* Reference: http://www.esra.org.ir/ */
if (system == GS_CONTENT_RATING_SYSTEM_ESRA) {
if (age >= 18)
return "+18";
if (age >= 15)
return "+15";
if (age >= 12)
return "+12";
if (age >= 7)
return "+7";
if (age >= 3)
return "+3";
return NULL;
}
if (system == GS_CONTENT_RATING_SYSTEM_CERO) {
if (age >= 18)
return "Z";
if (age >= 17)
return "D";
if (age >= 15)
return "C";
if (age >= 12)
return "B";
return "A";
}
if (system == GS_CONTENT_RATING_SYSTEM_OFLCNZ) {
if (age >= 18)
return "R18";
if (age >= 16)
return "R16";
if (age >= 15)
return "R15";
if (age >= 13)
return "R13";
return "G";
}
if (system == GS_CONTENT_RATING_SYSTEM_RUSSIA) {
if (age >= 18)
return "18+";
if (age >= 16)
return "16+";
if (age >= 12)
return "12+";
if (age >= 6)
return "6+";
return "0+";
}
if (system == GS_CONTENT_RATING_SYSTEM_MDA) {
if (age >= 18)
return "M18";
if (age >= 16)
return "ADV";
return "General";
}
if (system == GS_CONTENT_RATING_SYSTEM_GRAC) {
if (age >= 18)
return "18";
if (age >= 15)
return "15";
if (age >= 12)
return "12";
return "ALL";
}
if (system == GS_CONTENT_RATING_SYSTEM_ESRB) {
if (age >= 18)
return "Adults Only";
if (age >= 17)
return "Mature";
if (age >= 13)
return "Teen";
if (age >= 10)
return "Everyone 10+";
if (age >= 6)
return "Everyone";
return "Early Childhood";
}
/* IARC = everything else */
if (age >= 18)
return "18+";
if (age >= 16)
return "16+";
if (age >= 12)
return "12+";
if (age >= 7)
return "7+";
if (age >= 3)
return "3+";
return NULL;
}
/*
* parse_locale:
* @locale: (transfer full): a locale to parse
* @language_out: (out) (optional) (nullable): return location for the parsed
* language, or %NULL to ignore
* @territory_out: (out) (optional) (nullable): return location for the parsed
* territory, or %NULL to ignore
* @codeset_out: (out) (optional) (nullable): return location for the parsed
* codeset, or %NULL to ignore
* @modifier_out: (out) (optional) (nullable): return location for the parsed
* modifier, or %NULL to ignore
*
* Parse @locale as a locale string of the form
* `language[_territory][.codeset][@modifier]` see `man 3 setlocale` for
* details.
*
* On success, %TRUE will be returned, and the components of the locale will be
* returned in the given addresses, with each component not including any
* separators. Otherwise, %FALSE will be returned and the components will be set
* to %NULL.
*
* @locale is modified, and any returned non-%NULL pointers will point inside
* it.
*
* Returns: %TRUE on success, %FALSE otherwise
*/
static gboolean
parse_locale (gchar *locale /* (transfer full) */,
const gchar **language_out,
const gchar **territory_out,
const gchar **codeset_out,
const gchar **modifier_out)
{
gchar *separator;
const gchar *language = NULL, *territory = NULL, *codeset = NULL, *modifier = NULL;
separator = strrchr (locale, '@');
if (separator != NULL) {
modifier = separator + 1;
*separator = '\0';
}
separator = strrchr (locale, '.');
if (separator != NULL) {
codeset = separator + 1;
*separator = '\0';
}
separator = strrchr (locale, '_');
if (separator != NULL) {
territory = separator + 1;
*separator = '\0';
}
language = locale;
/* Parse failure? */
if (*language == '\0') {
language = NULL;
territory = NULL;
codeset = NULL;
modifier = NULL;
}
if (language_out != NULL)
*language_out = language;
if (territory_out != NULL)
*territory_out = territory;
if (codeset_out != NULL)
*codeset_out = codeset;
if (modifier_out != NULL)
*modifier_out = modifier;
return (language != NULL);
}
/* data obtained from https://en.wikipedia.org/wiki/Video_game_rating_system */
GsContentRatingSystem
gs_utils_content_rating_system_from_locale (const gchar *locale)
{
g_autofree gchar *locale_copy = g_strdup (locale);
const gchar *language, *territory;
/* Default to IARC for locales which cant be parsed. */
if (!parse_locale (locale_copy, &language, &territory, NULL, NULL))
return GS_CONTENT_RATING_SYSTEM_IARC;
/* Argentina */
if (g_strcmp0 (language, "ar") == 0)
return GS_CONTENT_RATING_SYSTEM_INCAA;
/* Australia */
if (g_strcmp0 (language, "au") == 0)
return GS_CONTENT_RATING_SYSTEM_ACB;
/* Brazil */
if (g_strcmp0 (language, "pt") == 0 &&
g_strcmp0 (territory, "BR") == 0)
return GS_CONTENT_RATING_SYSTEM_DJCTQ;
/* Taiwan */
if (g_strcmp0 (language, "zh") == 0 &&
g_strcmp0 (territory, "TW") == 0)
return GS_CONTENT_RATING_SYSTEM_GSRR;
/* Europe (but not Finland or Germany), India, Israel,
* Pakistan, Quebec, South Africa */
if ((g_strcmp0 (language, "en") == 0 &&
g_strcmp0 (territory, "GB") == 0) ||
g_strcmp0 (language, "gb") == 0 ||
g_strcmp0 (language, "al") == 0 ||
g_strcmp0 (language, "ad") == 0 ||
g_strcmp0 (language, "am") == 0 ||
g_strcmp0 (language, "at") == 0 ||
g_strcmp0 (language, "az") == 0 ||
g_strcmp0 (language, "by") == 0 ||
g_strcmp0 (language, "be") == 0 ||
g_strcmp0 (language, "ba") == 0 ||
g_strcmp0 (language, "bg") == 0 ||
g_strcmp0 (language, "hr") == 0 ||
g_strcmp0 (language, "cy") == 0 ||
g_strcmp0 (language, "cz") == 0 ||
g_strcmp0 (language, "dk") == 0 ||
g_strcmp0 (language, "ee") == 0 ||
g_strcmp0 (language, "fr") == 0 ||
g_strcmp0 (language, "ge") == 0 ||
g_strcmp0 (language, "gr") == 0 ||
g_strcmp0 (language, "hu") == 0 ||
g_strcmp0 (language, "is") == 0 ||
g_strcmp0 (language, "it") == 0 ||
g_strcmp0 (language, "kz") == 0 ||
g_strcmp0 (language, "xk") == 0 ||
g_strcmp0 (language, "lv") == 0 ||
g_strcmp0 (language, "fl") == 0 ||
g_strcmp0 (language, "lu") == 0 ||
g_strcmp0 (language, "lt") == 0 ||
g_strcmp0 (language, "mk") == 0 ||
g_strcmp0 (language, "mt") == 0 ||
g_strcmp0 (language, "md") == 0 ||
g_strcmp0 (language, "mc") == 0 ||
g_strcmp0 (language, "me") == 0 ||
g_strcmp0 (language, "nl") == 0 ||
g_strcmp0 (language, "no") == 0 ||
g_strcmp0 (language, "pl") == 0 ||
g_strcmp0 (language, "pt") == 0 ||
g_strcmp0 (language, "ro") == 0 ||
g_strcmp0 (language, "sm") == 0 ||
g_strcmp0 (language, "rs") == 0 ||
g_strcmp0 (language, "sk") == 0 ||
g_strcmp0 (language, "si") == 0 ||
g_strcmp0 (language, "es") == 0 ||
g_strcmp0 (language, "se") == 0 ||
g_strcmp0 (language, "ch") == 0 ||
g_strcmp0 (language, "tr") == 0 ||
g_strcmp0 (language, "ua") == 0 ||
g_strcmp0 (language, "va") == 0 ||
g_strcmp0 (language, "in") == 0 ||
g_strcmp0 (language, "il") == 0 ||
g_strcmp0 (language, "pk") == 0 ||
g_strcmp0 (language, "za") == 0)
return GS_CONTENT_RATING_SYSTEM_PEGI;
/* Finland */
if (g_strcmp0 (language, "fi") == 0)
return GS_CONTENT_RATING_SYSTEM_KAVI;
/* Germany */
if (g_strcmp0 (language, "de") == 0)
return GS_CONTENT_RATING_SYSTEM_USK;
/* Iran */
if (g_strcmp0 (language, "ir") == 0)
return GS_CONTENT_RATING_SYSTEM_ESRA;
/* Japan */
if (g_strcmp0 (language, "jp") == 0)
return GS_CONTENT_RATING_SYSTEM_CERO;
/* New Zealand */
if (g_strcmp0 (language, "nz") == 0)
return GS_CONTENT_RATING_SYSTEM_OFLCNZ;
/* Russia: Content rating law */
if (g_strcmp0 (language, "ru") == 0)
return GS_CONTENT_RATING_SYSTEM_RUSSIA;
/* Singapore */
if (g_strcmp0 (language, "sg") == 0)
return GS_CONTENT_RATING_SYSTEM_MDA;
/* South Korea */
if (g_strcmp0 (language, "kr") == 0)
return GS_CONTENT_RATING_SYSTEM_GRAC;
/* USA, Canada, Mexico */
if ((g_strcmp0 (language, "en") == 0 &&
g_strcmp0 (territory, "US") == 0) ||
g_strcmp0 (language, "us") == 0 ||
g_strcmp0 (language, "ca") == 0 ||
g_strcmp0 (language, "mx") == 0)
return GS_CONTENT_RATING_SYSTEM_ESRB;
/* everything else is IARC */
return GS_CONTENT_RATING_SYSTEM_IARC;
}
static const gchar *content_rating_strings[GS_CONTENT_RATING_SYSTEM_LAST][7] = {
{ "3+", "7+", "12+", "16+", "18+", NULL }, /* GS_CONTENT_RATING_SYSTEM_UNKNOWN */
{ "ATP", "+13", "+18", NULL }, /* GS_CONTENT_RATING_SYSTEM_INCAA */
{ "PG", "MA15+", "R18+", NULL }, /* GS_CONTENT_RATING_SYSTEM_ACB */
{ "L", "10", "12", "14", "16", "18", NULL }, /* GS_CONTENT_RATING_SYSTEM_DJCTQ */
{ "普通", "保護", "輔12", "輔15", "限制", NULL }, /* GS_CONTENT_RATING_SYSTEM_GSRR */
{ "3", "7", "12", "16", "18", NULL }, /* GS_CONTENT_RATING_SYSTEM_PEGI */
{ "3+", "7+", "12+", "16+", "18+", NULL }, /* GS_CONTENT_RATING_SYSTEM_KAVI */
{ "0", "6", "12", "16", "18", NULL}, /* GS_CONTENT_RATING_SYSTEM_USK */
{ "+3", "+7", "+12", "+15", "+18", NULL }, /* GS_CONTENT_RATING_SYSTEM_ESRA */
{ "A", "B", "C", "D", "Z", NULL }, /* GS_CONTENT_RATING_SYSTEM_CERO */
{ "G", "R13", "R15", "R16", "R18", NULL }, /* GS_CONTENT_RATING_SYSTEM_OFLCNZ */
{ "0+", "6+", "12+", "16+", "18+", NULL }, /* GS_CONTENT_RATING_SYSTEM_RUSSIA */
{ "General", "ADV", "M18", NULL }, /* GS_CONTENT_RATING_SYSTEM_MDA */
{ "ALL", "12", "15", "18", NULL }, /* GS_CONTENT_RATING_SYSTEM_GRAC */
{ "Early Childhood", "Everyone", "Everyone 10+", "Teen", "Mature", "Adults Only", NULL }, /* GS_CONTENT_RATING_SYSTEM_ESRB */
{ "3+", "7+", "12+", "16+", "18+", NULL }, /* GS_CONTENT_RATING_SYSTEM_IARC */
};
const gchar * const *
gs_utils_content_rating_get_values (GsContentRatingSystem system)
{
g_assert (system < GS_CONTENT_RATING_SYSTEM_LAST);
return content_rating_strings[system];
}
static guint content_rating_ages[GS_CONTENT_RATING_SYSTEM_LAST][7] = {
{ 3, 7, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_UNKNOWN */
{ 0, 13, 18 }, /* GS_CONTENT_RATING_SYSTEM_INCAA */
{ 0, 15, 18 }, /* GS_CONTENT_RATING_SYSTEM_ACB */
{ 0, 10, 12, 14, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_DJCTQ */
{ 0, 6, 12, 15, 18 }, /* GS_CONTENT_RATING_SYSTEM_GSRR */
{ 3, 7, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_PEGI */
{ 3, 7, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_KAVI */
{ 0, 6, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_USK */
{ 3, 7, 12, 15, 18 }, /* GS_CONTENT_RATING_SYSTEM_ESRA */
{ 0, 12, 15, 17, 18 }, /* GS_CONTENT_RATING_SYSTEM_CERO */
{ 0, 13, 15, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_OFLCNZ */
{ 0, 6, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_RUSSIA */
{ 0, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_MDA */
{ 0, 12, 15, 18 }, /* GS_CONTENT_RATING_SYSTEM_GRAC */
{ 0, 6, 10, 13, 17, 18 }, /* GS_CONTENT_RATING_SYSTEM_ESRB */
{ 3, 7, 12, 16, 18 }, /* GS_CONTENT_RATING_SYSTEM_IARC */
};
const guint *
gs_utils_content_rating_get_ages (GsContentRatingSystem system)
{
g_assert (system < GS_CONTENT_RATING_SYSTEM_LAST);
return content_rating_ages[system];
}
const struct {
const gchar *id;
MctAppFilterOarsValue value;
guint csm_age;
} id_to_csm_age[] = {
/* v1.0 */
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_MILD, 3 },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_MODERATE, 4 },
{ "violence-cartoon", MCT_APP_FILTER_OARS_VALUE_INTENSE, 6 },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_MILD, 3 },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_MODERATE, 7 },
{ "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_INTENSE, 8 },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_MILD, 4 },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_MODERATE, 9 },
{ "violence-realistic", MCT_APP_FILTER_OARS_VALUE_INTENSE, 14 },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_MILD, 9 },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_MODERATE, 11 },
{ "violence-bloodshed", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "violence-sexual", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-sexual", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_MILD, 11 },
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_MODERATE, 13 },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_MILD, 12 },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_MODERATE, 14 },
{ "drugs-tobacco", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "drugs-tobacco", MCT_APP_FILTER_OARS_VALUE_MILD, 10 },
{ "drugs-tobacco", MCT_APP_FILTER_OARS_VALUE_MODERATE, 13 },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_MILD, 12 },
{ "sex-nudity", MCT_APP_FILTER_OARS_VALUE_MODERATE, 14 },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_MILD, 13 },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_MODERATE, 14 },
{ "sex-themes", MCT_APP_FILTER_OARS_VALUE_INTENSE, 15 },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_MILD, 8 },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_MODERATE, 11 },
{ "language-profanity", MCT_APP_FILTER_OARS_VALUE_INTENSE, 14 },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_MILD, 3 },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_MODERATE, 8 },
{ "language-humor", MCT_APP_FILTER_OARS_VALUE_INTENSE, 14 },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_MILD, 9 },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_MODERATE,10 },
{ "language-discrimination", MCT_APP_FILTER_OARS_VALUE_INTENSE, 11 },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_MILD, 7 },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_MODERATE, 8 },
{ "money-advertising", MCT_APP_FILTER_OARS_VALUE_INTENSE, 10 },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_MILD, 7 },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_MODERATE, 10 },
{ "money-gambling", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_INTENSE, 15 },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_MILD, 4 },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_MODERATE, 10 },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_INTENSE, 13 },
{ "social-audio", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "social-audio", MCT_APP_FILTER_OARS_VALUE_INTENSE, 15 },
{ "social-contacts", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "social-contacts", MCT_APP_FILTER_OARS_VALUE_INTENSE, 12 },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_INTENSE, 13 },
{ "social-location", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "social-location", MCT_APP_FILTER_OARS_VALUE_INTENSE, 13 },
/* v1.1 additions */
{ "social-info", MCT_APP_FILTER_OARS_VALUE_MILD, 0 },
{ "social-info", MCT_APP_FILTER_OARS_VALUE_MODERATE, 13 },
{ "money-purchasing", MCT_APP_FILTER_OARS_VALUE_MILD, 12 },
{ "social-chat", MCT_APP_FILTER_OARS_VALUE_MODERATE, 14 },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_MILD, 10 },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_MODERATE, 13 },
{ "sex-homosexuality", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_MILD, 12 },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_MODERATE, 14 },
{ "sex-prostitution", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_MILD, 8 },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_MODERATE, 10 },
{ "sex-adultery", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_MODERATE, 10 },
{ "sex-appearance", MCT_APP_FILTER_OARS_VALUE_INTENSE, 15 },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_MILD, 13 },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_MODERATE, 15 },
{ "violence-worship", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_MILD, 13 },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_MODERATE, 15 },
{ "violence-desecration", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_NONE, 0 },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_MILD, 13 },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_MODERATE, 15 },
{ "violence-slavery", MCT_APP_FILTER_OARS_VALUE_INTENSE, 18 },
/* EOS customisation to add at least one CSM ↔ OARS mapping for ages 16 and 17,
* as these are used in many locale-specific ratings systems. Without them,
* mapping (e.g.) OFLCNZ R16 CSM 16 OARS CSM gives CSM 15, which then maps
* back to OFLCNZ R15, which is not what we want. The addition of these two
* mappings should not expose younger users to content they would not have seen
* with the default upstream mappings; it instead slightly raises the age at
* which users are allowed to see intense content in these two categories.
*
* See https://phabricator.endlessm.com/T23897#666769. */
{ "drugs-alcohol", MCT_APP_FILTER_OARS_VALUE_INTENSE, 16 },
{ "drugs-narcotics", MCT_APP_FILTER_OARS_VALUE_INTENSE, 17 },
{ NULL, 0, 0 } };
/**
* as_content_rating_id_value_to_csm_age:
* @id: the subsection ID e.g. "violence-cartoon"
* @value: the #AsContentRatingValue, e.g. %MCT_APP_FILTER_OARS_VALUE_INTENSE
*
* Gets the Common Sense Media approved age for a specific rating level.
*
* Returns: The age in years, or 0 for no details.
*
* Since: 0.5.12
**/
guint
as_content_rating_id_value_to_csm_age (const gchar *id, MctAppFilterOarsValue value)
{
guint i;
for (i = 0; id_to_csm_age[i].id != NULL; i++) {
if (value == id_to_csm_age[i].value &&
g_strcmp0 (id, id_to_csm_age[i].id) == 0)
return id_to_csm_age[i].csm_age;
}
return 0;
}
/**
* as_content_rating_id_csm_age_to_value:
* @id: the subsection ID e.g. "violence-cartoon"
* @age: the age
*
* Gets the #MctAppFilterOarsValue for a given age.
*
* Returns: the #MctAppFilterOarsValue
**/
MctAppFilterOarsValue
as_content_rating_id_csm_age_to_value (const gchar *id, guint age)
{
MctAppFilterOarsValue value;
guint i;
value = MCT_APP_FILTER_OARS_VALUE_UNKNOWN;
for (i = 0; id_to_csm_age[i].id != NULL; i++) {
if (age >= id_to_csm_age[i].csm_age &&
g_strcmp0 (id, id_to_csm_age[i].id) == 0)
value = MAX (value, id_to_csm_age[i].value);
}
return value;
}

View File

@ -1,61 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015-2016 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
G_BEGIN_DECLS
#include <glib-object.h>
#include <libmalcontent/malcontent.h>
typedef enum {
GS_CONTENT_RATING_SYSTEM_UNKNOWN,
GS_CONTENT_RATING_SYSTEM_INCAA,
GS_CONTENT_RATING_SYSTEM_ACB,
GS_CONTENT_RATING_SYSTEM_DJCTQ,
GS_CONTENT_RATING_SYSTEM_GSRR,
GS_CONTENT_RATING_SYSTEM_PEGI,
GS_CONTENT_RATING_SYSTEM_KAVI,
GS_CONTENT_RATING_SYSTEM_USK,
GS_CONTENT_RATING_SYSTEM_ESRA,
GS_CONTENT_RATING_SYSTEM_CERO,
GS_CONTENT_RATING_SYSTEM_OFLCNZ,
GS_CONTENT_RATING_SYSTEM_RUSSIA,
GS_CONTENT_RATING_SYSTEM_MDA,
GS_CONTENT_RATING_SYSTEM_GRAC,
GS_CONTENT_RATING_SYSTEM_ESRB,
GS_CONTENT_RATING_SYSTEM_IARC,
/*< private >*/
GS_CONTENT_RATING_SYSTEM_LAST
} GsContentRatingSystem;
const gchar *gs_utils_content_rating_age_to_str (GsContentRatingSystem system,
guint age);
GsContentRatingSystem gs_utils_content_rating_system_from_locale (const gchar *locale);
const gchar *gs_content_rating_key_value_to_str (const gchar *id,
MctAppFilterOarsValue value);
const gchar *gs_content_rating_system_to_str (GsContentRatingSystem system);
const gchar * const *gs_utils_content_rating_get_values (GsContentRatingSystem system);
const guint *gs_utils_content_rating_get_ages (GsContentRatingSystem system);
guint as_content_rating_id_value_to_csm_age (const gchar *id, MctAppFilterOarsValue value);
MctAppFilterOarsValue as_content_rating_id_csm_age_to_value (const gchar *id, guint age);
G_END_DECLS

View File

@ -4,6 +4,7 @@
<gresource prefix="/org/freedesktop/MalcontentUi/ui"> <gresource prefix="/org/freedesktop/MalcontentUi/ui">
<file preprocess="xml-stripblanks">restrict-applications-dialog.ui</file> <file preprocess="xml-stripblanks">restrict-applications-dialog.ui</file>
<file preprocess="xml-stripblanks">restrict-applications-selector.ui</file> <file preprocess="xml-stripblanks">restrict-applications-selector.ui</file>
<file>restricts-switch.css</file>
<file preprocess="xml-stripblanks">user-controls.ui</file> <file preprocess="xml-stripblanks">user-controls.ui</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@ -1,4 +1,4 @@
libmalcontent_ui_api_version = '0' libmalcontent_ui_api_version = '1'
libmalcontent_ui_api_name = 'malcontent-ui-' + libmalcontent_ui_api_version libmalcontent_ui_api_name = 'malcontent-ui-' + libmalcontent_ui_api_version
if not cc.has_function('atexit') if not cc.has_function('atexit')
@ -8,11 +8,10 @@ endif
resources = gnome.compile_resources( resources = gnome.compile_resources(
'resources', 'resources',
'malcontent-ui.gresource.xml', 'malcontent-ui.gresource.xml',
source_dir: meson.source_root(), source_dir: meson.current_source_dir(),
) )
libmalcontent_ui_sources = [ libmalcontent_ui_sources = [
'gs-content-rating.c',
'restrict-applications-dialog.c', 'restrict-applications-dialog.c',
'restrict-applications-selector.c', 'restrict-applications-selector.c',
'user-controls.c', 'user-controls.c',
@ -23,19 +22,18 @@ libmalcontent_ui_headers = [
'restrict-applications-selector.h', 'restrict-applications-selector.h',
'user-controls.h', 'user-controls.h',
] ]
libmalcontent_ui_private_headers = [
'gs-content-rating.h',
]
libmalcontent_ui_public_deps = [ libmalcontent_ui_public_deps = [
dependency('accountsservice', version: '>= 0.6.39'), dependency('accountsservice', version: '>= 0.6.39'),
dependency('gio-2.0', version: '>= 2.44'), dependency('gio-2.0', version: '>= 2.44'),
dependency('glib-2.0', version: '>= 2.54.2'), dependency('glib-2.0', version: '>= 2.54.2'),
dependency('gobject-2.0', version: '>= 2.54'), dependency('gobject-2.0', version: '>= 2.54'),
dependency('gtk+-3.0', version: '>= 3.24'), gtk_dep,
libadwaita_dep,
libmalcontent_dep, libmalcontent_dep,
] ]
libmalcontent_ui_private_deps = [ libmalcontent_ui_private_deps = [
dependency('appstream', version: '>= 0.12.10'),
dependency('flatpak'), dependency('flatpak'),
] ]
@ -43,7 +41,7 @@ libmalcontent_ui_private_deps = [
libmalcontent_ui_include_subdir = join_paths(libmalcontent_ui_api_name, 'libmalcontent-ui') libmalcontent_ui_include_subdir = join_paths(libmalcontent_ui_api_name, 'libmalcontent-ui')
libmalcontent_ui = library(libmalcontent_ui_api_name, libmalcontent_ui = library(libmalcontent_ui_api_name,
libmalcontent_ui_sources + libmalcontent_ui_headers + libmalcontent_ui_private_headers, libmalcontent_ui_sources + libmalcontent_ui_headers,
dependencies: libmalcontent_ui_public_deps + libmalcontent_ui_private_deps, dependencies: libmalcontent_ui_public_deps + libmalcontent_ui_private_deps,
include_directories: root_inc, include_directories: root_inc,
install: true, install: true,
@ -70,26 +68,26 @@ pkgconfig.generate(libmalcontent_ui,
libraries_private: libmalcontent_ui_private_deps, libraries_private: libmalcontent_ui_private_deps,
) )
gnome.generate_gir(libmalcontent_ui, libmalcontent_ui_gir = gnome.generate_gir(libmalcontent_ui,
sources: libmalcontent_ui_sources + libmalcontent_ui_headers + libmalcontent_ui_private_headers, sources: libmalcontent_ui_sources + libmalcontent_ui_headers,
nsversion: libmalcontent_ui_api_version, nsversion: libmalcontent_ui_api_version,
namespace: 'MalcontentUi', namespace: 'MalcontentUi',
symbol_prefix: 'mct_', symbol_prefix: 'mct_',
identifier_prefix: 'Mct', identifier_prefix: 'Mct',
export_packages: 'libmalcontent-ui', export_packages: 'libmalcontent-ui',
includes: ['AccountsService-1.0', 'Gio-2.0', 'GObject-2.0', 'Gtk-3.0'], includes: ['AccountsService-1.0', 'Gio-2.0', 'GObject-2.0', 'Gtk-4.0', 'Adw-1', libmalcontent_gir[0]],
install: true, install: true,
dependencies: libmalcontent_ui_dep, dependencies: libmalcontent_ui_dep,
) )
xmllint = find_program('xmllint', required: false) xmllint = find_program('xmllint', required: false)
if xmllint.found() if xmllint.found()
gtk_prefix = dependency('gtk+-3.0').get_pkgconfig_variable('prefix') gtk_prefix = gtk_dep.get_variable(pkgconfig: 'prefix')
test( test(
'validate-ui', xmllint, 'validate-ui', xmllint,
args: [ args: [
'--nonet', '--noblanks', '--noout', '--nonet', '--noblanks', '--noout',
'--relaxng', join_paths(gtk_prefix, 'share', 'gtk-3.0', 'gtkbuilder.rng'), '--relaxng', join_paths(gtk_prefix, 'share', 'gtk-4.0', 'gtk4builder.rng'),
files( files(
'restrict-applications-dialog.ui', 'restrict-applications-dialog.ui',
'restrict-applications-selector.ui', 'restrict-applications-selector.ui',

View File

@ -19,12 +19,14 @@
* - Philip Withnall <withnall@endlessm.com> * - Philip Withnall <withnall@endlessm.com>
*/ */
#include <act/act.h> #include "config.h"
#include <gio/gio.h> #include <gio/gio.h>
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include <glib/gi18n.h> #include <glib/gi18n-lib.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <adwaita.h>
#include "restrict-applications-dialog.h" #include "restrict-applications-dialog.h"
#include "restrict-applications-selector.h" #include "restrict-applications-selector.h"
@ -52,21 +54,28 @@ struct _MctRestrictApplicationsDialog
GtkDialog parent_instance; GtkDialog parent_instance;
MctRestrictApplicationsSelector *selector; MctRestrictApplicationsSelector *selector;
GtkLabel *description; AdwPreferencesGroup *group;
GtkSearchEntry *search_entry;
MctAppFilter *app_filter; /* (owned) (not nullable) */ MctAppFilter *app_filter; /* (owned) (not nullable) */
ActUser *user; /* (owned) (nullable) */ gchar *user_display_name; /* (owned) (nullable) */
}; };
G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, GTK_TYPE_DIALOG) static void search_entry_stop_search_cb (GtkSearchEntry *search_entry,
gpointer user_data);
static gboolean focus_search_cb (GtkWidget *widget,
GVariant *arguments,
gpointer user_data);
G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, ADW_TYPE_PREFERENCES_WINDOW)
typedef enum typedef enum
{ {
PROP_APP_FILTER = 1, PROP_APP_FILTER = 1,
PROP_USER, PROP_USER_DISPLAY_NAME,
} MctRestrictApplicationsDialogProperty; } MctRestrictApplicationsDialogProperty;
static GParamSpec *properties[PROP_USER + 1]; static GParamSpec *properties[PROP_USER_DISPLAY_NAME + 1];
static void static void
mct_restrict_applications_dialog_constructed (GObject *obj) mct_restrict_applications_dialog_constructed (GObject *obj)
@ -74,7 +83,9 @@ mct_restrict_applications_dialog_constructed (GObject *obj)
MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (obj); MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (obj);
g_assert (self->app_filter != NULL); g_assert (self->app_filter != NULL);
g_assert (self->user == NULL || ACT_IS_USER (self->user)); g_assert (self->user_display_name == NULL ||
(*self->user_display_name != '\0' &&
g_utf8_validate (self->user_display_name, -1, NULL)));
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->constructed (obj); G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->constructed (obj);
} }
@ -93,8 +104,8 @@ mct_restrict_applications_dialog_get_property (GObject *object,
g_value_set_boxed (value, self->app_filter); g_value_set_boxed (value, self->app_filter);
break; break;
case PROP_USER: case PROP_USER_DISPLAY_NAME:
g_value_set_object (value, self->user); g_value_set_string (value, self->user_display_name);
break; break;
default: default:
@ -116,8 +127,8 @@ mct_restrict_applications_dialog_set_property (GObject *object,
mct_restrict_applications_dialog_set_app_filter (self, g_value_get_boxed (value)); mct_restrict_applications_dialog_set_app_filter (self, g_value_get_boxed (value));
break; break;
case PROP_USER: case PROP_USER_DISPLAY_NAME:
mct_restrict_applications_dialog_set_user (self, g_value_get_object (value)); mct_restrict_applications_dialog_set_user_display_name (self, g_value_get_string (value));
break; break;
default: default:
@ -131,11 +142,24 @@ mct_restrict_applications_dialog_dispose (GObject *object)
MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)object; MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)object;
g_clear_pointer (&self->app_filter, mct_app_filter_unref); g_clear_pointer (&self->app_filter, mct_app_filter_unref);
g_clear_object (&self->user); g_clear_pointer (&self->user_display_name, g_free);
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->dispose (object); G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->dispose (object);
} }
static void
mct_restrict_applications_dialog_map (GtkWidget *widget)
{
MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)widget;
GTK_WIDGET_CLASS (mct_restrict_applications_dialog_parent_class)->map (widget);
/* Clear and focus the search entry, in case the dialogue is being shown for
* a second time. */
gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
}
static void static void
mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass *klass) mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass *klass)
{ {
@ -147,6 +171,8 @@ mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass
object_class->set_property = mct_restrict_applications_dialog_set_property; object_class->set_property = mct_restrict_applications_dialog_set_property;
object_class->dispose = mct_restrict_applications_dialog_dispose; object_class->dispose = mct_restrict_applications_dialog_dispose;
widget_class->map = mct_restrict_applications_dialog_map;
/** /**
* MctRestrictApplicationsDialog:app-filter: (not nullable) * MctRestrictApplicationsDialog:app-filter: (not nullable)
* *
@ -168,19 +194,22 @@ mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass
G_PARAM_EXPLICIT_NOTIFY); G_PARAM_EXPLICIT_NOTIFY);
/** /**
* MctRestrictApplicationsDialog:user: (nullable) * MctRestrictApplicationsDialog:user-display-name: (nullable)
* *
* The currently selected user account, or %NULL if no user is selected. * The display name for the currently selected user account, or %NULL if no
* user is selected. This will typically be the users full name (if known)
* or their username.
*
* If set, it must be valid UTF-8 and non-empty.
* *
* Since: 0.5.0 * Since: 0.5.0
*/ */
properties[PROP_USER] = properties[PROP_USER_DISPLAY_NAME] =
g_param_spec_object ("user", g_param_spec_string ("user-display-name",
"User", "User Display Name",
"The currently selected user account, or %NULL if no user is selected.", "The display name for the currently selected user account, or %NULL if no user is selected.",
ACT_TYPE_USER, NULL,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY); G_PARAM_EXPLICIT_NOTIFY);
@ -189,7 +218,16 @@ mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/restrict-applications-dialog.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/restrict-applications-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, selector); gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, selector);
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, description); gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, group);
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, search_entry);
gtk_widget_class_bind_template_callback (widget_class, search_entry_stop_search_cb);
gtk_widget_class_add_binding (widget_class,
GDK_KEY_f, GDK_CONTROL_MASK,
focus_search_cb,
NULL);
} }
static void static void
@ -199,25 +237,8 @@ mct_restrict_applications_dialog_init (MctRestrictApplicationsDialog *self)
g_type_ensure (MCT_TYPE_RESTRICT_APPLICATIONS_SELECTOR); g_type_ensure (MCT_TYPE_RESTRICT_APPLICATIONS_SELECTOR);
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
}
static const gchar * gtk_search_entry_set_key_capture_widget (self->search_entry, GTK_WIDGET (self));
get_user_display_name (ActUser *user)
{
const gchar *display_name;
g_return_val_if_fail (ACT_IS_USER (user), _("unknown"));
display_name = act_user_get_real_name (user);
if (display_name != NULL)
return display_name;
display_name = act_user_get_user_name (user);
if (display_name != NULL)
return display_name;
/* Translators: this is the full name for an unknown user account. */
return _("unknown");
} }
static void static void
@ -225,23 +246,42 @@ update_description (MctRestrictApplicationsDialog *self)
{ {
g_autofree gchar *description = NULL; g_autofree gchar *description = NULL;
if (self->user == NULL) if (self->user_display_name == NULL)
{ {
gtk_widget_hide (GTK_WIDGET (self->description)); adw_preferences_group_set_description (self->group, NULL);
return; return;
} }
/* Translators: the placeholder is a users full name */ /* Translators: the placeholder is a users full name */
description = g_strdup_printf (_("Allow %s to use the following installed applications."), description = g_strdup_printf (_("Restrict %s from using the following installed applications."),
get_user_display_name (self->user)); self->user_display_name);
gtk_label_set_text (self->description, description); adw_preferences_group_set_description (self->group, description);
gtk_widget_show (GTK_WIDGET (self->description)); }
static void
search_entry_stop_search_cb (GtkSearchEntry *search_entry,
gpointer user_data)
{
/* Clear the search text as the search filtering is bound to that. */
gtk_editable_set_text (GTK_EDITABLE (search_entry), "");
}
static gboolean
focus_search_cb (GtkWidget *widget,
GVariant *arguments,
gpointer user_data)
{
MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (widget);
gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
return TRUE;
} }
/** /**
* mct_restrict_applications_dialog_new: * mct_restrict_applications_dialog_new:
* @app_filter: (transfer none): the initial app filter configuration to show * @app_filter: (transfer none): the initial app filter configuration to show
* @user: (transfer none) (nullable): the user to show the app filter for * @user_display_name: (transfer none) (nullable): the display name of the user
* to show the app filter for, or %NULL if no user is selected
* *
* Create a new #MctRestrictApplicationsDialog widget. * Create a new #MctRestrictApplicationsDialog widget.
* *
@ -250,14 +290,16 @@ update_description (MctRestrictApplicationsDialog *self)
*/ */
MctRestrictApplicationsDialog * MctRestrictApplicationsDialog *
mct_restrict_applications_dialog_new (MctAppFilter *app_filter, mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
ActUser *user) const gchar *user_display_name)
{ {
g_return_val_if_fail (app_filter != NULL, NULL); g_return_val_if_fail (app_filter != NULL, NULL);
g_return_val_if_fail (user == NULL || ACT_IS_USER (user), NULL); g_return_val_if_fail (user_display_name == NULL ||
(*user_display_name != '\0' &&
g_utf8_validate (user_display_name, -1, NULL)), NULL);
return g_object_new (MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG, return g_object_new (MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG,
"app-filter", app_filter, "app-filter", app_filter,
"user", user, "user-display-name", user_display_name,
NULL); NULL);
} }
@ -318,45 +360,50 @@ mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *
} }
/** /**
* mct_restrict_applications_dialog_get_user: * mct_restrict_applications_dialog_get_user_display_name:
* @self: an #MctRestrictApplicationsDialog * @self: an #MctRestrictApplicationsDialog
* *
* Get the value of #MctRestrictApplicationsDialog:user. * Get the value of #MctRestrictApplicationsDialog:user-display-name.
* *
* Returns: (transfer none) (nullable): the user the dialog is configured for, * Returns: (transfer none) (nullable): the display name of the user the dialog
* or %NULL if unknown * is configured for, or %NULL if unknown
* Since: 0.5.0 * Since: 0.5.0
*/ */
ActUser * const gchar *
mct_restrict_applications_dialog_get_user (MctRestrictApplicationsDialog *self) mct_restrict_applications_dialog_get_user_display_name (MctRestrictApplicationsDialog *self)
{ {
g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL); g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL);
return self->user; return self->user_display_name;
} }
/** /**
* mct_restrict_applications_dialog_set_user: * mct_restrict_applications_dialog_set_user_display_name:
* @self: an #MctRestrictApplicationsDialog * @self: an #MctRestrictApplicationsDialog
* @user: (nullable) (transfer none): the user to configure the dialog for, * @user_display_name: (nullable) (transfer none): the display name of the user
* or %NULL if unknown * to configure the dialog for, or %NULL if unknown
* *
* Set the value of #MctRestrictApplicationsDialog:user. * Set the value of #MctRestrictApplicationsDialog:user-display-name.
* *
* Since: 0.5.0 * Since: 0.5.0
*/ */
void void
mct_restrict_applications_dialog_set_user (MctRestrictApplicationsDialog *self, mct_restrict_applications_dialog_set_user_display_name (MctRestrictApplicationsDialog *self,
ActUser *user) const gchar *user_display_name)
{ {
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self)); g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
g_return_if_fail (user == NULL || ACT_IS_USER (user)); g_return_if_fail (user_display_name == NULL ||
(*user_display_name != '\0' &&
g_utf8_validate (user_display_name, -1, NULL)));
if (g_strcmp0 (self->user_display_name, user_display_name) == 0)
return;
g_clear_pointer (&self->user_display_name, g_free);
self->user_display_name = g_strdup (user_display_name);
if (g_set_object (&self->user, user))
{
update_description (self); update_description (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_DISPLAY_NAME]);
}
} }
/** /**

View File

@ -21,28 +21,28 @@
#pragma once #pragma once
#include <act/act.h>
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <adwaita.h>
#include <libmalcontent/manager.h> #include <libmalcontent/manager.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG (mct_restrict_applications_dialog_get_type ()) #define MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG (mct_restrict_applications_dialog_get_type ())
G_DECLARE_FINAL_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, MCT, RESTRICT_APPLICATIONS_DIALOG, GtkDialog) G_DECLARE_FINAL_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, MCT, RESTRICT_APPLICATIONS_DIALOG, AdwPreferencesWindow)
MctRestrictApplicationsDialog *mct_restrict_applications_dialog_new (MctAppFilter *app_filter, MctRestrictApplicationsDialog *mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
ActUser *user); const gchar *user_display_name);
MctAppFilter *mct_restrict_applications_dialog_get_app_filter (MctRestrictApplicationsDialog *self); MctAppFilter *mct_restrict_applications_dialog_get_app_filter (MctRestrictApplicationsDialog *self);
void mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *self, void mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *self,
MctAppFilter *app_filter); MctAppFilter *app_filter);
ActUser *mct_restrict_applications_dialog_get_user (MctRestrictApplicationsDialog *self); const gchar *mct_restrict_applications_dialog_get_user_display_name (MctRestrictApplicationsDialog *self);
void mct_restrict_applications_dialog_set_user (MctRestrictApplicationsDialog *self, void mct_restrict_applications_dialog_set_user_display_name (MctRestrictApplicationsDialog *self,
ActUser *user); const gchar *user_display_name);
void mct_restrict_applications_dialog_build_app_filter (MctRestrictApplicationsDialog *self, void mct_restrict_applications_dialog_build_app_filter (MctRestrictApplicationsDialog *self,
MctAppFilterBuilder *builder); MctAppFilterBuilder *builder);

View File

@ -1,56 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright © 2020 Endless, Inc. --> <!-- Copyright © 2020 Endless, Inc. -->
<interface> <interface domain="malcontent">
<requires lib="gtk+" version="3.12"/> <requires lib="gtk+" version="3.12"/>
<template class="MctRestrictApplicationsDialog" parent="GtkDialog"> <template class="MctRestrictApplicationsDialog" parent="AdwPreferencesWindow">
<property name="title" translatable="yes">Restrict Applications</property> <property name="title" translatable="yes">Restrict Applications</property>
<property name="skip-taskbar-hint">True</property> <property name="default-width">500</property>
<property name="default-width">300</property>
<property name="default-height">500</property> <property name="default-height">500</property>
<child internal-child="headerbar"> <property name="search-enabled">False</property>
<object class="GtkHeaderBar"> <child>
<property name="title" translatable="yes">Restrict Applications</property> <object class="AdwPreferencesPage">
<property name="show-close-button">False</property> <child>
</object> <object class="AdwPreferencesGroup" id="group">
</child> <!-- Translated dynamically: -->
<child internal-child="vbox"> <property name="description">Restrict {username} from using the following installed applications.</property>
<child>
<object class="GtkBox"> <object class="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">True</property>
<property name="margin">18</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<child> <child>
<object class="GtkLabel" id="description"> <object class="GtkSearchEntry" id="search_entry">
<!-- Translated dynamically: --> <property name="placeholder-text" translatable="yes">Search for applications…</property>
<property name="label">Allow {username} to use the following installed applications.</property> <signal name="stop-search" handler="search_entry_stop_search_cb" />
<property name="visible">False</property>
<child internal-child="accessible">
<object class="AtkObject">
<property name="accessible-role">static</property>
</object>
</child>
</object> </object>
</child> </child>
<child> <child>
<object class="MctRestrictApplicationsSelector" id="selector"> <object class="MctRestrictApplicationsSelector" id="selector">
<property name="visible">True</property> <property name="search" bind-source="search_entry" bind-property="text" />
</object>
</child>
</object> </object>
<packing>
<property name="expand">True</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
<child type="action">
<object class="GtkButton" id="button_save">
<property name="can-default">True</property>
<property name="visible">True</property>
<property name="label" translatable="yes">_Save</property>
<property name="use-underline">True</property>
</object> </object>
</child> </child>
<action-widgets>
<action-widget response="apply" default="true">button_save</action-widget>
</action-widgets>
</template> </template>
</interface> </interface>

View File

@ -19,13 +19,16 @@
* - Philip Withnall <withnall@endlessm.com> * - Philip Withnall <withnall@endlessm.com>
*/ */
#include "config.h"
#include <flatpak.h> #include <flatpak.h>
#include <gio/gdesktopappinfo.h> #include <gio/gdesktopappinfo.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include <glib/gi18n.h> #include <glib/gi18n-lib.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <adwaita.h>
#include <libmalcontent/app-filter.h> #include <libmalcontent/app-filter.h>
#include "restrict-applications-selector.h" #include "restrict-applications-selector.h"
@ -38,6 +41,7 @@ static void app_info_changed_cb (GAppInfoMonitor *monitor,
static void reload_apps (MctRestrictApplicationsSelector *self); static void reload_apps (MctRestrictApplicationsSelector *self);
static GtkWidget *create_row_for_app_cb (gpointer item, static GtkWidget *create_row_for_app_cb (gpointer item,
gpointer user_data); gpointer user_data);
static char *app_info_dup_name (GAppInfo *app_info);
/** /**
* MctRestrictApplicationsSelector: * MctRestrictApplicationsSelector:
@ -51,6 +55,11 @@ static GtkWidget *create_row_for_app_cb (gpointer item,
* #MctAppFilterBuilder using * #MctAppFilterBuilder using
* mct_restrict_applications_selector_build_app_filter(). * mct_restrict_applications_selector_build_app_filter().
* *
* Search terms may be applied using #MctRestrictApplicationsSelector:search.
* These will filter the list of displayed apps so that only ones matching the
* search terms (by name, using UTF-8 normalisation and casefolding) will be
* displayed.
*
* Since: 0.5.0 * Since: 0.5.0
*/ */
struct _MctRestrictApplicationsSelector struct _MctRestrictApplicationsSelector
@ -59,15 +68,22 @@ struct _MctRestrictApplicationsSelector
GtkListBox *listbox; GtkListBox *listbox;
GListStore *apps; /* (owned) */ GList *cached_apps; /* (nullable) (owned) (element-type GAppInfo) */
GListStore *apps;
GtkFilterListModel *filtered_apps;
GtkStringFilter *search_filter;
GAppInfoMonitor *app_info_monitor; /* (owned) */ GAppInfoMonitor *app_info_monitor; /* (owned) */
gulong app_info_monitor_changed_id; gulong app_info_monitor_changed_id;
GHashTable *blacklisted_apps; /* (owned) (element-type GAppInfo) */ GHashTable *blocklisted_apps; /* (owned) (element-type GAppInfo) */
MctAppFilter *app_filter; /* (owned) */ MctAppFilter *app_filter; /* (owned) */
FlatpakInstallation *system_installation; /* (owned) */ FlatpakInstallation *system_installation; /* (owned) */
FlatpakInstallation *user_installation; /* (owned) */ FlatpakInstallation *user_installation; /* (owned) */
GtkCssProvider *css_provider; /* (owned) */
gchar *search; /* (nullable) (owned) */
}; };
G_DEFINE_TYPE (MctRestrictApplicationsSelector, mct_restrict_applications_selector, GTK_TYPE_BOX) G_DEFINE_TYPE (MctRestrictApplicationsSelector, mct_restrict_applications_selector, GTK_TYPE_BOX)
@ -75,9 +91,10 @@ G_DEFINE_TYPE (MctRestrictApplicationsSelector, mct_restrict_applications_select
typedef enum typedef enum
{ {
PROP_APP_FILTER = 1, PROP_APP_FILTER = 1,
PROP_SEARCH,
} MctRestrictApplicationsSelectorProperty; } MctRestrictApplicationsSelectorProperty;
static GParamSpec *properties[PROP_APP_FILTER + 1]; static GParamSpec *properties[PROP_SEARCH + 1];
enum { enum {
SIGNAL_CHANGED, SIGNAL_CHANGED,
@ -99,6 +116,9 @@ mct_restrict_applications_selector_constructed (GObject *obj)
g_assert (self->app_filter != NULL); g_assert (self->app_filter != NULL);
/* Load the apps. */
reload_apps (self);
G_OBJECT_CLASS (mct_restrict_applications_selector_parent_class)->constructed (obj); G_OBJECT_CLASS (mct_restrict_applications_selector_parent_class)->constructed (obj);
} }
@ -115,6 +135,9 @@ mct_restrict_applications_selector_get_property (GObject *object,
case PROP_APP_FILTER: case PROP_APP_FILTER:
g_value_set_boxed (value, self->app_filter); g_value_set_boxed (value, self->app_filter);
break; break;
case PROP_SEARCH:
g_value_set_string (value, self->search);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -134,6 +157,9 @@ mct_restrict_applications_selector_set_property (GObject *object,
case PROP_APP_FILTER: case PROP_APP_FILTER:
mct_restrict_applications_selector_set_app_filter (self, g_value_get_boxed (value)); mct_restrict_applications_selector_set_app_filter (self, g_value_get_boxed (value));
break; break;
case PROP_SEARCH:
mct_restrict_applications_selector_set_search (self, g_value_get_string (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -145,8 +171,8 @@ mct_restrict_applications_selector_dispose (GObject *object)
{ {
MctRestrictApplicationsSelector *self = (MctRestrictApplicationsSelector *)object; MctRestrictApplicationsSelector *self = (MctRestrictApplicationsSelector *)object;
g_clear_pointer (&self->blacklisted_apps, g_hash_table_unref); g_clear_pointer (&self->blocklisted_apps, g_hash_table_unref);
g_clear_object (&self->apps); g_clear_list (&self->cached_apps, g_object_unref);
if (self->app_info_monitor != NULL && self->app_info_monitor_changed_id != 0) if (self->app_info_monitor != NULL && self->app_info_monitor_changed_id != 0)
{ {
@ -157,6 +183,8 @@ mct_restrict_applications_selector_dispose (GObject *object)
g_clear_pointer (&self->app_filter, mct_app_filter_unref); g_clear_pointer (&self->app_filter, mct_app_filter_unref);
g_clear_object (&self->system_installation); g_clear_object (&self->system_installation);
g_clear_object (&self->user_installation); g_clear_object (&self->user_installation);
g_clear_object (&self->css_provider);
g_clear_pointer (&self->search, g_free);
G_OBJECT_CLASS (mct_restrict_applications_selector_parent_class)->dispose (object); G_OBJECT_CLASS (mct_restrict_applications_selector_parent_class)->dispose (object);
} }
@ -191,6 +219,23 @@ mct_restrict_applications_selector_class_init (MctRestrictApplicationsSelectorCl
G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY); G_PARAM_EXPLICIT_NOTIFY);
/**
* MctRestrictApplicationsSelector:search: (nullable)
*
* Search terms to filter the displayed list of apps by, or %NULL to not
* filter the search.
*
* Since: 0.12.0
*/
properties[PROP_SEARCH] =
g_param_spec_string ("search",
"Search",
"Search terms to filter the displayed list of apps by.",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties); g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
/** /**
@ -212,14 +257,18 @@ mct_restrict_applications_selector_class_init (MctRestrictApplicationsSelectorCl
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/restrict-applications-selector.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/restrict-applications-selector.ui");
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsSelector, listbox); gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsSelector, listbox);
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsSelector, apps);
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsSelector, filtered_apps);
gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsSelector, search_filter);
gtk_widget_class_bind_template_callback (widget_class, app_info_dup_name);
} }
static void static void
mct_restrict_applications_selector_init (MctRestrictApplicationsSelector *self) mct_restrict_applications_selector_init (MctRestrictApplicationsSelector *self)
{ {
gtk_widget_init_template (GTK_WIDGET (self));
self->apps = g_list_store_new (G_TYPE_APP_INFO); gtk_widget_init_template (GTK_WIDGET (self));
self->app_info_monitor = g_app_info_monitor_get (); self->app_info_monitor = g_app_info_monitor_get ();
self->app_info_monitor_changed_id = self->app_info_monitor_changed_id =
@ -227,18 +276,22 @@ mct_restrict_applications_selector_init (MctRestrictApplicationsSelector *self)
(GCallback) app_info_changed_cb, self); (GCallback) app_info_changed_cb, self);
gtk_list_box_bind_model (self->listbox, gtk_list_box_bind_model (self->listbox,
G_LIST_MODEL (self->apps), G_LIST_MODEL (self->filtered_apps),
create_row_for_app_cb, create_row_for_app_cb,
self, self,
NULL); NULL);
self->blacklisted_apps = g_hash_table_new_full (g_direct_hash, self->blocklisted_apps = g_hash_table_new_full (g_direct_hash,
g_direct_equal, g_direct_equal,
g_object_unref, g_object_unref,
NULL); NULL);
self->system_installation = flatpak_installation_new_system (NULL, NULL); self->system_installation = flatpak_installation_new_system (NULL, NULL);
self->user_installation = flatpak_installation_new_user (NULL, NULL); self->user_installation = flatpak_installation_new_user (NULL, NULL);
self->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (self->css_provider,
"/org/freedesktop/MalcontentUi/ui/restricts-switch.css");
} }
static void static void
@ -251,30 +304,45 @@ on_switch_active_changed_cb (GtkSwitch *s,
gboolean allowed; gboolean allowed;
app = g_object_get_data (G_OBJECT (s), "GAppInfo"); app = g_object_get_data (G_OBJECT (s), "GAppInfo");
allowed = gtk_switch_get_active (s); allowed = !gtk_switch_get_active (s);
if (allowed) if (allowed)
{ {
gboolean removed; gboolean removed;
g_debug ("Removing %s from blacklisted apps", g_app_info_get_id (app)); g_debug ("Removing %s from blocklisted apps", g_app_info_get_id (app));
removed = g_hash_table_remove (self->blacklisted_apps, app); removed = g_hash_table_remove (self->blocklisted_apps, app);
g_assert (removed); g_assert (removed);
} }
else else
{ {
gboolean added; gboolean added;
g_debug ("Blacklisting %s", g_app_info_get_id (app)); g_debug ("Blocklisting %s", g_app_info_get_id (app));
added = g_hash_table_add (self->blacklisted_apps, g_object_ref (app)); added = g_hash_table_add (self->blocklisted_apps, g_object_ref (app));
g_assert (added); g_assert (added);
} }
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
} }
static void
update_listbox_row_switch (MctRestrictApplicationsSelector *self,
GtkSwitch *w)
{
GAppInfo *app = g_object_get_data (G_OBJECT (w), "GAppInfo");
gboolean allowed = mct_app_filter_is_appinfo_allowed (self->app_filter, app);
gtk_switch_set_active (w, !allowed);
if (allowed)
g_hash_table_remove (self->blocklisted_apps, app);
else
g_hash_table_add (self->blocklisted_apps, g_object_ref (app));
}
static GtkWidget * static GtkWidget *
create_row_for_app_cb (gpointer item, create_row_for_app_cb (gpointer item,
gpointer user_data) gpointer user_data)
@ -282,10 +350,9 @@ create_row_for_app_cb (gpointer item,
MctRestrictApplicationsSelector *self = MCT_RESTRICT_APPLICATIONS_SELECTOR (user_data); MctRestrictApplicationsSelector *self = MCT_RESTRICT_APPLICATIONS_SELECTOR (user_data);
GAppInfo *app = G_APP_INFO (item); GAppInfo *app = G_APP_INFO (item);
g_autoptr(GIcon) icon = NULL; g_autoptr(GIcon) icon = NULL;
GtkWidget *box, *w; GtkWidget *row, *w;
gboolean allowed;
const gchar *app_name; const gchar *app_name;
gint size; GtkStyleContext *context;
app_name = g_app_info_get_name (app); app_name = g_app_info_get_name (app);
@ -297,46 +364,43 @@ create_row_for_app_cb (gpointer item,
else else
g_object_ref (icon); g_object_ref (icon);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); row = adw_action_row_new ();
gtk_container_set_border_width (GTK_CONTAINER (box), 12);
gtk_widget_set_margin_end (box, 12);
/* Icon */ /* Icon */
w = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG); w = gtk_image_new_from_gicon (icon);
gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &size, NULL); gtk_image_set_icon_size (GTK_IMAGE (w), GTK_ICON_SIZE_LARGE);
gtk_image_set_pixel_size (GTK_IMAGE (w), size); adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
gtk_container_add (GTK_CONTAINER (box), w);
/* App name label */ /* App name label */
w = g_object_new (GTK_TYPE_LABEL, adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), app_name);
"label", app_name,
"hexpand", TRUE,
"xalign", 0.0,
NULL);
gtk_container_add (GTK_CONTAINER (box), w);
/* Switch */ /* Switch */
w = g_object_new (GTK_TYPE_SWITCH, w = g_object_new (GTK_TYPE_SWITCH,
"valign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (box), w); context = gtk_widget_get_style_context (w);
gtk_style_context_add_class (context, "restricts");
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (self->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1);
adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
adw_action_row_set_activatable_widget (ADW_ACTION_ROW (row), w);
gtk_widget_show_all (box); gtk_widget_set_focusable (GTK_WIDGET (row), FALSE);
/* Fetch status from AccountService */ /* Fetch status from AccountService */
allowed = mct_app_filter_is_appinfo_allowed (self->app_filter, app); g_object_set_data (G_OBJECT (row), "GtkSwitch", w);
gtk_switch_set_active (GTK_SWITCH (w), allowed);
g_object_set_data_full (G_OBJECT (w), "GAppInfo", g_object_ref (app), g_object_unref); g_object_set_data_full (G_OBJECT (w), "GAppInfo", g_object_ref (app), g_object_unref);
update_listbox_row_switch (self, GTK_SWITCH (w));
if (allowed)
g_hash_table_remove (self->blacklisted_apps, app);
else
g_hash_table_add (self->blacklisted_apps, g_object_ref (app));
g_signal_connect (w, "notify::active", G_CALLBACK (on_switch_active_changed_cb), self); g_signal_connect (w, "notify::active", G_CALLBACK (on_switch_active_changed_cb), self);
return box; return row;
}
static char *
app_info_dup_name (GAppInfo *app_info)
{
return g_strdup (g_app_info_get_name (app_info));
} }
static gint static gint
@ -347,8 +411,8 @@ compare_app_info_cb (gconstpointer a,
GAppInfo *app_a = (GAppInfo*) a; GAppInfo *app_a = (GAppInfo*) a;
GAppInfo *app_b = (GAppInfo*) b; GAppInfo *app_b = (GAppInfo*) b;
return g_utf8_collate (g_app_info_get_display_name (app_a), return g_utf8_collate (g_app_info_get_name (app_a),
g_app_info_get_display_name (app_b)); g_app_info_get_name (app_b));
} }
static gint static gint
@ -357,6 +421,7 @@ app_compare_id_length_cb (gconstpointer a,
{ {
GAppInfo *info_a = (GAppInfo *) a, *info_b = (GAppInfo *) b; GAppInfo *info_a = (GAppInfo *) a, *info_b = (GAppInfo *) b;
const gchar *id_a, *id_b; const gchar *id_a, *id_b;
gsize id_a_len, id_b_len;
id_a = g_app_info_get_id (info_a); id_a = g_app_info_get_id (info_a);
id_b = g_app_info_get_id (info_b); id_b = g_app_info_get_id (info_b);
@ -368,17 +433,76 @@ app_compare_id_length_cb (gconstpointer a,
else if (id_b == NULL) else if (id_b == NULL)
return 1; return 1;
return strlen (id_a) - strlen (id_b); id_a_len = strlen (id_a);
id_b_len = strlen (id_b);
if (id_a_len == id_b_len)
return strcmp (id_a, id_b);
else
return id_a_len - id_b_len;
} }
/* Elements in @added_out and @removed_out are valid as long as @old_apps and
* @new_apps are valid.
*
* Both lists have to be sorted the same before calling this function. */
static void
diff_app_lists (GList *old_apps,
GList *new_apps,
GPtrArray **added_out,
GPtrArray **removed_out)
{
g_autoptr(GPtrArray) added = g_ptr_array_new_with_free_func (NULL);
g_autoptr(GPtrArray) removed = g_ptr_array_new_with_free_func (NULL);
GList *o, *n;
g_return_if_fail (added_out != NULL);
g_return_if_fail (removed_out != NULL);
for (o = old_apps, n = new_apps; o != NULL || n != NULL;)
{
int comparison;
if (o == NULL)
comparison = 1;
else if (n == NULL)
comparison = -1;
else
comparison = app_compare_id_length_cb (o->data, n->data);
if (comparison < 0)
{
g_ptr_array_add (removed, o->data);
o = o->next;
}
else if (comparison > 0)
{
g_ptr_array_add (added, n->data);
n = n->next;
}
else
{
o = o->next;
n = n->next;
}
}
*added_out = g_steal_pointer (&added);
*removed_out = g_steal_pointer (&removed);
}
/* This is quite expensive to call, as theres no way to avoid calling
* g_app_info_get_all() to see if anythings changed; and thats quite expensive. */
static void static void
reload_apps (MctRestrictApplicationsSelector *self) reload_apps (MctRestrictApplicationsSelector *self)
{ {
GList *iter, *apps; g_autolist(GAppInfo) old_apps = NULL;
g_autolist(GAppInfo) new_apps = NULL;
g_autoptr(GPtrArray) added_apps = NULL, removed_apps = NULL;
g_autoptr(GHashTable) seen_flatpak_ids = NULL; g_autoptr(GHashTable) seen_flatpak_ids = NULL;
g_autoptr(GHashTable) seen_executables = NULL; g_autoptr(GHashTable) seen_executables = NULL;
apps = g_app_info_get_all (); old_apps = g_steal_pointer (&self->cached_apps);
new_apps = g_app_info_get_all ();
/* Sort the apps by increasing length of #GAppInfo ID. When coupled with the /* Sort the apps by increasing length of #GAppInfo ID. When coupled with the
* deduplication of flatpak IDs and executable paths, below, this should ensure that we * deduplication of flatpak IDs and executable paths, below, this should ensure that we
@ -387,20 +511,46 @@ reload_apps (MctRestrictApplicationsSelector *self)
* *
* This is designed to avoid listing all the components of LibreOffice for example, * This is designed to avoid listing all the components of LibreOffice for example,
* which all share an app ID and hence have the same entry in the parental controls * which all share an app ID and hence have the same entry in the parental controls
* app filter. */ * app filter.
apps = g_list_sort (apps, app_compare_id_length_cb); *
* Then diff the old and new lists so that the code below doesnt end up
* removing more rows than are necessary, and hence potentially losing
* in-progress user input. */
new_apps = g_list_sort (new_apps, app_compare_id_length_cb);
diff_app_lists (old_apps, new_apps, &added_apps, &removed_apps);
g_debug ("%s: Diffed old and new app lists: %u apps added, %u apps removed",
G_STRFUNC, added_apps->len, removed_apps->len);
seen_flatpak_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); seen_flatpak_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
seen_executables = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); seen_executables = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_list_store_remove_all (self->apps); /* Remove items first. */
for (guint i = 0; i < removed_apps->len; i++)
for (iter = apps; iter; iter = iter->next)
{ {
GAppInfo *app; GAppInfo *app = removed_apps->pdata[i];
guint pos;
gboolean found;
found = g_list_store_find_with_equal_func (self->apps, app,
(GEqualFunc) g_app_info_equal, &pos);
/* The app being removed may have not passed the condition checks below
* to have been added to self->apps. */
if (!found)
continue;
g_debug ("Removing app %s", g_app_info_get_id (app));
g_list_store_remove (self->apps, pos);
}
/* Now add the new items. */
for (guint i = 0; i < added_apps->len; i++)
{
GAppInfo *app = added_apps->pdata[i];
const gchar *app_name; const gchar *app_name;
const gchar * const *supported_types; const gchar * const *supported_types;
app = iter->data;
app_name = g_app_info_get_name (app); app_name = g_app_info_get_name (app);
supported_types = g_app_info_get_supported_types (app); supported_types = g_app_info_get_supported_types (app);
@ -408,11 +558,9 @@ reload_apps (MctRestrictApplicationsSelector *self)
if (!G_IS_DESKTOP_APP_INFO (app) || if (!G_IS_DESKTOP_APP_INFO (app) ||
!g_app_info_should_show (app) || !g_app_info_should_show (app) ||
app_name[0] == '\0' || app_name[0] == '\0' ||
/* Endless' link apps have the "eos-link" prefix, and should be ignored too */
g_str_has_prefix (g_app_info_get_id (app), "eos-link") ||
/* FIXME: Only list flatpak apps and apps with X-Parental-Controls /* FIXME: Only list flatpak apps and apps with X-Parental-Controls
* key set for now; we really need a system-wide MAC to be able to * key set for now; we really need a system-wide MAC to be able to
* reliably support blacklisting system programs. */ * reliably support blocklisting system programs. */
(!g_desktop_app_info_has_key (G_DESKTOP_APP_INFO (app), "X-Flatpak") && (!g_desktop_app_info_has_key (G_DESKTOP_APP_INFO (app), "X-Flatpak") &&
!g_desktop_app_info_has_key (G_DESKTOP_APP_INFO (app), "X-Parental-Controls")) || !g_desktop_app_info_has_key (G_DESKTOP_APP_INFO (app), "X-Parental-Controls")) ||
/* Web browsers are special cased */ /* Web browsers are special cased */
@ -471,21 +619,17 @@ reload_apps (MctRestrictApplicationsSelector *self)
self); self);
} }
g_list_free_full (apps, g_object_unref); /* Update the cache for next time. */
self->cached_apps = g_steal_pointer (&new_apps);
} }
static void static void
app_info_changed_cb (GAppInfoMonitor *monitor, app_info_changed_cb (GAppInfoMonitor *monitor,
gpointer user_data) gpointer user_data)
{ {
/* FIXME: We should update the list of apps here, but we cant call
* reload_apps() because that will dump and reload the entire list, losing
* any changes the user has already made to the set of switches. We need
* something more fine-grained.
MctRestrictApplicationsSelector *self = MCT_RESTRICT_APPLICATIONS_SELECTOR (user_data); MctRestrictApplicationsSelector *self = MCT_RESTRICT_APPLICATIONS_SELECTOR (user_data);
reload_apps (self); reload_apps (self);
*/
} }
/* Will return %NULL if @flatpak_id is not installed. */ /* Will return %NULL if @flatpak_id is not installed. */
@ -572,7 +716,7 @@ mct_restrict_applications_selector_build_app_filter (MctRestrictApplicationsSele
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self)); g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self));
g_return_if_fail (builder != NULL); g_return_if_fail (builder != NULL);
g_hash_table_iter_init (&iter, self->blacklisted_apps); g_hash_table_iter_init (&iter, self->blocklisted_apps);
while (g_hash_table_iter_next (&iter, (gpointer) &app, NULL)) while (g_hash_table_iter_next (&iter, (gpointer) &app, NULL))
{ {
g_autofree gchar *flatpak_id = NULL; g_autofree gchar *flatpak_id = NULL;
@ -587,12 +731,12 @@ mct_restrict_applications_selector_build_app_filter (MctRestrictApplicationsSele
if (!flatpak_ref) if (!flatpak_ref)
{ {
g_warning ("Skipping blacklisting Flatpak ID %s due to it not being installed", flatpak_id); g_warning ("Skipping blocklisting Flatpak ID %s due to it not being installed", flatpak_id);
continue; continue;
} }
g_debug ("\t\t → Blacklisting Flatpak ref: %s", flatpak_ref); g_debug ("\t\t → Blocklisting Flatpak ref: %s", flatpak_ref);
mct_app_filter_builder_blacklist_flatpak_ref (builder, flatpak_ref); mct_app_filter_builder_blocklist_flatpak_ref (builder, flatpak_ref);
} }
else else
{ {
@ -601,12 +745,12 @@ mct_restrict_applications_selector_build_app_filter (MctRestrictApplicationsSele
if (!path) if (!path)
{ {
g_warning ("Skipping blacklisting executable %s due to it not being found", executable); g_warning ("Skipping blocklisting executable %s due to it not being found", executable);
continue; continue;
} }
g_debug ("\t\t → Blacklisting path: %s", path); g_debug ("\t\t → Blocklisting path: %s", path);
mct_app_filter_builder_blacklist_path (builder, path); mct_app_filter_builder_blocklist_path (builder, path);
} }
} }
} }
@ -648,6 +792,7 @@ mct_restrict_applications_selector_set_app_filter (MctRestrictApplicationsSelect
MctAppFilter *app_filter) MctAppFilter *app_filter)
{ {
g_autoptr(MctAppFilter) owned_app_filter = NULL; g_autoptr(MctAppFilter) owned_app_filter = NULL;
guint n_apps;
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self)); g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self));
@ -665,6 +810,70 @@ mct_restrict_applications_selector_set_app_filter (MctRestrictApplicationsSelect
g_clear_pointer (&self->app_filter, mct_app_filter_unref); g_clear_pointer (&self->app_filter, mct_app_filter_unref);
self->app_filter = mct_app_filter_ref (app_filter); self->app_filter = mct_app_filter_ref (app_filter);
reload_apps (self); /* Update the status of each app row. */
n_apps = g_list_model_get_n_items (G_LIST_MODEL (self->filtered_apps));
for (guint i = 0; i < n_apps; i++)
{
GtkListBoxRow *row;
GtkWidget *w;
/* Navigate the widget hierarchy set up in create_row_for_app_cb(). */
row = gtk_list_box_get_row_at_index (self->listbox, i);
g_assert (row != NULL && GTK_IS_LIST_BOX_ROW (row));
w = g_object_get_data (G_OBJECT (row), "GtkSwitch");
g_assert (w != NULL && GTK_IS_SWITCH (w));
update_listbox_row_switch (self, GTK_SWITCH (w));
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APP_FILTER]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APP_FILTER]);
} }
/**
* mct_restrict_applications_selector_get_search:
* @self: an #MctRestrictApplicationsSelector
*
* Get the value of #MctRestrictApplicationsSelector:search.
*
* Returns: current search terms, or %NULL if no search filtering is active
* Since: 0.12.0
*/
const gchar *
mct_restrict_applications_selector_get_search (MctRestrictApplicationsSelector *self)
{
g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self), NULL);
return self->search;
}
/**
* mct_restrict_applications_selector_set_search:
* @self: an #MctRestrictApplicationsSelector
* @search: (nullable): search terms, or %NULL to not filter the app list
*
* Set the value of #MctRestrictApplicationsSelector:search, or clear it to
* %NULL.
*
* Since: 0.12.0
*/
void
mct_restrict_applications_selector_set_search (MctRestrictApplicationsSelector *self,
const gchar *search)
{
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_SELECTOR (self));
/* Squash empty search terms down to nothing. */
if (search != NULL && *search == '\0')
search = NULL;
if (g_strcmp0 (search, self->search) == 0)
return;
g_clear_pointer (&self->search, g_free);
self->search = g_strdup (search);
gtk_string_filter_set_search (self->search_filter, self->search);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SEARCH]);
}

View File

@ -21,7 +21,6 @@
#pragma once #pragma once
#include <act/act.h>
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
@ -42,4 +41,8 @@ void mct_restrict_applications_selector_set_app_filter (MctRestrictAppl
void mct_restrict_applications_selector_build_app_filter (MctRestrictApplicationsSelector *self, void mct_restrict_applications_selector_build_app_filter (MctRestrictApplicationsSelector *self,
MctAppFilterBuilder *builder); MctAppFilterBuilder *builder);
const gchar *mct_restrict_applications_selector_get_search (MctRestrictApplicationsSelector *self);
void mct_restrict_applications_selector_set_search (MctRestrictApplicationsSelector *self,
const gchar *search);
G_END_DECLS G_END_DECLS

View File

@ -1,32 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright © 2020 Endless, Inc. --> <!-- Copyright © 2020 Endless, Inc. -->
<interface> <interface domain="malcontent">
<requires lib="gtk+" version="3.12"/> <requires lib="gtk+" version="3.12"/>
<template class="MctRestrictApplicationsSelector" parent="GtkBox"> <template class="MctRestrictApplicationsSelector" parent="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="hscrollbar-policy">never</property>
<property name="min-content-height">100</property>
<property name="max-content-height">400</property>
<property name="propagate-natural-height">True</property>
<property name="shadow-type">etched-in</property>
<child> <child>
<object class="GtkListBox" id="listbox"> <object class="GtkListBox" id="listbox">
<property name="visible">True</property> <property name="hexpand">True</property>
<property name="selection-mode">none</property> <property name="selection-mode">none</property>
<child type="placeholder"> <child type="placeholder">
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">No applications found to restrict.</property> <property name="label" translatable="yes">No applications found to restrict.</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
</object> </object>
</child> </child>
</object>
</child> <style>
<class name="content"/>
</style>
</object> </object>
</child> </child>
</template> </template>
<object class="GListStore" id="apps">
<property name="item-type">GAppInfo</property>
</object>
<object class="GtkFilterListModel" id="filtered_apps">
<property name="model">apps</property>
<property name="filter">search_filter</property>
</object>
<object class="GtkStringFilter" id="search_filter">
<property name="expression">
<closure type="gchararray" function="app_info_dup_name" />
</property>
</object>
</interface> </interface>

View File

@ -0,0 +1,18 @@
/* FIXME: This negative variant of a GtkSwitch should probably be
* upstreamed to GTK. See https://gitlab.gnome.org/GNOME/gtk/issues/2470 */
switch:checked.restricts {
background-color: @yellow_5;
}
switch:checked.restricts, switch:checked.restricts slider {
border-color: @yellow_3;
}
switch:disabled.restricts {
border-color: @borders;
background-color: @insensitive_bg_color;
}
switch:disabled.restricts slider {
filter: grayscale(100%);
}

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,18 @@
#pragma once #pragma once
#include <act/act.h> #include <act/act.h>
#include <gio/gio.h>
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <adwaita.h>
#include <libmalcontent/malcontent.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define MCT_TYPE_USER_CONTROLS (mct_user_controls_get_type()) #define MCT_TYPE_USER_CONTROLS (mct_user_controls_get_type())
G_DECLARE_FINAL_TYPE (MctUserControls, mct_user_controls, MCT, USER_CONTROLS, GtkGrid) G_DECLARE_FINAL_TYPE (MctUserControls, mct_user_controls, MCT, USER_CONTROLS, AdwBin)
ActUser *mct_user_controls_get_user (MctUserControls *self); ActUser *mct_user_controls_get_user (MctUserControls *self);
void mct_user_controls_set_user (MctUserControls *self, void mct_user_controls_set_user (MctUserControls *self,
@ -39,4 +44,26 @@ GPermission *mct_user_controls_get_permission (MctUserControls *self);
void mct_user_controls_set_permission (MctUserControls *self, void mct_user_controls_set_permission (MctUserControls *self,
GPermission *permission); GPermission *permission);
MctAppFilter *mct_user_controls_get_app_filter (MctUserControls *self);
void mct_user_controls_set_app_filter (MctUserControls *self,
MctAppFilter *app_filter);
ActUserAccountType mct_user_controls_get_user_account_type (MctUserControls *self);
void mct_user_controls_set_user_account_type (MctUserControls *self,
ActUserAccountType user_account_type);
const gchar *mct_user_controls_get_user_locale (MctUserControls *self);
void mct_user_controls_set_user_locale (MctUserControls *self,
const gchar *user_locale);
const gchar *mct_user_controls_get_user_display_name (MctUserControls *self);
void mct_user_controls_set_user_display_name (MctUserControls *self,
const gchar *user_display_name);
void mct_user_controls_set_description (MctUserControls *self,
const gchar *description);
void mct_user_controls_build_app_filter (MctUserControls *self,
MctAppFilterBuilder *builder);
G_END_DECLS G_END_DECLS

View File

@ -1,535 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright © 2018, 2019, 2020 Endless, Inc. --> <!-- Copyright © 2018, 2019, 2020 Endless, Inc. -->
<interface> <interface domain="malcontent">
<requires lib="gtk+" version="3.12"/> <requires lib="gtk+" version="3.12"/>
<template class="MctUserControls" parent="GtkGrid"> <template class="MctUserControls" parent="AdwBin">
<property name="visible">True</property> <child>
<property name="margin-top">18</property> <object class="GtkBox">
<property name="row-spacing">6</property> <property name="spacing">24</property>
<property name="column-spacing">12</property> <property name="orientation">vertical</property>
<property name="valign">start</property> <child>
<object class="AdwPreferencesGroup">
<child>
<object class="GtkLabel" id="description_label">
<property name="wrap">True</property>
<property name="xalign">0.0</property>
<property name="yalign">0.0</property>
</object>
</child>
</object>
</child>
<!-- Application Usage Restrictions --> <!-- Application Usage Restrictions -->
<child> <child>
<object class="GtkLabel"> <object class="AdwPreferencesGroup">
<property name="visible">True</property> <property name="title" translatable="yes">Application Usage Restrictions</property>
<property name="xalign">0.0</property> <child>
<property name="label" translatable="yes">Application Usage Restrictions</property> <object class="AdwActionRow" id="restrict_web_browsers_row">
<attributes> <property name="title" translatable="yes">Restrict _Web Browsers</property>
<attribute name="weight" value="bold" /> <property name="use_underline">True</property>
</attributes> <property name="activatable_widget">restrict_web_browsers_switch</property>
<!-- Set dynamically from user-controls.c: -->
<property name="subtitle">Prevents {username} from running web browsers. Limited web content may still be available in other applications.</property>
<property name="subtitle_lines">0</property>
<property name="focusable">False</property>
<child>
<object class="GtkSwitch" id="restrict_web_browsers_switch">
<property name="halign">end</property>
<property name="valign">center</property>
<signal name="notify::active" handler="on_restrict_web_browsers_switch_active_changed_cb" object="MctUserControls" swapped="no" />
<style>
<class name="restricts" />
</style>
</object>
</child>
</object> </object>
<packing>
<property name="top-attach">0</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkFrame"> <object class="AdwActionRow" id="restrict_applications_row">
<property name="visible">True</property> <property name="activatable">True</property>
<property name="can_focus">False</property> <property name="title" translatable="yes">_Restrict Applications</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="selection_mode">none</property>
<property name="activate_on_single_click">False</property>
<child>
<object class="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin-left">12</property>
<property name="margin-right">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel" id="allow_web_browsers_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Allow _Web Browsers</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="mnemonic_widget">allow_web_browsers_switch</property> <!-- Set dynamically from user-controls.c: -->
<accessibility> <property name="subtitle">Prevents specified applications from being used by {username}.</property>
<relation target="allow_web_browsers_switch" type="label-for"/> <property name="subtitle_lines">0</property>
</accessibility> <property name="action-name">permissions.restrict-applications</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="allow_web_browsers_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Prevents the user from running web browsers, but limited web content may still be available in other applications</property>
<attributes>
<attribute name="scale" value="0.88"/>
</attributes>
<style>
<class name="dim-label" />
</style>
<accessibility>
<relation target="allow_web_browsers_switch" type="description-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="allow_web_browsers_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<signal name="notify::active" handler="on_allow_web_browsers_switch_active_changed_cb" object="MctUserControls" swapped="no" />
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin-left">12</property>
<property name="margin-right">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel" id="restrict_applications_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Restrict Applications</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">restrict_applications_button</property>
<accessibility>
<relation target="restrict_applications_button" type="label-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="restrict_applications_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Prevents particular applications from being used</property>
<attributes>
<attribute name="scale" value="0.88"/>
</attributes>
<style>
<class name="dim-label" />
</style>
<accessibility>
<relation target="restrict_applications_button" type="description-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="restrict_applications_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_restrict_applications_button_clicked_cb" object="MctUserControls" swapped="no" />
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="icon-name">go-next-symbolic</property>
<property name="icon-name">pan-end-symbolic</property>
<property name="icon-size">4</property><!-- GTK_ICON_SIZE_BUTTON -->
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
<style>
<class name="content"/>
</style>
</object> </object>
</child> </child>
</object>
<packing>
<property name="top-attach">1</property>
<property name="left-attach">0</property>
</packing>
</child>
<!-- Software Installation Restrictions --> <!-- Software Installation Restrictions -->
<child> <child>
<object class="GtkLabel"> <object class="AdwPreferencesGroup">
<property name="visible">True</property> <property name="title" translatable="yes">Software Installation Restrictions</property>
<property name="margin-top">12</property>
<property name="xalign">0.0</property>
<property name="label" translatable="yes">Software Installation Restrictions</property>
<attributes>
<attribute name="weight" value="bold" />
</attributes>
</object>
<packing>
<property name="top-attach">2</property>
<property name="left-attach">0</property>
</packing>
</child>
<child> <child>
<object class="GtkFrame"> <object class="AdwActionRow" id="restrict_software_installation_row">
<property name="visible">True</property> <property name="visible" bind-source="restrict_software_installation_switch" bind-property="visible" bind-flags="default|sync-create" />
<property name="can_focus">False</property> <property name="title" translatable="yes">Restrict Application _Installation</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="selection_mode">none</property>
<property name="activate_on_single_click">False</property>
<child>
<object class="GtkListBoxRow">
<property name="visible" bind-source="allow_user_installation_switch" bind-property="visible" bind-flags="default|sync-create" />
<property name="can_focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin-left">12</property>
<property name="margin-right">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel" id="allow_user_installation_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Application _Installation</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="mnemonic_widget">allow_user_installation_switch</property> <property name="activatable_widget">restrict_software_installation_switch</property>
<accessibility> <!-- Set dynamically from user-controls.c: -->
<relation target="allow_user_installation_switch" type="label-for"/> <property name="subtitle">Prevents {username} from installing applications.</property>
</accessibility> <property name="subtitle_lines">0</property>
</object> <property name="focusable">False</property>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="allow_user_installation_description"> <object class="GtkSwitch" id="restrict_software_installation_switch">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Restricts the user from installing applications</property>
<attributes>
<attribute name="scale" value="0.88"/>
</attributes>
<style>
<class name="dim-label" />
</style>
<accessibility>
<relation target="allow_user_installation_switch" type="description-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="allow_user_installation_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">center</property> <property name="valign">center</property>
<signal name="notify::active" handler="on_allow_installation_switch_active_changed_cb" object="MctUserControls" swapped="no" /> <signal name="notify::active" handler="on_restrict_installation_switch_active_changed_cb" object="MctUserControls" swapped="no" />
</object> <style>
<packing> <class name="restricts" />
<property name="left-attach">1</property> </style>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkListBoxRow"> <object class="AdwActionRow">
<property name="visible" bind-source="allow_system_installation_switch" bind-property="visible" bind-flags="default|sync-create" /> <property name="title" translatable="yes">Application _Suitability</property>
<property name="can_focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin-left">12</property>
<property name="margin-right">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel" id="allow_system_installation_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Application Installation for _Others</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="mnemonic_widget">allow_system_installation_switch</property> <property name="activatable_widget">oars_button</property>
<accessibility> <property name="subtitle" translatable="yes">Restricts the browsing or installation of applications unsuitable for this age or younger.</property>
<relation target="allow_system_installation_switch" type="label-for"/> <property name="subtitle_lines">0</property>
</accessibility> <property name="focusable">False</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="allow_system_installation_description"> <object class="GtkMenuButton" id="oars_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Restricts the user from installing applications for all users</property>
<attributes>
<attribute name="scale" value="0.88"/>
</attributes>
<style>
<class name="dim-label" />
</style>
<accessibility>
<relation target="allow_system_installation_switch" type="description-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="allow_system_installation_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">center</property> <property name="valign">center</property>
<signal name="notify::active" handler="on_allow_installation_switch_active_changed_cb" object="MctUserControls" swapped="no" /> <property name="popover">oars_popover</property>
</object> <property name="always-show-arrow">True</property>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
<child>
<object class="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin-left">12</property>
<property name="margin-right">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel" id="restriction_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Application _Suitability</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">restriction_button</property>
<accessibility>
<relation target="restriction_button" type="label-for"/>
<relation target="restriction_button" type="flows-to"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="restriction_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Restricts the applications the user can browse or install to those suitable for certain ages</property>
<attributes>
<attribute name="scale" value="0.88"/>
</attributes>
<style> <style>
<class name="dim-label" /> <class name="content"/>
</style> </style>
<accessibility>
<relation target="restriction_button" type="description-for"/>
</accessibility>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkMenuButton" id="restriction_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="popover">restriction_popover</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object>
</child>
</object>
<packing>
<property name="top-attach">3</property>
<property name="left-attach">0</property>
</packing>
</child>
</template> </template>
<object class="GtkPopoverMenu" id="restriction_popover"> <object class="GtkPopoverMenu" id="oars_popover" />
<accessibility>
<relation target="restriction_button" type="popup-for"/>
</accessibility>
</object>
<menu id="age_menu" /> <menu id="age_menu" />
<object class="GtkSizeGroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="restriction_button" />
<widget name="restriction_popover" />
</widgets>
</object>
<object class="GtkSizeGroup">
<property name="mode">horizontal</property>
<widgets>
<widget name="allow_web_browsers_label" />
<widget name="allow_web_browsers_description" />
<widget name="restrict_applications_label" />
<widget name="restrict_applications_description" />
<widget name="restriction_label" />
<widget name="allow_user_installation_label" />
<widget name="allow_system_installation_label" />
</widgets>
</object>
<object class="MctRestrictApplicationsDialog" id="restrict_applications_dialog"> <object class="MctRestrictApplicationsDialog" id="restrict_applications_dialog">
<property name="visible">False</property> <property name="visible">False</property>
<property name="modal">True</property> <property name="modal">True</property>
<property name="destroy-with-parent">False</property> <property name="destroy-with-parent">False</property>
<property name="use-header-bar">1</property> <signal name="close-request" handler="on_restrict_applications_dialog_close_request_cb" />
<signal name="delete-event" handler="on_restrict_applications_dialog_delete_event_cb" />
<signal name="response" handler="on_restrict_applications_dialog_response_cb" />
</object> </object>
</interface> </interface>

View File

@ -31,9 +31,9 @@ G_BEGIN_DECLS
/** /**
* MctAppFilterListType: * MctAppFilterListType:
* @MCT_APP_FILTER_LIST_BLACKLIST: Any program in the list is not allowed to * @MCT_APP_FILTER_LIST_BLOCKLIST: Any program in the list is not allowed to
* be run. * be run.
* @MCT_APP_FILTER_LIST_WHITELIST: Any program not in the list is not allowed * @MCT_APP_FILTER_LIST_ALLOWLIST: Any program not in the list is not allowed
* to be run. * to be run.
* *
* Different semantics for interpreting an application list. * Different semantics for interpreting an application list.
@ -42,17 +42,18 @@ G_BEGIN_DECLS
*/ */
typedef enum typedef enum
{ {
MCT_APP_FILTER_LIST_BLACKLIST, MCT_APP_FILTER_LIST_BLOCKLIST,
MCT_APP_FILTER_LIST_WHITELIST, MCT_APP_FILTER_LIST_ALLOWLIST,
} MctAppFilterListType; } MctAppFilterListType;
struct _MctAppFilter struct _MctAppFilter
{ {
/*< private >*/
gint ref_count; gint ref_count;
uid_t user_id; uid_t user_id;
gchar **app_list; /* (owned) (array zero-terminated=1) */ gchar **app_list; /* (not nullable) (owned) (array zero-terminated=1) */
MctAppFilterListType app_list_type; MctAppFilterListType app_list_type;
GVariant *oars_ratings; /* (type a{ss}) (owned non-floating) */ GVariant *oars_ratings; /* (type a{ss}) (owned non-floating) */

View File

@ -96,7 +96,7 @@ mct_app_filter_unref (MctAppFilter *filter)
* *
* Get the user ID of the user this #MctAppFilter is for. * Get the user ID of the user this #MctAppFilter is for.
* *
* Returns: user ID of the relevant user * Returns: user ID of the relevant user, or `(uid_t) -1` if unknown
* Since: 0.2.0 * Since: 0.2.0
*/ */
uid_t uid_t
@ -108,6 +108,69 @@ mct_app_filter_get_user_id (MctAppFilter *filter)
return filter->user_id; return filter->user_id;
} }
static MctAppFilterOarsValue
oars_str_to_enum (const gchar *value_str)
{
if (g_str_equal (value_str, "none"))
return MCT_APP_FILTER_OARS_VALUE_NONE;
else if (g_str_equal (value_str, "mild"))
return MCT_APP_FILTER_OARS_VALUE_MILD;
else if (g_str_equal (value_str, "moderate"))
return MCT_APP_FILTER_OARS_VALUE_MODERATE;
else if (g_str_equal (value_str, "intense"))
return MCT_APP_FILTER_OARS_VALUE_INTENSE;
else
return MCT_APP_FILTER_OARS_VALUE_UNKNOWN;
}
/**
* mct_app_filter_is_enabled:
* @filter: an #MctAppFilter
*
* Check whether the app filter is enabled and is going to impose at least one
* restriction on the user. This gives a high level view of whether app filter
* parental controls are enabled for the given user.
*
* Returns: %TRUE if the app filter contains at least one non-default value,
* %FALSE if its entirely default
* Since: 0.7.0
*/
gboolean
mct_app_filter_is_enabled (MctAppFilter *filter)
{
gboolean oars_ratings_all_intense_or_unknown;
GVariantIter iter;
const gchar *oars_value;
g_return_val_if_fail (filter != NULL, FALSE);
g_return_val_if_fail (filter->ref_count >= 1, FALSE);
/* The least restrictive OARS filter has all values as intense, or unknown. */
oars_ratings_all_intense_or_unknown = TRUE;
g_variant_iter_init (&iter, filter->oars_ratings);
while (g_variant_iter_loop (&iter, "{&s&s}", NULL, &oars_value))
{
MctAppFilterOarsValue value = oars_str_to_enum (oars_value);
if (value != MCT_APP_FILTER_OARS_VALUE_UNKNOWN &&
value != MCT_APP_FILTER_OARS_VALUE_INTENSE)
{
oars_ratings_all_intense_or_unknown = FALSE;
break;
}
}
/* Check all fields against their default values. Ignore
* `allow_system_installation` since its false by default, so the default
* value is already the most restrictive. */
return ((filter->app_list_type == MCT_APP_FILTER_LIST_BLOCKLIST &&
filter->app_list[0] != NULL) ||
filter->app_list_type == MCT_APP_FILTER_LIST_ALLOWLIST ||
!oars_ratings_all_intense_or_unknown ||
!filter->allow_user_installation);
}
/** /**
* mct_app_filter_is_path_allowed: * mct_app_filter_is_path_allowed:
* @filter: an #MctAppFilter * @filter: an #MctAppFilter
@ -139,9 +202,9 @@ mct_app_filter_is_path_allowed (MctAppFilter *filter,
switch (filter->app_list_type) switch (filter->app_list_type)
{ {
case MCT_APP_FILTER_LIST_BLACKLIST: case MCT_APP_FILTER_LIST_BLOCKLIST:
return !path_in_list; return !path_in_list;
case MCT_APP_FILTER_LIST_WHITELIST: case MCT_APP_FILTER_LIST_ALLOWLIST:
return path_in_list; return path_in_list;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
@ -202,9 +265,9 @@ mct_app_filter_is_flatpak_ref_allowed (MctAppFilter *filter,
switch (filter->app_list_type) switch (filter->app_list_type)
{ {
case MCT_APP_FILTER_LIST_BLACKLIST: case MCT_APP_FILTER_LIST_BLOCKLIST:
return !ref_in_list; return !ref_in_list;
case MCT_APP_FILTER_LIST_WHITELIST: case MCT_APP_FILTER_LIST_ALLOWLIST:
return ref_in_list; return ref_in_list;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
@ -218,7 +281,7 @@ mct_app_filter_is_flatpak_ref_allowed (MctAppFilter *filter,
* *
* Check whether the flatpak app with the given @app_id is allowed to be run * Check whether the flatpak app with the given @app_id is allowed to be run
* according to this app filter. This is a globbing match, matching @app_id * according to this app filter. This is a globbing match, matching @app_id
* against potentially multiple entries in the blacklist, as the blacklist * against potentially multiple entries in the blocklist, as the blocklist
* contains flatpak refs (for example, `app/org.gnome.Builder/x86_64/master`) * contains flatpak refs (for example, `app/org.gnome.Builder/x86_64/master`)
* which contain architecture and branch information. App IDs (for example, * which contain architecture and branch information. App IDs (for example,
* `org.gnome.Builder`) do not contain architecture or branch information. * `org.gnome.Builder`) do not contain architecture or branch information.
@ -252,9 +315,9 @@ mct_app_filter_is_flatpak_app_allowed (MctAppFilter *filter,
switch (filter->app_list_type) switch (filter->app_list_type)
{ {
case MCT_APP_FILTER_LIST_BLACKLIST: case MCT_APP_FILTER_LIST_BLOCKLIST:
return !id_in_list; return !id_in_list;
case MCT_APP_FILTER_LIST_WHITELIST: case MCT_APP_FILTER_LIST_ALLOWLIST:
return id_in_list; return id_in_list;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
@ -368,8 +431,8 @@ is_valid_content_type (const gchar *content_type)
* according to this app filter. * according to this app filter.
* *
* Note that this method doesnt match content subtypes. For example, if * Note that this method doesnt match content subtypes. For example, if
* `application/xml` is added to the blacklist but `application/xspf+xml` is not, * `application/xml` is added to the blocklist but `application/xspf+xml` is not,
* a check for whether `application/xspf+xml` is blacklisted would return false. * a check for whether `application/xspf+xml` is blocklisted would return false.
* *
* Returns: %TRUE if the user this @filter corresponds to is allowed to run * Returns: %TRUE if the user this @filter corresponds to is allowed to run
* programs handling @content_type according to the @filter policy; * programs handling @content_type according to the @filter policy;
@ -390,9 +453,9 @@ mct_app_filter_is_content_type_allowed (MctAppFilter *filter,
switch (filter->app_list_type) switch (filter->app_list_type)
{ {
case MCT_APP_FILTER_LIST_BLACKLIST: case MCT_APP_FILTER_LIST_BLOCKLIST:
return !ref_in_list; return !ref_in_list;
case MCT_APP_FILTER_LIST_WHITELIST: case MCT_APP_FILTER_LIST_ALLOWLIST:
return ref_in_list; return ref_in_list;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
@ -477,16 +540,7 @@ mct_app_filter_get_oars_value (MctAppFilter *filter,
if (!g_variant_lookup (filter->oars_ratings, oars_section, "&s", &value_str)) if (!g_variant_lookup (filter->oars_ratings, oars_section, "&s", &value_str))
return MCT_APP_FILTER_OARS_VALUE_UNKNOWN; return MCT_APP_FILTER_OARS_VALUE_UNKNOWN;
if (g_str_equal (value_str, "none")) return oars_str_to_enum (value_str);
return MCT_APP_FILTER_OARS_VALUE_NONE;
else if (g_str_equal (value_str, "mild"))
return MCT_APP_FILTER_OARS_VALUE_MILD;
else if (g_str_equal (value_str, "moderate"))
return MCT_APP_FILTER_OARS_VALUE_MODERATE;
else if (g_str_equal (value_str, "intense"))
return MCT_APP_FILTER_OARS_VALUE_INTENSE;
else
return MCT_APP_FILTER_OARS_VALUE_UNKNOWN;
} }
/** /**
@ -533,6 +587,201 @@ mct_app_filter_is_system_installation_allowed (MctAppFilter *filter)
return filter->allow_system_installation; return filter->allow_system_installation;
} }
/**
* _mct_app_filter_build_app_filter_variant:
* @filter: an #MctAppFilter
*
* Build a #GVariant which contains the app filter from @filter, in the format
* used for storing it in AccountsService.
*
* Returns: (transfer floating): a new, floating #GVariant containing the app
* filter
*/
static GVariant *
_mct_app_filter_build_app_filter_variant (MctAppFilter *filter)
{
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(bas)"));
g_return_val_if_fail (filter != NULL, NULL);
g_return_val_if_fail (filter->ref_count >= 1, NULL);
g_variant_builder_add (&builder, "b",
(filter->app_list_type == MCT_APP_FILTER_LIST_ALLOWLIST));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
for (gsize i = 0; filter->app_list[i] != NULL; i++)
g_variant_builder_add (&builder, "s", filter->app_list[i]);
g_variant_builder_close (&builder);
return g_variant_builder_end (&builder);
}
/**
* mct_app_filter_serialize:
* @filter: an #MctAppFilter
*
* Build a #GVariant which contains the app filter from @filter, in an opaque
* variant format. This format may change in future, but
* mct_app_filter_deserialize() is guaranteed to always be able to load any
* variant produced by the current or any previous version of
* mct_app_filter_serialize().
*
* Returns: (transfer floating): a new, floating #GVariant containing the app
* filter
* Since: 0.7.0
*/
GVariant *
mct_app_filter_serialize (MctAppFilter *filter)
{
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{sv}"));
g_return_val_if_fail (filter != NULL, NULL);
g_return_val_if_fail (filter->ref_count >= 1, NULL);
/* The serialisation format is exactly the
* `com.endlessm.ParentalControls.AppFilter` D-Bus interface. */
g_variant_builder_add (&builder, "{sv}", "AppFilter",
_mct_app_filter_build_app_filter_variant (filter));
g_variant_builder_add (&builder, "{sv}", "OarsFilter",
g_variant_new ("(s@a{ss})", "oars-1.1",
filter->oars_ratings));
g_variant_builder_add (&builder, "{sv}", "AllowUserInstallation",
g_variant_new_boolean (filter->allow_user_installation));
g_variant_builder_add (&builder, "{sv}", "AllowSystemInstallation",
g_variant_new_boolean (filter->allow_system_installation));
return g_variant_builder_end (&builder);
}
/**
* mct_app_filter_deserialize:
* @variant: a serialized app filter variant
* @user_id: the ID of the user the app filter relates to
* @error: return location for a #GError, or %NULL
*
* Deserialize an app filter previously serialized with
* mct_app_filter_serialize(). This function guarantees to be able to
* deserialize any serialized form from this version or older versions of
* libmalcontent.
*
* If deserialization fails, %MCT_MANAGER_ERROR_INVALID_DATA will be returned.
*
* Returns: (transfer full): deserialized app filter
* Since: 0.7.0
*/
MctAppFilter *
mct_app_filter_deserialize (GVariant *variant,
uid_t user_id,
GError **error)
{
gboolean is_allowlist;
g_auto(GStrv) app_list = NULL;
const gchar *content_rating_kind;
g_autoptr(GVariant) oars_variant = NULL;
gboolean allow_user_installation;
gboolean allow_system_installation;
g_autoptr(MctAppFilter) app_filter = NULL;
g_return_val_if_fail (variant != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Check the overall type. */
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}")))
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("App filter for user %u was in an unrecognized format"),
(guint) user_id);
return NULL;
}
/* Extract the properties we care about. The default values here should be
* kept in sync with those in the `com.endlessm.ParentalControls.AppFilter`
* D-Bus interface. */
if (!g_variant_lookup (variant, "AppFilter", "(b^as)",
&is_allowlist, &app_list))
{
/* Default value. */
is_allowlist = FALSE;
app_list = g_new0 (gchar *, 1);
}
if (!g_variant_lookup (variant, "OarsFilter", "(&s@a{ss})",
&content_rating_kind, &oars_variant))
{
/* Default value. */
content_rating_kind = "oars-1.1";
oars_variant = g_variant_new ("a{ss}", NULL);
}
/* Check that the OARS filter is in a format we support. Currently, thats
* only oars-1.0 and oars-1.1. */
if (!g_str_equal (content_rating_kind, "oars-1.0") &&
!g_str_equal (content_rating_kind, "oars-1.1"))
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("OARS filter for user %u has an unrecognized kind %s"),
(guint) user_id, content_rating_kind);
return NULL;
}
if (!g_variant_lookup (variant, "AllowUserInstallation", "b",
&allow_user_installation))
{
/* Default value. */
allow_user_installation = TRUE;
}
if (!g_variant_lookup (variant, "AllowSystemInstallation", "b",
&allow_system_installation))
{
/* Default value. */
allow_system_installation = FALSE;
}
/* Success. Create an #MctAppFilter object to contain the results. */
app_filter = g_new0 (MctAppFilter, 1);
app_filter->ref_count = 1;
app_filter->user_id = user_id;
app_filter->app_list = g_steal_pointer (&app_list);
app_filter->app_list_type =
is_allowlist ? MCT_APP_FILTER_LIST_ALLOWLIST : MCT_APP_FILTER_LIST_BLOCKLIST;
app_filter->oars_ratings = g_steal_pointer (&oars_variant);
app_filter->allow_user_installation = allow_user_installation;
app_filter->allow_system_installation = allow_system_installation;
return g_steal_pointer (&app_filter);
}
/**
* mct_app_filter_equal:
* @a: (not nullable): an #MctAppFilter
* @b: (not nullable): an #MctAppFilter
*
* Check whether app filters @a and @b are equal.
*
* Returns: %TRUE if @a and @b are equal, %FALSE otherwise
* Since: 0.10.0
*/
gboolean
mct_app_filter_equal (MctAppFilter *a,
MctAppFilter *b)
{
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (a->ref_count >= 1, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
g_return_val_if_fail (b->ref_count >= 1, FALSE);
return (a->user_id == b->user_id &&
a->app_list_type == b->app_list_type &&
a->allow_user_installation == b->allow_user_installation &&
a->allow_system_installation == b->allow_system_installation &&
g_strv_equal ((const gchar * const *) a->app_list, (const gchar * const *) b->app_list) &&
g_variant_equal (a->oars_ratings, b->oars_ratings));
}
/* /*
* Actual implementation of #MctAppFilterBuilder. * Actual implementation of #MctAppFilterBuilder.
* *
@ -540,7 +789,7 @@ mct_app_filter_is_system_installation_allowed (MctAppFilter *filter)
*/ */
typedef struct typedef struct
{ {
GPtrArray *blacklist; /* (nullable) (owned) (element-type utf8) */ GPtrArray *blocklist; /* (nullable) (owned) (element-type utf8) */
GHashTable *oars; /* (nullable) (owned) (element-type utf8 MctAppFilterOarsValue) */ GHashTable *oars; /* (nullable) (owned) (element-type utf8 MctAppFilterOarsValue) */
gboolean allow_user_installation; gboolean allow_user_installation;
gboolean allow_system_installation; gboolean allow_system_installation;
@ -578,7 +827,7 @@ mct_app_filter_builder_init (MctAppFilterBuilder *builder)
MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder; MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder;
g_return_if_fail (_builder != NULL); g_return_if_fail (_builder != NULL);
g_return_if_fail (_builder->blacklist == NULL); g_return_if_fail (_builder->blocklist == NULL);
g_return_if_fail (_builder->oars == NULL); g_return_if_fail (_builder->oars == NULL);
memcpy (builder, &local_builder, sizeof (local_builder)); memcpy (builder, &local_builder, sizeof (local_builder));
@ -604,7 +853,7 @@ mct_app_filter_builder_clear (MctAppFilterBuilder *builder)
g_return_if_fail (_builder != NULL); g_return_if_fail (_builder != NULL);
g_clear_pointer (&_builder->blacklist, g_ptr_array_unref); g_clear_pointer (&_builder->blocklist, g_ptr_array_unref);
g_clear_pointer (&_builder->oars, g_hash_table_unref); g_clear_pointer (&_builder->oars, g_hash_table_unref);
} }
@ -654,8 +903,8 @@ mct_app_filter_builder_copy (MctAppFilterBuilder *builder)
_copy = (MctAppFilterBuilderReal *) copy; _copy = (MctAppFilterBuilderReal *) copy;
mct_app_filter_builder_clear (copy); mct_app_filter_builder_clear (copy);
if (_builder->blacklist != NULL) if (_builder->blocklist != NULL)
_copy->blacklist = g_ptr_array_ref (_builder->blacklist); _copy->blocklist = g_ptr_array_ref (_builder->blocklist);
if (_builder->oars != NULL) if (_builder->oars != NULL)
_copy->oars = g_hash_table_ref (_builder->oars); _copy->oars = g_hash_table_ref (_builder->oars);
_copy->allow_user_installation = _builder->allow_user_installation; _copy->allow_user_installation = _builder->allow_user_installation;
@ -705,11 +954,11 @@ mct_app_filter_builder_end (MctAppFilterBuilder *builder)
g_autoptr(GVariant) oars_variant = NULL; g_autoptr(GVariant) oars_variant = NULL;
g_return_val_if_fail (_builder != NULL, NULL); g_return_val_if_fail (_builder != NULL, NULL);
g_return_val_if_fail (_builder->blacklist != NULL, NULL); g_return_val_if_fail (_builder->blocklist != NULL, NULL);
g_return_val_if_fail (_builder->oars != NULL, NULL); g_return_val_if_fail (_builder->oars != NULL, NULL);
/* Ensure the paths list is %NULL-terminated. */ /* Ensure the paths list is %NULL-terminated. */
g_ptr_array_add (_builder->blacklist, NULL); g_ptr_array_add (_builder->blocklist, NULL);
/* Build the OARS variant. */ /* Build the OARS variant. */
g_hash_table_iter_init (&iter, _builder->oars); g_hash_table_iter_init (&iter, _builder->oars);
@ -740,8 +989,8 @@ mct_app_filter_builder_end (MctAppFilterBuilder *builder)
app_filter = g_new0 (MctAppFilter, 1); app_filter = g_new0 (MctAppFilter, 1);
app_filter->ref_count = 1; app_filter->ref_count = 1;
app_filter->user_id = -1; app_filter->user_id = -1;
app_filter->app_list = (gchar **) g_ptr_array_free (g_steal_pointer (&_builder->blacklist), FALSE); app_filter->app_list = (gchar **) g_ptr_array_free (g_steal_pointer (&_builder->blocklist), FALSE);
app_filter->app_list_type = MCT_APP_FILTER_LIST_BLACKLIST; app_filter->app_list_type = MCT_APP_FILTER_LIST_BLOCKLIST;
app_filter->oars_ratings = g_steal_pointer (&oars_variant); app_filter->oars_ratings = g_steal_pointer (&oars_variant);
app_filter->allow_user_installation = _builder->allow_user_installation; app_filter->allow_user_installation = _builder->allow_user_installation;
app_filter->allow_system_installation = _builder->allow_system_installation; app_filter->allow_system_installation = _builder->allow_system_installation;
@ -752,24 +1001,24 @@ mct_app_filter_builder_end (MctAppFilterBuilder *builder)
} }
/** /**
* mct_app_filter_builder_blacklist_path: * mct_app_filter_builder_blocklist_path:
* @builder: an initialised #MctAppFilterBuilder * @builder: an initialised #MctAppFilterBuilder
* @path: (type filename): an absolute path to blacklist * @path: (type filename): an absolute path to blocklist
* *
* Add @path to the blacklist of app paths in the filter under construction. It * Add @path to the blocklist of app paths in the filter under construction. It
* will be canonicalised (without doing any I/O) before being added. * will be canonicalised (without doing any I/O) before being added.
* The canonicalised @path will not be added again if its already been added. * The canonicalised @path will not be added again if its already been added.
* *
* Since: 0.2.0 * Since: 0.2.0
*/ */
void void
mct_app_filter_builder_blacklist_path (MctAppFilterBuilder *builder, mct_app_filter_builder_blocklist_path (MctAppFilterBuilder *builder,
const gchar *path) const gchar *path)
{ {
MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder; MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder;
g_return_if_fail (_builder != NULL); g_return_if_fail (_builder != NULL);
g_return_if_fail (_builder->blacklist != NULL); g_return_if_fail (_builder->blocklist != NULL);
g_return_if_fail (path != NULL); g_return_if_fail (path != NULL);
g_return_if_fail (g_path_is_absolute (path)); g_return_if_fail (g_path_is_absolute (path));
@ -778,67 +1027,67 @@ mct_app_filter_builder_blacklist_path (MctAppFilterBuilder *builder,
NULL, NULL, NULL); NULL, NULL, NULL);
g_return_if_fail (canonical_path_utf8 != NULL); g_return_if_fail (canonical_path_utf8 != NULL);
if (!g_ptr_array_find_with_equal_func (_builder->blacklist, if (!g_ptr_array_find_with_equal_func (_builder->blocklist,
canonical_path_utf8, g_str_equal, NULL)) canonical_path_utf8, g_str_equal, NULL))
g_ptr_array_add (_builder->blacklist, g_steal_pointer (&canonical_path_utf8)); g_ptr_array_add (_builder->blocklist, g_steal_pointer (&canonical_path_utf8));
} }
/** /**
* mct_app_filter_builder_blacklist_flatpak_ref: * mct_app_filter_builder_blocklist_flatpak_ref:
* @builder: an initialised #MctAppFilterBuilder * @builder: an initialised #MctAppFilterBuilder
* @app_ref: a flatpak app ref to blacklist * @app_ref: a flatpak app ref to blocklist
* *
* Add @app_ref to the blacklist of flatpak refs in the filter under * Add @app_ref to the blocklist of flatpak refs in the filter under
* construction. The @app_ref will not be added again if its already been * construction. The @app_ref will not be added again if its already been
* added. * added.
* *
* Since: 0.2.0 * Since: 0.2.0
*/ */
void void
mct_app_filter_builder_blacklist_flatpak_ref (MctAppFilterBuilder *builder, mct_app_filter_builder_blocklist_flatpak_ref (MctAppFilterBuilder *builder,
const gchar *app_ref) const gchar *app_ref)
{ {
MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder; MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder;
g_return_if_fail (_builder != NULL); g_return_if_fail (_builder != NULL);
g_return_if_fail (_builder->blacklist != NULL); g_return_if_fail (_builder->blocklist != NULL);
g_return_if_fail (app_ref != NULL); g_return_if_fail (app_ref != NULL);
g_return_if_fail (is_valid_flatpak_ref (app_ref)); g_return_if_fail (is_valid_flatpak_ref (app_ref));
if (!g_ptr_array_find_with_equal_func (_builder->blacklist, if (!g_ptr_array_find_with_equal_func (_builder->blocklist,
app_ref, g_str_equal, NULL)) app_ref, g_str_equal, NULL))
g_ptr_array_add (_builder->blacklist, g_strdup (app_ref)); g_ptr_array_add (_builder->blocklist, g_strdup (app_ref));
} }
/** /**
* mct_app_filter_builder_blacklist_content_type: * mct_app_filter_builder_blocklist_content_type:
* @builder: an initialised #MctAppFilterBuilder * @builder: an initialised #MctAppFilterBuilder
* @content_type: a content type to blacklist * @content_type: a content type to blocklist
* *
* Add @content_type to the blacklist of content types in the filter under * Add @content_type to the blocklist of content types in the filter under
* construction. The @content_type will not be added again if its already been * construction. The @content_type will not be added again if its already been
* added. * added.
* *
* Note that this method doesnt handle content subtypes. For example, if * Note that this method doesnt handle content subtypes. For example, if
* `application/xml` is added to the blacklist but `application/xspf+xml` is not, * `application/xml` is added to the blocklist but `application/xspf+xml` is not,
* a check for whether `application/xspf+xml` is blacklisted would return false. * a check for whether `application/xspf+xml` is blocklisted would return false.
* *
* Since: 0.4.0 * Since: 0.4.0
*/ */
void void
mct_app_filter_builder_blacklist_content_type (MctAppFilterBuilder *builder, mct_app_filter_builder_blocklist_content_type (MctAppFilterBuilder *builder,
const gchar *content_type) const gchar *content_type)
{ {
MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder; MctAppFilterBuilderReal *_builder = (MctAppFilterBuilderReal *) builder;
g_return_if_fail (_builder != NULL); g_return_if_fail (_builder != NULL);
g_return_if_fail (_builder->blacklist != NULL); g_return_if_fail (_builder->blocklist != NULL);
g_return_if_fail (content_type != NULL); g_return_if_fail (content_type != NULL);
g_return_if_fail (is_valid_content_type (content_type)); g_return_if_fail (is_valid_content_type (content_type));
if (!g_ptr_array_find_with_equal_func (_builder->blacklist, if (!g_ptr_array_find_with_equal_func (_builder->blocklist,
content_type, g_str_equal, NULL)) content_type, g_str_equal, NULL))
g_ptr_array_add (_builder->blacklist, g_strdup (content_type)); g_ptr_array_add (_builder->blocklist, g_strdup (content_type));
} }
/** /**

View File

@ -78,6 +78,9 @@ void mct_app_filter_unref (MctAppFilter *filter);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctAppFilter, mct_app_filter_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctAppFilter, mct_app_filter_unref)
uid_t mct_app_filter_get_user_id (MctAppFilter *filter); uid_t mct_app_filter_get_user_id (MctAppFilter *filter);
gboolean mct_app_filter_is_enabled (MctAppFilter *filter);
gboolean mct_app_filter_is_path_allowed (MctAppFilter *filter, gboolean mct_app_filter_is_path_allowed (MctAppFilter *filter,
const gchar *path); const gchar *path);
gboolean mct_app_filter_is_flatpak_ref_allowed (MctAppFilter *filter, gboolean mct_app_filter_is_flatpak_ref_allowed (MctAppFilter *filter,
@ -96,6 +99,14 @@ MctAppFilterOarsValue mct_app_filter_get_oars_value (MctAppFilter *filter,
gboolean mct_app_filter_is_user_installation_allowed (MctAppFilter *filter); gboolean mct_app_filter_is_user_installation_allowed (MctAppFilter *filter);
gboolean mct_app_filter_is_system_installation_allowed (MctAppFilter *filter); gboolean mct_app_filter_is_system_installation_allowed (MctAppFilter *filter);
GVariant *mct_app_filter_serialize (MctAppFilter *filter);
MctAppFilter *mct_app_filter_deserialize (GVariant *variant,
uid_t user_id,
GError **error);
gboolean mct_app_filter_equal (MctAppFilter *a,
MctAppFilter *b);
/** /**
* MctAppFilterBuilder: * MctAppFilterBuilder:
* *
@ -157,11 +168,11 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctAppFilterBuilder, mct_app_filter_builder_free)
MctAppFilter *mct_app_filter_builder_end (MctAppFilterBuilder *builder); MctAppFilter *mct_app_filter_builder_end (MctAppFilterBuilder *builder);
void mct_app_filter_builder_blacklist_path (MctAppFilterBuilder *builder, void mct_app_filter_builder_blocklist_path (MctAppFilterBuilder *builder,
const gchar *path); const gchar *path);
void mct_app_filter_builder_blacklist_flatpak_ref (MctAppFilterBuilder *builder, void mct_app_filter_builder_blocklist_flatpak_ref (MctAppFilterBuilder *builder,
const gchar *app_ref); const gchar *app_ref);
void mct_app_filter_builder_blacklist_content_type (MctAppFilterBuilder *builder, void mct_app_filter_builder_blocklist_content_type (MctAppFilterBuilder *builder,
const gchar *content_type); const gchar *content_type);
void mct_app_filter_builder_set_oars_value (MctAppFilterBuilder *builder, void mct_app_filter_builder_set_oars_value (MctAppFilterBuilder *builder,

View File

@ -0,0 +1,122 @@
/*
If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
destructors, in a sane way, including e.g. on library unload. If not you're on
your own.
Some compilers need #pragma to handle this, which does not work with macros,
so the way you need to use this is (for constructors):
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
#endif
G_DEFINE_CONSTRUCTOR(my_constructor)
static void my_constructor(void) {
...
}
*/
#ifndef __GTK_DOC_IGNORE__
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
#define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
/* Visual studio 2008 and later has _Pragma */
#include <stdlib.h>
#define G_HAS_CONSTRUCTORS 1
/* We do some weird things to avoid the constructors being optimized
* away on VS2015 if WholeProgramOptimization is enabled. First we
* make a reference to the array from the wrapper to make sure its
* references. Then we use a pragma to make sure the wrapper function
* symbol is always included at the link stage. Also, the symbols
* need to be extern (but not dllexport), even though they are not
* really used from another object file.
*/
/* We need to account for differences between the mangling of symbols
* for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed
* with an underscore but symbols on x64 are not.
*/
#ifdef _WIN64
#define G_MSVC_SYMBOL_PREFIX ""
#else
#define G_MSVC_SYMBOL_PREFIX "_"
#endif
#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
#define G_MSVC_CTOR(_func,_sym_prefix) \
static void _func(void); \
extern int (* _array ## _func)(void); \
int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \
__pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
__pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
#define G_MSVC_DTOR(_func,_sym_prefix) \
static void _func(void); \
extern int (* _array ## _func)(void); \
int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \
__pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
__pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
#elif defined (_MSC_VER)
#define G_HAS_CONSTRUCTORS 1
/* Pre Visual studio 2008 must use #pragma section */
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
section(".CRT$XCU",read)
#define G_DEFINE_CONSTRUCTOR(_func) \
static void _func(void); \
static int _func ## _wrapper(void) { _func(); return 0; } \
__declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
section(".CRT$XCU",read)
#define G_DEFINE_DESTRUCTOR(_func) \
static void _func(void); \
static int _func ## _constructor(void) { atexit (_func); return 0; } \
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
#elif defined(__SUNPRO_C)
/* This is not tested, but i believe it should work, based on:
* http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
*/
#define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
init(_func)
#define G_DEFINE_CONSTRUCTOR(_func) \
static void _func(void);
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
fini(_func)
#define G_DEFINE_DESTRUCTOR(_func) \
static void _func(void);
#else
/* constructors not supported for this compiler */
#endif
#endif /* __GTK_DOC_IGNORE__ */

51
libmalcontent/init.c Normal file
View File

@ -0,0 +1,51 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright © 2020 Endless Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* - Philip Withnall <withnall@endlessm.com>
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include "gconstructor.h"
static void
mct_init (void)
{
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
}
#ifdef G_HAS_CONSTRUCTORS
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(mct_init_ctor)
#endif
G_DEFINE_CONSTRUCTOR(mct_init_ctor)
static void
mct_init_ctor (void)
{
mct_init ();
}
#else
#error Your platform/compiler is missing constructor support
#endif

View File

@ -23,5 +23,6 @@
#pragma once #pragma once
#include <libmalcontent/app-filter.h> #include <libmalcontent/app-filter.h>
#include <libmalcontent/enums.h>
#include <libmalcontent/manager.h> #include <libmalcontent/manager.h>
#include <libmalcontent/session-limits.h> #include <libmalcontent/session-limits.h>

View File

@ -98,7 +98,7 @@ mct_manager_set_property (GObject *object,
switch ((MctManagerProperty) property_id) switch ((MctManagerProperty) property_id)
{ {
case PROP_CONNECTION: case PROP_CONNECTION:
/* Construct-only. May be %NULL. */ /* Construct-only. May not be %NULL. */
g_assert (self->connection == NULL); g_assert (self->connection == NULL);
self->connection = g_value_dup_object (value); self->connection = g_value_dup_object (value);
g_assert (self->connection != NULL); g_assert (self->connection != NULL);
@ -167,7 +167,7 @@ mct_manager_class_init (MctManagerClass *klass)
object_class->set_property = mct_manager_set_property; object_class->set_property = mct_manager_set_property;
/** /**
* MctManager:connection: * MctManager:connection: (not nullable)
* *
* A connection to the system bus, where accounts-service runs. Its provided * A connection to the system bus, where accounts-service runs. Its provided
* mostly for testing purposes, or to allow an existing connection to be * mostly for testing purposes, or to allow an existing connection to be
@ -257,37 +257,6 @@ _mct_manager_user_changed_cb (GDBusConnection *connection,
g_signal_emit_by_name (manager, "app-filter-changed", uid); g_signal_emit_by_name (manager, "app-filter-changed", uid);
} }
/**
* _mct_app_filter_build_app_filter_variant:
* @filter: an #MctAppFilter
*
* Build a #GVariant which contains the app filter from @filter, in the format
* used for storing it in AccountsService.
*
* Returns: (transfer floating): a new, floating #GVariant containing the app
* filter
* Since: 0.2.0
*/
static GVariant *
_mct_app_filter_build_app_filter_variant (MctAppFilter *filter)
{
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(bas)"));
g_return_val_if_fail (filter != NULL, NULL);
g_return_val_if_fail (filter->ref_count >= 1, NULL);
g_variant_builder_add (&builder, "b",
(filter->app_list_type == MCT_APP_FILTER_LIST_WHITELIST));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
for (gsize i = 0; filter->app_list[i] != NULL; i++)
g_variant_builder_add (&builder, "s", filter->app_list[i]);
g_variant_builder_close (&builder);
return g_variant_builder_end (&builder);
}
/* Check if @error is a D-Bus remote error matching @expected_error_name. */ /* Check if @error is a D-Bus remote error matching @expected_error_name. */
static gboolean static gboolean
bus_remote_error_matches (const GError *error, bus_remote_error_matches (const GError *error,
@ -311,12 +280,20 @@ bus_error_to_manager_error (const GError *bus_error,
if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED) || if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED) ||
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.PermissionDenied")) bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.PermissionDenied"))
return g_error_new (MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_PERMISSION_DENIED, return g_error_new (MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_PERMISSION_DENIED,
_("Not allowed to query app filter data for user %u"), _("Not allowed to query parental controls data for user %u"),
(guint) user_id); (guint) user_id);
else if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) || else if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) ||
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.Failed")) bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.Failed"))
return g_error_new (MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_INVALID_USER, return g_error_new (MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_INVALID_USER,
_("User %u does not exist"), (guint) user_id); _("User %u does not exist"), (guint) user_id);
else if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) ||
g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
/* If accountsservice is not available on the system bus, then the
* com.endlessm.ParentalControls.AppFilter extension interface
* certainly can't be available. */
return g_error_new_literal (MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_DISABLED,
_("System accounts service not available"));
else else
return g_error_copy (bus_error); return g_error_copy (bus_error);
} }
@ -386,13 +363,6 @@ mct_manager_get_app_filter (MctManager *self,
g_autoptr(GVariant) result_variant = NULL; g_autoptr(GVariant) result_variant = NULL;
g_autoptr(GVariant) properties = NULL; g_autoptr(GVariant) properties = NULL;
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
g_autoptr(MctAppFilter) app_filter = NULL;
gboolean is_whitelist;
g_auto(GStrv) app_list = NULL;
const gchar *content_rating_kind;
g_autoptr(GVariant) oars_variant = NULL;
gboolean allow_user_installation;
gboolean allow_system_installation;
g_return_val_if_fail (MCT_IS_MANAGER (self), NULL); g_return_val_if_fail (MCT_IS_MANAGER (self), NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
@ -443,62 +413,16 @@ mct_manager_get_app_filter (MctManager *self,
/* Extract the properties we care about. They may be silently omitted from the /* Extract the properties we care about. They may be silently omitted from the
* results if we dont have permission to access them. */ * results if we dont have permission to access them. */
properties = g_variant_get_child_value (result_variant, 0); properties = g_variant_get_child_value (result_variant, 0);
if (!g_variant_lookup (properties, "AppFilter", "(b^as)", if (!g_variant_lookup (properties, "AppFilter", "(b^as)", NULL, NULL))
&is_whitelist, &app_list))
{ {
g_set_error (error, MCT_MANAGER_ERROR, g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_PERMISSION_DENIED, MCT_MANAGER_ERROR_PERMISSION_DENIED,
_("Not allowed to query app filter data for user %u"), _("Not allowed to query parental controls data for user %u"),
(guint) user_id); (guint) user_id);
return NULL; return NULL;
} }
if (!g_variant_lookup (properties, "OarsFilter", "(&s@a{ss})", return mct_app_filter_deserialize (properties, user_id, error);
&content_rating_kind, &oars_variant))
{
/* Default value. */
content_rating_kind = "oars-1.1";
oars_variant = g_variant_new ("a{ss}", NULL);
}
/* Check that the OARS filter is in a format we support. Currently, thats
* only oars-1.0 and oars-1.1. */
if (!g_str_equal (content_rating_kind, "oars-1.0") &&
!g_str_equal (content_rating_kind, "oars-1.1"))
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("OARS filter for user %u has an unrecognized kind %s"),
(guint) user_id, content_rating_kind);
return NULL;
}
if (!g_variant_lookup (properties, "AllowUserInstallation", "b",
&allow_user_installation))
{
/* Default value. */
allow_user_installation = TRUE;
}
if (!g_variant_lookup (properties, "AllowSystemInstallation", "b",
&allow_system_installation))
{
/* Default value. */
allow_system_installation = FALSE;
}
/* Success. Create an #MctAppFilter object to contain the results. */
app_filter = g_new0 (MctAppFilter, 1);
app_filter->ref_count = 1;
app_filter->user_id = user_id;
app_filter->app_list = g_steal_pointer (&app_list);
app_filter->app_list_type =
is_whitelist ? MCT_APP_FILTER_LIST_WHITELIST : MCT_APP_FILTER_LIST_BLACKLIST;
app_filter->oars_ratings = g_steal_pointer (&oars_variant);
app_filter->allow_user_installation = allow_user_installation;
app_filter->allow_system_installation = allow_system_installation;
return g_steal_pointer (&app_filter);
} }
static void get_app_filter_thread_cb (GTask *task, static void get_app_filter_thread_cb (GTask *task,
@ -632,14 +556,10 @@ mct_manager_set_app_filter (MctManager *self,
GError **error) GError **error)
{ {
g_autofree gchar *object_path = NULL; g_autofree gchar *object_path = NULL;
g_autoptr(GVariant) app_filter_variant = NULL; g_autoptr(GVariant) properties_variant = NULL;
g_autoptr(GVariant) oars_filter_variant = NULL; g_autoptr(GVariant) properties_value = NULL;
g_autoptr(GVariant) allow_user_installation_variant = NULL; const gchar *properties_key = NULL;
g_autoptr(GVariant) allow_system_installation_variant = NULL; GVariantIter iter;
g_autoptr(GVariant) app_filter_result_variant = NULL;
g_autoptr(GVariant) oars_filter_result_variant = NULL;
g_autoptr(GVariant) allow_user_installation_result_variant = NULL;
g_autoptr(GVariant) allow_system_installation_result_variant = NULL;
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE); g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE);
@ -654,13 +574,14 @@ mct_manager_set_app_filter (MctManager *self,
if (object_path == NULL) if (object_path == NULL)
return FALSE; return FALSE;
app_filter_variant = _mct_app_filter_build_app_filter_variant (app_filter); properties_variant = mct_app_filter_serialize (app_filter);
oars_filter_variant = g_variant_new ("(s@a{ss})", "oars-1.1",
app_filter->oars_ratings);
allow_user_installation_variant = g_variant_new_boolean (app_filter->allow_user_installation);
allow_system_installation_variant = g_variant_new_boolean (app_filter->allow_system_installation);
app_filter_result_variant = g_variant_iter_init (&iter, properties_variant);
while (g_variant_iter_loop (&iter, "{&sv}", &properties_key, &properties_value))
{
g_autoptr(GVariant) result_variant = NULL;
result_variant =
g_dbus_connection_call_sync (self->connection, g_dbus_connection_call_sync (self->connection,
"org.freedesktop.Accounts", "org.freedesktop.Accounts",
object_path, object_path,
@ -668,8 +589,8 @@ mct_manager_set_app_filter (MctManager *self,
"Set", "Set",
g_variant_new ("(ssv)", g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.AppFilter", "com.endlessm.ParentalControls.AppFilter",
"AppFilter", properties_key,
g_steal_pointer (&app_filter_variant)), properties_value),
G_VARIANT_TYPE ("()"), G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE) (flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION ? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
@ -682,74 +603,6 @@ mct_manager_set_app_filter (MctManager *self,
g_propagate_error (error, bus_error_to_manager_error (local_error, user_id)); g_propagate_error (error, bus_error_to_manager_error (local_error, user_id));
return FALSE; return FALSE;
} }
oars_filter_result_variant =
g_dbus_connection_call_sync (self->connection,
"org.freedesktop.Accounts",
object_path,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.AppFilter",
"OarsFilter",
g_steal_pointer (&oars_filter_variant)),
G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
: G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout, ms */
cancellable,
&local_error);
if (local_error != NULL)
{
g_propagate_error (error, bus_error_to_manager_error (local_error, user_id));
return FALSE;
}
allow_user_installation_result_variant =
g_dbus_connection_call_sync (self->connection,
"org.freedesktop.Accounts",
object_path,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.AppFilter",
"AllowUserInstallation",
g_steal_pointer (&allow_user_installation_variant)),
G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
: G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout, ms */
cancellable,
&local_error);
if (local_error != NULL)
{
g_propagate_error (error, bus_error_to_manager_error (local_error, user_id));
return FALSE;
}
allow_system_installation_result_variant =
g_dbus_connection_call_sync (self->connection,
"org.freedesktop.Accounts",
object_path,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.AppFilter",
"AllowSystemInstallation",
g_steal_pointer (&allow_system_installation_variant)),
G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
: G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout, ms */
cancellable,
&local_error);
if (local_error != NULL)
{
g_propagate_error (error, bus_error_to_manager_error (local_error, user_id));
return FALSE;
} }
return TRUE; return TRUE;
@ -893,9 +746,6 @@ mct_manager_get_session_limits (MctManager *self,
g_autoptr(GVariant) result_variant = NULL; g_autoptr(GVariant) result_variant = NULL;
g_autoptr(GVariant) properties = NULL; g_autoptr(GVariant) properties = NULL;
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
g_autoptr(MctSessionLimits) session_limits = NULL;
guint32 limit_type;
guint32 daily_start_time, daily_end_time;
g_return_val_if_fail (MCT_IS_MANAGER (self), NULL); g_return_val_if_fail (MCT_IS_MANAGER (self), NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
@ -946,55 +796,16 @@ mct_manager_get_session_limits (MctManager *self,
/* Extract the properties we care about. They may be silently omitted from the /* Extract the properties we care about. They may be silently omitted from the
* results if we dont have permission to access them. */ * results if we dont have permission to access them. */
properties = g_variant_get_child_value (result_variant, 0); properties = g_variant_get_child_value (result_variant, 0);
if (!g_variant_lookup (properties, "LimitType", "u", if (!g_variant_lookup (properties, "LimitType", "u", NULL))
&limit_type))
{ {
g_set_error (error, MCT_MANAGER_ERROR, g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_PERMISSION_DENIED, MCT_MANAGER_ERROR_PERMISSION_DENIED,
_("Not allowed to query session limits data for user %u"), _("Not allowed to query parental controls data for user %u"),
(guint) user_id); (guint) user_id);
return NULL; return NULL;
} }
/* Check that the limit type is something we support. */ return mct_session_limits_deserialize (properties, user_id, error);
G_STATIC_ASSERT (sizeof (limit_type) >= sizeof (MctSessionLimitsType));
if ((guint) limit_type > MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE)
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("Session limit for user %u has an unrecognized type %u"),
(guint) user_id, limit_type);
return NULL;
}
if (!g_variant_lookup (properties, "DailySchedule", "(uu)",
&daily_start_time, &daily_end_time))
{
/* Default value. */
daily_start_time = 0;
daily_end_time = 24 * 60 * 60;
}
if (daily_start_time >= daily_end_time ||
daily_end_time > 24 * 60 * 60)
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("Session limit for user %u has invalid daily schedule %u%u"),
(guint) user_id, daily_start_time, daily_end_time);
return NULL;
}
/* Success. Create an #MctSessionLimits object to contain the results. */
session_limits = g_new0 (MctSessionLimits, 1);
session_limits->ref_count = 1;
session_limits->user_id = user_id;
session_limits->limit_type = limit_type;
session_limits->daily_start_time = daily_start_time;
session_limits->daily_end_time = daily_end_time;
return g_steal_pointer (&session_limits);
} }
static void get_session_limits_thread_cb (GTask *task, static void get_session_limits_thread_cb (GTask *task,
@ -1128,11 +939,12 @@ mct_manager_set_session_limits (MctManager *self,
GError **error) GError **error)
{ {
g_autofree gchar *object_path = NULL; g_autofree gchar *object_path = NULL;
g_autoptr(GVariant) limit_variant = NULL;
const gchar *limit_property_name = NULL;
g_autoptr(GVariant) limit_type_variant = NULL; g_autoptr(GVariant) limit_type_variant = NULL;
g_autoptr(GVariant) limit_result_variant = NULL;
g_autoptr(GVariant) limit_type_result_variant = NULL; g_autoptr(GVariant) limit_type_result_variant = NULL;
g_autoptr(GVariant) properties_variant = NULL;
g_autoptr(GVariant) properties_value = NULL;
const gchar *properties_key = NULL;
GVariantIter iter;
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE); g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE);
@ -1147,29 +959,22 @@ mct_manager_set_session_limits (MctManager *self,
if (object_path == NULL) if (object_path == NULL)
return FALSE; return FALSE;
switch (session_limits->limit_type) properties_variant = mct_session_limits_serialize (session_limits);
g_variant_iter_init (&iter, properties_variant);
while (g_variant_iter_loop (&iter, "{&sv}", &properties_key, &properties_value))
{ {
case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE: g_autoptr(GVariant) result_variant = NULL;
limit_variant = g_variant_new ("(uu)",
session_limits->daily_start_time, /* Change the limit type last, so all the details of the new limit are
session_limits->daily_end_time); * correct by the time its changed over. */
limit_property_name = "DailySchedule"; if (g_str_equal (properties_key, "LimitType"))
break; {
case MCT_SESSION_LIMITS_TYPE_NONE: limit_type_variant = g_steal_pointer (&properties_value);
limit_variant = NULL; continue;
limit_property_name = NULL;
break;
default:
g_assert_not_reached ();
} }
limit_type_variant = g_variant_new_uint32 (session_limits->limit_type); result_variant =
if (limit_property_name != NULL)
{
/* Change the details of the new limit first, so that all the properties are
* correct by the time the limit type is changed over. */
limit_result_variant =
g_dbus_connection_call_sync (self->connection, g_dbus_connection_call_sync (self->connection,
"org.freedesktop.Accounts", "org.freedesktop.Accounts",
object_path, object_path,
@ -1177,8 +982,8 @@ mct_manager_set_session_limits (MctManager *self,
"Set", "Set",
g_variant_new ("(ssv)", g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.SessionLimits", "com.endlessm.ParentalControls.SessionLimits",
limit_property_name, properties_key,
g_steal_pointer (&limit_variant)), properties_value),
G_VARIANT_TYPE ("()"), G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE) (flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION ? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
@ -1202,7 +1007,7 @@ mct_manager_set_session_limits (MctManager *self,
g_variant_new ("(ssv)", g_variant_new ("(ssv)",
"com.endlessm.ParentalControls.SessionLimits", "com.endlessm.ParentalControls.SessionLimits",
"LimitType", "LimitType",
g_steal_pointer (&limit_type_variant)), limit_type_variant),
G_VARIANT_TYPE ("()"), G_VARIANT_TYPE ("()"),
(flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE) (flags & MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE)
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION ? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION

View File

@ -2,6 +2,7 @@ libmalcontent_api_version = '0'
libmalcontent_api_name = 'malcontent-' + libmalcontent_api_version libmalcontent_api_name = 'malcontent-' + libmalcontent_api_version
libmalcontent_sources = [ libmalcontent_sources = [
'app-filter.c', 'app-filter.c',
'init.c',
'manager.c', 'manager.c',
'session-limits.c', 'session-limits.c',
] ]
@ -13,6 +14,7 @@ libmalcontent_headers = [
] ]
libmalcontent_private_headers = [ libmalcontent_private_headers = [
'app-filter-private.h', 'app-filter-private.h',
'gconstructor.h',
'session-limits-private.h', 'session-limits-private.h',
] ]
@ -28,8 +30,14 @@ libmalcontent_private_deps = [
# FIXME: Would be good to use subdir here: https://github.com/mesonbuild/meson/issues/2969 # FIXME: Would be good to use subdir here: https://github.com/mesonbuild/meson/issues/2969
libmalcontent_include_subdir = join_paths(libmalcontent_api_name, 'libmalcontent') libmalcontent_include_subdir = join_paths(libmalcontent_api_name, 'libmalcontent')
enums = gnome.mkenums_simple('enums',
sources: libmalcontent_headers,
install_header: true,
install_dir: join_paths(includedir, libmalcontent_include_subdir),
)
libmalcontent = library(libmalcontent_api_name, libmalcontent = library(libmalcontent_api_name,
libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers, libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers + enums,
dependencies: libmalcontent_public_deps + libmalcontent_private_deps, dependencies: libmalcontent_public_deps + libmalcontent_private_deps,
include_directories: root_inc, include_directories: root_inc,
install: true, install: true,
@ -39,6 +47,7 @@ libmalcontent = library(libmalcontent_api_name,
libmalcontent_dep = declare_dependency( libmalcontent_dep = declare_dependency(
link_with: libmalcontent, link_with: libmalcontent,
include_directories: root_inc, include_directories: root_inc,
sources: libmalcontent_headers + [enums[1]],
) )
# Public library bits. # Public library bits.
@ -56,8 +65,8 @@ pkgconfig.generate(libmalcontent,
libraries_private: libmalcontent_private_deps, libraries_private: libmalcontent_private_deps,
) )
gnome.generate_gir(libmalcontent, libmalcontent_gir = gnome.generate_gir(libmalcontent,
sources: libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers, sources: libmalcontent_sources + libmalcontent_headers + enums,
nsversion: libmalcontent_api_version, nsversion: libmalcontent_api_version,
namespace: 'Malcontent', namespace: 'Malcontent',
symbol_prefix: 'mct_', symbol_prefix: 'mct_',

View File

@ -50,6 +50,7 @@ typedef enum
struct _MctSessionLimits struct _MctSessionLimits
{ {
/*< private >*/
gint ref_count; gint ref_count;
uid_t user_id; uid_t user_id;

View File

@ -26,6 +26,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <libmalcontent/manager.h>
#include <libmalcontent/session-limits.h> #include <libmalcontent/session-limits.h>
#include "libmalcontent/session-limits-private.h" #include "libmalcontent/session-limits-private.h"
@ -85,7 +86,7 @@ mct_session_limits_unref (MctSessionLimits *limits)
* *
* Get the user ID of the user this #MctSessionLimits is for. * Get the user ID of the user this #MctSessionLimits is for.
* *
* Returns: user ID of the relevant user * Returns: user ID of the relevant user, or `(uid_t) -1` if unknown
* Since: 0.5.0 * Since: 0.5.0
*/ */
uid_t uid_t
@ -97,6 +98,31 @@ mct_session_limits_get_user_id (MctSessionLimits *limits)
return limits->user_id; return limits->user_id;
} }
/**
* mct_session_limits_is_enabled:
* @limits: an #MctSessionLimits
*
* Check whether any session limits are enabled and are going to impose at least
* one restriction on the user. This gives a high level view of whether session
* limit parental controls are enabled for the given user.
*
* This function is equivalent to the value returned by the
* `time_limit_enabled_out` argument of
* mct_session_limits_check_time_remaining().
*
* Returns: %TRUE if the session limits object contains at least one restrictive
* session limit, %FALSE if there are no limits in place
* Since: 0.7.0
*/
gboolean
mct_session_limits_is_enabled (MctSessionLimits *limits)
{
g_return_val_if_fail (limits != NULL, FALSE);
g_return_val_if_fail (limits->ref_count >= 1, FALSE);
return (limits->limit_type != MCT_SESSION_LIMITS_TYPE_NONE);
}
/** /**
* mct_session_limits_check_time_remaining: * mct_session_limits_check_time_remaining:
* @limits: an #MctSessionLimits * @limits: an #MctSessionLimits
@ -190,6 +216,149 @@ out:
return user_allowed_now; return user_allowed_now;
} }
/**
* mct_session_limits_serialize:
* @limits: an #MctSessionLimits
*
* Build a #GVariant which contains the session limits from @limits, in an
* opaque variant format. This format may change in future, but
* mct_session_limits_deserialize() is guaranteed to always be able to load any
* variant produced by the current or any previous version of
* mct_session_limits_serialize().
*
* Returns: (transfer floating): a new, floating #GVariant containing the
* session limits
* Since: 0.7.0
*/
GVariant *
mct_session_limits_serialize (MctSessionLimits *limits)
{
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{sv}"));
g_autoptr(GVariant) limit_variant = NULL;
const gchar *limit_property_name;
g_return_val_if_fail (limits != NULL, NULL);
g_return_val_if_fail (limits->ref_count >= 1, NULL);
/* The serialisation format is exactly the
* `com.endlessm.ParentalControls.SessionLimits` D-Bus interface. */
switch (limits->limit_type)
{
case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE:
limit_variant = g_variant_new ("(uu)",
limits->daily_start_time,
limits->daily_end_time);
limit_property_name = "DailySchedule";
break;
case MCT_SESSION_LIMITS_TYPE_NONE:
limit_variant = NULL;
limit_property_name = NULL;
break;
default:
g_assert_not_reached ();
}
if (limit_property_name != NULL)
{
g_variant_builder_add (&builder, "{sv}", limit_property_name,
g_steal_pointer (&limit_variant));
}
g_variant_builder_add (&builder, "{sv}", "LimitType",
g_variant_new_uint32 (limits->limit_type));
return g_variant_builder_end (&builder);
}
/**
* mct_session_limits_deserialize:
* @variant: a serialized session limits variant
* @user_id: the ID of the user the session limits relate to
* @error: return location for a #GError, or %NULL
*
* Deserialize a set of session limits previously serialized with
* mct_session_limits_serialize(). This function guarantees to be able to
* deserialize any serialized form from this version or older versions of
* libmalcontent.
*
* If deserialization fails, %MCT_MANAGER_ERROR_INVALID_DATA will be returned.
*
* Returns: (transfer full): deserialized session limits
* Since: 0.7.0
*/
MctSessionLimits *
mct_session_limits_deserialize (GVariant *variant,
uid_t user_id,
GError **error)
{
g_autoptr(MctSessionLimits) session_limits = NULL;
guint32 limit_type;
guint32 daily_start_time, daily_end_time;
g_return_val_if_fail (variant != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* Check the overall type. */
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}")))
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("Session limit for user %u was in an unrecognized format"),
(guint) user_id);
return NULL;
}
/* Extract the properties we care about. The default values here should be
* kept in sync with those in the `com.endlessm.ParentalControls.SessionLimits`
* D-Bus interface. */
if (!g_variant_lookup (variant, "LimitType", "u",
&limit_type))
{
/* Default value. */
limit_type = MCT_SESSION_LIMITS_TYPE_NONE;
}
/* Check that the limit type is something we support. */
G_STATIC_ASSERT (sizeof (limit_type) >= sizeof (MctSessionLimitsType));
if ((guint) limit_type > MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE)
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("Session limit for user %u has an unrecognized type %u"),
(guint) user_id, limit_type);
return NULL;
}
if (!g_variant_lookup (variant, "DailySchedule", "(uu)",
&daily_start_time, &daily_end_time))
{
/* Default value. */
daily_start_time = 0;
daily_end_time = 24 * 60 * 60;
}
if (daily_start_time >= daily_end_time ||
daily_end_time > 24 * 60 * 60)
{
g_set_error (error, MCT_MANAGER_ERROR,
MCT_MANAGER_ERROR_INVALID_DATA,
_("Session limit for user %u has invalid daily schedule %u%u"),
(guint) user_id, daily_start_time, daily_end_time);
return NULL;
}
/* Success. Create an #MctSessionLimits object to contain the results. */
session_limits = g_new0 (MctSessionLimits, 1);
session_limits->ref_count = 1;
session_limits->user_id = user_id;
session_limits->limit_type = limit_type;
session_limits->daily_start_time = daily_start_time;
session_limits->daily_end_time = daily_end_time;
return g_steal_pointer (&session_limits);
}
/* /*
* Actual implementation of #MctSessionLimitsBuilder. * Actual implementation of #MctSessionLimitsBuilder.
* *

View File

@ -52,11 +52,19 @@ void mct_session_limits_unref (MctSessionLimits *limits);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctSessionLimits, mct_session_limits_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctSessionLimits, mct_session_limits_unref)
uid_t mct_session_limits_get_user_id (MctSessionLimits *limits); uid_t mct_session_limits_get_user_id (MctSessionLimits *limits);
gboolean mct_session_limits_is_enabled (MctSessionLimits *limits);
gboolean mct_session_limits_check_time_remaining (MctSessionLimits *limits, gboolean mct_session_limits_check_time_remaining (MctSessionLimits *limits,
guint64 now_usecs, guint64 now_usecs,
guint64 *time_remaining_secs_out, guint64 *time_remaining_secs_out,
gboolean *time_limit_enabled_out); gboolean *time_limit_enabled_out);
GVariant *mct_session_limits_serialize (MctSessionLimits *limits);
MctSessionLimits *mct_session_limits_deserialize (GVariant *variant,
uid_t user_id,
GError **error);
/** /**
* MctSessionLimitsBuilder: * MctSessionLimitsBuilder:
* *

View File

@ -85,6 +85,191 @@ test_app_filter_refs (void)
/* Final ref is dropped by g_autoptr(). */ /* Final ref is dropped by g_autoptr(). */
} }
/* Basic test of mct_app_filter_serialize() on an app filter. */
static void
test_app_filter_serialize (void)
{
g_auto(MctAppFilterBuilder) builder = MCT_APP_FILTER_BUILDER_INIT ();
g_autoptr(MctAppFilter) filter = NULL;
g_autoptr(GVariant) serialized = NULL;
/* Use an empty #MctAppFilter. */
filter = mct_app_filter_builder_end (&builder);
/* We cant assert anything about the serialisation format, since its opaque. */
serialized = mct_app_filter_serialize (filter);
g_assert_nonnull (serialized);
}
/* Basic test of mct_app_filter_deserialize() on various current and historic
* serialised app filter variants. */
static void
test_app_filter_deserialize (void)
{
/* These are all opaque. Older versions should be kept around to test
* backwards compatibility. */
const gchar *valid_app_filters[] =
{
"@a{sv} {}",
"{ 'AppFilter': <(true, @as [])> }",
"{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'mild' })> }",
"{ 'AllowUserInstallation': <true> }",
"{ 'AllowSystemInstallation': <true> }",
};
for (gsize i = 0; i < G_N_ELEMENTS (valid_app_filters); i++)
{
g_autoptr(GVariant) serialized = NULL;
g_autoptr(MctAppFilter) filter = NULL;
g_autoptr(GError) local_error = NULL;
g_test_message ("%" G_GSIZE_FORMAT ": %s", i, valid_app_filters[i]);
serialized = g_variant_parse (NULL, valid_app_filters[i], NULL, NULL, NULL);
g_assert (serialized != NULL);
filter = mct_app_filter_deserialize (serialized, 1, &local_error);
g_assert_no_error (local_error);
g_assert_nonnull (filter);
}
}
/* Test of mct_app_filter_deserialize() on various invalid variants. */
static void
test_app_filter_deserialize_invalid (void)
{
const gchar *invalid_app_filters[] =
{
"false",
"()",
"{ 'OarsFilter': <('invalid', { 'violence-cartoon': 'mild' })> }",
};
for (gsize i = 0; i < G_N_ELEMENTS (invalid_app_filters); i++)
{
g_autoptr(GVariant) serialized = NULL;
g_autoptr(MctAppFilter) filter = NULL;
g_autoptr(GError) local_error = NULL;
g_test_message ("%" G_GSIZE_FORMAT ": %s", i, invalid_app_filters[i]);
serialized = g_variant_parse (NULL, invalid_app_filters[i], NULL, NULL, NULL);
g_assert (serialized != NULL);
filter = mct_app_filter_deserialize (serialized, 1, &local_error);
g_assert_error (local_error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_INVALID_DATA);
g_assert_null (filter);
}
}
/* Test that mct_app_filter_equal() returns the correct results on various
* app filters. */
static void
test_app_filter_equal (void)
{
g_auto(MctAppFilterBuilder) builder = MCT_APP_FILTER_BUILDER_INIT ();
MctAppFilter *equal_filters[2];
const gchar *unequal_filters_serialised[] =
{
"{ 'AppFilter': <(true, @as ['/usr/bin/gnome-software'])> }",
"{ 'AppFilter': <(false, @as ['/usr/bin/gnome-software'])> }",
"{ 'AllowUserInstallation': <true> }",
"{ 'AllowSystemInstallation': <true> }",
"{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'mild' })> }",
};
MctAppFilter *unequal_filters[G_N_ELEMENTS (unequal_filters_serialised)];
/* Build a couple of filters which are identical. */
equal_filters[0] = mct_app_filter_builder_end (&builder);
mct_app_filter_builder_init (&builder);
equal_filters[1] = mct_app_filter_builder_end (&builder);
/* And a load of filters which are not. */
for (gsize i = 0; i < G_N_ELEMENTS (unequal_filters_serialised); i++)
{
g_autoptr(GVariant) serialized = NULL;
serialized = g_variant_parse (NULL, unequal_filters_serialised[i], NULL, NULL, NULL);
g_assert (serialized != NULL);
unequal_filters[i] = mct_app_filter_deserialize (serialized, 1, NULL);
g_assert (unequal_filters[i] != NULL);
}
/* Test the equality checks on them all. */
for (gsize i = 0; i < G_N_ELEMENTS (equal_filters); i++)
for (gsize j = 0; j < G_N_ELEMENTS (equal_filters); j++)
g_assert_true (mct_app_filter_equal (equal_filters[i], equal_filters[j]));
for (gsize i = 0; i < G_N_ELEMENTS (unequal_filters); i++)
{
for (gsize j = 0; j < G_N_ELEMENTS (equal_filters); j++)
g_assert_false (mct_app_filter_equal (unequal_filters[i], equal_filters[j]));
for (gsize j = 0; j < G_N_ELEMENTS (unequal_filters); j++)
{
if (i != j)
g_assert_false (mct_app_filter_equal (unequal_filters[i], unequal_filters[j]));
else
g_assert_true (mct_app_filter_equal (unequal_filters[i], unequal_filters[j]));
}
}
for (gsize i = 0; i < G_N_ELEMENTS (equal_filters); i++)
mct_app_filter_unref (equal_filters[i]);
for (gsize i = 0; i < G_N_ELEMENTS (unequal_filters); i++)
mct_app_filter_unref (unequal_filters[i]);
}
/* Test that mct_app_filter_is_enabled() returns the correct results on various
* app filters. */
static void
test_app_filter_is_enabled (void)
{
const struct
{
const gchar *serialized;
gboolean is_enabled;
}
app_filters[] =
{
{ "@a{sv} {}", FALSE },
{ "{ 'AppFilter': <(true, @as [])> }", TRUE },
{ "{ 'AppFilter': <(false, @as [])> }", FALSE },
{ "{ 'AppFilter': <(false, @as [ '/usr/bin/gnome-software' ])> }", TRUE },
{ "{ 'OarsFilter': <('oars-1.1', @a{ss} {})> }", FALSE },
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'mild' })> }", TRUE },
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'intense' })> }", FALSE },
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': '' })> }", FALSE }, /* technically an invalid serialisation */
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'none' })> }", TRUE },
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'mild', 'violence-realistic': 'intense' })> }", TRUE },
{ "{ 'OarsFilter': <('oars-1.1', { 'violence-cartoon': 'mild', 'violence-realistic': 'none' })> }", TRUE },
{ "{ 'AllowUserInstallation': <true> }", FALSE },
{ "{ 'AllowUserInstallation': <false> }", TRUE },
{ "{ 'AllowSystemInstallation': <true> }", FALSE },
{ "{ 'AllowSystemInstallation': <false> }", FALSE },
};
for (gsize i = 0; i < G_N_ELEMENTS (app_filters); i++)
{
g_autoptr(GVariant) variant = NULL;
g_autoptr(MctAppFilter) filter = NULL;
g_test_message ("%" G_GSIZE_FORMAT ": %s", i, app_filters[i].serialized);
variant = g_variant_parse (NULL, app_filters[i].serialized, NULL, NULL, NULL);
g_assert (variant != NULL);
filter = mct_app_filter_deserialize (variant, 1, NULL);
g_assert (filter != NULL);
if (app_filters[i].is_enabled)
g_assert_true (mct_app_filter_is_enabled (filter));
else
g_assert_false (mct_app_filter_is_enabled (filter));
}
}
/* Fixture for tests which use an #MctAppFilterBuilder. The builder can either /* Fixture for tests which use an #MctAppFilterBuilder. The builder can either
* be heap- or stack-allocated. @builder will always be a valid pointer to it. * be heap- or stack-allocated. @builder will always be a valid pointer to it.
*/ */
@ -149,13 +334,13 @@ test_app_filter_builder_non_empty (BuilderFixture *fixture,
g_autoptr(MctAppFilter) filter = NULL; g_autoptr(MctAppFilter) filter = NULL;
g_autofree const gchar **sections = NULL; g_autofree const gchar **sections = NULL;
mct_app_filter_builder_blacklist_path (fixture->builder, "/bin/true"); mct_app_filter_builder_blocklist_path (fixture->builder, "/bin/true");
mct_app_filter_builder_blacklist_path (fixture->builder, "/usr/bin/gnome-software"); mct_app_filter_builder_blocklist_path (fixture->builder, "/usr/bin/gnome-software");
mct_app_filter_builder_blacklist_flatpak_ref (fixture->builder, mct_app_filter_builder_blocklist_flatpak_ref (fixture->builder,
"app/org.doom.Doom/x86_64/master"); "app/org.doom.Doom/x86_64/stable");
mct_app_filter_builder_blacklist_content_type (fixture->builder, mct_app_filter_builder_blocklist_content_type (fixture->builder,
"x-scheme-handler/http"); "x-scheme-handler/http");
mct_app_filter_builder_set_oars_value (fixture->builder, "drugs-alcohol", mct_app_filter_builder_set_oars_value (fixture->builder, "drugs-alcohol",
@ -167,15 +352,17 @@ test_app_filter_builder_non_empty (BuilderFixture *fixture,
filter = mct_app_filter_builder_end (fixture->builder); filter = mct_app_filter_builder_end (fixture->builder);
g_assert_true (mct_app_filter_is_enabled (filter));
g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false")); g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false"));
g_assert_false (mct_app_filter_is_path_allowed (filter, g_assert_false (mct_app_filter_is_path_allowed (filter,
"/usr/bin/gnome-software")); "/usr/bin/gnome-software"));
g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter, g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter,
"app/org.gnome.Ponies/x86_64/master")); "app/org.gnome.Ponies/x86_64/stable"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.gnome.Ponies")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.gnome.Ponies"));
g_assert_false (mct_app_filter_is_flatpak_ref_allowed (filter, g_assert_false (mct_app_filter_is_flatpak_ref_allowed (filter,
"app/org.doom.Doom/x86_64/master")); "app/org.doom.Doom/x86_64/stable"));
g_assert_false (mct_app_filter_is_flatpak_app_allowed (filter, "org.doom.Doom")); g_assert_false (mct_app_filter_is_flatpak_app_allowed (filter, "org.doom.Doom"));
g_assert_false (mct_app_filter_is_content_type_allowed (filter, g_assert_false (mct_app_filter_is_content_type_allowed (filter,
@ -208,15 +395,17 @@ test_app_filter_builder_empty (BuilderFixture *fixture,
filter = mct_app_filter_builder_end (fixture->builder); filter = mct_app_filter_builder_end (fixture->builder);
g_assert_false (mct_app_filter_is_enabled (filter));
g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false")); g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false"));
g_assert_true (mct_app_filter_is_path_allowed (filter, g_assert_true (mct_app_filter_is_path_allowed (filter,
"/usr/bin/gnome-software")); "/usr/bin/gnome-software"));
g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter, g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter,
"app/org.gnome.Ponies/x86_64/master")); "app/org.gnome.Ponies/x86_64/stable"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.gnome.Ponies")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.gnome.Ponies"));
g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter, g_assert_true (mct_app_filter_is_flatpak_ref_allowed (filter,
"app/org.doom.Doom/x86_64/master")); "app/org.doom.Doom/x86_64/stable"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.doom.Doom")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (filter, "org.doom.Doom"));
g_assert_true (mct_app_filter_is_content_type_allowed (filter, g_assert_true (mct_app_filter_is_content_type_allowed (filter,
@ -250,11 +439,12 @@ test_app_filter_builder_copy_empty (void)
builder_copy = mct_app_filter_builder_copy (builder); builder_copy = mct_app_filter_builder_copy (builder);
mct_app_filter_builder_init (builder_copy); mct_app_filter_builder_init (builder_copy);
mct_app_filter_builder_blacklist_path (builder_copy, "/bin/true"); mct_app_filter_builder_blocklist_path (builder_copy, "/bin/true");
mct_app_filter_builder_blacklist_content_type (builder_copy, mct_app_filter_builder_blocklist_content_type (builder_copy,
"x-scheme-handler/http"); "x-scheme-handler/http");
filter = mct_app_filter_builder_end (builder_copy); filter = mct_app_filter_builder_end (builder_copy);
g_assert_true (mct_app_filter_is_enabled (filter));
g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false")); g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false"));
g_assert_false (mct_app_filter_is_path_allowed (filter, "/bin/true")); g_assert_false (mct_app_filter_is_path_allowed (filter, "/bin/true"));
g_assert_true (mct_app_filter_is_content_type_allowed (filter, g_assert_true (mct_app_filter_is_content_type_allowed (filter,
@ -274,14 +464,15 @@ test_app_filter_builder_copy_full (void)
g_autoptr(MctAppFilterBuilder) builder_copy = NULL; g_autoptr(MctAppFilterBuilder) builder_copy = NULL;
g_autoptr(MctAppFilter) filter = NULL; g_autoptr(MctAppFilter) filter = NULL;
mct_app_filter_builder_blacklist_path (builder, "/bin/true"); mct_app_filter_builder_blocklist_path (builder, "/bin/true");
mct_app_filter_builder_blacklist_content_type (builder, mct_app_filter_builder_blocklist_content_type (builder,
"x-scheme-handler/http"); "x-scheme-handler/http");
mct_app_filter_builder_set_allow_user_installation (builder, FALSE); mct_app_filter_builder_set_allow_user_installation (builder, FALSE);
mct_app_filter_builder_set_allow_system_installation (builder, TRUE); mct_app_filter_builder_set_allow_system_installation (builder, TRUE);
builder_copy = mct_app_filter_builder_copy (builder); builder_copy = mct_app_filter_builder_copy (builder);
filter = mct_app_filter_builder_end (builder_copy); filter = mct_app_filter_builder_end (builder_copy);
g_assert_true (mct_app_filter_is_enabled (filter));
g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false")); g_assert_true (mct_app_filter_is_path_allowed (filter, "/bin/false"));
g_assert_false (mct_app_filter_is_path_allowed (filter, "/bin/true")); g_assert_false (mct_app_filter_is_path_allowed (filter, "/bin/true"));
g_assert_true (mct_app_filter_is_content_type_allowed (filter, g_assert_true (mct_app_filter_is_content_type_allowed (filter,
@ -413,9 +604,9 @@ test_app_filter_appinfo (void)
"MimeType=x-scheme-handler/http\n" }, "MimeType=x-scheme-handler/http\n" },
}; };
mct_app_filter_builder_blacklist_path (&builder, "/bin/false"); mct_app_filter_builder_blocklist_path (&builder, "/bin/false");
mct_app_filter_builder_blacklist_flatpak_ref (&builder, "app/org.gnome.Nasty/x86_64/stable"); mct_app_filter_builder_blocklist_flatpak_ref (&builder, "app/org.gnome.Nasty/x86_64/stable");
mct_app_filter_builder_blacklist_content_type (&builder, "x-scheme-handler/http"); mct_app_filter_builder_blocklist_content_type (&builder, "x-scheme-handler/http");
filter = mct_app_filter_builder_end (&builder); filter = mct_app_filter_builder_end (&builder);
@ -614,17 +805,18 @@ test_app_filter_bus_get (BusFixture *fixture,
/* Check the app filter properties. */ /* Check the app filter properties. */
g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid); g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid);
g_assert_true (mct_app_filter_is_enabled (app_filter));
g_assert_false (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Builder")); g_assert_false (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Builder"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Chess")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Chess"));
} }
/* Test that getting an #MctAppFilter containing a whitelist from the mock D-Bus /* Test that getting an #MctAppFilter containing a allowlist from the mock D-Bus
* service works, and that the #MctAppFilter methods handle the whitelist * service works, and that the #MctAppFilter methods handle the allowlist
* correctly. * correctly.
* *
* The mock D-Bus replies are generated in get_app_filter_server_cb(). */ * The mock D-Bus replies are generated in get_app_filter_server_cb(). */
static void static void
test_app_filter_bus_get_whitelist (BusFixture *fixture, test_app_filter_bus_get_allowlist (BusFixture *fixture,
gconstpointer test_data) gconstpointer test_data)
{ {
g_autoptr(MctAppFilter) app_filter = NULL; g_autoptr(MctAppFilter) app_filter = NULL;
@ -636,8 +828,8 @@ test_app_filter_bus_get_whitelist (BusFixture *fixture,
"'AllowUserInstallation': <true>," "'AllowUserInstallation': <true>,"
"'AllowSystemInstallation': <true>," "'AllowSystemInstallation': <true>,"
"'AppFilter': <(true, [" "'AppFilter': <(true, ["
"'app/org.gnome.Whitelisted1/x86_64/stable'," "'app/org.gnome.Allowlisted1/x86_64/stable',"
"'app/org.gnome.Whitelisted2/x86_64/stable'," "'app/org.gnome.Allowlisted2/x86_64/stable',"
"'/usr/bin/true'," "'/usr/bin/true',"
"'text/plain'" "'text/plain'"
"])>," "])>,"
@ -656,14 +848,15 @@ test_app_filter_bus_get_whitelist (BusFixture *fixture,
g_assert_no_error (local_error); g_assert_no_error (local_error);
g_assert_nonnull (app_filter); g_assert_nonnull (app_filter);
/* Check the app filter properties. The returned filter is a whitelist, /* Check the app filter properties. The returned filter is a allowlist,
* whereas typically a blacklist is returned. */ * whereas typically a blocklist is returned. */
g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid); g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid);
g_assert_true (mct_app_filter_is_enabled (app_filter));
g_assert_false (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Builder")); g_assert_false (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Builder"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Whitelisted1")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Allowlisted1"));
g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Whitelisted2")); g_assert_true (mct_app_filter_is_flatpak_app_allowed (app_filter, "org.gnome.Allowlisted2"));
g_assert_true (mct_app_filter_is_flatpak_ref_allowed (app_filter, "app/org.gnome.Whitelisted1/x86_64/stable")); g_assert_true (mct_app_filter_is_flatpak_ref_allowed (app_filter, "app/org.gnome.Allowlisted1/x86_64/stable"));
g_assert_false (mct_app_filter_is_flatpak_ref_allowed (app_filter, "app/org.gnome.Whitelisted1/x86_64/unknown")); g_assert_false (mct_app_filter_is_flatpak_ref_allowed (app_filter, "app/org.gnome.Allowlisted1/x86_64/unknown"));
g_assert_true (mct_app_filter_is_path_allowed (app_filter, "/usr/bin/true")); g_assert_true (mct_app_filter_is_path_allowed (app_filter, "/usr/bin/true"));
g_assert_false (mct_app_filter_is_path_allowed (app_filter, "/usr/bin/false")); g_assert_false (mct_app_filter_is_path_allowed (app_filter, "/usr/bin/false"));
g_assert_true (mct_app_filter_is_content_type_allowed (app_filter, g_assert_true (mct_app_filter_is_content_type_allowed (app_filter,
@ -714,6 +907,7 @@ test_app_filter_bus_get_all_oars_values (BusFixture *fixture,
/* Check the OARS filter properties. Each OARS value should have been parsed /* Check the OARS filter properties. Each OARS value should have been parsed
* correctly, except for the unknown `other` one. */ * correctly, except for the unknown `other` one. */
g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid); g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid);
g_assert_true (mct_app_filter_is_enabled (app_filter));
g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-bloodshed"), ==, g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-bloodshed"), ==,
MCT_APP_FILTER_OARS_VALUE_NONE); MCT_APP_FILTER_OARS_VALUE_NONE);
g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-sexual"), ==, g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-sexual"), ==,
@ -761,6 +955,7 @@ test_app_filter_bus_get_defaults (BusFixture *fixture,
/* Check the default values for the properties. */ /* Check the default values for the properties. */
g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid); g_assert_cmpuint (mct_app_filter_get_user_id (app_filter), ==, fixture->valid_uid);
g_assert_false (mct_app_filter_is_enabled (app_filter));
oars_sections = mct_app_filter_get_oars_sections (app_filter); oars_sections = mct_app_filter_get_oars_sections (app_filter);
g_assert_cmpuint (g_strv_length ((gchar **) oars_sections), ==, 0); g_assert_cmpuint (g_strv_length ((gchar **) oars_sections), ==, 0);
g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-bloodshed"), ==, g_assert_cmpint (mct_app_filter_get_oars_value (app_filter, "violence-bloodshed"), ==,
@ -1164,10 +1359,10 @@ test_app_filter_bus_set (BusFixture *fixture,
}; };
/* Build an app filter. */ /* Build an app filter. */
mct_app_filter_builder_blacklist_path (&builder, "/usr/bin/false"); mct_app_filter_builder_blocklist_path (&builder, "/usr/bin/false");
mct_app_filter_builder_blacklist_path (&builder, "/usr/bin/banned"); mct_app_filter_builder_blocklist_path (&builder, "/usr/bin/banned");
mct_app_filter_builder_blacklist_flatpak_ref (&builder, "app/org.gnome.Nasty/x86_64/stable"); mct_app_filter_builder_blocklist_flatpak_ref (&builder, "app/org.gnome.Nasty/x86_64/stable");
mct_app_filter_builder_blacklist_content_type (&builder, "x-scheme-handler/http"); mct_app_filter_builder_blocklist_content_type (&builder, "x-scheme-handler/http");
mct_app_filter_builder_set_oars_value (&builder, "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_INTENSE); mct_app_filter_builder_set_oars_value (&builder, "violence-fantasy", MCT_APP_FILTER_OARS_VALUE_INTENSE);
mct_app_filter_builder_set_allow_user_installation (&builder, TRUE); mct_app_filter_builder_set_allow_user_installation (&builder, TRUE);
mct_app_filter_builder_set_allow_system_installation (&builder, TRUE); mct_app_filter_builder_set_allow_system_installation (&builder, TRUE);
@ -1381,6 +1576,14 @@ main (int argc,
g_test_add_func ("/app-filter/types", test_app_filter_types); g_test_add_func ("/app-filter/types", test_app_filter_types);
g_test_add_func ("/app-filter/refs", test_app_filter_refs); g_test_add_func ("/app-filter/refs", test_app_filter_refs);
g_test_add_func ("/app-filter/serialize", test_app_filter_serialize);
g_test_add_func ("/app-filter/deserialize", test_app_filter_deserialize);
g_test_add_func ("/app-filter/deserialize/invalid", test_app_filter_deserialize_invalid);
g_test_add_func ("/app-filter/equal", test_app_filter_equal);
g_test_add_func ("/app-filter/is-enabled", test_app_filter_is_enabled);
g_test_add ("/app-filter/builder/stack/non-empty", BuilderFixture, NULL, g_test_add ("/app-filter/builder/stack/non-empty", BuilderFixture, NULL,
builder_set_up_stack, test_app_filter_builder_non_empty, builder_set_up_stack, test_app_filter_builder_non_empty,
builder_tear_down_stack); builder_tear_down_stack);
@ -1410,8 +1613,8 @@ main (int argc,
bus_set_up, test_app_filter_bus_get, bus_tear_down); bus_set_up, test_app_filter_bus_get, bus_tear_down);
g_test_add ("/app-filter/bus/get/sync", BusFixture, GUINT_TO_POINTER (FALSE), g_test_add ("/app-filter/bus/get/sync", BusFixture, GUINT_TO_POINTER (FALSE),
bus_set_up, test_app_filter_bus_get, bus_tear_down); bus_set_up, test_app_filter_bus_get, bus_tear_down);
g_test_add ("/app-filter/bus/get/whitelist", BusFixture, NULL, g_test_add ("/app-filter/bus/get/allowlist", BusFixture, NULL,
bus_set_up, test_app_filter_bus_get_whitelist, bus_tear_down); bus_set_up, test_app_filter_bus_get_allowlist, bus_tear_down);
g_test_add ("/app-filter/bus/get/all-oars-values", BusFixture, NULL, g_test_add ("/app-filter/bus/get/all-oars-values", BusFixture, NULL,
bus_set_up, test_app_filter_bus_get_all_oars_values, bus_tear_down); bus_set_up, test_app_filter_bus_get_all_oars_values, bus_tear_down);
g_test_add ("/app-filter/bus/get/defaults", BusFixture, NULL, g_test_add ("/app-filter/bus/get/defaults", BusFixture, NULL,

View File

@ -3,8 +3,8 @@ deps = [
dependency('gio-unix-2.0', version: '>= 2.44'), dependency('gio-unix-2.0', version: '>= 2.44'),
dependency('glib-2.0', version: '>= 2.60.0'), dependency('glib-2.0', version: '>= 2.60.0'),
dependency('gobject-2.0', version: '>= 2.44'), dependency('gobject-2.0', version: '>= 2.44'),
dependency('glib-testing-0', fallback: ['libglib-testing', 'libglib_testing_dep']),
libmalcontent_dep, libmalcontent_dep,
libglib_testing_dep,
] ]
envs = test_env + [ envs = test_env + [
@ -34,8 +34,8 @@ accounts_service_iface_c = custom_target(
) )
accounts_service_extension_ifaces = [ accounts_service_extension_ifaces = [
join_paths(meson.source_root(), 'accounts-service', 'com.endlessm.ParentalControls.AppFilter.xml'), join_paths(meson.current_source_dir(), '..', '..', 'accounts-service', 'com.endlessm.ParentalControls.AppFilter.xml'),
join_paths(meson.source_root(), 'accounts-service', 'com.endlessm.ParentalControls.SessionLimits.xml'), join_paths(meson.current_source_dir(), '..', '..', 'accounts-service', 'com.endlessm.ParentalControls.SessionLimits.xml'),
] ]
accounts_service_extension_iface_h = custom_target( accounts_service_extension_iface_h = custom_target(

View File

@ -92,6 +92,84 @@ test_session_limits_check_time_remaining_invalid_time (void)
g_assert_true (time_limit_enabled); g_assert_true (time_limit_enabled);
} }
/* Basic test of mct_session_limits_serialize() on session limits. */
static void
test_session_limits_serialize (void)
{
g_auto(MctSessionLimitsBuilder) builder = MCT_SESSION_LIMITS_BUILDER_INIT ();
g_autoptr(MctSessionLimits) limits = NULL;
g_autoptr(GVariant) serialized = NULL;
/* Use an empty #MctSessionLimits. */
limits = mct_session_limits_builder_end (&builder);
/* We cant assert anything about the serialisation format, since its opaque. */
serialized = mct_session_limits_serialize (limits);
g_assert_nonnull (serialized);
}
/* Basic test of mct_session_limits_deserialize() on various current and historic
* serialised app filter variants. */
static void
test_session_limits_deserialize (void)
{
/* These are all opaque. Older versions should be kept around to test
* backwards compatibility. */
const gchar *valid_session_limits[] =
{
"@a{sv} {}",
"{ 'LimitType': <@u 0> }",
"{ 'LimitType': <@u 1>, 'DailySchedule': <(@u 0, @u 100)> }",
"{ 'DailySchedule': <(@u 0, @u 100)> }",
};
for (gsize i = 0; i < G_N_ELEMENTS (valid_session_limits); i++)
{
g_autoptr(GVariant) serialized = NULL;
g_autoptr(MctSessionLimits) limits = NULL;
g_autoptr(GError) local_error = NULL;
g_test_message ("%" G_GSIZE_FORMAT ": %s", i, valid_session_limits[i]);
serialized = g_variant_parse (NULL, valid_session_limits[i], NULL, NULL, NULL);
g_assert (serialized != NULL);
limits = mct_session_limits_deserialize (serialized, 1, &local_error);
g_assert_no_error (local_error);
g_assert_nonnull (limits);
}
}
/* Test of mct_session_limits_deserialize() on various invalid variants. */
static void
test_session_limits_deserialize_invalid (void)
{
const gchar *invalid_session_limits[] =
{
"false",
"()",
"{ 'LimitType': <@u 100> }",
"{ 'DailySchedule': <(@u 100, @u 0)> }",
"{ 'DailySchedule': <(@u 0, @u 4294967295)> }",
};
for (gsize i = 0; i < G_N_ELEMENTS (invalid_session_limits); i++)
{
g_autoptr(GVariant) serialized = NULL;
g_autoptr(MctSessionLimits) limits = NULL;
g_autoptr(GError) local_error = NULL;
g_test_message ("%" G_GSIZE_FORMAT ": %s", i, invalid_session_limits[i]);
serialized = g_variant_parse (NULL, invalid_session_limits[i], NULL, NULL, NULL);
g_assert (serialized != NULL);
limits = mct_session_limits_deserialize (serialized, 1, &local_error);
g_assert_error (local_error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_INVALID_DATA);
g_assert_null (limits);
}
}
/* Fixture for tests which use an #MctSessionLimitsBuilder. The builder can /* Fixture for tests which use an #MctSessionLimitsBuilder. The builder can
* either be heap- or stack-allocated. @builder will always be a valid pointer * either be heap- or stack-allocated. @builder will always be a valid pointer
* to it. * to it.
@ -440,6 +518,7 @@ test_session_limits_bus_get (BusFixture *fixture,
/* Check the session limits properties. */ /* Check the session limits properties. */
g_assert_cmpuint (mct_session_limits_get_user_id (session_limits), ==, fixture->valid_uid); g_assert_cmpuint (mct_session_limits_get_user_id (session_limits), ==, fixture->valid_uid);
g_assert_true (mct_session_limits_is_enabled (session_limits));
g_assert_false (mct_session_limits_check_time_remaining (session_limits, usec (0), g_assert_false (mct_session_limits_check_time_remaining (session_limits, usec (0),
&time_remaining_secs, &time_limit_enabled)); &time_remaining_secs, &time_limit_enabled));
g_assert_true (time_limit_enabled); g_assert_true (time_limit_enabled);
@ -502,6 +581,7 @@ test_session_limits_bus_get_none (BusFixture *fixture,
/* Check the session limits properties. */ /* Check the session limits properties. */
g_assert_cmpuint (mct_session_limits_get_user_id (session_limits), ==, fixture->valid_uid); g_assert_cmpuint (mct_session_limits_get_user_id (session_limits), ==, fixture->valid_uid);
g_assert_false (mct_session_limits_is_enabled (session_limits));
g_assert_true (mct_session_limits_check_time_remaining (session_limits, usec (0), g_assert_true (mct_session_limits_check_time_remaining (session_limits, usec (0),
&time_remaining_secs, &time_limit_enabled)); &time_remaining_secs, &time_limit_enabled));
g_assert_false (time_limit_enabled); g_assert_false (time_limit_enabled);
@ -1130,6 +1210,10 @@ main (int argc,
g_test_add_func ("/session-limits/check-time-remaining/invalid-time", g_test_add_func ("/session-limits/check-time-remaining/invalid-time",
test_session_limits_check_time_remaining_invalid_time); test_session_limits_check_time_remaining_invalid_time);
g_test_add_func ("/session-limits/serialize", test_session_limits_serialize);
g_test_add_func ("/session-limits/deserialize", test_session_limits_deserialize);
g_test_add_func ("/session-limits/deserialize/invalid", test_session_limits_deserialize_invalid);
g_test_add ("/session-limits/builder/stack/non-empty", BuilderFixture, NULL, g_test_add ("/session-limits/builder/stack/non-empty", BuilderFixture, NULL,
builder_set_up_stack, test_session_limits_builder_non_empty, builder_set_up_stack, test_session_limits_builder_non_empty,
builder_tear_down_stack); builder_tear_down_stack);

View File

@ -1,11 +1,11 @@
.\" Manpage for malcontent\-client. .\" Manpage for malcontent\-client.
.\" Documentation is under the same licence as the malcontent .\" Documentation is under the same licence as the malcontent
.\" package. .\" package.
.TH man 8 "13 Jun 2019" "1.1" "malcontent\-client man page" .TH man 8 "27 Oct 2020" "1.2" "malcontent\-client man page"
.\" .\"
.SH NAME .SH NAME
.IX Header "NAME" .IX Header "NAME"
malcontent\-client Parental Controls Access Utility malcontent\-client \- Parental Controls Access Utility
.\" .\"
.SH SYNOPSIS .SH SYNOPSIS
.IX Header "SYNOPSIS" .IX Header "SYNOPSIS"
@ -13,19 +13,27 @@ malcontent\-client — Parental Controls Access Utility
\fBmalcontent\-client get\-app\-filter [\-q] [\-n] [\fPUSER\fB] \fBmalcontent\-client get\-app\-filter [\-q] [\-n] [\fPUSER\fB]
.PP .PP
\fBmalcontent\-client check\-app\-filter [\-q] [\-n] [\fPUSER\fB] \fPARG\fB \fBmalcontent\-client check\-app\-filter [\-q] [\-n] [\fPUSER\fB] \fPARG\fB
.PP
\fBmalcontent\-client set\-app\-filter [\-q] [\-n] [\fPUSER\fB] \fPARG\fB
.PP
\fBmalcontent\-client oars\-section [\-q] [\-n] [\fPUSER\fB] \fPSECTION\fB
.PP
\fBmalcontent\-client get\-session\-limits [\-q] [\-n] [\fPUSER\fB]
.PP
\fBmalcontent\-client monitor [\-q] [\fPUSER\fB]
.\" .\"
.SH DESCRIPTION .SH DESCRIPTION
.IX Header "DESCRIPTION" .IX Header "DESCRIPTION"
.\" .\"
\fBmalcontent\-client\fP is a utility for querying and updating the \fBmalcontent\-client\fP is a utility for querying and updating the
parental controls settings for users on the system. It will typically require parental controls settings for users on the system. It will typically require
adminstrator access to do anything more than query the current users parental administrator access to do anything more than query the current users parental
controls. controls.
.PP .PP
It communicates with accounts-service, which stores parental controls data. It communicates with accounts-service, which stores parental controls data.
.PP .PP
Its first argument is a command to run. Currently, the only supported commands Its first argument is a command to run. The supported commands are documented
are \fBget\-app\-filter\fP and \fBcheck\-app\-filter\fP. below.
.PP .PP
The command line API and output format are unstable and likely to change in The command line API and output format are unstable and likely to change in
future versions of \fBmalcontent\-client\fP. future versions of \fBmalcontent\-client\fP.
@ -33,6 +41,13 @@ future versions of \fBmalcontent\-client\fP.
.SH \fBget\-app\-filter\fP OPTIONS .SH \fBget\-app\-filter\fP OPTIONS
.IX Header "get\-app\-filter OPTIONS" .IX Header "get\-app\-filter OPTIONS"
.\" .\"
Get the app filter for a user. For example:
.RS
.ad l
# malcontent\-client get\-app\-filter timmy
.ad b
.RE
.\"
.IP "\fBUSER\fP" .IP "\fBUSER\fP"
Username or ID of the user to get the app filter for. If not specified, the Username or ID of the user to get the app filter for. If not specified, the
current user will be used by default. current user will be used by default.
@ -49,6 +64,18 @@ authorization.)
.SH \fBcheck\-app\-filter\fP OPTIONS .SH \fBcheck\-app\-filter\fP OPTIONS
.IX Header "check\-app\-filter OPTIONS" .IX Header "check\-app\-filter OPTIONS"
.\" .\"
Check if a given program, content type or flatpak ref is permitted to be used by
a user, according to their current app filter. For example:
.RS
.ad l
# malcontent\-client check\-app\-filter timmy $(which gnome\-calculator)
.PP
# malcontent\-client check\-app\-filter timmy x\-scheme\-handler/http
.PP
# malcontent\-client check\-app\-filter timmy app/com.realm667.WolfenDoom_Blade_of_Agony/x86_64/stable
.ad b
.RE
.\"
.IP "\fBUSER\fP" .IP "\fBUSER\fP"
Username or ID of the user to get the app filter for. If not specified, the Username or ID of the user to get the app filter for. If not specified, the
current user will be used by default. current user will be used by default.
@ -66,6 +93,127 @@ Do not allow interactive authorization with polkit. If this is needed to
complete the operation, the operation will fail. (Default: Allow interactive complete the operation, the operation will fail. (Default: Allow interactive
authorization.) authorization.)
.\" .\"
.SH \fBset\-app\-filter\fP OPTIONS
.IX Header "set\-app\-filter OPTIONS"
.\"
Set the app filter for a user, replacing all previous values in it. For example:
.RS
.ad l
# malcontent\-client set\-app\-filter timmy \\
\-\-disallow\-user\-installation \\
$(which gnome\-calculator) \\
x\-scheme\-handler/http \\
app/com.realm667.WolfenDoom_Blade_of_Agony/x86_64/stable
.ad b
.RE
.\"
.IP "\fBUSER\fP"
Username or ID of the user to set the app filter for. If not specified, the
current user will be used by default.
.\"
.IP "\fBARG\fP"
Item to filter in the users app filter. This could either be an absolute path
or flatpak ref of a program to block; a content type to block all programs
handling that type; or an OARS \fBsection=value\fP pair to block installation of
apps with a more extreme rating for that OARS section. Multiple items may be
specified, and they will replace the users current app filter in entirety. If
zero items are specified, the app filter is cleared.
.\"
.IP "\fB\-\-allow\-user\-installation\fP"
Allow the user to install flatpaks to their user repository.
.\"
.IP "\fB\-\-disallow\-user\-installation\fP"
Disallow the user from installing flatpaks to their user repository.
.\"
.IP "\fB\-\-allow\-system\-installation\fP"
Allow the user to install flatpaks to the system repository.
.\"
.IP "\fB\-\-disallow\-system\-installation\fP"
Disallow the user from installing flatpaks to the system repository.
.\"
.IP "\fB\-q\fP, \fB\-\-quiet\fP"
Only output error messages, and no informational messages, as the operation
progresses. (Default: Output informational messages.)
.\"
.IP "\fB\-n\fP, \fB\-\-no\-interactive\fP"
Do not allow interactive authorization with polkit. If this is needed to
complete the operation, the operation will fail. (Default: Allow interactive
authorization.)
.\"
.SH \fBoars\-section\fP OPTIONS
.IX Header "oars\-section OPTIONS"
.\"
Get the value set for a specific OARS section from the app filter of the given
user. For example:
.RS
.ad l
# malcontent\-client oars\-section timmy language\-profanity
.ad b
.RE
.\"
.IP "\fBUSER\fP"
Username or ID of the user to get the OARS filter for. If not specified, the
current user will be used by default.
.\"
.IP "\fBSECTION\fP"
OARS section to get the restriction level of the given user for.
For example, \fBlanguage\-profanity\fP.
.\"
.IP "\fB\-q\fP, \fB\-\-quiet\fP"
Only output error messages, and no informational messages, as the operation
progresses. (Default: Output informational messages.)
.\"
.IP "\fB\-n\fP, \fB\-\-no\-interactive\fP"
Do not allow interactive authorization with polkit. If this is needed to
complete the operation, the operation will fail. (Default: Allow interactive
authorization.)
.\"
.SH \fBget\-session\-limits\fP OPTIONS
.IX Header "get\-session\-limits OPTIONS"
.\"
Get the session limits set for a user. For example:
.RS
.ad l
# malcontent\-client get\-session\-limits timmy
.ad b
.RE
.\"
.IP "\fBUSER\fP"
Username or ID of the user to get the session limits for. If not specified, the
current user will be used by default.
.\"
.IP "\fB\-q\fP, \fB\-\-quiet\fP"
Only output error messages, and no informational messages, as the operation
progresses. (Default: Output informational messages.)
.\"
.IP "\fB\-n\fP, \fB\-\-no\-interactive\fP"
Do not allow interactive authorization with polkit. If this is needed to
complete the operation, the operation will fail. (Default: Allow interactive
authorization.)
.\"
.IP "\fB\-\-now yyyy\-mm\-ddThh:mm:ssZ\fP"
Check session limits (in particular, session expiry time) against the given
date/time, provided in ISO 8601 format. (Default: Current date/time.)
.\"
.SH \fBmonitor\fP OPTIONS
.IX Header "monitor OPTIONS"
.\"
Monitor changes to the parental controls settings for a specific user. For
example:
.RS
.ad l
# malcontent\-client monitor timmy
.ad b
.RE
.\"
.IP "\fBUSER\fP"
Username or ID of the user to monitor the parental controls for. If not
specified, the current user will be used by default.
.\"
.IP "\fB\-q\fP, \fB\-\-quiet\fP"
Only output error messages, and no informational messages, as the operation
progresses. (Default: Output informational messages.)
.\"
.SH "ENVIRONMENT" .SH "ENVIRONMENT"
.IX Header "ENVIRONMENT" .IX Header "ENVIRONMENT"
.\" .\"
@ -119,7 +267,7 @@ An operation failed and no more specific error information is available.
.\" .\"
Any bugs which are found should be reported on the project website: Any bugs which are found should be reported on the project website:
.br .br
\fIhttps://support.endlessm.com/\fP \fIhttps://gitlab.freedesktop.org/pwithnall/malcontent/-/issues\fP
.\" .\"
.SH AUTHOR .SH AUTHOR
.IX Header "AUTHOR" .IX Header "AUTHOR"

View File

@ -297,6 +297,7 @@ def command_check_app_filter(user, arg, quiet=False, interactive=True):
# when passing flatpak IDs as argument # when passing flatpak IDs as argument
is_maybe_content_type = not is_maybe_flatpak_id and is_valid_content_type(arg) is_maybe_content_type = not is_maybe_flatpak_id and is_valid_content_type(arg)
is_maybe_path = os.path.exists(arg) is_maybe_path = os.path.exists(arg)
is_maybe_desktop_file = arg.endswith('.desktop')
recognised_types = sum([is_maybe_flatpak_id, is_maybe_flatpak_ref, recognised_types = sum([is_maybe_flatpak_id, is_maybe_flatpak_ref,
is_maybe_content_type, is_maybe_path]) is_maybe_content_type, is_maybe_path])
@ -320,6 +321,11 @@ def command_check_app_filter(user, arg, quiet=False, interactive=True):
# Content type # Content type
is_allowed = app_filter.is_content_type_allowed(arg) is_allowed = app_filter.is_content_type_allowed(arg)
noun = 'Content type' noun = 'Content type'
elif is_maybe_path and is_maybe_desktop_file
path = os.path.abspath(arg)
app_info = Gio.DesktopAppInfo.new_from_filename(path)
is_allowed = app_filter.is_appinfo_allowed(app_info)
noun = 'Desktop file'
elif is_maybe_path: elif is_maybe_path:
path = os.path.abspath(arg) path = os.path.abspath(arg)
is_allowed = app_filter.is_path_allowed(path) is_allowed = app_filter.is_path_allowed(path)
@ -385,12 +391,12 @@ def command_set_app_filter(user, allow_user_installation=True,
file=sys.stderr) file=sys.stderr)
raise SystemExit(EXIT_INVALID_OPTION) raise SystemExit(EXIT_INVALID_OPTION)
elif is_maybe_flatpak_ref: elif is_maybe_flatpak_ref:
builder.blacklist_flatpak_ref(arg) builder.blocklist_flatpak_ref(arg)
elif is_maybe_content_type: elif is_maybe_content_type:
builder.blacklist_content_type(arg) builder.blocklist_content_type(arg)
elif is_maybe_path: elif is_maybe_path:
path = os.path.abspath(arg) path = os.path.abspath(arg)
builder.blacklist_path(path) builder.blocklist_path(path)
else: else:
raise AssertionError('code should not be reached') raise AssertionError('code should not be reached')
@ -523,7 +529,7 @@ def main():
'flatpak repo') 'flatpak repo')
parser_set_app_filter.add_argument('app_filter_args', nargs='*', parser_set_app_filter.add_argument('app_filter_args', nargs='*',
help='paths, content types or flatpak ' help='paths, content types or flatpak '
'refs to blacklist and OARS ' 'refs to blocklist and OARS '
'section=value pairs to store') 'section=value pairs to store')
parser_set_app_filter.set_defaults(allow_user_installation=True, parser_set_app_filter.set_defaults(allow_user_installation=True,
allow_system_installation=False) allow_system_installation=False)

View File

@ -27,6 +27,7 @@
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <adwaita.h>
#include <libmalcontent-ui/malcontent-ui.h> #include <libmalcontent-ui/malcontent-ui.h>
#include <polkit/polkit.h> #include <polkit/polkit.h>
@ -48,6 +49,9 @@ static void permission_notify_allowed_cb (GObject *obj,
gpointer user_data); gpointer user_data);
static void user_accounts_panel_button_clicked_cb (GtkButton *button, static void user_accounts_panel_button_clicked_cb (GtkButton *button,
gpointer user_data); gpointer user_data);
static void about_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data);
static void help_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data);
static void quit_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data);
/** /**
@ -64,6 +68,7 @@ struct _MctApplication
GCancellable *cancellable; /* (owned) */ GCancellable *cancellable; /* (owned) */
GDBusConnection *dbus_connection; /* (owned) */
ActUserManager *user_manager; /* (owned) */ ActUserManager *user_manager; /* (owned) */
GPermission *permission; /* (owned) */ GPermission *permission; /* (owned) */
@ -72,10 +77,10 @@ struct _MctApplication
MctUserSelector *user_selector; MctUserSelector *user_selector;
MctUserControls *user_controls; MctUserControls *user_controls;
GtkStack *main_stack; GtkStack *main_stack;
GtkLabel *error_title; AdwStatusPage *error_page;
GtkLabel *error_message;
GtkLockButton *lock_button; GtkLockButton *lock_button;
GtkButton *user_accounts_panel_button; GtkButton *user_accounts_panel_button;
GtkLabel *help_label;
}; };
G_DEFINE_TYPE (MctApplication, mct_application, GTK_TYPE_APPLICATION) G_DEFINE_TYPE (MctApplication, mct_application, GTK_TYPE_APPLICATION)
@ -90,9 +95,26 @@ static void
mct_application_constructed (GObject *object) mct_application_constructed (GObject *object)
{ {
GApplication *application = G_APPLICATION (object); GApplication *application = G_APPLICATION (object);
const GOptionEntry options[] =
{
{ "user", 'u', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL,
/* Translators: This documents the --user command line option to malcontent-control: */
N_("User to select in the UI"),
/* Translators: This is a placeholder for a command line argument value: */
N_("USERNAME") },
{ NULL, },
};
g_application_set_application_id (application, "org.freedesktop.MalcontentControl"); g_application_set_application_id (application, "org.freedesktop.MalcontentControl");
g_application_add_main_option_entries (application, options);
g_application_set_flags (application, g_application_get_flags (application) | G_APPLICATION_HANDLES_COMMAND_LINE);
/* Translators: This is a summary of what the application does, displayed when
* its run with --help: */
g_application_set_option_context_parameter_string (application,
N_("— view and edit parental controls"));
/* Localisation */ /* Localisation */
bindtextdomain ("malcontent", PACKAGE_LOCALE_DIR); bindtextdomain ("malcontent", PACKAGE_LOCALE_DIR);
bind_textdomain_codeset ("malcontent", "UTF-8"); bind_textdomain_codeset ("malcontent", "UTF-8");
@ -125,6 +147,7 @@ mct_application_dispose (GObject *object)
g_clear_object (&self->permission); g_clear_object (&self->permission);
} }
g_clear_object (&self->dbus_connection);
g_clear_error (&self->permission_error); g_clear_error (&self->permission_error);
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
@ -161,11 +184,20 @@ mct_application_activate (GApplication *application)
builder = gtk_builder_new (); builder = gtk_builder_new ();
g_assert (self->dbus_connection == NULL);
self->dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, self->cancellable, &local_error);
if (self->dbus_connection == NULL)
{
g_error ("Error getting system bus: %s", local_error->message);
return;
}
g_assert (self->user_manager == NULL); g_assert (self->user_manager == NULL);
self->user_manager = g_object_ref (act_user_manager_get_default ()); self->user_manager = g_object_ref (act_user_manager_get_default ());
gtk_builder_set_translation_domain (builder, "malcontent"); gtk_builder_set_translation_domain (builder, "malcontent");
gtk_builder_expose_object (builder, "user_manager", G_OBJECT (self->user_manager)); gtk_builder_expose_object (builder, "user_manager", G_OBJECT (self->user_manager));
gtk_builder_expose_object (builder, "dbus_connection", G_OBJECT (self->dbus_connection));
gtk_builder_add_from_resource (builder, "/org/freedesktop/MalcontentControl/ui/main.ui", &local_error); gtk_builder_add_from_resource (builder, "/org/freedesktop/MalcontentControl/ui/main.ui", &local_error);
g_assert (local_error == NULL); g_assert (local_error == NULL);
@ -177,8 +209,7 @@ mct_application_activate (GApplication *application)
self->main_stack = GTK_STACK (gtk_builder_get_object (builder, "main_stack")); self->main_stack = GTK_STACK (gtk_builder_get_object (builder, "main_stack"));
self->user_selector = MCT_USER_SELECTOR (gtk_builder_get_object (builder, "user_selector")); self->user_selector = MCT_USER_SELECTOR (gtk_builder_get_object (builder, "user_selector"));
self->user_controls = MCT_USER_CONTROLS (gtk_builder_get_object (builder, "user_controls")); self->user_controls = MCT_USER_CONTROLS (gtk_builder_get_object (builder, "user_controls"));
self->error_title = GTK_LABEL (gtk_builder_get_object (builder, "error_title")); self->error_page = ADW_STATUS_PAGE (gtk_builder_get_object (builder, "error_page"));
self->error_message = GTK_LABEL (gtk_builder_get_object (builder, "error_message"));
self->lock_button = GTK_LOCK_BUTTON (gtk_builder_get_object (builder, "lock_button")); self->lock_button = GTK_LOCK_BUTTON (gtk_builder_get_object (builder, "lock_button"));
self->user_accounts_panel_button = GTK_BUTTON (gtk_builder_get_object (builder, "user_accounts_panel_button")); self->user_accounts_panel_button = GTK_BUTTON (gtk_builder_get_object (builder, "user_accounts_panel_button"));
@ -197,13 +228,56 @@ mct_application_activate (GApplication *application)
user_selector_notify_user_cb (G_OBJECT (self->user_selector), NULL, self); user_selector_notify_user_cb (G_OBJECT (self->user_selector), NULL, self);
user_manager_notify_is_loaded_cb (G_OBJECT (self->user_manager), NULL, self); user_manager_notify_is_loaded_cb (G_OBJECT (self->user_manager), NULL, self);
gtk_widget_show (GTK_WIDGET (window)); gtk_window_present (GTK_WINDOW (window));
} }
/* Bring the window to the front. */ /* Bring the window to the front. */
gtk_window_present (window); gtk_window_present (window);
} }
static void
mct_application_startup (GApplication *application)
{
const GActionEntry app_entries[] =
{
{ "about", about_action_cb, NULL, NULL, NULL, { 0, } },
{ "help", help_action_cb, NULL, NULL, NULL, { 0, } },
{ "quit", quit_action_cb, NULL, NULL, NULL, { 0, } },
};
/* Chain up. */
G_APPLICATION_CLASS (mct_application_parent_class)->startup (application);
adw_init ();
g_action_map_add_action_entries (G_ACTION_MAP (application), app_entries,
G_N_ELEMENTS (app_entries), application);
gtk_application_set_accels_for_action (GTK_APPLICATION (application),
"app.help", (const gchar * const[]) { "F1", NULL });
gtk_application_set_accels_for_action (GTK_APPLICATION (application),
"app.quit", (const gchar * const[]) { "<Primary>q", "<Primary>w", NULL });
}
static gint
mct_application_command_line (GApplication *application,
GApplicationCommandLine *command_line)
{
MctApplication *self = MCT_APPLICATION (application);
GVariantDict *options = g_application_command_line_get_options_dict (command_line);
const gchar *username;
/* Show the application. */
g_application_activate (application);
/* Select a user if requested. */
if (g_variant_dict_lookup (options, "user", "&s", &username) &&
!mct_user_selector_select_user_by_username (self->user_selector, username))
g_warning ("Failed to select user %s", username);
return 0; /* exit status */
}
static void static void
mct_application_class_init (MctApplicationClass *klass) mct_application_class_init (MctApplicationClass *klass)
{ {
@ -214,6 +288,81 @@ mct_application_class_init (MctApplicationClass *klass)
object_class->dispose = mct_application_dispose; object_class->dispose = mct_application_dispose;
application_class->activate = mct_application_activate; application_class->activate = mct_application_activate;
application_class->startup = mct_application_startup;
application_class->command_line = mct_application_command_line;
}
static void
about_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data)
{
MctApplication *self = MCT_APPLICATION (user_data);
const gchar *authors[] =
{
"Philip Withnall <withnall@endlessm.com>",
"Georges Basile Stavracas Neto <georges@endlessm.com>",
"Andre Moreira Magalhaes <andre@endlessm.com>",
NULL
};
gtk_show_about_dialog (mct_application_get_main_window (self),
"version", VERSION,
"copyright", _("Copyright © 2019, 2020 Endless Mobile, Inc."),
"authors", authors,
/* Translators: this should be "translated" to the
names of people who have translated Malcontent into
this language, one per line. */
"translator-credits", _("translator-credits"),
"logo-icon-name", "org.freedesktop.MalcontentControl",
"license-type", GTK_LICENSE_GPL_2_0,
"wrap-license", TRUE,
/* Translators: "Malcontent" is the brand name of this
project, so should not be translated. */
"website-label", _("Malcontent Website"),
"website", "https://gitlab.freedesktop.org/pwithnall/malcontent",
NULL);
}
static void
on_malcontent_help_shown_finished_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
MctApplication *self = MCT_APPLICATION (user_data);
g_autoptr(GError) local_error = NULL;
if (!gtk_show_uri_full_finish (mct_application_get_main_window (self),
result,
&local_error))
{
GtkWidget *dialog = gtk_message_dialog_new (mct_application_get_main_window (self),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
_("The help contents could not be displayed"));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", local_error->message);
gtk_window_present (GTK_WINDOW (dialog));
}
}
static void
help_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data)
{
MctApplication *self = MCT_APPLICATION (user_data);
gtk_show_uri_full (mct_application_get_main_window (self),
"help:malcontent",
GDK_CURRENT_TIME,
NULL,
on_malcontent_help_shown_finished_cb,
self);
}
static void
quit_action_cb (GSimpleAction *action, GVariant *parameters, gpointer user_data)
{
MctApplication *self = MCT_APPLICATION (user_data);
g_application_quit (G_APPLICATION (self));
} }
static void static void
@ -235,9 +384,9 @@ update_main_stack (MctApplication *self)
if ((is_user_manager_loaded && act_user_manager_no_service (self->user_manager)) || if ((is_user_manager_loaded && act_user_manager_no_service (self->user_manager)) ||
self->permission_error != NULL) self->permission_error != NULL)
{ {
gtk_label_set_label (self->error_title, adw_status_page_set_title (self->error_page,
_("Failed to load user data from the system")); _("Failed to load user data from the system"));
gtk_label_set_label (self->error_message, adw_status_page_set_description (self->error_page,
_("Please make sure that the AccountsService is installed and enabled.")); _("Please make sure that the AccountsService is installed and enabled."));
new_page_name = "error"; new_page_name = "error";
@ -258,10 +407,28 @@ update_main_stack (MctApplication *self)
} }
else if (is_permission_loaded && is_user_manager_loaded) else if (is_permission_loaded && is_user_manager_loaded)
{ {
g_autofree gchar *help_label = NULL;
/* Translators: Replace the link to commonsensemedia.org with some
* localised guidance for parents/carers on how to set restrictions on
* their child/caree in a responsible way which is in keeping with the
* best practice and culture of the region. If no suitable localised
* guidance exists, and if the default commonsensemedia.org link is not
* suitable, please file an issue against malcontent so we can discuss
* further!
* https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/new
*/
help_label = g_strdup_printf (_("Its recommended that restrictions are "
"set as part of an ongoing conversation "
"with %s. <a href='https://www.commonsensemedia.org/privacy-and-internet-safety'>"
"Read guidance</a> on what to consider."),
act_user_get_real_name (selected_user));
mct_user_controls_set_description (self->user_controls, help_label);
mct_user_controls_set_user (self->user_controls, selected_user); mct_user_controls_set_user (self->user_controls, selected_user);
new_page_name = "controls"; new_page_name = "controls";
new_focus_widget = GTK_WIDGET (self->user_selector); new_focus_widget = GTK_WIDGET (self->user_controls);
} }
else else
{ {

View File

@ -18,6 +18,7 @@
* *
* Authors: * Authors:
* - Felipe Borges <felipeborges@gnome.org> * - Felipe Borges <felipeborges@gnome.org>
* - Georges Basile Stavracas Neto <georges@endlessos.org>
* - Philip Withnall <withnall@endlessm.com> * - Philip Withnall <withnall@endlessm.com>
*/ */
@ -29,13 +30,16 @@
#define ARROW_SIZE 20 #define ARROW_SIZE 20
#define MCT_TYPE_CAROUSEL_LAYOUT (mct_carousel_layout_get_type ())
G_DECLARE_FINAL_TYPE (MctCarouselLayout, mct_carousel_layout, MCT, CAROUSEL_LAYOUT, GtkLayoutManager)
struct _MctCarouselItem { struct _MctCarouselItem {
GtkRadioButton parent; GtkButton parent;
gint page; gint page;
}; };
G_DEFINE_TYPE (MctCarouselItem, mct_carousel_item, GTK_TYPE_RADIO_BUTTON) G_DEFINE_TYPE (MctCarouselItem, mct_carousel_item, GTK_TYPE_BUTTON)
GtkWidget * GtkWidget *
mct_carousel_item_new (void) mct_carousel_item_new (void)
@ -43,28 +47,36 @@ mct_carousel_item_new (void)
return g_object_new (MCT_TYPE_CAROUSEL_ITEM, NULL); return g_object_new (MCT_TYPE_CAROUSEL_ITEM, NULL);
} }
void
mct_carousel_item_set_child (MctCarouselItem *self,
GtkWidget *child)
{
g_return_if_fail (MCT_IS_CAROUSEL_ITEM (self));
gtk_button_set_child (GTK_BUTTON (self), child);
}
static void static void
mct_carousel_item_class_init (MctCarouselItemClass *klass) mct_carousel_item_class_init (MctCarouselItemClass *klass)
{ {
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "carousel-item");
} }
static void static void
mct_carousel_item_init (MctCarouselItem *self) mct_carousel_item_init (MctCarouselItem *self)
{ {
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (self), FALSE);
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)),
"carousel-item");
} }
struct _MctCarousel { struct _MctCarousel {
GtkRevealer parent; AdwBin parent;
GtkRevealer *revealer;
GList *children; GList *children;
gint visible_page; gint visible_page;
MctCarouselItem *selected_item; MctCarouselItem *selected_item;
GtkWidget *last_box; GtkWidget *last_box;
GtkWidget *arrow; GtkWidget *arrow;
gint arrow_start_x;
/* Widgets */ /* Widgets */
GtkStack *stack; GtkStack *stack;
@ -74,7 +86,7 @@ struct _MctCarousel {
GtkStyleProvider *provider; GtkStyleProvider *provider;
}; };
G_DEFINE_TYPE (MctCarousel, mct_carousel, GTK_TYPE_REVEALER) G_DEFINE_TYPE (MctCarousel, mct_carousel, ADW_TYPE_BIN)
enum { enum {
ITEM_ACTIVATED, ITEM_ACTIVATED,
@ -91,9 +103,9 @@ mct_carousel_item_get_x (MctCarouselItem *item,
{ {
GtkWidget *widget, *parent; GtkWidget *widget, *parent;
gint width; gint width;
gint dest_x; gdouble dest_x;
parent = GTK_WIDGET (carousel->stack); parent = GTK_WIDGET (carousel->revealer);
widget = GTK_WIDGET (item); widget = GTK_WIDGET (item);
width = gtk_widget_get_allocated_width (widget); width = gtk_widget_get_allocated_width (widget);
@ -116,8 +128,6 @@ mct_carousel_move_arrow (MctCarousel *self)
GtkStyleContext *context; GtkStyleContext *context;
gchar *css; gchar *css;
gint end_x; gint end_x;
GtkSettings *settings;
gboolean animations;
if (!self->selected_item) if (!self->selected_item)
return; return;
@ -129,31 +139,9 @@ mct_carousel_move_arrow (MctCarousel *self)
gtk_style_context_remove_provider (context, self->provider); gtk_style_context_remove_provider (context, self->provider);
g_clear_object (&self->provider); g_clear_object (&self->provider);
settings = gtk_widget_get_settings (GTK_WIDGET (self)); css = g_strdup_printf ("* { margin-left: %dpx; }", end_x);
g_object_get (settings, "gtk-enable-animations", &animations, NULL);
/* Animate the arrow movement if animations are enabled. Otherwise,
* jump the arrow to the right location instantly. */
if (animations)
{
css = g_strdup_printf ("@keyframes arrow_keyframes-%d-%d {\n"
" from { margin-left: %dpx; }\n"
" to { margin-left: %dpx; }\n"
"}\n"
"* {\n"
" animation-name: arrow_keyframes-%d-%d;\n"
"}\n",
self->arrow_start_x, end_x,
self->arrow_start_x, end_x,
self->arrow_start_x, end_x);
}
else
{
css = g_strdup_printf ("* { margin-left: %dpx }", end_x);
}
self->provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ()); self->provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (self->provider), css, -1, NULL); gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (self->provider), css, -1);
gtk_style_context_add_provider (context, self->provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); gtk_style_context_add_provider (context, self->provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_free (css); g_free (css);
@ -178,7 +166,7 @@ update_buttons_visibility (MctCarousel *self)
/** /**
* mct_carousel_find_item: * mct_carousel_find_item:
* @carousel: an MctCarousel instance * @carousel: an MctCarousel instance
* @data: user data passed to the comparation function * @data: user data passed to the comparison function
* @func: the function to call for each element. * @func: the function to call for each element.
* It should return 0 when the desired element is found * It should return 0 when the desired element is found
* *
@ -234,10 +222,7 @@ mct_carousel_select_item (MctCarousel *self,
} }
if (self->selected_item != NULL) if (self->selected_item != NULL)
{
page_changed = (self->selected_item->page != item->page); page_changed = (self->selected_item->page != item->page);
self->arrow_start_x = mct_carousel_item_get_x (self->selected_item, self);
}
self->selected_item = item; self->selected_item = item;
self->visible_page = item->page; self->visible_page = item->page;
@ -300,59 +285,44 @@ mct_carousel_goto_next_page (GtkWidget *button,
mct_carousel_select_item_at_index (self, self->visible_page * ITEMS_PER_PAGE); mct_carousel_select_item_at_index (self, self->visible_page * ITEMS_PER_PAGE);
} }
static void void
mct_carousel_add (GtkContainer *container, mct_carousel_add (MctCarousel *self,
GtkWidget *widget) MctCarouselItem *item)
{ {
MctCarousel *self = MCT_CAROUSEL (container);
gboolean last_box_is_full; gboolean last_box_is_full;
if (!MCT_IS_CAROUSEL_ITEM (widget)) g_return_if_fail (MCT_IS_CAROUSEL (self));
{ g_return_if_fail (MCT_IS_CAROUSEL_ITEM (item));
GTK_CONTAINER_CLASS (mct_carousel_parent_class)->add (container, widget);
return;
}
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "menu"); self->children = g_list_append (self->children, item);
gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); item->page = get_last_page_number (self);
g_signal_connect (item, "clicked", G_CALLBACK (on_item_toggled), self);
self->children = g_list_append (self->children, widget);
MCT_CAROUSEL_ITEM (widget)->page = get_last_page_number (self);
if (self->selected_item != NULL)
gtk_radio_button_join_group (GTK_RADIO_BUTTON (widget), GTK_RADIO_BUTTON (self->selected_item));
g_signal_connect (widget, "button-press-event", G_CALLBACK (on_item_toggled), self);
last_box_is_full = ((g_list_length (self->children) - 1) % ITEMS_PER_PAGE == 0); last_box_is_full = ((g_list_length (self->children) - 1) % ITEMS_PER_PAGE == 0);
if (last_box_is_full) if (last_box_is_full)
{ {
g_autofree gchar *page = NULL; g_autofree gchar *page = NULL;
page = g_strdup_printf ("%d", MCT_CAROUSEL_ITEM (widget)->page); page = g_strdup_printf ("%d", item->page);
self->last_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); self->last_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
gtk_widget_show (self->last_box); gtk_widget_set_hexpand (self->last_box, TRUE);
gtk_widget_set_valign (self->last_box, GTK_ALIGN_CENTER); gtk_widget_set_valign (self->last_box, GTK_ALIGN_CENTER);
gtk_box_set_homogeneous (GTK_BOX (self->last_box), TRUE);
gtk_stack_add_named (self->stack, self->last_box, page); gtk_stack_add_named (self->stack, self->last_box, page);
} }
gtk_widget_show_all (widget); gtk_box_append (GTK_BOX (self->last_box), GTK_WIDGET (item));
gtk_box_pack_start (GTK_BOX (self->last_box), widget, TRUE, FALSE, 10);
update_buttons_visibility (self); update_buttons_visibility (self);
} }
static void
destroy_widget_cb (GtkWidget *widget,
gpointer user_data)
{
gtk_widget_destroy (widget);
}
void void
mct_carousel_purge_items (MctCarousel *self) mct_carousel_purge_items (MctCarousel *self)
{ {
gtk_container_forall (GTK_CONTAINER (self->stack), GtkWidget *child;
destroy_widget_cb,
NULL); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->stack))) != NULL)
gtk_stack_remove (self->stack, child);
g_list_free (self->children); g_list_free (self->children);
self->children = NULL; self->children = NULL;
@ -386,7 +356,6 @@ mct_carousel_class_init (MctCarouselClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass); GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
gtk_widget_class_set_template_from_resource (wclass, gtk_widget_class_set_template_from_resource (wclass,
"/org/freedesktop/MalcontentControl/ui/carousel.ui"); "/org/freedesktop/MalcontentControl/ui/carousel.ui");
@ -395,13 +364,14 @@ mct_carousel_class_init (MctCarouselClass *klass)
gtk_widget_class_bind_template_child (wclass, MctCarousel, go_back_button); gtk_widget_class_bind_template_child (wclass, MctCarousel, go_back_button);
gtk_widget_class_bind_template_child (wclass, MctCarousel, go_next_button); gtk_widget_class_bind_template_child (wclass, MctCarousel, go_next_button);
gtk_widget_class_bind_template_child (wclass, MctCarousel, arrow); gtk_widget_class_bind_template_child (wclass, MctCarousel, arrow);
gtk_widget_class_bind_template_child (wclass, MctCarousel, revealer);
gtk_widget_class_bind_template_callback (wclass, mct_carousel_goto_previous_page); gtk_widget_class_bind_template_callback (wclass, mct_carousel_goto_previous_page);
gtk_widget_class_bind_template_callback (wclass, mct_carousel_goto_next_page); gtk_widget_class_bind_template_callback (wclass, mct_carousel_goto_next_page);
object_class->dispose = mct_carousel_dispose; gtk_widget_class_set_layout_manager_type (wclass, MCT_TYPE_CAROUSEL_LAYOUT);
container_class->add = mct_carousel_add; object_class->dispose = mct_carousel_dispose;
signals[ITEM_ACTIVATED] = signals[ITEM_ACTIVATED] =
g_signal_new ("item-activated", g_signal_new ("item-activated",
@ -414,19 +384,6 @@ mct_carousel_class_init (MctCarouselClass *klass)
MCT_TYPE_CAROUSEL_ITEM); MCT_TYPE_CAROUSEL_ITEM);
} }
static void
on_size_allocate (MctCarousel *self)
{
if (self->selected_item == NULL)
return;
if (gtk_stack_get_transition_running (self->stack))
return;
self->arrow_start_x = mct_carousel_item_get_x (self->selected_item, self);
mct_carousel_move_arrow (self);
}
static void static void
on_transition_running (MctCarousel *self) on_transition_running (MctCarousel *self)
{ {
@ -445,13 +402,12 @@ mct_carousel_init (MctCarousel *self)
gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider), gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider),
"/org/freedesktop/MalcontentControl/ui/carousel.css"); "/org/freedesktop/MalcontentControl/ui/carousel.css");
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), gtk_style_context_add_provider_for_display (gdk_display_get_default (),
provider, provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1);
g_object_unref (provider); g_object_unref (provider);
g_signal_connect_swapped (self->stack, "size-allocate", G_CALLBACK (on_size_allocate), self);
g_signal_connect_swapped (self->stack, "notify::transition-running", G_CALLBACK (on_transition_running), self); g_signal_connect_swapped (self->stack, "notify::transition-running", G_CALLBACK (on_transition_running), self);
} }
@ -460,3 +416,77 @@ mct_carousel_get_item_count (MctCarousel *self)
{ {
return g_list_length (self->children); return g_list_length (self->children);
} }
void
mct_carousel_set_revealed (MctCarousel *self,
gboolean revealed)
{
g_return_if_fail (MCT_IS_CAROUSEL (self));
gtk_revealer_set_reveal_child (self->revealer, revealed);
}
struct _MctCarouselLayout {
GtkLayoutManager parent;
};
G_DEFINE_FINAL_TYPE (MctCarouselLayout, mct_carousel_layout, GTK_TYPE_LAYOUT_MANAGER)
static void
mct_carousel_layout_measure (GtkLayoutManager *layout_manager,
GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
MctCarousel *carousel;
g_assert (MCT_IS_CAROUSEL (widget));
carousel = MCT_CAROUSEL (widget);
gtk_widget_measure (GTK_WIDGET (carousel->revealer),
orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
mct_carousel_layout_allocate (GtkLayoutManager *layout_manager,
GtkWidget *widget,
int width,
int height,
int baseline)
{
MctCarousel *carousel;
g_assert (MCT_IS_CAROUSEL (widget));
carousel = MCT_CAROUSEL (widget);
gtk_widget_allocate (GTK_WIDGET (carousel->revealer), width, height, baseline, NULL);
if (carousel->selected_item == NULL)
return;
if (gtk_stack_get_transition_running (carousel->stack))
return;
mct_carousel_move_arrow (carousel);
}
static void
mct_carousel_layout_class_init (MctCarouselLayoutClass *klass)
{
GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
layout_manager_class->measure = mct_carousel_layout_measure;
layout_manager_class->allocate = mct_carousel_layout_allocate;
}
static void
mct_carousel_layout_init (MctCarouselLayout *self)
{
}

View File

@ -22,9 +22,18 @@
margin-bottom: -2px; margin-bottom: -2px;
} }
.carousel-item { carousel-item {
background: transparent; background: transparent;
box-shadow: none; box-shadow: none;
border: none; border: none;
color: @theme_fg_color; color: @theme_fg_color;
} }
carousel-item:focus:focus-visible avatar {
/* this should actually be $focus_border_color from
* gtk/theme/Default/_colors.scss, but we have to simplify the theming slightly */
outline-color: @theme_selected_bg_color;
outline-offset: -2px;
outline-width: 2px;
outline-style: solid;
}

View File

@ -18,24 +18,28 @@
* *
* Authors: * Authors:
* - Felipe Borges <felipeborges@gnome.org> * - Felipe Borges <felipeborges@gnome.org>
* - Georges Basile Stavracas Neto <georges@endlessos.org>
* - Philip Withnall <withnall@endlessm.com> * - Philip Withnall <withnall@endlessm.com>
*/ */
#pragma once #pragma once
#include <gtk/gtk.h> #include <adwaita.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define MCT_TYPE_CAROUSEL_ITEM (mct_carousel_item_get_type ()) #define MCT_TYPE_CAROUSEL_ITEM (mct_carousel_item_get_type ())
G_DECLARE_FINAL_TYPE (MctCarouselItem, mct_carousel_item, MCT, CAROUSEL_ITEM, GtkRadioButton) G_DECLARE_FINAL_TYPE (MctCarouselItem, mct_carousel_item, MCT, CAROUSEL_ITEM, GtkButton)
#define MCT_TYPE_CAROUSEL (mct_carousel_get_type ()) #define MCT_TYPE_CAROUSEL (mct_carousel_get_type ())
G_DECLARE_FINAL_TYPE (MctCarousel, mct_carousel, MCT, CAROUSEL, GtkRevealer) G_DECLARE_FINAL_TYPE (MctCarousel, mct_carousel, MCT, CAROUSEL, AdwBin)
GtkWidget *mct_carousel_item_new (void); GtkWidget *mct_carousel_item_new (void);
void mct_carousel_item_set_child (MctCarouselItem *self,
GtkWidget *child);
MctCarousel *mct_carousel_new (void); MctCarousel *mct_carousel_new (void);
void mct_carousel_purge_items (MctCarousel *self); void mct_carousel_purge_items (MctCarousel *self);
@ -49,4 +53,10 @@ void mct_carousel_select_item (MctCarousel *self,
guint mct_carousel_get_item_count (MctCarousel *self); guint mct_carousel_get_item_count (MctCarousel *self);
void mct_carousel_add (MctCarousel *self,
MctCarouselItem *item);
void mct_carousel_set_revealed (MctCarousel *self,
gboolean revealed);
G_END_DECLS G_END_DECLS

View File

@ -3,17 +3,20 @@
<!-- Copyright © 2020 Endless, Inc. --> <!-- Copyright © 2020 Endless, Inc. -->
<interface> <interface>
<requires lib="gtk+" version="3.12"/> <requires lib="gtk+" version="3.12"/>
<template class="MctCarousel" parent="GtkRevealer"> <template class="MctCarousel" parent="AdwBin">
<child>
<object class="GtkRevealer" id="revealer">
<property name="transition_duration">400</property> <property name="transition_duration">400</property>
<property name="reveal-child">True</property> <property name="reveal-child">True</property>
<child> <child>
<object class="GtkOverlay"> <object class="GtkOverlay">
<property name="visible">True</property>
<property name="hexpand">True</property> <property name="hexpand">True</property>
<property name="border_width">16</property>
<child> <child>
<object class="GtkStack" id="stack"> <object class="GtkStack" id="stack">
<property name="visible">True</property> <property name="margin-top">16</property>
<property name="margin-bottom">16</property>
<property name="margin-start">16</property>
<property name="margin-end">16</property>
<property name="transition_duration">400</property> <property name="transition_duration">400</property>
<property name="transition_type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property> <property name="transition_type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property>
<style> <style>
@ -22,81 +25,54 @@
</object> </object>
</child> </child>
<child type="overlay"> <child type="overlay">
<object class="GtkOverlay">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="border_width">12</property>
<child>
<object class="GtkButton" id="go_back_button"> <object class="GtkButton" id="go_back_button">
<property name="visible">False</property> <property name="visible">False</property>
<property name="can_focus">True</property> <property name="halign">start</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="icon_name">go-previous-symbolic</property>
<accessibility>
<property name="label" translatable="yes">Previous Page</property>
</accessibility>
<style> <style>
<class name="circular"/> <class name="circular"/>
</style> </style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon-size">4</property>
<property name="icon_name">go-previous-symbolic</property>
<child internal-child="accessible">
<object class="AtkObject">
<property name="accessible-name" translatable="yes">Previous Page</property>
</object>
</child>
</object>
</child>
<signal name="clicked" handler="mct_carousel_goto_previous_page" object="MctCarousel" swapped="no"/> <signal name="clicked" handler="mct_carousel_goto_previous_page" object="MctCarousel" swapped="no"/>
</object> </object>
<packing>
<property name="pack_type">GTK_PACK_START</property>
</packing>
</child> </child>
<child> <child type="overlay">
<object class="GtkButton" id="go_next_button"> <object class="GtkButton" id="go_next_button">
<property name="can_focus">True</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="halign">end</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="hexpand">True</property>
<property name="icon_name">go-next-symbolic</property>
<accessibility>
<property name="label" translatable="yes">Next Page</property>
</accessibility>
<style> <style>
<class name="circular"/> <class name="circular"/>
</style> </style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon-size">4</property>
<property name="icon_name">go-next-symbolic</property>
<child internal-child="accessible">
<object class="AtkObject">
<property name="accessible-name" translatable="yes">Next Page</property>
</object>
</child>
</object>
</child>
<signal name="clicked" handler="mct_carousel_goto_next_page" object="MctCarousel" swapped="no"/> <signal name="clicked" handler="mct_carousel_goto_next_page" object="MctCarousel" swapped="no"/>
</object> </object>
<packing>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</object>
</child> </child>
<child type="overlay"> <child type="overlay">
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="can-focus">False</property>
<property name="valign">GTK_ALIGN_END</property> <property name="valign">GTK_ALIGN_END</property>
<style> <style>
<class name="carousel-arrow-container"/> <class name="carousel-arrow-container"/>
</style> </style>
<child> <child>
<object class="GtkOverlay"> <object class="GtkOverlay">
<property name="visible">True</property>
<child> <child>
<object class="GtkBox" id="arrow"> <object class="GtkBox" id="arrow">
<property name="visible">True</property>
<property name="halign">GTK_ALIGN_END</property> <property name="halign">GTK_ALIGN_END</property>
<style> <style>
<class name="carousel-arrow"/> <class name="carousel-arrow"/>
@ -105,7 +81,6 @@
</child> </child>
<child type="overlay"> <child type="overlay">
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="halign">GTK_ALIGN_END</property> <property name="halign">GTK_ALIGN_END</property>
<style> <style>
<class name="carousel-inner-arrow"/> <class name="carousel-inner-arrow"/>
@ -115,14 +90,8 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="pass-through">True</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="pass-through">True</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -0,0 +1,8 @@
install_data(
join_paths('scalable', application_id + '.svg'),
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps'),
)
install_data(
join_paths('symbolic', application_id + '-symbolic.svg'),
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'symbolic', 'apps'),
)

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><clipPath id="a"><path d="M0 0h128v128H0z"/></clipPath><clipPath id="c"><path d="M0 0h128v128H0z"/></clipPath><clipPath id="i"><path d="M0 0h128v128H0z"/></clipPath><clipPath id="g"><path d="M0 0h128v128H0z"/></clipPath><g id="m" clip-path="url(#i)"><use xlink:href="#j" mask="url(#k)"/></g><g id="e" clip-path="url(#a)"><path d="M124 66c0 33.137-26.863 60-60 60S4 99.137 4 66 30.863 6 64 6s60 26.863 60 60zm0 0" fill="url(#b)"/><path d="M124 63c0 32.586-26.863 59-60 59S4 95.586 4 63 30.863 4 64 4s60 26.414 60 59zm0 0" fill="#f8e45c"/><path d="M52.785 24.977a9.317 9.317 0 000 18.632 9.317 9.317 0 000-18.632zm-5.543 22.277c-.988 0-1.937.39-2.637 1.09L28.25 65.19c-3.656 3.512 1.758 8.926 5.27 5.27l10.933-10.934-.937 1.09v36.196c-.07 5.039 7.464 5.039 7.394 0V78.867c0-2.906 3.738-2.906 3.738 0v17.945c-.07 5.04 7.485 5.04 7.414 0v-27.78l3.567 7.624c2.02 4.531 8.82 1.508 6.812-3.027L61.535 49.465a3.729 3.729 0 00-3.406-2.211zm0 0M84.848 61.16a7.46 7.46 0 017.46 7.461 7.464 7.464 0 01-14.926 0 7.464 7.464 0 017.466-7.46zm0 0" fill="#3d3846"/><path d="M71.707 75.426c-3.078-.059-3.953 4.183-1.105 5.351l7.18 2.84V97.91c-.052 3.762 5.613 3.762 5.562 0v-3.969c0-1.804 2.832-1.726 2.832 0v3.797c-.051 3.758 5.492 3.758 5.437 0v-8.156l1.207 2.09c1.852 3.21 6.668.43 4.813-2.781l-5.29-9.164a2.792 2.792 0 00-2.41-1.391H79.57l-6.785-2.672a2.708 2.708 0 00-1.078-.238zm0 0" fill="#3d3846"/><path d="M64 6.95C32.52 6.95 7 32.042 7 63c0 30.957 25.52 56.05 57 56.05S121 93.958 121 63c0-30.957-25.52-56.05-57-56.05zm0 3.706c29.398 0 53.23 23.434 53.23 52.344S93.398 115.344 64 115.344c-29.398 0-53.23-23.434-53.23-52.344S34.602 10.656 64 10.656zm0 0" fill="#3d3846"/></g><g id="f" clip-path="url(#c)" filter="url(#d)"><use xlink:href="#e"/></g><g id="j" clip-path="url(#g)"><path d="M128 80.64V128H0V80.64zm0 0" fill="url(#h)"/><path d="M13.309 80.64L60.664 128H81.88l-47.36-47.36zm42.421 0L103.094 128h21.215L76.945 80.64zm42.43 0L128 110.48V89.27l-8.629-8.63zM0 88.548v21.215L18.238 128h21.215zm0 0"/></g><linearGradient id="l" gradientUnits="userSpaceOnUse" x1="0" y1="269.463" x2="118.926" y2="269.463" gradientTransform="translate(0 -172)"><stop offset="0" stop-color="#e5a50a"/><stop offset=".414" stop-color="#fbdf9b"/><stop offset=".813" stop-color="#e5a50a"/><stop offset="1" stop-color="#f8ca5b"/></linearGradient><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="300" y1="235" x2="428" y2="235" gradientTransform="matrix(0 .37 -.98462 0 295.385 -30.36)"><stop offset="0" stop-color="#f9f06b"/><stop offset="1" stop-color="#f5c211"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="0" y1="269.463" x2="118.926" y2="269.463" gradientTransform="translate(0 -172)"><stop offset="0" stop-color="#e5a50a"/><stop offset=".414" stop-color="#fbdf9b"/><stop offset=".813" stop-color="#e5a50a"/><stop offset="1" stop-color="#f8ca5b"/></linearGradient><mask id="k"><g filter="url(#d)"><path fill-opacity=".8" d="M0 0h128v128H0z"/></g></mask><mask id="n"><use xlink:href="#f"/></mask><filter id="d" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"><feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter></defs><path d="M124 66c0 33.137-26.863 60-60 60S4 99.137 4 66 30.863 6 64 6s60 26.863 60 60zm0 0" fill="url(#l)"/><path d="M124 63c0 32.586-26.863 59-60 59S4 95.586 4 63 30.863 4 64 4s60 26.414 60 59zm0 0" fill="#f8e45c"/><path d="M52.785 24.977a9.317 9.317 0 000 18.632 9.317 9.317 0 000-18.632zm-5.543 22.277c-.988 0-1.937.39-2.637 1.09L28.25 65.19c-3.656 3.512 1.758 8.926 5.27 5.27l10.933-10.934-.937 1.09v36.196c-.07 5.039 7.464 5.039 7.394 0V78.867c0-2.906 3.738-2.906 3.738 0v17.945c-.07 5.04 7.485 5.04 7.414 0v-27.78l3.567 7.624c2.02 4.531 8.82 1.508 6.812-3.027L61.535 49.465a3.729 3.729 0 00-3.406-2.211zm0 0M84.848 61.16a7.46 7.46 0 017.46 7.461 7.464 7.464 0 01-14.926 0 7.464 7.464 0 017.466-7.46zm0 0" fill="#3d3846"/><path d="M71.707 75.426c-3.078-.059-3.953 4.183-1.105 5.351l7.18 2.84V97.91c-.052 3.762 5.613 3.762 5.562 0v-3.969c0-1.804 2.832-1.726 2.832 0v3.797c-.051 3.758 5.492 3.758 5.437 0v-8.156l1.207 2.09c1.852 3.21 6.668.43 4.813-2.781l-5.29-9.164a2.792 2.792 0 00-2.41-1.391H79.57l-6.785-2.672a2.708 2.708 0 00-1.078-.238zm0 0" fill="#3d3846"/><path d="M64 6.95C32.52 6.95 7 32.042 7 63c0 30.957 25.52 56.05 57 56.05S121 93.958 121 63c0-30.957-25.52-56.05-57-56.05zm0 3.706c29.398 0 53.23 23.434 53.23 52.344S93.398 115.344 64 115.344c-29.398 0-53.23-23.434-53.23-52.344S34.602 10.656 64 10.656zm0 0" fill="#3d3846"/><use xlink:href="#m" mask="url(#n)"/></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="0" y1="269.463" x2="118.926" y2="269.463" gradientTransform="translate(0 -172)"><stop offset="0" stop-color="#e5a50a"/><stop offset=".414" stop-color="#fbdf9b"/><stop offset=".813" stop-color="#e5a50a"/><stop offset="1" stop-color="#f8ca5b"/></linearGradient></defs><path d="M124 66c0 33.137-26.863 60-60 60S4 99.137 4 66 30.863 6 64 6s60 26.863 60 60zm0 0" fill="url(#a)"/><path d="M124 63c0 32.586-26.863 59-60 59S4 95.586 4 63 30.863 4 64 4s60 26.414 60 59zm0 0" fill="#f8e45c"/><path d="M52.785 24.977a9.317 9.317 0 000 18.632 9.317 9.317 0 000-18.632zm-5.543 22.277c-.988 0-1.937.39-2.637 1.09L28.25 65.19c-3.656 3.512 1.758 8.926 5.27 5.27l10.933-10.934-.937 1.09v36.196c-.07 5.039 7.464 5.039 7.394 0V78.867c0-2.906 3.738-2.906 3.738 0v17.945c-.07 5.04 7.485 5.04 7.414 0v-27.78l3.567 7.624c2.02 4.531 8.82 1.508 6.812-3.027L61.535 49.465a3.729 3.729 0 00-3.406-2.211zm0 0M84.848 61.16a7.46 7.46 0 017.46 7.461 7.464 7.464 0 01-14.926 0 7.464 7.464 0 017.466-7.46zm0 0" fill="#3d3846"/><path d="M71.707 75.426c-3.078-.059-3.953 4.183-1.105 5.351l7.18 2.84V97.91c-.052 3.762 5.613 3.762 5.562 0v-3.969c0-1.804 2.832-1.726 2.832 0v3.797c-.051 3.758 5.492 3.758 5.437 0v-8.156l1.207 2.09c1.852 3.21 6.668.43 4.813-2.781l-5.29-9.164a2.792 2.792 0 00-2.41-1.391H79.57l-6.785-2.672a2.708 2.708 0 00-1.078-.238zm0 0" fill="#3d3846"/><path d="M64 6.95C32.52 6.95 7 32.042 7 63c0 30.957 25.52 56.05 57 56.05S121 93.958 121 63c0-30.957-25.52-56.05-57-56.05zm0 3.706c29.398 0 53.23 23.434 53.23 52.344S93.398 115.344 64 115.344c-29.398 0-53.23-23.434-53.23-52.344S34.602 10.656 64 10.656zm0 0" fill="#3d3846"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#2e3436"><path d="M8 2.5C8 3.879 6.879 5 5.5 5A2.502 2.502 0 013 2.5C3 1.121 4.121 0 5.5 0S8 1.121 8 2.5zm0 0M12.5 5C13.879 5 15 6.121 15 7.5S13.879 10 12.5 10A2.502 2.502 0 0110 7.5C10 6.121 11.121 5 12.5 5zm0 0"/><path d="M10 11c-1.352-.02-1.352 2.02 0 2h1v2a.998.998 0 001.5.863A1 1 0 0014 15v-.137c.867.5 1.848-.437 1.387-1.324l-.95-1.812C14.087 11.117 13.845 11 13 11zm0 0" fill-rule="evenodd"/><path d="M4 6a1 1 0 00-.707.293l-3 3a.992.992 0 00-.273.973.99.99 0 00.714.714.992.992 0 00.973-.273L3.25 9.16 3 10.93V15c-.004.36.184.695.496.879.313.18.695.18 1.008 0 .312-.184.5-.52.496-.879v-2.5s0-.5.5-.5.5.5.5.5V15c-.004.36.184.695.496.879.313.18.695.18 1.008 0 .312-.184.5-.52.496-.879v-3.285l.086.191c.223.504.816.73 1.32.508.504-.223.73-.816.508-1.32l-2-4.5C7.754 6.234 7.394 6 7 6zm0 0" fill-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 899 B

View File

@ -2,233 +2,178 @@
<!-- Copyright © 2019, 2020 Endless Mobile, Inc. --> <!-- Copyright © 2019, 2020 Endless Mobile, Inc. -->
<interface> <interface>
<requires lib="gtk+" version="3.12"/> <requires lib="gtk+" version="3.12"/>
<object class="GtkApplicationWindow" id="main_window"> <object class="AdwApplicationWindow" id="main_window">
<property name="default-width">500</property> <property name="default-width">540</property>
<property name="default-height">600</property> <property name="default-height">580</property>
<child>
<object class="GtkStack" id="main_stack">
<property name="visible">True</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="border_width">0</property> <child>
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">True</property>
<property name="title-widget">
<object class="AdwWindowTitle">
<!-- Translators: This is the title of the main window -->
<property name="title" translatable="yes">Parental Controls</property>
</object>
</property>
<child type="end">
<object class="GtkMenuButton" id="primary_menu">
<property name="direction">none</property>
<property name="menu-model">primary-menu</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkShortcutController">
<property name="scope">global</property>
<child>
<object class="GtkShortcut">
<property name="trigger">F10</property>
<property name="action">activate</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="main_stack">
<child>
<object class="GtkStackPage">
<property name="name">controls</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child> <child>
<object class="MctUserSelector" id="user_selector"> <object class="MctUserSelector" id="user_selector">
<property name="visible">True</property>
<property name="user-manager">user_manager</property> <property name="user-manager">user_manager</property>
<property name="show-administrators">False</property> <property name="show-administrators">False</property>
<accessibility> <accessibility>
<relation target="user_controls" type="controller-for"/> <relation name="controls">user_controls</relation>
</accessibility> </accessibility>
</object> </object>
<packing>
<property name="fill">False</property>
<property name="expand">False</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="AdwPreferencesPage">
<property name="visible">True</property> <child>
<property name="hscrollbar-policy">never</property> <object class="AdwPreferencesGroup">
<property name="min-content-height">350</property>
<child> <child>
<object class="MctUserControls" id="user_controls"> <object class="MctUserControls" id="user_controls">
<property name="visible">True</property> <!-- Content is set in code; this string is just a placeholder -->
<property name="margin">12</property> <property name="description">Its recommended that restrictions are set as part of an ongoing conversation with $name. Read guidance on what to consider.</property>
<property name="height-request">270</property>
<property name="dbus-connection">dbus_connection</property>
<property name="vexpand">True</property>
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">True</property>
</packing>
</child> </child>
</object> </object>
<packing> </child>
<property name="name">controls</property> </object>
</packing> </property>
</object>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkStackPage">
<property name="visible">True</property> <property name="name">unlock</property>
<property name="orientation">vertical</property> <property name="child">
<property name="hexpand">True</property> <object class="AdwStatusPage">
<property name="vexpand">True</property> <property name="title" translatable="yes">Permission Required</property>
<child type="center"> <property name="description" translatable="yes">Permission is required to view and change user parental controls settings.</property>
<object class="GtkBox"> <property name="icon-name">org.freedesktop.MalcontentControl</property>
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="margin">18</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Permission Required</property>
<attributes>
<attribute name="scale" value="1.4"/>
</attributes>
<child internal-child="accessible">
<object class="AtkObject">
<property name="AtkObject::accessible-role">static</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Permission is required to view and change parental controls settings for other users.</property>
<property name="wrap">True</property>
<child internal-child="accessible">
<object class="AtkObject">
<property name="AtkObject::accessible-role">static</property>
</object>
</child>
</object>
</child>
<child> <child>
<object class="GtkLockButton" id="lock_button"> <object class="GtkLockButton" id="lock_button">
<property name="visible">True</property>
<property name="halign">center</property> <property name="halign">center</property>
<property name="can-default">True</property> <style>
<property name="has-default">True</property> <class name="suggested-action" />
<property name="can-focus">True</property> <class name="pill" />
</style>
</object> </object>
</child> </child>
</object> </object>
</child> </property>
</object> </object>
<packing>
<property name="name">unlock</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkStackPage">
<property name="visible">True</property> <property name="name">no-other-users</property>
<property name="orientation">vertical</property> <property name="child">
<property name="hexpand">True</property> <object class="AdwStatusPage">
<property name="vexpand">True</property> <property name="icon-name">system-users-symbolic</property>
<child type="center"> <property name="title" translatable="yes">No Standard User Accounts</property>
<object class="GtkBox"> <property name="description" translatable="yes">Parental controls can only be applied to standard user
<property name="visible">True</property> accounts. These can be created in the user settings.</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="margin">18</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">No Child Users Configured</property>
<attributes>
<attribute name="scale" value="1.4"/>
</attributes>
<child internal-child="accessible">
<object class="AtkObject">
<property name="AtkObject::accessible-role">static</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">No child users are currently set up on the system. Create one before setting up their parental controls.</property>
<property name="wrap">True</property>
<child internal-child="accessible">
<object class="AtkObject">
<property name="AtkObject::accessible-role">static</property>
</object>
</child>
</object>
</child>
<child> <child>
<object class="GtkButton" id="user_accounts_panel_button"> <object class="GtkButton" id="user_accounts_panel_button">
<property name="visible">True</property> <property name="label" translatable="yes">_User Settings</property>
<property name="label" translatable="yes">Create _Child User</property>
<property name="halign">center</property> <property name="halign">center</property>
<property name="can-default">True</property>
<property name="has-default">True</property>
<property name="use-underline">True</property> <property name="use-underline">True</property>
<property name="can-focus">True</property>
<style> <style>
<class name="suggested-action"/> <class name="suggested-action"/>
</style> </style>
</object> </object>
</child> </child>
</object> </object>
</child> </property>
</object> </object>
<packing>
<property name="name">no-other-users</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="hexpand">True</property> <property name="hexpand">True</property>
<property name="vexpand">True</property> <property name="vexpand">True</property>
<child type="center"> <child type="center">
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Loading…</property> <property name="label" translatable="yes">Loading…</property>
<attributes> <property name="vexpand">True</property>
<attribute name="scale" value="1.4"/> <style>
</attributes> <class name="title-1" />
<child internal-child="accessible"> </style>
<object class="AtkObject">
<property name="AtkObject::accessible-role">static</property>
</object> </object>
</child> </child>
</object> </object>
</child> </property>
</object> </object>
<packing>
<property name="name">loading</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkStackPage">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child type="center">
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="error_title">
<property name="visible">True</property>
<property name="label"></property>
<attributes>
<attribute name="scale" value="1.4"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel" id="error_message">
<property name="visible">True</property>
<property name="label"></property>
</object>
</child>
</object>
</child>
<child internal-child="accessible">
<object class="AtkObject">
<property name="AtkObject::accessible-role">alert</property>
</object>
</child>
</object>
<packing>
<property name="name">error</property> <property name="name">error</property>
</packing> <property name="child">
<object class="AdwStatusPage" id="error_page">
<property name="icon-name">dialog-error-symbolic</property>
</object>
</property>
</object>
</child>
</object>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
<menu id="primary-menu">
<section>
<item>
<attribute name="action">app.help</attribute>
<attribute name="label" translatable="yes">_Help</attribute>
</item>
<item>
<attribute name="action">app.about</attribute>
<attribute name="label" translatable="yes">_About Parental Controls</attribute>
</item>
</section>
</menu>
</interface> </interface>

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -7,7 +7,7 @@ endif
resources = gnome.compile_resources( resources = gnome.compile_resources(
'resources', 'resources',
'malcontent-control.gresource.xml', 'malcontent-control.gresource.xml',
source_dir: meson.source_root(), source_dir: meson.current_source_dir(),
) )
malcontent_control = executable('malcontent-control', malcontent_control = executable('malcontent-control',
@ -27,9 +27,9 @@ malcontent_control = executable('malcontent-control',
dependency('gio-2.0', version: '>= 2.44'), dependency('gio-2.0', version: '>= 2.44'),
dependency('glib-2.0', version: '>= 2.54.2'), dependency('glib-2.0', version: '>= 2.54.2'),
dependency('gobject-2.0', version: '>= 2.54'), dependency('gobject-2.0', version: '>= 2.54'),
dependency('gtk+-3.0'), gtk_dep,
dependency('flatpak'),
dependency('polkit-gobject-1'), dependency('polkit-gobject-1'),
libadwaita_dep,
libmalcontent_dep, libmalcontent_dep,
libmalcontent_ui_dep, libmalcontent_ui_dep,
], ],
@ -37,11 +37,11 @@ malcontent_control = executable('malcontent-control',
install: true, install: true,
) )
desktop_file = i18n.merge_file('desktop-file', desktop_file = i18n.merge_file(
type: 'desktop', type: 'desktop',
input: '@0@.desktop.in'.format(application_id), input: '@0@.desktop.in'.format(application_id),
output: '@0@.desktop'.format(application_id), output: '@0@.desktop'.format(application_id),
po_dir: join_paths(meson.source_root(), 'po'), po_dir: join_paths(meson.current_source_dir(), '..', 'po'),
install: true, install: true,
install_dir: join_paths(get_option('datadir'), 'applications'), install_dir: join_paths(get_option('datadir'), 'applications'),
) )
@ -58,10 +58,10 @@ if desktop_file_validate.found()
) )
endif endif
appdata_file = i18n.merge_file('appdata-file', appdata_file = i18n.merge_file(
input: '@0@.appdata.xml.in'.format(application_id), input: '@0@.appdata.xml.in'.format(application_id),
output: '@0@.appdata.xml'.format(application_id), output: '@0@.appdata.xml'.format(application_id),
po_dir: join_paths(meson.source_root(), 'po'), po_dir: join_paths(meson.current_source_dir(), '..', 'po'),
install: true, install: true,
install_dir: join_paths(get_option('datadir'), 'metainfo'), install_dir: join_paths(get_option('datadir'), 'metainfo'),
) )
@ -79,12 +79,12 @@ endif
xmllint = find_program('xmllint', required: false) xmllint = find_program('xmllint', required: false)
if xmllint.found() if xmllint.found()
gtk_prefix = dependency('gtk+-3.0').get_pkgconfig_variable('prefix') gtk_prefix = gtk_dep.get_variable(pkgconfig: 'prefix')
test( test(
'validate-ui', xmllint, 'validate-ui', xmllint,
args: [ args: [
'--nonet', '--noblanks', '--noout', '--nonet', '--noblanks', '--noout',
'--relaxng', join_paths(gtk_prefix, 'share', 'gtk-3.0', 'gtkbuilder.rng'), '--relaxng', join_paths(gtk_prefix, 'share', 'gtk-4.0', 'gtk4builder.rng'),
files( files(
'carousel.ui', 'carousel.ui',
'main.ui', 'main.ui',
@ -95,10 +95,10 @@ if xmllint.found()
) )
endif endif
policy_file = i18n.merge_file('policy-file', policy_file = i18n.merge_file(
input: '@0@.policy.in'.format(application_id), input: '@0@.policy.in'.format(application_id),
output: '@0@.policy'.format(application_id), output: '@0@.policy'.format(application_id),
po_dir: join_paths(meson.source_root(), 'po'), po_dir: join_paths(meson.current_source_dir(), '..', 'po'),
install: true, install: true,
install_dir: join_paths(get_option('datadir'), 'polkit-1', 'actions'), install_dir: join_paths(get_option('datadir'), 'polkit-1', 'actions'),
) )
@ -113,6 +113,6 @@ if xmllint.found()
) )
endif endif
# FIXME: Add icons and tests # FIXME: Add tests
#subdir('icons') subdir('icons')
#subdir('tests') #subdir('tests')

View File

@ -19,22 +19,23 @@
installed software they can run. installed software they can run.
</p> </p>
</description> </description>
<!--
<screenshots> <screenshots>
<screenshot type="default" width="400" height="480"> <screenshot height="552" width="699" type="default">
<image>https://FIXME/malcontent-control.png</image> <image>https://gitlab.freedesktop.org/pwithnall/malcontent/-/raw/HEAD/malcontent-control/malcontent-control.png</image>
<caption>Main window</caption>
</screenshot> </screenshot>
</screenshots> </screenshots>
-->
<provides> <provides>
<binary>malcontent-control</binary> <binary>malcontent-control</binary>
</provides> </provides>
<launchable type="desktop-id">org.freedesktop.MalcontentControl.desktop</launchable> <launchable type="desktop-id">org.freedesktop.MalcontentControl.desktop</launchable>
<url type="homepage">https://gitlab.freedesktop.org/pwithnall/malcontent</url> <url type="homepage">https://gitlab.freedesktop.org/pwithnall/malcontent</url>
<url type="bugtracker">https://gitlab.freedesktop.org/pwithnall/malcontent/issues</url> <url type="bugtracker">https://gitlab.freedesktop.org/pwithnall/malcontent/issues</url>
<url type="donation">http://www.gnome.org/friends/</url> <url type="donation">https://www.gnome.org/donate/</url>
<url type="vcs-browser">https://gitlab.freedesktop.org/pwithnall/malcontent</url>
<url type="translate">https://wiki.gnome.org/TranslationProject/LocalisationGuide</url> <url type="translate">https://wiki.gnome.org/TranslationProject/LocalisationGuide</url>
<update_contact>philip_at_tecnocode.co.uk</update_contact> <update_contact>philip_at_tecnocode.co.uk</update_contact>
<compulsory_for_desktop>GNOME</compulsory_for_desktop>
<project_group>GNOME</project_group> <project_group>GNOME</project_group>
<developer_name>The GNOME Project</developer_name> <developer_name>The GNOME Project</developer_name>
<kudos> <kudos>
@ -44,8 +45,132 @@
</kudos> </kudos>
<translation type="gettext">malcontent</translation> <translation type="gettext">malcontent</translation>
<releases> <releases>
<release version="0.11.1" date="2023-03-16" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.11.0" date="2022-08-12" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Use libappstream instead of appstream-glib</li>
<li>Port to GTK4</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.5" date="2022-05-31" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>German translation of the user help</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.4" date="2022-03-09" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Italian translation of the user help</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.3" date="2021-11-01" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Prevent malcontent-control from being uninstalled and removing core desktop components with it</li>
<li>Improve keyboard navigation of the interface</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.2" date="2021-09-17" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Hide the launcher for malcontent-control from gnome-shell if using the GNOME desktop; find it via gnome-control-center instead</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.1" date="2021-03-11" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Sort apps by displayed name when listing them</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.10.0" date="2020-12-09" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Reload the application list when apps are installed or removed</li>
<li>Fix some data loss consistency problems in the UI</li>
<li>Hide support for flatpak user repositories, as they are typically not configured</li>
<li>Minor improvements to parental controls application UI</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.9.0" date="2020-09-03" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Minor improvements to parental controls application UI</li>
<li>Choose rating system by territory rather than language</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.8.0" date="2020-04-28" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Minor improvements to parental controls application UI</li>
<li>Add a user manual</li>
<li>Translation updates</li>
</ul>
</description>
</release>
<release version="0.7.0" date="2020-03-24" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Minor improvements to parental controls application UI</li>
<li>Translations to Ukrainian and Polish</li>
</ul>
</description>
</release>
<release version="0.6.0" date="2020-02-26" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Improve parental controls application UI and add icon</li>
<li>Support for indicating which accounts are parent accounts</li>
</ul>
</description>
</release>
<release version="0.5.0" date="2020-02-14" type="stable">
<description>
<p>This is a stable release with the following changes:</p>
<ul>
<li>Initial release of basic parental controls application</li>
<li>Support for setting app installation and run restrictions on users</li>
</ul>
</description>
</release>
<release version="0.4.0" date="2019-07-17" type="stable"> <release version="0.4.0" date="2019-07-17" type="stable">
<description> <description>
<p>This is a stable release with the following changes:</p>
<ul> <ul>
<li>Maintenance release of underlying parental controls library</li> <li>Maintenance release of underlying parental controls library</li>
</ul> </ul>

View File

@ -7,6 +7,7 @@ Icon=org.freedesktop.MalcontentControl
Terminal=false Terminal=false
Type=Application Type=Application
Categories=GTK;GNOME;System; Categories=GTK;GNOME;System;
NotShowIn=GNOME;
StartupNotify=true StartupNotify=true
# Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon! # Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon!
Keywords=parental controls;screen time;app restrictions;web browser restrictions;oars;usage;usage limit;kid;child; Keywords=parental controls;screen time;app restrictions;web browser restrictions;oars;usage;usage limit;kid;child;

View File

@ -13,6 +13,6 @@
<allow_inactive>no</allow_inactive> <allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active> <allow_active>auth_admin_keep</allow_active>
</defaults> </defaults>
<annotate key="org.freedesktop.policykit.imply">com.endlessm.ParentalControls.AppFilter.ReadAny com.endlessm.ParentalControls.AppFilter.ChangeAny</annotate> <annotate key="org.freedesktop.policykit.imply">com.endlessm.ParentalControls.AppFilter.ReadAny com.endlessm.ParentalControls.AppFilter.ChangeAny com.endlessm.ParentalControls.AppFilter.ReadOwn com.endlessm.ParentalControls.AppFilter.ChangeOwn</annotate>
</action> </action>
</policyconfig> </policyconfig>

View File

@ -1,5 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
* *
* Copyright © 2022 Endless Mobile, Inc.
* Copyright © 2015 Red Hat, Inc. * Copyright © 2015 Red Hat, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -16,10 +17,11 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
* *
* Authors: * Authors:
* - Georges Basile Stavracas Neto <georges@endlessos.org>
* - Ondrej Holy <oholy@redhat.com> * - Ondrej Holy <oholy@redhat.com>
*/ */
#include <gtk/gtk.h> #include <adwaita.h>
#include <act/act.h> #include <act/act.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -28,108 +30,49 @@
struct _MctUserImage struct _MctUserImage
{ {
GtkImage parent_instance; AdwBin parent_instance;
AdwAvatar *avatar;
ActUser *user; ActUser *user;
}; };
G_DEFINE_TYPE (MctUserImage, mct_user_image, GTK_TYPE_IMAGE) G_DEFINE_TYPE (MctUserImage, mct_user_image, ADW_TYPE_BIN)
static GdkPixbuf * static GdkTexture *
round_image (GdkPixbuf *pixbuf) render_user_icon_texture (ActUser *user)
{ {
GdkPixbuf *dest = NULL; g_autoptr(GdkTexture) texture = NULL;
cairo_surface_t *surface; g_autoptr(GError) error = NULL;
cairo_t *cr;
gint size;
size = gdk_pixbuf_get_width (pixbuf);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
cr = cairo_create (surface);
/* Clip a circle */
cairo_arc (cr, size / 2, size / 2, size / 2, 0, 2 * G_PI);
cairo_clip (cr);
cairo_new_path (cr);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
dest = gdk_pixbuf_get_from_surface (surface, 0, 0, size, size);
cairo_surface_destroy (surface);
cairo_destroy (cr);
return dest;
}
static cairo_surface_t *
render_user_icon (ActUser *user,
gint icon_size,
gint scale)
{
g_autoptr(GdkPixbuf) source_pixbuf = NULL;
GdkPixbuf *pixbuf = NULL;
GError *error;
const gchar *icon_file; const gchar *icon_file;
cairo_surface_t *surface = NULL;
g_return_val_if_fail (ACT_IS_USER (user), NULL); g_return_val_if_fail (ACT_IS_USER (user), NULL);
g_return_val_if_fail (icon_size > 12, NULL);
icon_file = act_user_get_icon_file (user); icon_file = act_user_get_icon_file (user);
pixbuf = NULL; if (icon_file == NULL)
if (icon_file) return NULL;
texture = gdk_texture_new_from_filename (icon_file, &error);
if (error != NULL)
{ {
source_pixbuf = gdk_pixbuf_new_from_file_at_size (icon_file, g_warning ("Error loading user icon: %s", error->message);
icon_size * scale, return NULL;
icon_size * scale,
NULL);
if (source_pixbuf)
pixbuf = round_image (source_pixbuf);
} }
if (pixbuf != NULL) return g_steal_pointer (&texture);
goto out;
error = NULL;
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
"avatar-default",
icon_size * scale,
GTK_ICON_LOOKUP_FORCE_SIZE,
&error);
if (error)
{
g_warning ("%s", error->message);
g_error_free (error);
}
out:
if (pixbuf != NULL)
{
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, NULL);
g_object_unref (pixbuf);
}
return surface;
} }
static void static void
render_image (MctUserImage *image) render_image (MctUserImage *image)
{ {
cairo_surface_t *surface; g_autoptr(GdkTexture) texture = NULL;
gint scale, pixel_size;
if (image->user == NULL) if (image->user == NULL)
return; return;
pixel_size = gtk_image_get_pixel_size (GTK_IMAGE (image)); texture = render_user_icon_texture (image->user);
scale = gtk_widget_get_scale_factor (GTK_WIDGET (image)); adw_avatar_set_custom_image (image->avatar, GDK_PAINTABLE (texture));
surface = render_user_icon (image->user, adw_avatar_set_text (image->avatar, act_user_get_real_name (image->user));
pixel_size > 0 ? pixel_size : 48,
scale);
gtk_image_set_from_surface (GTK_IMAGE (image), surface);
cairo_surface_destroy (surface);
} }
void void
@ -163,8 +106,8 @@ mct_user_image_class_init (MctUserImageClass *class)
static void static void
mct_user_image_init (MctUserImage *image) mct_user_image_init (MctUserImage *image)
{ {
g_signal_connect_swapped (image, "notify::scale-factor", G_CALLBACK (render_image), image); image->avatar = ADW_AVATAR (adw_avatar_new (48, NULL, TRUE));
g_signal_connect_swapped (image, "notify::pixel-size", G_CALLBACK (render_image), image); adw_bin_set_child (ADW_BIN (image), GTK_WIDGET (image->avatar));
} }
GtkWidget * GtkWidget *

View File

@ -1,5 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
* *
* Copyright © 2022 Endless Mobile, Inc.
* Copyright © 2015 Red Hat, Inc. * Copyright © 2015 Red Hat, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -16,19 +17,20 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
* *
* Authors: * Authors:
* - Georges Basile Stavracas Neto <georges@endlessos.org>
* - Ondrej Holy <oholy@redhat.com> * - Ondrej Holy <oholy@redhat.com>
*/ */
#pragma once #pragma once
#include <gtk/gtk.h> #include <adwaita.h>
#include <act/act.h> #include <act/act.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define MCT_TYPE_USER_IMAGE (mct_user_image_get_type ()) #define MCT_TYPE_USER_IMAGE (mct_user_image_get_type ())
G_DECLARE_FINAL_TYPE (MctUserImage, mct_user_image, MCT, USER_IMAGE, GtkImage) G_DECLARE_FINAL_TYPE (MctUserImage, mct_user_image, MCT, USER_IMAGE, AdwBin)
GtkWidget *mct_user_image_new (void); GtkWidget *mct_user_image_new (void);
void mct_user_image_set_user (MctUserImage *image, void mct_user_image_set_user (MctUserImage *image,

View File

@ -309,8 +309,8 @@ sort_users (gconstpointer a,
ActUser *ua, *ub; ActUser *ua, *ub;
gint result; gint result;
ua = ACT_USER (a); ua = ACT_USER ((gpointer) a);
ub = ACT_USER (b); ub = ACT_USER ((gpointer) b);
/* Make sure the current user is shown first */ /* Make sure the current user is shown first */
if (act_user_get_uid (ua) == getuid ()) if (act_user_get_uid (ua) == getuid ())
@ -344,7 +344,7 @@ user_compare (gconstpointer i,
gint result; gint result;
item = (MctCarouselItem *) i; item = (MctCarouselItem *) i;
user = ACT_USER (u); user = ACT_USER ((gpointer) u);
uid_a = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "uid")); uid_a = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "uid"));
uid_b = act_user_get_uid (user); uid_b = act_user_get_uid (user);
@ -370,11 +370,11 @@ reload_users (MctUserSelector *self,
g_object_get (settings, "gtk-enable-animations", &animations, NULL); g_object_get (settings, "gtk-enable-animations", &animations, NULL);
g_object_set (settings, "gtk-enable-animations", FALSE, NULL); g_object_set (settings, "gtk-enable-animations", FALSE, NULL);
mct_carousel_purge_items (self->carousel);
list = act_user_manager_list_users (self->user_manager); list = act_user_manager_list_users (self->user_manager);
g_debug ("Got %u users", g_slist_length (list)); g_debug ("Got %u users", g_slist_length (list));
mct_carousel_purge_items (self->carousel);
list = g_slist_sort (list, (GCompareFunc) sort_users); list = g_slist_sort (list, (GCompareFunc) sort_users);
for (l = list; l; l = l->next) for (l = list; l; l = l->next)
{ {
@ -397,7 +397,7 @@ reload_users (MctUserSelector *self,
g_object_set (settings, "gtk-enable-animations", animations, NULL); g_object_set (settings, "gtk-enable-animations", animations, NULL);
gtk_revealer_set_reveal_child (GTK_REVEALER (self->carousel), TRUE); mct_carousel_set_revealed (self->carousel, TRUE);
} }
static GtkWidget * static GtkWidget *
@ -411,7 +411,7 @@ create_carousel_entry (MctUserSelector *self,
widget = mct_user_image_new (); widget = mct_user_image_new ();
mct_user_image_set_user (MCT_USER_IMAGE (widget), user); mct_user_image_set_user (MCT_USER_IMAGE (widget), user);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); gtk_box_append (GTK_BOX (box), widget);
label = g_strdup_printf ("<b>%s</b>", label = g_strdup_printf ("<b>%s</b>",
get_real_or_user_name (user)); get_real_or_user_name (user));
@ -419,7 +419,7 @@ create_carousel_entry (MctUserSelector *self,
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
gtk_widget_set_margin_top (widget, 5); gtk_widget_set_margin_top (widget, 5);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); gtk_box_append (GTK_BOX (box), widget);
g_free (label); g_free (label);
if (act_user_get_uid (user) == getuid ()) if (act_user_get_uid (user) == getuid ())
@ -431,7 +431,7 @@ create_carousel_entry (MctUserSelector *self,
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
g_free (label); g_free (label);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); gtk_box_append (GTK_BOX (box), widget);
gtk_style_context_add_class (gtk_widget_get_style_context (widget), gtk_style_context_add_class (gtk_widget_get_style_context (widget),
"dim-label"); "dim-label");
@ -455,10 +455,10 @@ user_added_cb (ActUserManager *user_manager,
widget = create_carousel_entry (self, user); widget = create_carousel_entry (self, user);
item = mct_carousel_item_new (); item = mct_carousel_item_new ();
gtk_container_add (GTK_CONTAINER (item), widget); mct_carousel_item_set_child (MCT_CAROUSEL_ITEM (item), widget);
g_object_set_data (G_OBJECT (item), "uid", GINT_TO_POINTER (act_user_get_uid (user))); g_object_set_data (G_OBJECT (item), "uid", GINT_TO_POINTER (act_user_get_uid (user)));
gtk_container_add (GTK_CONTAINER (self->carousel), item); mct_carousel_add (self->carousel, MCT_CAROUSEL_ITEM (item));
} }
static void static void
@ -506,3 +506,38 @@ mct_user_selector_get_user (MctUserSelector *self)
return self->user; return self->user;
} }
/**
* mct_user_selector_select_user_by_username:
* @self: an #MctUserSelector
* @username: username of the user to select
*
* Selects the given @username in the widget. This might fail if @username isnt
* a valid user, or if they arent listed in the selector due to being an
* administrator (see #MctUserSelector:show-administrators).
*
* Returns: %TRUE if the user was successfully selected, %FALSE otherwise
* Since: 0.10.0
*/
gboolean
mct_user_selector_select_user_by_username (MctUserSelector *self,
const gchar *username)
{
MctCarouselItem *item = NULL;
ActUser *user = NULL;
g_return_val_if_fail (MCT_IS_USER_SELECTOR (self), FALSE);
g_return_val_if_fail (username != NULL && *username != '\0', FALSE);
user = act_user_manager_get_user (self->user_manager, username);
if (user == NULL)
return FALSE;
item = mct_carousel_find_item (self->carousel, user, user_compare);
if (item == NULL)
return FALSE;
mct_carousel_select_item (self->carousel, item);
return TRUE;
}

View File

@ -34,4 +34,7 @@ MctUserSelector *mct_user_selector_new (ActUserManager *user_manager);
ActUser *mct_user_selector_get_user (MctUserSelector *self); ActUser *mct_user_selector_get_user (MctUserSelector *self);
gboolean mct_user_selector_select_user_by_username (MctUserSelector *self,
const gchar *username);
G_END_DECLS G_END_DECLS

View File

@ -5,7 +5,6 @@
<template class="MctUserSelector" parent="GtkBox"> <template class="MctUserSelector" parent="GtkBox">
<child> <child>
<object class="MctCarousel" id="carousel"> <object class="MctCarousel" id="carousel">
<property name="visible">True</property>
<property name="hexpand">True</property> <property name="hexpand">True</property>
<signal name="item-activated" handler="carousel_item_activated"/> <signal name="item-activated" handler="carousel_item_activated"/>
</object> </object>

View File

@ -1,6 +1,6 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns="http://usefulinc.com/ns/doap#"> <Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns="http://usefulinc.com/ns/doap#">
<name xml:lang="en">malcontent</name> <name xml:lang="en">malcontent</name>
<shortdesc xml:lang="en">malcontent provides restrictions for children on Linux systems</shortdesc> <shortdesc xml:lang="en">malcontent provides parental controls functionality on Linux systems</shortdesc>
<description xml:lang="en">malcontent implements support for restricting the abilities of non-administrator accounts on a Linux system.</description> <description xml:lang="en">malcontent implements support for restricting the abilities of non-administrator accounts on a Linux system.</description>
<homepage rdf:resource="https://gitlab.freedesktop.org/pwithnall/malcontent"/> <homepage rdf:resource="https://gitlab.freedesktop.org/pwithnall/malcontent"/>
<license rdf:resource="http://usefulinc.com/doap/licenses/lgpl"/> <license rdf:resource="http://usefulinc.com/doap/licenses/lgpl"/>

View File

@ -1,7 +1,7 @@
project('malcontent', 'c', project('malcontent', 'c',
version : '0.5.0', version : '0.12.0',
meson_version : '>= 0.49.0', meson_version : '>= 0.59.0',
license: 'LGPLv2.1+', license: ['LGPL-2.1-or-later', 'GPL-2.0-or-later'],
default_options : [ default_options : [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
'warning_level=2', 'warning_level=2',
@ -13,14 +13,15 @@ gnome = import('gnome')
i18n = import('i18n') i18n = import('i18n')
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
meson_make_symlink = join_paths(meson.source_root(), 'tools', 'meson-make-symlink.py') meson_make_symlink = join_paths(meson.current_source_dir(), 'tools', 'meson-make-symlink.py')
po_dir = join_paths(meson.source_root(), 'po') po_dir = join_paths(meson.current_source_dir(), 'po')
prefix = get_option('prefix') prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir')) bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir')) datadir = join_paths(prefix, get_option('datadir'))
libdir = join_paths(prefix, get_option('libdir')) libdir = join_paths(prefix, get_option('libdir'))
libexecdir = join_paths(prefix, get_option('libexecdir')) libexecdir = join_paths(prefix, get_option('libexecdir'))
includedir = join_paths(prefix, get_option('includedir'))
# FIXME: This isnt exposed in accountsservice.pc # FIXME: This isnt exposed in accountsservice.pc
# See https://gitlab.freedesktop.org/accountsservice/accountsservice/merge_requests/16 # See https://gitlab.freedesktop.org/accountsservice/accountsservice/merge_requests/16
@ -33,22 +34,18 @@ if pamlibdir == ''
endif endif
dbus = dependency('dbus-1') dbus = dependency('dbus-1')
dbusinterfacesdir = dbus.get_pkgconfig_variable('interfaces_dir', dbusinterfacesdir = dbus.get_variable(pkgconfig: 'interfaces_dir',
define_variable: ['datadir', datadir]) pkgconfig_define: ['datadir', datadir])
polkit_gobject = dependency('polkit-gobject-1') polkit_gobject = dependency('polkit-gobject-1')
polkitpolicydir = polkit_gobject.get_pkgconfig_variable('policydir', polkitpolicydir = polkit_gobject.get_variable(pkgconfig: 'policydir',
define_variable: ['prefix', prefix]) pkgconfig_define: ['prefix', prefix])
libglib_testing = subproject('libglib-testing')
libglib_testing_dep = dependency(
'libglib-testing',
fallback: ['libglib-testing', 'libglib_testing_dep'],
)
config_h = configuration_data() config_h = configuration_data()
config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name()) config_h.set_quoted('GETTEXT_PACKAGE', 'malcontent')
config_h.set_quoted('PACKAGE_LOCALE_DIR', join_paths(get_option('localedir'), meson.project_name())) config_h.set_quoted('PACKAGE_LOCALE_DIR', join_paths(get_option('prefix'), get_option('localedir')))
config_h.set_quoted('PAMLIBDIR', pamlibdir)
config_h.set_quoted('VERSION', meson.project_version())
configure_file( configure_file(
output: 'config.h', output: 'config.h',
configuration: config_h, configuration: config_h,
@ -127,9 +124,33 @@ test_env = [
] ]
subdir('accounts-service') subdir('accounts-service')
subdir('help')
if not get_option('use_system_libmalcontent')
subdir('libmalcontent') subdir('libmalcontent')
else
libmalcontent_api_version = '0'
libmalcontent_dep = dependency('malcontent-' + libmalcontent_api_version, version: meson.project_version())
libmalcontent_gir = ['Malcontent-' + libmalcontent_api_version,
'Malcontent-' + libmalcontent_api_version + '.typelib']
endif
if get_option('ui').enabled()
gtk_dep = dependency('gtk4', version: '>= 4.6')
libadwaita_dep = dependency(
'libadwaita-1',
version: '>= 1.1',
fallback: ['libadwaita', 'libadwaita_dep'],
default_options: ['examples=false', 'introspection=disabled', 'tests=false', 'vapi=false'],
)
subdir('libmalcontent-ui') subdir('libmalcontent-ui')
endif
subdir('malcontent-client') subdir('malcontent-client')
if get_option('ui').enabled()
subdir('malcontent-control') subdir('malcontent-control')
gnome.post_install(
gtk_update_icon_cache: true,
update_desktop_database: true,
)
endif
subdir('pam') subdir('pam')
subdir('po') subdir('po')

View File

@ -9,3 +9,21 @@ option(
type: 'string', type: 'string',
description: 'directory for PAM modules' description: 'directory for PAM modules'
) )
option(
'ui',
type: 'feature',
value: 'enabled',
description: 'enable UI library'
)
option(
'use_system_libmalcontent',
type: 'boolean',
value: false,
description: 'use installed libmalcontent rather than building it; used in distros to break a dependency cycle'
)
option(
'privileged_group',
type: 'string',
value: 'wheel',
description: 'name of group that has elevated permissions'
)

View File

@ -24,6 +24,7 @@
#include <glib.h> #include <glib.h>
#include <locale.h> #include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h"
/* Test that the `pam_malcontent.so` module can be loaded using dlopen() and /* Test that the `pam_malcontent.so` module can be loaded using dlopen() and
* that it exports the appropriate symbols for PAM to be able to use it. */ * that it exports the appropriate symbols for PAM to be able to use it. */
@ -37,6 +38,13 @@ test_pam_malcontent_dlopen (void)
module_path = g_test_build_filename (G_TEST_BUILT, "..", "pam_malcontent.so", NULL); module_path = g_test_build_filename (G_TEST_BUILT, "..", "pam_malcontent.so", NULL);
/* Installed tests version. */
if (!g_file_test (module_path, G_FILE_TEST_EXISTS))
{
g_free (module_path);
module_path = g_build_filename (PAMLIBDIR, "pam_malcontent.so", NULL);
}
/* Check the module can be loaded. */ /* Check the module can be loaded. */
handle = dlopen (module_path, RTLD_NOW); handle = dlopen (module_path, RTLD_NOW);
g_assert_nonnull (handle); g_assert_nonnull (handle);

View File

@ -0,0 +1,51 @@
af
ar
bg
bn
ca
ca@valencia
cs
da
de
el
eo
es
eu
fa
fi
fr
fur
gd
gl
he
hi
hr
hu
id
it
ka
kk
ko
lt
lv
ml
ms
nb
nl
oc
pa
pl
pt
pt_BR
ro
ru
sk
sl
sr
sr@latin
sv
th
tr
uk
vi
zh_TW

View File

@ -1,8 +1,9 @@
# List of source files containing translatable strings. # List of source files containing translatable strings.
# Please keep this file sorted alphabetically. # Please keep this file sorted alphabetically.
accounts-service/com.endlessm.ParentalControls.policy.in accounts-service/com.endlessm.ParentalControls.policy.in
libmalcontent/app-filter.c
libmalcontent/manager.c libmalcontent/manager.c
libmalcontent-ui/gs-content-rating.c libmalcontent/session-limits.c
libmalcontent-ui/restrict-applications-dialog.c libmalcontent-ui/restrict-applications-dialog.c
libmalcontent-ui/restrict-applications-dialog.ui libmalcontent-ui/restrict-applications-dialog.ui
libmalcontent-ui/restrict-applications-selector.c libmalcontent-ui/restrict-applications-selector.c
@ -10,8 +11,10 @@ libmalcontent-ui/restrict-applications-selector.ui
libmalcontent-ui/user-controls.c libmalcontent-ui/user-controls.c
libmalcontent-ui/user-controls.ui libmalcontent-ui/user-controls.ui
malcontent-control/application.c malcontent-control/application.c
malcontent-control/carousel.ui
malcontent-control/main.ui malcontent-control/main.ui
malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in
malcontent-control/org.freedesktop.MalcontentControl.desktop.in malcontent-control/org.freedesktop.MalcontentControl.desktop.in
malcontent-control/org.freedesktop.MalcontentControl.policy.in malcontent-control/org.freedesktop.MalcontentControl.policy.in
malcontent-control/user-selector.c
pam/pam_malcontent.c pam/pam_malcontent.c

757
po/af.po Normal file
View File

@ -0,0 +1,757 @@
# Afrikaans translations for malcontent package.
# Copyright (C) 2020 THE malcontent'S COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Automatically generated, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-10 12:04+0100\n"
"PO-Revision-Date: 2020-04-15 13:42+0100\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: af\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: accounts-service/com.endlessm.ParentalControls.policy.in:4
msgid "Change your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:5
msgid "Authentication is required to change your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:14
msgid "Read your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:15
msgid "Authentication is required to read your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:24
msgid "Change another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:25
msgid "Authentication is required to change another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:34
msgid "Read another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:35
msgid "Authentication is required to read another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:44
msgid "Change your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:45
msgid "Authentication is required to change your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:54
msgid "Read your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:55
msgid "Authentication is required to read your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:64
msgid "Change another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:65
msgid "Authentication is required to change another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:74
msgid "Read another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:75
msgid "Authentication is required to read another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:84
msgid "Change your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:85
msgid "Authentication is required to change your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:94
msgid "Read your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:95
msgid "Authentication is required to read your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:104
msgid "Change another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:105
msgid "Authentication is required to change another users account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:114
msgid "Read another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:115
msgid "Authentication is required to read another users account info."
msgstr ""
#: libmalcontent/app-filter.c:694
#, c-format
msgid "App filter for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/app-filter.c:725
#, c-format
msgid "OARS filter for user %u has an unrecognized kind %s"
msgstr ""
#: libmalcontent/manager.c:283 libmalcontent/manager.c:412
#, c-format
msgid "Not allowed to query app filter data for user %u"
msgstr ""
#: libmalcontent/manager.c:288
#, c-format
msgid "User %u does not exist"
msgstr ""
#: libmalcontent/manager.c:394
msgid "App filtering is globally disabled"
msgstr ""
#: libmalcontent/manager.c:777
msgid "Session limits are globally disabled"
msgstr ""
#: libmalcontent/manager.c:795
#, c-format
msgid "Not allowed to query session limits data for user %u"
msgstr ""
#: libmalcontent/session-limits.c:306
#, c-format
msgid "Session limit for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/session-limits.c:328
#, c-format
msgid "Session limit for user %u has an unrecognized type %u"
msgstr ""
#: libmalcontent/session-limits.c:346
#, c-format
msgid "Session limit for user %u has invalid daily schedule %u%u"
msgstr ""
#. TRANSLATORS: This is the formatting of English and localized name
#. of the rating e.g. "Adults Only (solo adultos)"
#: libmalcontent-ui/gs-content-rating.c:75
#, c-format
msgid "%s (%s)"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:209
msgid "General"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:218
msgid "ALL"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:222
#: libmalcontent-ui/gs-content-rating.c:485
msgid "Adults Only"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:224
#: libmalcontent-ui/gs-content-rating.c:484
msgid "Mature"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:226
#: libmalcontent-ui/gs-content-rating.c:483
msgid "Teen"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:228
#: libmalcontent-ui/gs-content-rating.c:482
msgid "Everyone 10+"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:230
#: libmalcontent-ui/gs-content-rating.c:481
msgid "Everyone"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:232
#: libmalcontent-ui/gs-content-rating.c:480
msgid "Early Childhood"
msgstr ""
#. Translators: the placeholder is a users full name
#: libmalcontent-ui/restrict-applications-dialog.c:222
#, c-format
msgid "Restrict %s from using the following installed applications."
msgstr ""
#: libmalcontent-ui/restrict-applications-dialog.ui:6
#: libmalcontent-ui/restrict-applications-dialog.ui:12
msgid "Restrict Applications"
msgstr ""
#: libmalcontent-ui/restrict-applications-selector.ui:24
msgid "No applications found to restrict."
msgstr ""
#. Translators: this is the full name for an unknown user account.
#: libmalcontent-ui/user-controls.c:242 libmalcontent-ui/user-controls.c:253
msgid "unknown"
msgstr ""
#: libmalcontent-ui/user-controls.c:338 libmalcontent-ui/user-controls.c:425
#: libmalcontent-ui/user-controls.c:711
msgid "All Ages"
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:514
#, c-format
msgid ""
"Prevents %s from running web browsers. Limited web content may still be "
"available in other applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:519
#, c-format
msgid "Prevents specified applications from being used by %s."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:524
#, c-format
msgid "Prevents %s from installing applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:529
#, c-format
msgid "Applications installed by %s will not appear for other users."
msgstr ""
#: libmalcontent-ui/user-controls.ui:17
msgid "Application Usage Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:68
msgid "Restrict _Web Browsers"
msgstr ""
#: libmalcontent-ui/user-controls.ui:152
msgid "_Restrict Applications"
msgstr ""
#: libmalcontent-ui/user-controls.ui:231
msgid "Software Installation Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:281
msgid "Restrict Application _Installation"
msgstr ""
#: libmalcontent-ui/user-controls.ui:366
msgid "Restrict Application Installation for _Others"
msgstr ""
#: libmalcontent-ui/user-controls.ui:451
msgid "Application _Suitability"
msgstr ""
#: libmalcontent-ui/user-controls.ui:473
msgid ""
"Restricts browsing or installation of applications to applications suitable "
"for certain ages or above."
msgstr ""
#. Translators: This is the title of the main window
#. Translators: the name of the application as it appears in a software center
#: malcontent-control/application.c:105 malcontent-control/main.ui:12
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:9
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:3
msgid "Parental Controls"
msgstr ""
#: malcontent-control/application.c:270
msgid "Copyright © 2019, 2020 Endless Mobile, Inc."
msgstr ""
#. Translators: this should be "translated" to the
#. names of people who have translated Malcontent into
#. this language, one per line.
#: malcontent-control/application.c:275
msgid "translator-credits"
msgstr ""
#. Translators: "Malcontent" is the brand name of this
#. project, so should not be translated.
#: malcontent-control/application.c:281
msgid "Malcontent Website"
msgstr ""
#: malcontent-control/application.c:299
msgid "The help contents could not be displayed"
msgstr ""
#: malcontent-control/application.c:336
msgid "Failed to load user data from the system"
msgstr ""
#: malcontent-control/application.c:338
msgid "Please make sure that the AccountsService is installed and enabled."
msgstr ""
#: malcontent-control/carousel.ui:48
msgid "Previous Page"
msgstr ""
#: malcontent-control/carousel.ui:74
msgid "Next Page"
msgstr ""
#: malcontent-control/main.ui:93
msgid "Permission Required"
msgstr ""
#: malcontent-control/main.ui:107
msgid ""
"Permission is required to view and change user parental controls settings."
msgstr ""
#: malcontent-control/main.ui:148
msgid "No Child Users Configured"
msgstr ""
#: malcontent-control/main.ui:162
msgid ""
"No child users are currently set up on the system. Create one before setting "
"up their parental controls."
msgstr ""
#: malcontent-control/main.ui:174
msgid "Create _Child User"
msgstr ""
#: malcontent-control/main.ui:202
msgid "Loading…"
msgstr ""
#: malcontent-control/main.ui:265
msgid "_Help"
msgstr "_Hulp"
#: malcontent-control/main.ui:269
msgid "_About Parental Controls"
msgstr ""
#. Translators: the brief summary of the application as it appears in a software center.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:12
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:4
msgid "Set parental controls and monitor usage by users"
msgstr ""
#. Translators: These are the application description paragraphs in the AppData file.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:16
msgid ""
"Manage users parental controls restrictions, controlling how long they can "
"use the computer for, what software they can install, and what installed "
"software they can run."
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:39
msgid "The GNOME Project"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:50
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:59
msgid "Minor improvements to parental controls application UI"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:51
msgid "Add a user manual"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:52
msgid "Translation updates"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:60
msgid "Translations to Ukrainian and Polish"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:67
msgid "Improve parental controls application UI and add icon"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:68
msgid "Support for indicating which accounts are parent accounts"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:75
msgid "Initial release of basic parental controls application"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:76
msgid "Support for setting app installation and run restrictions on users"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:83
msgid "Maintenance release of underlying parental controls library"
msgstr ""
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:7
msgid "org.freedesktop.MalcontentControl"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:13
msgid ""
"parental controls;screen time;app restrictions;web browser restrictions;oars;"
"usage;usage limit;kid;child;"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:9
msgid "Manage parental controls"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:10
msgid "Authentication is required to read and change user parental controls"
msgstr ""
#: malcontent-control/user-selector.c:426
msgid "Your account"
msgstr "Jou rekening"
#. Always allow root, to avoid a situation where this PAM module prevents
#. * all users logging in with no way of recovery.
#: pam/pam_malcontent.c:142 pam/pam_malcontent.c:188
#, c-format
msgid "User %s has no time limits enabled"
msgstr ""
#: pam/pam_malcontent.c:151 pam/pam_malcontent.c:172
#, c-format
msgid "Error getting session limits for user %s: %s"
msgstr ""
#: pam/pam_malcontent.c:182
#, c-format
msgid "User %s has no time remaining"
msgstr ""
#: pam/pam_malcontent.c:200
#, c-format
msgid "Error setting time limit on login session: %s"
msgstr ""
#~ msgid "No cartoon violence"
#~ msgstr "Geen animasie geweld nie"
#~ msgid "Cartoon characters in unsafe situations"
#~ msgstr "Animasiekarakters in onveilige situasies"
#~ msgid "Cartoon characters in aggressive conflict"
#~ msgstr "Animasiekarakters in aggressiewe konflik"
#~ msgid "Graphic violence involving cartoon characters"
#~ msgstr "Grafiese geweld met animasiekarakters"
#~ msgid "No fantasy violence"
#~ msgstr "Geen fantasie geweld nie"
#~ msgid "Characters in unsafe situations easily distinguishable from reality"
#~ msgstr ""
#~ "Karakters in onveilige situasies wat maklik onderskei kan word van die "
#~ "werklikheid"
#~ msgid ""
#~ "Characters in aggressive conflict easily distinguishable from reality"
#~ msgstr ""
#~ "Karakters in aggressiewe konflik wat maklik onderskei kan word van die "
#~ "werklikheid"
#~ msgid "Graphic violence easily distinguishable from reality"
#~ msgstr "Grafiese geweld wat maklik onderskei kan word van die werklikheid"
#~ msgid "No realistic violence"
#~ msgstr "Geen realistiese geweld nie"
#~ msgid "Mildly realistic characters in unsafe situations"
#~ msgstr "Effens realistiese karakters in onveilige situasies"
#~ msgid "Depictions of realistic characters in aggressive conflict"
#~ msgstr "Uitbeeldings van realistiese karakters in aggressiewe konflik"
#~ msgid "Graphic violence involving realistic characters"
#~ msgstr "Grafiese geweld met realistiese karakters"
#~ msgid "No bloodshed"
#~ msgstr "Geen bloedvergieting nie"
#~ msgid "Unrealistic bloodshed"
#~ msgstr "Onrealistiese bloedvergieting"
#~ msgid "Realistic bloodshed"
#~ msgstr "Realistiese bloedvergieting"
#~ msgid "Depictions of bloodshed and the mutilation of body parts"
#~ msgstr "Uitbeeldings van bloedvergieting en die verminking van liggaamsdele"
#~ msgid "No sexual violence"
#~ msgstr "Geen seksuele geweld nie"
#~ msgid "Rape or other violent sexual behavior"
#~ msgstr "Verkragting of ander gewelddadige seksuele gedrag"
#~ msgid "No references to alcohol"
#~ msgstr "Geen verwysings na alkohol nie"
#~ msgid "References to alcoholic beverages"
#~ msgstr "Verwysings na alkoholiese drankies"
#~ msgid "Use of alcoholic beverages"
#~ msgstr "Gebruik van alkoholiese drank"
#~ msgid "No references to illicit drugs"
#~ msgstr "Geen verwysings na onwettige dwelms"
#~ msgid "References to illicit drugs"
#~ msgstr "Verwysings na onwettige dwelms"
#~ msgid "Use of illicit drugs"
#~ msgstr "Gebruik van onwettige dwelms"
#~ msgid "References to tobacco products"
#~ msgstr "Verwysings na tabakprodukte"
#~ msgid "Use of tobacco products"
#~ msgstr "Gebruik van tabaksprodukte"
#~ msgid "No nudity of any sort"
#~ msgstr "Geen naaktheid van enige aard nie"
#~ msgid "Brief artistic nudity"
#~ msgstr "Kort kuns naaktheid"
#~ msgid "Prolonged nudity"
#~ msgstr "Langdurige naaktheid"
#~ msgid "No references or depictions of sexual nature"
#~ msgstr "Geen verwysings of uitbeeldings van 'n seksuele aard nie"
#~ msgid "Provocative references or depictions"
#~ msgstr "Aanloklike verwysings of afbeeldings"
#~ msgid "Sexual references or depictions"
#~ msgstr "Seksuele verwysings of afbeeldings"
#~ msgid "Graphic sexual behavior"
#~ msgstr "Grafiese seksuele gedrag"
#~ msgid "No profanity of any kind"
#~ msgstr "Geen vloek van enige aard nie"
#~ msgid "Mild or infrequent use of profanity"
#~ msgstr "Sagte of ongereelde gebruik van vloek"
#~ msgid "Moderate use of profanity"
#~ msgstr "Matige gebruik van vloek"
#~ msgid "Strong or frequent use of profanity"
#~ msgstr "Sterk of gereelde gebruik van vloek"
#~ msgid "No inappropriate humor"
#~ msgstr "Geen onvanpaste humor nie"
#~ msgid "Slapstick humor"
#~ msgstr "Slapstick humor"
#~ msgid "Vulgar or bathroom humor"
#~ msgstr "Onvanpaste of badkamer humor"
#~ msgid "Mature or sexual humor"
#~ msgstr "Volwasse of seksuele humor"
#~ msgid "No discriminatory language of any kind"
#~ msgstr "Geen diskriminerende taal van enige aard nie"
#~ msgid "Negativity towards a specific group of people"
#~ msgstr "Negatiwiteit teenoor 'n spesifieke groep mense"
#~ msgid "Discrimination designed to cause emotional harm"
#~ msgstr "Diskriminasie bedoel om emosionele skade te veroorsaak"
#~ msgid "Explicit discrimination based on gender, sexuality, race or religion"
#~ msgstr ""
#~ "Eksplisiete diskriminasie gebaseer op geslag, seksualiteit, ras of "
#~ "godsdiens"
#~ msgid "No advertising of any kind"
#~ msgstr "Geen advertensies van enige aard nie"
#~ msgid "Product placement"
#~ msgstr "Produk plasing"
#~ msgid "Explicit references to specific brands or trademarked products"
#~ msgstr "Verwysings na spesifieke handelsmerke"
#~ msgid "Users are encouraged to purchase specific real-world items"
#~ msgstr "Gebruikers word aangemoedig om spesifieke werklike items te koop"
#~ msgid "No gambling of any kind"
#~ msgstr "Geen dobbel van enige aard nie"
#~ msgid "Gambling on random events using tokens or credits"
#~ msgstr "Dobbel op sommige geleenthede deur gebruik te maak van krediete"
#~ msgid "Gambling using “play” money"
#~ msgstr "Dobbel met \"speel\" geld"
#~ msgid "Gambling using real money"
#~ msgstr "Dobbel met regte geld"
#~ msgid "No ability to spend money"
#~ msgstr "Geen vermoë om geld te spandeer nie"
#~ msgid "Users are encouraged to donate real money"
#~ msgstr "Spelers word aangemoedig om werklike geld te skenk"
#~ msgid "Ability to spend real money in-game"
#~ msgstr "Vermoë om geld te spandeer in die spel"
#~ msgid "No way to chat with other users"
#~ msgstr "Geen manier om met ander gebruikers te klets nie"
#~ msgid "Moderated chat functionality between users"
#~ msgstr "Gemodereerde kletsfunksie tussen gebruikers"
#~ msgid "Uncontrolled chat functionality between users"
#~ msgstr "Onbeheerde kletsfunksie tussen gebruikers"
#~ msgid "No way to talk with other users"
#~ msgstr "Geen manier om met ander gebruikers te praat nie"
#~ msgid "Uncontrolled audio or video chat functionality between users"
#~ msgstr "Onbeheerde klank- of videokletsfunksies tussen gebruikers"
#~ msgid "No sharing of social network usernames or email addresses"
#~ msgstr "Geen deel van sosiale netwerk gebruikersname of e-pos adresse nie"
#~ msgid "Sharing social network usernames or email addresses"
#~ msgstr "Deel van sosiale netwerk gebruikers name of e-pos adresse"
#~ msgid "No sharing of user information with 3rd parties"
#~ msgstr "Geen deel van gebruikersinligting met 3de partye nie"
#~ msgid "Checking for the latest application version"
#~ msgstr "Kyk tans vir die nuutste weergawe van die toepassing"
#~ msgid "Sharing diagnostic data that does not let others identify the user"
#~ msgstr "Deel anonieme diagnostiese data"
#~ msgid "Sharing information that lets others identify the user"
#~ msgstr ""
#~ "Deel inligting wat ander in staat sal kan stel om die gebruiker te "
#~ "identifiseer"
#~ msgid "No sharing of physical location to other users"
#~ msgstr "Geen deel van fisiese ligging aan ander gebruikers nie"
#~ msgid "Sharing physical location to other users"
#~ msgstr "Deel fisiese ligging aan ander gebruikers"
#~ msgid "No references to homosexuality"
#~ msgstr "Geen verwysings na homoseksualiteit"
#~ msgid "Indirect references to homosexuality"
#~ msgstr "Indirekte verwysings na homoseksualiteit"
#~ msgid "Kissing between people of the same gender"
#~ msgstr "Soen tussen mense van dieselfde geslag"
#~ msgid "Graphic sexual behavior between people of the same gender"
#~ msgstr "Grafiese seksuele gedrag tussen mense van dieselfde geslag"
#~ msgid "No references to prostitution"
#~ msgstr "Geen verwysings na prostitusie nie"
#~ msgid "Indirect references to prostitution"
#~ msgstr "Indirekte verwysings na prostitusie"
#~ msgid "Graphic depictions of the act of prostitution"
#~ msgstr "Grafiese uitbeeldings van die daad van prostitusie"
#~ msgid "No references to adultery"
#~ msgstr "Geen verwysings na owerspel nie"
#~ msgid "Indirect references to adultery"
#~ msgstr "Indirekte verwysings na owerspel"
#~ msgid "Graphic depictions of the act of adultery"
#~ msgstr "Grafiese uitbeeldings van die daad van owerspel"
#~ msgid "No sexualized characters"
#~ msgstr "Geen seksuele karakters nie"
#~ msgid "Scantily clad human characters"
#~ msgstr "Skraps geklede menslike karakters"
#~ msgid "Overtly sexualized human characters"
#~ msgstr "Uitermatige seksuele menslike karakters"
#~ msgid "No references to desecration"
#~ msgstr "Geen verwysings na ontheiliging nie"
#~ msgid "Depictions of modern-day human desecration"
#~ msgstr "Uitbeeldings van moderne menslike ontheiliging"
#~ msgid "Graphic depictions of modern-day desecration"
#~ msgstr "Grafiese uitbeeldings van moderne ontheiliging"
#~ msgid "No visible dead human remains"
#~ msgstr "Geen sigbare dooie menslike oorskot"
#~ msgid "Visible dead human remains"
#~ msgstr "Sigbare dooie menslike oorskot"
#~ msgid "Dead human remains that are exposed to the elements"
#~ msgstr "Dooie menslike oorskot wat aan die elemente blootgestel is"
#~ msgid "Graphic depictions of desecration of human bodies"
#~ msgstr "Grafiese uitbeeldings van die ontheiliging van menslike liggame"
#~ msgid "No references to slavery"
#~ msgstr "Geen verwysings na slawerny nie"
#~ msgid "Depictions of modern-day slavery"
#~ msgstr "Uitbeeldings van modererende slawerny"
#~ msgid "Graphic depictions of modern-day slavery"
#~ msgstr "Grafiese uitbeeldings van modererende slawerny"

778
po/ar.po Normal file
View File

@ -0,0 +1,778 @@
# Arabic translations for malcontent package.
# Copyright (C) 2020 THE malcontent'S COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Automatically generated, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-10 12:08+0100\n"
"PO-Revision-Date: 2020-04-17 21:58+0000\n"
"Last-Translator: Will Thompson <wjt@endlessm.com>, 2020\n"
"Language-Team: Arabic (https://www.transifex.com/endless-os/teams/9016/ar/)\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: accounts-service/com.endlessm.ParentalControls.policy.in:4
msgid "Change your own app filter"
msgstr "قُم بتغيير عناصر تصفية تطبيقك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:5
msgid "Authentication is required to change your app filter."
msgstr "المصادقة مطلوبة لتغيير عناصر تصفية تطبيقك."
#: accounts-service/com.endlessm.ParentalControls.policy.in:14
msgid "Read your own app filter"
msgstr "اقرأ عناصر تصفية تطبيقك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:15
msgid "Authentication is required to read your app filter."
msgstr "المصادقة مطلوبة لقراءة عناصر تصفية تطبيقك."
#: accounts-service/com.endlessm.ParentalControls.policy.in:24
msgid "Change another users app filter"
msgstr "قم بتغيير مرشح تطبيق مستخدم آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:25
msgid "Authentication is required to change another users app filter."
msgstr "المصادقة مطلوبة لتغيير عناصر تصفية التطبيق الخاص بمستخدمٍ آخر."
#: accounts-service/com.endlessm.ParentalControls.policy.in:34
msgid "Read another users app filter"
msgstr "قراءة مرشح تطبيقات مستخدم آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:35
msgid "Authentication is required to read another users app filter."
msgstr "المصادقة مطلوبة لقراءة مرشح تطبيق مستخدم آخر."
#: accounts-service/com.endlessm.ParentalControls.policy.in:44
msgid "Change your own session limits"
msgstr "تغيير حدود جلستك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:45
msgid "Authentication is required to change your session limits."
msgstr "المصادقة مطلوبة لتغيير حدود جلستك."
#: accounts-service/com.endlessm.ParentalControls.policy.in:54
msgid "Read your own session limits"
msgstr "قراءة حدود الجلسة الخاصة بك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:55
msgid "Authentication is required to read your session limits."
msgstr "المصادقة مطلوبة لقراءة حدود جلستك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:64
msgid "Change another users session limits"
msgstr "تغيير حدود الجلسات لمستخدمٍ آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:65
msgid "Authentication is required to change another users session limits."
msgstr "المصادقة مطلوبة لتغيير حدود جلسة مستخدمٍ آخر."
#: accounts-service/com.endlessm.ParentalControls.policy.in:74
msgid "Read another users session limits"
msgstr "اقرأ حدود جلسات مستخدمٍ آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:75
msgid "Authentication is required to read another users session limits."
msgstr "المصادقة مطلوبة لقراءة حدود جلسات مستخدم آخر."
#: accounts-service/com.endlessm.ParentalControls.policy.in:84
msgid "Change your own account info"
msgstr "قُم بتغيير معلومات حسابك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:85
msgid "Authentication is required to change your account info."
msgstr "المصادقة مطلوبة لتغيير معلومات حسابك."
#: accounts-service/com.endlessm.ParentalControls.policy.in:94
msgid "Read your own account info"
msgstr "قراءة معلومات الحساب الخاص بك"
#: accounts-service/com.endlessm.ParentalControls.policy.in:95
msgid "Authentication is required to read your account info."
msgstr "المصادقة مطلوبة لقراءة معلومات حسابك."
#: accounts-service/com.endlessm.ParentalControls.policy.in:104
msgid "Change another users account info"
msgstr "تغيير معلومات حساب مستخدمٍ آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:105
msgid "Authentication is required to change another users account info."
msgstr "المصادقة مطلوبة لتغيير معلومات حساب مستخدم آخر."
#: accounts-service/com.endlessm.ParentalControls.policy.in:114
msgid "Read another users account info"
msgstr "قراءة معلومات حساب مستخدم آخر"
#: accounts-service/com.endlessm.ParentalControls.policy.in:115
msgid "Authentication is required to read another users account info."
msgstr "المصادقة مطلوبة لقراءة معلومات حساب مستخدمٍ آخر."
#: libmalcontent/app-filter.c:694
#, c-format
msgid "App filter for user %u was in an unrecognized format"
msgstr "عناصر تصفية التطبيق للمستخدم %u كانت بتنسيق غير معروف"
#: libmalcontent/app-filter.c:725
#, c-format
msgid "OARS filter for user %u has an unrecognized kind %s"
msgstr "يحتوي مرشح OARS للمستخدم %u على %s مجهول"
#: libmalcontent/manager.c:283 libmalcontent/manager.c:412
#, c-format
msgid "Not allowed to query app filter data for user %u"
msgstr "غير مسموح بالاستعلام عن بيانات فلتر التطبيق للمستخدم %u "
#: libmalcontent/manager.c:288
#, c-format
msgid "User %u does not exist"
msgstr "المستخدم %u غير موجود"
#: libmalcontent/manager.c:394
msgid "App filtering is globally disabled"
msgstr "تم تعطيل ترشيح التطبيقات بشكل شامل"
#: libmalcontent/manager.c:777
msgid "Session limits are globally disabled"
msgstr "حدود الجلسات معطلة بصورة شاملة"
#: libmalcontent/manager.c:795
#, c-format
msgid "Not allowed to query session limits data for user %u"
msgstr "غير مسموح بالاستعلام عن بيانات حدود الجلسة للمستخدم %u"
#: libmalcontent/session-limits.c:306
#, c-format
msgid "Session limit for user %u was in an unrecognized format"
msgstr "كان حد الجلسة للمستخدم %u بتنسيق غير معروف"
#: libmalcontent/session-limits.c:328
#, c-format
msgid "Session limit for user %u has an unrecognized type %u"
msgstr "لدى حد جلسة المستخدم %u نوعاً مجهولاً '%u'"
#: libmalcontent/session-limits.c:346
#, c-format
msgid "Session limit for user %u has invalid daily schedule %u%u"
msgstr "حدود الجلسة للمستخدم %u لها جدول زمني يومي غير صالح %u%u "
#. TRANSLATORS: This is the formatting of English and localized name
#. of the rating e.g. "Adults Only (solo adultos)"
#: libmalcontent-ui/gs-content-rating.c:75
#, c-format
msgid "%s (%s)"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:209
msgid "General"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:218
msgid "ALL"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:222
#: libmalcontent-ui/gs-content-rating.c:485
msgid "Adults Only"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:224
#: libmalcontent-ui/gs-content-rating.c:484
msgid "Mature"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:226
#: libmalcontent-ui/gs-content-rating.c:483
msgid "Teen"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:228
#: libmalcontent-ui/gs-content-rating.c:482
msgid "Everyone 10+"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:230
#: libmalcontent-ui/gs-content-rating.c:481
msgid "Everyone"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:232
#: libmalcontent-ui/gs-content-rating.c:480
msgid "Early Childhood"
msgstr ""
#. Translators: the placeholder is a users full name
#: libmalcontent-ui/restrict-applications-dialog.c:222
#, c-format
msgid "Restrict %s from using the following installed applications."
msgstr "تقييد %s من استخدام التطبيقات المثبتة التالية."
#: libmalcontent-ui/restrict-applications-dialog.ui:6
#: libmalcontent-ui/restrict-applications-dialog.ui:12
msgid "Restrict Applications"
msgstr "تقييد التطبيقات"
#: libmalcontent-ui/restrict-applications-selector.ui:24
msgid "No applications found to restrict."
msgstr "لم يتم العثور على تطبيقات لتقييدها."
#. Translators: this is the full name for an unknown user account.
#: libmalcontent-ui/user-controls.c:242 libmalcontent-ui/user-controls.c:253
msgid "unknown"
msgstr "غير معروف"
#: libmalcontent-ui/user-controls.c:338 libmalcontent-ui/user-controls.c:425
#: libmalcontent-ui/user-controls.c:711
msgid "All Ages"
msgstr "جميع الأعمار"
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:514
#, c-format
msgid ""
"Prevents %s from running web browsers. Limited web content may still be "
"available in other applications."
msgstr ""
"يمنع %s من تشغيل متصفحات الإنترنت. قد يظل محتوى الإنترنت المحدود متاحاً في "
"تطبيقات أخرى."
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:519
#, c-format
msgid "Prevents specified applications from being used by %s."
msgstr "يمنع استخدام تطبيقات محددة من قبل %s."
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:524
#, c-format
msgid "Prevents %s from installing applications."
msgstr "يمنع %s تثبيت التطبيقات."
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:529
#, c-format
msgid "Applications installed by %s will not appear for other users."
msgstr "لن تظهر التطبيقات المثبتة بواسطة %s للمستخدمين الآخرين."
#: libmalcontent-ui/user-controls.ui:17
msgid "Application Usage Restrictions"
msgstr "قيود استخدام التطبيق"
#: libmalcontent-ui/user-controls.ui:68
msgid "Restrict _Web Browsers"
msgstr "تقييد متصفحات الإنترنت"
#: libmalcontent-ui/user-controls.ui:152
msgid "_Restrict Applications"
msgstr "تقييد التطبيقات"
#: libmalcontent-ui/user-controls.ui:231
msgid "Software Installation Restrictions"
msgstr "قيود تثبيت البرنامج"
#: libmalcontent-ui/user-controls.ui:281
msgid "Restrict Application _Installation"
msgstr "تقييد تثبيت التطبيق"
#: libmalcontent-ui/user-controls.ui:366
msgid "Restrict Application Installation for _Others"
msgstr "تقييد تثبيت التطبيق على الآخرين"
#: libmalcontent-ui/user-controls.ui:451
msgid "Application _Suitability"
msgstr "ملاءمة التطبيق"
#: libmalcontent-ui/user-controls.ui:473
msgid ""
"Restricts browsing or installation of applications to applications suitable "
"for certain ages or above."
msgstr ""
"يقتصر تصفح أو تثبيت التطبيقات على تطبيقات مناسبة لفئة عمرية معينة أو أكبر."
#. Translators: This is the title of the main window
#. Translators: the name of the application as it appears in a software center
#: malcontent-control/application.c:105 malcontent-control/main.ui:12
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:9
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:3
msgid "Parental Controls"
msgstr "أدوات الإشراف العائلي"
#: malcontent-control/application.c:270
msgid "Copyright © 2019, 2020 Endless Mobile, Inc."
msgstr "حقوق النشر © 2019، 2020 Endless Mobile، Inc."
#. Translators: this should be "translated" to the
#. names of people who have translated Malcontent into
#. this language, one per line.
#: malcontent-control/application.c:275
msgid "translator-credits"
msgstr ""
#. Translators: "Malcontent" is the brand name of this
#. project, so should not be translated.
#: malcontent-control/application.c:281
msgid "Malcontent Website"
msgstr "موقع Malcontent"
#: malcontent-control/application.c:299
msgid "The help contents could not be displayed"
msgstr "لا يمكن عرض محتويات المساعدة"
#: malcontent-control/application.c:336
msgid "Failed to load user data from the system"
msgstr "فشل تحميل بيانات المستخدم من النظام"
#: malcontent-control/application.c:338
msgid "Please make sure that the AccountsService is installed and enabled."
msgstr "يُرجى التأكد من تثبيت خدمة الحسابات وتمكينها."
#: malcontent-control/carousel.ui:48
msgid "Previous Page"
msgstr "الصفحة السابقة"
#: malcontent-control/carousel.ui:74
msgid "Next Page"
msgstr "الصفحة التالية"
#: malcontent-control/main.ui:93
msgid "Permission Required"
msgstr "الإذن مطلوب"
#: malcontent-control/main.ui:107
msgid ""
"Permission is required to view and change user parental controls settings."
msgstr "الإذن مطلوب لعرض وتغيير إعدادات الإشراف العائلي لحساب المستخدم."
#: malcontent-control/main.ui:148
msgid "No Child Users Configured"
msgstr "لم يتم تهيئة مستخدمين فرعيين"
#: malcontent-control/main.ui:162
msgid ""
"No child users are currently set up on the system. Create one before setting "
"up their parental controls."
msgstr ""
"لا توجد حالياً حسابات لمستخدمين أطفال على النظام. قُم بإنشاء حساب واحد قبل "
"تهيئة أدوات الإشراف العائلي الخاصة بها."
#: malcontent-control/main.ui:174
msgid "Create _Child User"
msgstr "إنشاء حساب لطفل"
#: malcontent-control/main.ui:202
msgid "Loading…"
msgstr "جارٍ التحميل..."
#: malcontent-control/main.ui:265
msgid "_Help"
msgstr "م_ساعدة"
#: malcontent-control/main.ui:269
msgid "_About Parental Controls"
msgstr "نبذة عن الإشراف العائلي"
#. Translators: the brief summary of the application as it appears in a software center.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:12
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:4
msgid "Set parental controls and monitor usage by users"
msgstr "قُم بضبط الإشراف العائلي ومراقبة الاستخدام بواسطة المستخدمين"
#. Translators: These are the application description paragraphs in the AppData file.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:16
msgid ""
"Manage users parental controls restrictions, controlling how long they can "
"use the computer for, what software they can install, and what installed "
"software they can run."
msgstr ""
"إدارة قيود الإشراف العائلي للمستخدمين، والتحكم في المدة التي يمكنهم خلالها "
"استخدام الكمبيوتر، والبرنامج الذي يمكنهم تثبيته، والبرنامج المثبت الذي "
"يمكنهم تشغيله"
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:39
msgid "The GNOME Project"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:50
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:59
msgid "Minor improvements to parental controls application UI"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:51
msgid "Add a user manual"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:52
msgid "Translation updates"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:60
msgid "Translations to Ukrainian and Polish"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:67
msgid "Improve parental controls application UI and add icon"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:68
msgid "Support for indicating which accounts are parent accounts"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:75
msgid "Initial release of basic parental controls application"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:76
msgid "Support for setting app installation and run restrictions on users"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:83
msgid "Maintenance release of underlying parental controls library"
msgstr ""
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:7
msgid "org.freedesktop.MalcontentControl"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:13
msgid ""
"parental controls;screen time;app restrictions;web browser restrictions;oars;"
"usage;usage limit;kid;child;"
msgstr ""
"إعدادات التحكم الأبوي؛ الوقت الذي يقضى بمشاهدة الشاشة؛ القيود الخاصة "
"بالتطبيقات؛ القيود الخاصة بمتصفحات الإنترنت؛ فتح خدمة تقارير مؤتمتة؛ "
"الاستخدام؛ حدود الاستخدام؛ الطفل؛ الطفل؛ "
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:9
msgid "Manage parental controls"
msgstr "إدارة الإشراف العائلي"
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:10
msgid "Authentication is required to read and change user parental controls"
msgstr "المصادقة مطلوبة لقراءة وتغيير إعدادات التحكم الأبوية الخاصة بالمستخدم"
#: malcontent-control/user-selector.c:426
msgid "Your account"
msgstr "حسابك"
#. Always allow root, to avoid a situation where this PAM module prevents
#. * all users logging in with no way of recovery.
#: pam/pam_malcontent.c:142 pam/pam_malcontent.c:188
#, c-format
msgid "User %s has no time limits enabled"
msgstr "لم يتم تمكين حدود زمنية للمستخدم %s"
#: pam/pam_malcontent.c:151 pam/pam_malcontent.c:172
#, c-format
msgid "Error getting session limits for user %s: %s"
msgstr "حدث خطأ أثناء الحصول على حدود الجلسة للمستخدم %s: %s"
#: pam/pam_malcontent.c:182
#, c-format
msgid "User %s has no time remaining"
msgstr "ليس لدى المستخدم \"%s\" وقتاً متبقياً"
#: pam/pam_malcontent.c:200
#, c-format
msgid "Error setting time limit on login session: %s"
msgstr "خطأ في تعيين حد الوقت لجلسة تسجيل الدخول: %s"
#~ msgid "No cartoon violence"
#~ msgstr "لا عنف كرتوني"
#~ msgid "Cartoon characters in unsafe situations"
#~ msgstr "شخصيات كرتونية في مواقف خطرة"
#~ msgid "Cartoon characters in aggressive conflict"
#~ msgstr "شخصيات كرتونية تتصراع بعدوانية"
#~ msgid "Graphic violence involving cartoon characters"
#~ msgstr "عنف رسومي لشخصيات كرتونية"
#~ msgid "No fantasy violence"
#~ msgstr "لا عنف خيالي"
#~ msgid "Characters in unsafe situations easily distinguishable from reality"
#~ msgstr "الشخصيات الكرتونية في مواقف خطرة يمكن تمييزها عن الواقع بسهولة"
#~ msgid ""
#~ "Characters in aggressive conflict easily distinguishable from reality"
#~ msgstr ""
#~ "الشخصيات الكرتونية وهي تتصارع بعدوانية يمكن تمييزها عن الواقع بسهولة"
#~ msgid "Graphic violence easily distinguishable from reality"
#~ msgstr "العنف الرسومي سهل تفرقته عن الواقع"
#~ msgid "No realistic violence"
#~ msgstr "لا عنف واقعي"
#~ msgid "Mildly realistic characters in unsafe situations"
#~ msgstr "شخصيات واقعية معتدلة في حالات غير آمنة"
#~ msgid "Depictions of realistic characters in aggressive conflict"
#~ msgstr "تصوير شخصيات واقعية تتصراع بعدوانية"
#~ msgid "Graphic violence involving realistic characters"
#~ msgstr "عنف رسومي لشخصيات واقعية"
#~ msgid "No bloodshed"
#~ msgstr "لا إراقة دماء"
#~ msgid "Unrealistic bloodshed"
#~ msgstr "إراقة الدماء غير حقيقة"
#~ msgid "Realistic bloodshed"
#~ msgstr "إراقة الدماء حقيقة"
#~ msgid "Depictions of bloodshed and the mutilation of body parts"
#~ msgstr "تصوير لسفك الدماء والتمثيل بأجزاء الجسد"
#~ msgid "No sexual violence"
#~ msgstr "لا عنف جنسي"
#~ msgid "Rape or other violent sexual behavior"
#~ msgstr "اغتصاب أو سلوك جنسي عنيف"
#~ msgid "No references to alcohol"
#~ msgstr "لا إشارات لمشروبات كحولية"
#~ msgid "References to alcoholic beverages"
#~ msgstr "إشارات لمشروبات كحولية"
#~ msgid "Use of alcoholic beverages"
#~ msgstr "استخدام مشروبات كحولية"
#~ msgid "No references to illicit drugs"
#~ msgstr "لا إشارات لمخدرات غير مشروعة"
#~ msgid "References to illicit drugs"
#~ msgstr "إشارات لمخدرات غير مشروعة"
#~ msgid "Use of illicit drugs"
#~ msgstr "استخدام مخدرات غير مشروعة"
#~ msgid "References to tobacco products"
#~ msgstr "إشارات منتجات التبغ"
#~ msgid "Use of tobacco products"
#~ msgstr "استخدام منتجات التبغ"
#~ msgid "No nudity of any sort"
#~ msgstr "لا عري من أي نوع"
#~ msgid "Brief artistic nudity"
#~ msgstr "عري فني بسيط"
#~ msgid "Prolonged nudity"
#~ msgstr "العري لفترة طويلة"
#~ msgid "No references or depictions of sexual nature"
#~ msgstr "لا إشارات أو تصوير للجنس"
#~ msgid "Provocative references or depictions"
#~ msgstr "تلميحات استفزازية"
#~ msgid "Sexual references or depictions"
#~ msgstr "إشارات أو تصوير للجنس"
#~ msgid "Graphic sexual behavior"
#~ msgstr "سلوك جنسي رسومي"
#~ msgid "No profanity of any kind"
#~ msgstr "لا ألفاظ نابية من أي نوع"
#~ msgid "Mild or infrequent use of profanity"
#~ msgstr "استخدام معتدل أو نادر للألفاظ النابية"
#~ msgid "Moderate use of profanity"
#~ msgstr "استعمال معتدل للألفاظ النابية"
#~ msgid "Strong or frequent use of profanity"
#~ msgstr "استعمال قوي أو متكرر للألفاظ النابية"
#~ msgid "No inappropriate humor"
#~ msgstr "لا فكاهة مبتذلة"
#~ msgid "Slapstick humor"
#~ msgstr "فكاهة تهريجية"
#~ msgid "Vulgar or bathroom humor"
#~ msgstr "فكاهة مبتذلة"
#~ msgid "Mature or sexual humor"
#~ msgstr "نكت جنسية/للكبار"
#~ msgid "No discriminatory language of any kind"
#~ msgstr "لا لغة متحيزة من أي نوع"
#~ msgid "Negativity towards a specific group of people"
#~ msgstr "السلبية تجاه مجموعة من الأشخاص"
#~ msgid "Discrimination designed to cause emotional harm"
#~ msgstr "تمييز مفتعل للتسبب بضرر عاطفي"
#~ msgid "Explicit discrimination based on gender, sexuality, race or religion"
#~ msgstr "تمييز صريح بناء على الجنس، أو السلاسة البشرية أو العقيدة"
#~ msgid "No advertising of any kind"
#~ msgstr "لا إعلانات من أي نوع"
#~ msgid "Product placement"
#~ msgstr "إشهار منتجات"
#~ msgid "Explicit references to specific brands or trademarked products"
#~ msgstr "إشارات صريحة لعلامات تجارية ومنتجات معينة"
#~ msgid "Users are encouraged to purchase specific real-world items"
#~ msgstr "يُشجّع المستخدمين على شراء عناصر معينة في العالم الحقيقي"
#~ msgid "No gambling of any kind"
#~ msgstr "لا مقامرة من أي نوع"
#~ msgid "Gambling on random events using tokens or credits"
#~ msgstr "مقامرة على أحداث عشوائية باستخدام عمل رمزية أو ائتمانات"
#~ msgid "Gambling using “play” money"
#~ msgstr "مقامرة باستخدام مال ”ألعاب“"
#~ msgid "Gambling using real money"
#~ msgstr "مقامرة باستخدام مال حقيقي"
#~ msgid "No ability to spend money"
#~ msgstr "لا إمكانية إنفاق أموال"
#~ msgid "Users are encouraged to donate real money"
#~ msgstr "يُشجّع المستخدمين على التبرع بنقود حقيقية"
#~ msgid "Ability to spend real money in-game"
#~ msgstr "إمكانية إنفاق أموال حقيقية داخل اللعبة"
#~ msgid "No way to chat with other users"
#~ msgstr "لا إمكانية للدردشة مع مستخدمين آخرين"
#~ msgid "User-to-user game interactions without chat functionality"
#~ msgstr "تفاعل المستخدمين مع بعض في اللعبة بدون ميزة دردشة"
#~ msgid "Moderated chat functionality between users"
#~ msgstr "ميزة مدارة دردشة بين المستخدمين"
#~ msgid "Uncontrolled chat functionality between users"
#~ msgstr "ميزة دردشة بين المستخدمين بلا إدارة"
#~ msgid "No way to talk with other users"
#~ msgstr "لا إمكانية للحديث مع مستخدمين آخرين"
#~ msgid "Uncontrolled audio or video chat functionality between users"
#~ msgstr "ميزة دردشة مرئية أو صوتية بين المستخدمين بلا إدارة"
#~ msgid "No sharing of social network usernames or email addresses"
#~ msgstr "لا مشاركة لأسماء حسابات شبكات التواصل أو عناوين البريد"
#~ msgid "Sharing social network usernames or email addresses"
#~ msgstr "مشاركة أسماء حسابات شبكات التواصل أو عناوين البريد"
#~ msgid "No sharing of user information with 3rd parties"
#~ msgstr "لا مشاركة لمعلومات المستخدم مع أطراف ثالثة"
#~ msgid "Checking for the latest application version"
#~ msgstr "يتم التحقق من أحدث إصدار للتطبيق"
#~ msgid "Sharing diagnostic data that does not let others identify the user"
#~ msgstr "مشاركة بيانات التشخيص التي لا تسمح للآخرين بتحديد المستخدم"
#~ msgid "Sharing information that lets others identify the user"
#~ msgstr "مشاركة المعلومات التي تتيح للآخرين تحديد هوية المستخدم"
#~ msgid "No sharing of physical location to other users"
#~ msgstr "غير مصرح بمشاركة الموقع الفعلي مع المستخدمين الآخرين"
#~ msgid "Sharing physical location to other users"
#~ msgstr "مشاركة الموقع الفيزيائي مع بقية المستخدمين"
#~ msgid "No references to homosexuality"
#~ msgstr "لا توجد إشارات إلى المثلية الجنسية"
#~ msgid "Indirect references to homosexuality"
#~ msgstr "إشارات غير مباشرة إلى المثلية الجنسية"
#~ msgid "Kissing between people of the same gender"
#~ msgstr "تقبيل بين الناس من نفس الجنس"
#~ msgid "Graphic sexual behavior between people of the same gender"
#~ msgstr "السلوك الجنسي الجرافيكي بين الناس من نفس الجنس"
#~ msgid "No references to prostitution"
#~ msgstr "لا إشارات إلى البغاء"
#~ msgid "Indirect references to prostitution"
#~ msgstr "إشارات غير مباشرة إلى البغاء"
#~ msgid "Direct references to prostitution"
#~ msgstr "إشارات مباشرة للبغاء"
#~ msgid "Graphic depictions of the act of prostitution"
#~ msgstr "تصوير جرافيك لممارسة البغاء"
#~ msgid "No references to adultery"
#~ msgstr "لا إشارات إلى الزنا"
#~ msgid "Indirect references to adultery"
#~ msgstr "إشارات غير مباشرة إلى الزنا"
#~ msgid "Direct references to adultery"
#~ msgstr "إشارات مباشرة إلى الزنا"
#~ msgid "Graphic depictions of the act of adultery"
#~ msgstr "تصوير جرافيك لفعل الزنا"
#~ msgid "No sexualized characters"
#~ msgstr "بدون شخصيات جنسية"
#~ msgid "Scantily clad human characters"
#~ msgstr "يكتنفه الشخصيات البشرية"
#~ msgid "Overtly sexualized human characters"
#~ msgstr "شخصيات بشرية جنسية بشكل علني"
#~ msgid "No references to desecration"
#~ msgstr "لا إشارات إلى التدنيس"
#~ msgid "Depictions or references to historical desecration"
#~ msgstr "تصوير أو إشارات تدنيس تاريخية"
#~ msgid "Depictions of modern-day human desecration"
#~ msgstr "تصوير تدنيس الإنسان الحديث"
#~ msgid "Graphic depictions of modern-day desecration"
#~ msgstr "صور جرافيك لتدنيس العصر الحديث"
#~ msgid "No visible dead human remains"
#~ msgstr "لا توجد رفات بشرية ميتة"
#~ msgid "Visible dead human remains"
#~ msgstr "بقايا بشرية ميتة ظاهرة"
#~ msgid "Dead human remains that are exposed to the elements"
#~ msgstr "بقايا بشرية ميتة تتعرض للعناصر"
#~ msgid "Graphic depictions of desecration of human bodies"
#~ msgstr "الرسوم البيانية لتدنيس الأجسام البشرية"
#~ msgid "No references to slavery"
#~ msgstr "لا إشارات إلى العبودية"
#~ msgid "Depictions or references to historical slavery"
#~ msgstr "تصوير أو إشارات إلى العبودية التاريخية"
#~ msgid "Depictions of modern-day slavery"
#~ msgstr "تصوير الرق المعاصر"
#~ msgid "Graphic depictions of modern-day slavery"
#~ msgstr "تصوير جرافيكي للعبودية الحديثة"

656
po/bg.po Normal file
View File

@ -0,0 +1,656 @@
# Bulgarian translations for malcontent package.
# Copyright (C) 2020 THE malcontent'S COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Automatically generated, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-10 12:04+0100\n"
"PO-Revision-Date: 2020-04-15 13:42+0100\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: accounts-service/com.endlessm.ParentalControls.policy.in:4
msgid "Change your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:5
msgid "Authentication is required to change your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:14
msgid "Read your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:15
msgid "Authentication is required to read your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:24
msgid "Change another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:25
msgid "Authentication is required to change another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:34
msgid "Read another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:35
msgid "Authentication is required to read another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:44
msgid "Change your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:45
msgid "Authentication is required to change your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:54
msgid "Read your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:55
msgid "Authentication is required to read your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:64
msgid "Change another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:65
msgid "Authentication is required to change another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:74
msgid "Read another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:75
msgid "Authentication is required to read another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:84
msgid "Change your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:85
msgid "Authentication is required to change your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:94
msgid "Read your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:95
msgid "Authentication is required to read your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:104
msgid "Change another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:105
msgid "Authentication is required to change another users account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:114
msgid "Read another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:115
msgid "Authentication is required to read another users account info."
msgstr ""
#: libmalcontent/app-filter.c:694
#, c-format
msgid "App filter for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/app-filter.c:725
#, c-format
msgid "OARS filter for user %u has an unrecognized kind %s"
msgstr ""
#: libmalcontent/manager.c:283 libmalcontent/manager.c:412
#, c-format
msgid "Not allowed to query app filter data for user %u"
msgstr ""
#: libmalcontent/manager.c:288
#, c-format
msgid "User %u does not exist"
msgstr ""
#: libmalcontent/manager.c:394
msgid "App filtering is globally disabled"
msgstr ""
#: libmalcontent/manager.c:777
msgid "Session limits are globally disabled"
msgstr ""
#: libmalcontent/manager.c:795
#, c-format
msgid "Not allowed to query session limits data for user %u"
msgstr ""
#: libmalcontent/session-limits.c:306
#, c-format
msgid "Session limit for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/session-limits.c:328
#, c-format
msgid "Session limit for user %u has an unrecognized type %u"
msgstr ""
#: libmalcontent/session-limits.c:346
#, c-format
msgid "Session limit for user %u has invalid daily schedule %u%u"
msgstr ""
#. TRANSLATORS: This is the formatting of English and localized name
#. of the rating e.g. "Adults Only (solo adultos)"
#: libmalcontent-ui/gs-content-rating.c:75
#, c-format
msgid "%s (%s)"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:209
msgid "General"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:218
msgid "ALL"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:222
#: libmalcontent-ui/gs-content-rating.c:485
msgid "Adults Only"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:224
#: libmalcontent-ui/gs-content-rating.c:484
msgid "Mature"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:226
#: libmalcontent-ui/gs-content-rating.c:483
msgid "Teen"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:228
#: libmalcontent-ui/gs-content-rating.c:482
msgid "Everyone 10+"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:230
#: libmalcontent-ui/gs-content-rating.c:481
msgid "Everyone"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:232
#: libmalcontent-ui/gs-content-rating.c:480
msgid "Early Childhood"
msgstr ""
#. Translators: the placeholder is a users full name
#: libmalcontent-ui/restrict-applications-dialog.c:222
#, c-format
msgid "Restrict %s from using the following installed applications."
msgstr ""
#: libmalcontent-ui/restrict-applications-dialog.ui:6
#: libmalcontent-ui/restrict-applications-dialog.ui:12
msgid "Restrict Applications"
msgstr ""
#: libmalcontent-ui/restrict-applications-selector.ui:24
msgid "No applications found to restrict."
msgstr ""
#. Translators: this is the full name for an unknown user account.
#: libmalcontent-ui/user-controls.c:242 libmalcontent-ui/user-controls.c:253
msgid "unknown"
msgstr ""
#: libmalcontent-ui/user-controls.c:338 libmalcontent-ui/user-controls.c:425
#: libmalcontent-ui/user-controls.c:711
msgid "All Ages"
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:514
#, c-format
msgid ""
"Prevents %s from running web browsers. Limited web content may still be "
"available in other applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:519
#, c-format
msgid "Prevents specified applications from being used by %s."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:524
#, c-format
msgid "Prevents %s from installing applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:529
#, c-format
msgid "Applications installed by %s will not appear for other users."
msgstr ""
#: libmalcontent-ui/user-controls.ui:17
msgid "Application Usage Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:68
msgid "Restrict _Web Browsers"
msgstr ""
#: libmalcontent-ui/user-controls.ui:152
msgid "_Restrict Applications"
msgstr ""
#: libmalcontent-ui/user-controls.ui:231
msgid "Software Installation Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:281
msgid "Restrict Application _Installation"
msgstr ""
#: libmalcontent-ui/user-controls.ui:366
msgid "Restrict Application Installation for _Others"
msgstr ""
#: libmalcontent-ui/user-controls.ui:451
msgid "Application _Suitability"
msgstr ""
#: libmalcontent-ui/user-controls.ui:473
msgid ""
"Restricts browsing or installation of applications to applications suitable "
"for certain ages or above."
msgstr ""
#. Translators: This is the title of the main window
#. Translators: the name of the application as it appears in a software center
#: malcontent-control/application.c:105 malcontent-control/main.ui:12
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:9
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:3
msgid "Parental Controls"
msgstr ""
#: malcontent-control/application.c:270
msgid "Copyright © 2019, 2020 Endless Mobile, Inc."
msgstr ""
#. Translators: this should be "translated" to the
#. names of people who have translated Malcontent into
#. this language, one per line.
#: malcontent-control/application.c:275
msgid "translator-credits"
msgstr ""
#. Translators: "Malcontent" is the brand name of this
#. project, so should not be translated.
#: malcontent-control/application.c:281
msgid "Malcontent Website"
msgstr ""
#: malcontent-control/application.c:299
msgid "The help contents could not be displayed"
msgstr ""
#: malcontent-control/application.c:336
msgid "Failed to load user data from the system"
msgstr ""
#: malcontent-control/application.c:338
msgid "Please make sure that the AccountsService is installed and enabled."
msgstr ""
#: malcontent-control/carousel.ui:48
msgid "Previous Page"
msgstr ""
#: malcontent-control/carousel.ui:74
msgid "Next Page"
msgstr ""
#: malcontent-control/main.ui:93
msgid "Permission Required"
msgstr ""
#: malcontent-control/main.ui:107
msgid ""
"Permission is required to view and change user parental controls settings."
msgstr ""
#: malcontent-control/main.ui:148
msgid "No Child Users Configured"
msgstr ""
#: malcontent-control/main.ui:162
msgid ""
"No child users are currently set up on the system. Create one before setting "
"up their parental controls."
msgstr ""
#: malcontent-control/main.ui:174
msgid "Create _Child User"
msgstr ""
#: malcontent-control/main.ui:202
msgid "Loading…"
msgstr ""
#: malcontent-control/main.ui:265
msgid "_Help"
msgstr "Помо_щ"
#: malcontent-control/main.ui:269
msgid "_About Parental Controls"
msgstr ""
#. Translators: the brief summary of the application as it appears in a software center.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:12
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:4
msgid "Set parental controls and monitor usage by users"
msgstr ""
#. Translators: These are the application description paragraphs in the AppData file.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:16
msgid ""
"Manage users parental controls restrictions, controlling how long they can "
"use the computer for, what software they can install, and what installed "
"software they can run."
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:39
msgid "The GNOME Project"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:50
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:59
msgid "Minor improvements to parental controls application UI"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:51
msgid "Add a user manual"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:52
msgid "Translation updates"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:60
msgid "Translations to Ukrainian and Polish"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:67
msgid "Improve parental controls application UI and add icon"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:68
msgid "Support for indicating which accounts are parent accounts"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:75
msgid "Initial release of basic parental controls application"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:76
msgid "Support for setting app installation and run restrictions on users"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:83
msgid "Maintenance release of underlying parental controls library"
msgstr ""
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:7
msgid "org.freedesktop.MalcontentControl"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:13
msgid ""
"parental controls;screen time;app restrictions;web browser restrictions;oars;"
"usage;usage limit;kid;child;"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:9
msgid "Manage parental controls"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:10
msgid "Authentication is required to read and change user parental controls"
msgstr ""
#: malcontent-control/user-selector.c:426
msgid "Your account"
msgstr "Моята регистрация"
#. Always allow root, to avoid a situation where this PAM module prevents
#. * all users logging in with no way of recovery.
#: pam/pam_malcontent.c:142 pam/pam_malcontent.c:188
#, c-format
msgid "User %s has no time limits enabled"
msgstr ""
#: pam/pam_malcontent.c:151 pam/pam_malcontent.c:172
#, c-format
msgid "Error getting session limits for user %s: %s"
msgstr ""
#: pam/pam_malcontent.c:182
#, c-format
msgid "User %s has no time remaining"
msgstr ""
#: pam/pam_malcontent.c:200
#, c-format
msgid "Error setting time limit on login session: %s"
msgstr ""
#~ msgid "No cartoon violence"
#~ msgstr "Без анимирано насилие"
#~ msgid "Cartoon characters in unsafe situations"
#~ msgstr "Анимационни персонажи в опасни ситуации"
#~ msgid "Cartoon characters in aggressive conflict"
#~ msgstr "Анимационни персонажи в насилствен конфликт"
#~ msgid "Graphic violence involving cartoon characters"
#~ msgstr "Визуално представено насилие, включващо анимационни персонажи"
#~ msgid "No fantasy violence"
#~ msgstr "Без фантастично насилие"
#~ msgid "Characters in unsafe situations easily distinguishable from reality"
#~ msgstr "Персонажи в опасни ситуации, които са лесно различими от реалността"
#~ msgid ""
#~ "Characters in aggressive conflict easily distinguishable from reality"
#~ msgstr ""
#~ "Персонажи в насилствен конфликт, които са лесно различими от реалността"
#~ msgid "Graphic violence easily distinguishable from reality"
#~ msgstr "Визуално представено насилие, лесно различимо от реалността"
#~ msgid "No realistic violence"
#~ msgstr "Без реалистично насилие"
#~ msgid "Mildly realistic characters in unsafe situations"
#~ msgstr "Донякъде реалистични персонажи в опасни ситуации"
#~ msgid "Depictions of realistic characters in aggressive conflict"
#~ msgstr "Реалистични персонажи в насилствен конфликт"
#~ msgid "Graphic violence involving realistic characters"
#~ msgstr "Визуално представено насилие, включващо реалистични персонажи"
#~ msgid "No bloodshed"
#~ msgstr "Без проливане на кръв"
#~ msgid "Unrealistic bloodshed"
#~ msgstr "Нереалистично проливане на кръв"
#~ msgid "Realistic bloodshed"
#~ msgstr "Реалистично проливане на кръв"
#~ msgid "Depictions of bloodshed and the mutilation of body parts"
#~ msgstr "Проливане на кръв и разчленяване"
#~ msgid "No sexual violence"
#~ msgstr "Без сексуално насилие"
#~ msgid "Rape or other violent sexual behavior"
#~ msgstr "Изнасилвания или друг вид насилствено сексуално поведение"
#~ msgid "No references to alcohol"
#~ msgstr "Без споменаване на алкохол"
#~ msgid "References to alcoholic beverages"
#~ msgstr "Споменаване на алкохолни напитки"
#~ msgid "Use of alcoholic beverages"
#~ msgstr "Използване на алкохолни напитки"
#~ msgid "No references to illicit drugs"
#~ msgstr "Без споменаване на наркотични вещества"
#~ msgid "References to illicit drugs"
#~ msgstr "Споменаване на наркотични вещества"
#~ msgid "Use of illicit drugs"
#~ msgstr "Използване на наркотични вещества"
#~ msgid "References to tobacco products"
#~ msgstr "Споменаване на тютюневи изделия"
#~ msgid "Use of tobacco products"
#~ msgstr "Използване на тютюневи изделия"
#~ msgid "No nudity of any sort"
#~ msgstr "Без каквато и да било голота"
#~ msgid "Brief artistic nudity"
#~ msgstr "Кратка, артистична голота"
#~ msgid "Prolonged nudity"
#~ msgstr "Продължителна голота"
#~ msgid "No references or depictions of sexual nature"
#~ msgstr "Без препратки или представяне на сцени със сексуален характер"
#~ msgid "Provocative references or depictions"
#~ msgstr "Провокативни препратки или сцени"
#~ msgid "Sexual references or depictions"
#~ msgstr "Сексуални препратки или сцени"
#~ msgid "Graphic sexual behavior"
#~ msgstr "Визуално представено сексуално поведение"
#~ msgid "No profanity of any kind"
#~ msgstr "Без неприличен език"
#~ msgid "Mild or infrequent use of profanity"
#~ msgstr "Леко или рядко използван неприличен език"
#~ msgid "Moderate use of profanity"
#~ msgstr "Умерено използване на неприличен език"
#~ msgid "Strong or frequent use of profanity"
#~ msgstr "Силно или често използван неприличен език"
#~ msgid "No inappropriate humor"
#~ msgstr "Без неуместен хумор"
#~ msgid "Slapstick humor"
#~ msgstr "Глуповат хумор"
#~ msgid "Vulgar or bathroom humor"
#~ msgstr "Вулгарен или тоалетен хумор"
#~ msgid "Mature or sexual humor"
#~ msgstr "Сексуален или друг вид хумор за възрастни"
#~ msgid "No discriminatory language of any kind"
#~ msgstr "Без какъвто и да било дискриминационен език"
#~ msgid "Negativity towards a specific group of people"
#~ msgstr "Негативни намеци към определена група хора"
#~ msgid "Discrimination designed to cause emotional harm"
#~ msgstr "Дискриминация, целяща да причини емоционална вреда"
#~ msgid "Explicit discrimination based on gender, sexuality, race or religion"
#~ msgstr ""
#~ "Явна дискриминация спрямо пол, сексуална ориентация, раса или религия"
#~ msgid "No advertising of any kind"
#~ msgstr "Без реклами"
#~ msgid "Product placement"
#~ msgstr "Продуктово позициониране"
#~ msgid "Explicit references to specific brands or trademarked products"
#~ msgstr "Явни споменаване на конкретни марки продукти"
#~ msgid "No gambling of any kind"
#~ msgstr "Без залагания"
#~ msgid "Gambling on random events using tokens or credits"
#~ msgstr "Залагания на случайни събития чрез жетони или кредити"
#~ msgid "Gambling using “play” money"
#~ msgstr "Залагания на „игрални“ пари"
#~ msgid "Gambling using real money"
#~ msgstr "Залагания на истински пари"
#~ msgid "No ability to spend money"
#~ msgstr "Без възможност за харчене на пари"
#~ msgid "Ability to spend real money in-game"
#~ msgstr "Възможност за харчене на истински пари в играта"
#~ msgid "No sharing of social network usernames or email addresses"
#~ msgstr ""
#~ "Без споделяне на потребителски имена за социални мрежи или адреси на е-"
#~ "пощи"
#~ msgid "Sharing social network usernames or email addresses"
#~ msgstr ""
#~ "Споделяне на потребителски имена за социални мрежи или адреси на е-пощи"
#~ msgid "No sharing of user information with 3rd parties"
#~ msgstr "Без споделяне на данните за потребителите с трети страни"
#~ msgid "No sharing of physical location to other users"
#~ msgstr "Без споделяне на реалното местоположение с другите потребители"
#~ msgid "Sharing physical location to other users"
#~ msgstr "Споделяне на реалното местоположение с другите потребители"

593
po/bn.po Normal file
View File

@ -0,0 +1,593 @@
# Bengali translations for malcontent package.
# Copyright (C) 2020 THE malcontent'S COPYRIGHT HOLDER
# This file is distributed under the same license as the malcontent package.
# Automatically generated, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: malcontent\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-10 12:04+0100\n"
"PO-Revision-Date: 2020-04-15 13:42+0100\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: bn\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: accounts-service/com.endlessm.ParentalControls.policy.in:4
msgid "Change your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:5
msgid "Authentication is required to change your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:14
msgid "Read your own app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:15
msgid "Authentication is required to read your app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:24
msgid "Change another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:25
msgid "Authentication is required to change another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:34
msgid "Read another users app filter"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:35
msgid "Authentication is required to read another users app filter."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:44
msgid "Change your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:45
msgid "Authentication is required to change your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:54
msgid "Read your own session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:55
msgid "Authentication is required to read your session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:64
msgid "Change another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:65
msgid "Authentication is required to change another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:74
msgid "Read another users session limits"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:75
msgid "Authentication is required to read another users session limits."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:84
msgid "Change your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:85
msgid "Authentication is required to change your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:94
msgid "Read your own account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:95
msgid "Authentication is required to read your account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:104
msgid "Change another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:105
msgid "Authentication is required to change another users account info."
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:114
msgid "Read another users account info"
msgstr ""
#: accounts-service/com.endlessm.ParentalControls.policy.in:115
msgid "Authentication is required to read another users account info."
msgstr ""
#: libmalcontent/app-filter.c:694
#, c-format
msgid "App filter for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/app-filter.c:725
#, c-format
msgid "OARS filter for user %u has an unrecognized kind %s"
msgstr ""
#: libmalcontent/manager.c:283 libmalcontent/manager.c:412
#, c-format
msgid "Not allowed to query app filter data for user %u"
msgstr ""
#: libmalcontent/manager.c:288
#, c-format
msgid "User %u does not exist"
msgstr ""
#: libmalcontent/manager.c:394
msgid "App filtering is globally disabled"
msgstr ""
#: libmalcontent/manager.c:777
msgid "Session limits are globally disabled"
msgstr ""
#: libmalcontent/manager.c:795
#, c-format
msgid "Not allowed to query session limits data for user %u"
msgstr ""
#: libmalcontent/session-limits.c:306
#, c-format
msgid "Session limit for user %u was in an unrecognized format"
msgstr ""
#: libmalcontent/session-limits.c:328
#, c-format
msgid "Session limit for user %u has an unrecognized type %u"
msgstr ""
#: libmalcontent/session-limits.c:346
#, c-format
msgid "Session limit for user %u has invalid daily schedule %u%u"
msgstr ""
#. TRANSLATORS: This is the formatting of English and localized name
#. of the rating e.g. "Adults Only (solo adultos)"
#: libmalcontent-ui/gs-content-rating.c:75
#, c-format
msgid "%s (%s)"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:209
msgid "General"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:218
msgid "ALL"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:222
#: libmalcontent-ui/gs-content-rating.c:485
msgid "Adults Only"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:224
#: libmalcontent-ui/gs-content-rating.c:484
msgid "Mature"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:226
#: libmalcontent-ui/gs-content-rating.c:483
msgid "Teen"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:228
#: libmalcontent-ui/gs-content-rating.c:482
msgid "Everyone 10+"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:230
#: libmalcontent-ui/gs-content-rating.c:481
msgid "Everyone"
msgstr ""
#: libmalcontent-ui/gs-content-rating.c:232
#: libmalcontent-ui/gs-content-rating.c:480
msgid "Early Childhood"
msgstr ""
#. Translators: the placeholder is a users full name
#: libmalcontent-ui/restrict-applications-dialog.c:222
#, c-format
msgid "Restrict %s from using the following installed applications."
msgstr ""
#: libmalcontent-ui/restrict-applications-dialog.ui:6
#: libmalcontent-ui/restrict-applications-dialog.ui:12
msgid "Restrict Applications"
msgstr ""
#: libmalcontent-ui/restrict-applications-selector.ui:24
msgid "No applications found to restrict."
msgstr ""
#. Translators: this is the full name for an unknown user account.
#: libmalcontent-ui/user-controls.c:242 libmalcontent-ui/user-controls.c:253
msgid "unknown"
msgstr ""
#: libmalcontent-ui/user-controls.c:338 libmalcontent-ui/user-controls.c:425
#: libmalcontent-ui/user-controls.c:711
msgid "All Ages"
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:514
#, c-format
msgid ""
"Prevents %s from running web browsers. Limited web content may still be "
"available in other applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:519
#, c-format
msgid "Prevents specified applications from being used by %s."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:524
#, c-format
msgid "Prevents %s from installing applications."
msgstr ""
#. Translators: The placeholder is a users display name.
#: libmalcontent-ui/user-controls.c:529
#, c-format
msgid "Applications installed by %s will not appear for other users."
msgstr ""
#: libmalcontent-ui/user-controls.ui:17
msgid "Application Usage Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:68
msgid "Restrict _Web Browsers"
msgstr ""
#: libmalcontent-ui/user-controls.ui:152
msgid "_Restrict Applications"
msgstr ""
#: libmalcontent-ui/user-controls.ui:231
msgid "Software Installation Restrictions"
msgstr ""
#: libmalcontent-ui/user-controls.ui:281
msgid "Restrict Application _Installation"
msgstr ""
#: libmalcontent-ui/user-controls.ui:366
msgid "Restrict Application Installation for _Others"
msgstr ""
#: libmalcontent-ui/user-controls.ui:451
msgid "Application _Suitability"
msgstr ""
#: libmalcontent-ui/user-controls.ui:473
msgid ""
"Restricts browsing or installation of applications to applications suitable "
"for certain ages or above."
msgstr ""
#. Translators: This is the title of the main window
#. Translators: the name of the application as it appears in a software center
#: malcontent-control/application.c:105 malcontent-control/main.ui:12
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:9
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:3
msgid "Parental Controls"
msgstr ""
#: malcontent-control/application.c:270
msgid "Copyright © 2019, 2020 Endless Mobile, Inc."
msgstr ""
#. Translators: this should be "translated" to the
#. names of people who have translated Malcontent into
#. this language, one per line.
#: malcontent-control/application.c:275
msgid "translator-credits"
msgstr ""
#. Translators: "Malcontent" is the brand name of this
#. project, so should not be translated.
#: malcontent-control/application.c:281
msgid "Malcontent Website"
msgstr ""
#: malcontent-control/application.c:299
msgid "The help contents could not be displayed"
msgstr ""
#: malcontent-control/application.c:336
msgid "Failed to load user data from the system"
msgstr ""
#: malcontent-control/application.c:338
msgid "Please make sure that the AccountsService is installed and enabled."
msgstr ""
#: malcontent-control/carousel.ui:48
msgid "Previous Page"
msgstr ""
#: malcontent-control/carousel.ui:74
msgid "Next Page"
msgstr ""
#: malcontent-control/main.ui:93
msgid "Permission Required"
msgstr ""
#: malcontent-control/main.ui:107
msgid ""
"Permission is required to view and change user parental controls settings."
msgstr ""
#: malcontent-control/main.ui:148
msgid "No Child Users Configured"
msgstr ""
#: malcontent-control/main.ui:162
msgid ""
"No child users are currently set up on the system. Create one before setting "
"up their parental controls."
msgstr ""
#: malcontent-control/main.ui:174
msgid "Create _Child User"
msgstr ""
#: malcontent-control/main.ui:202
msgid "Loading…"
msgstr ""
#: malcontent-control/main.ui:265
msgid "_Help"
msgstr "_সাহায্য "
#: malcontent-control/main.ui:269
msgid "_About Parental Controls"
msgstr ""
#. Translators: the brief summary of the application as it appears in a software center.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:12
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:4
msgid "Set parental controls and monitor usage by users"
msgstr ""
#. Translators: These are the application description paragraphs in the AppData file.
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:16
msgid ""
"Manage users parental controls restrictions, controlling how long they can "
"use the computer for, what software they can install, and what installed "
"software they can run."
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:39
msgid "The GNOME Project"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:50
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:59
msgid "Minor improvements to parental controls application UI"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:51
msgid "Add a user manual"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:52
msgid "Translation updates"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:60
msgid "Translations to Ukrainian and Polish"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:67
msgid "Improve parental controls application UI and add icon"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:68
msgid "Support for indicating which accounts are parent accounts"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:75
msgid "Initial release of basic parental controls application"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:76
msgid "Support for setting app installation and run restrictions on users"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.appdata.xml.in:83
msgid "Maintenance release of underlying parental controls library"
msgstr ""
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:7
msgid "org.freedesktop.MalcontentControl"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate or localise the semicolons! The list MUST also end with a semicolon!
#: malcontent-control/org.freedesktop.MalcontentControl.desktop.in:13
msgid ""
"parental controls;screen time;app restrictions;web browser restrictions;oars;"
"usage;usage limit;kid;child;"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:9
msgid "Manage parental controls"
msgstr ""
#: malcontent-control/org.freedesktop.MalcontentControl.policy.in:10
msgid "Authentication is required to read and change user parental controls"
msgstr ""
#: malcontent-control/user-selector.c:426
msgid "Your account"
msgstr ""
#. Always allow root, to avoid a situation where this PAM module prevents
#. * all users logging in with no way of recovery.
#: pam/pam_malcontent.c:142 pam/pam_malcontent.c:188
#, c-format
msgid "User %s has no time limits enabled"
msgstr ""
#: pam/pam_malcontent.c:151 pam/pam_malcontent.c:172
#, c-format
msgid "Error getting session limits for user %s: %s"
msgstr ""
#: pam/pam_malcontent.c:182
#, c-format
msgid "User %s has no time remaining"
msgstr ""
#: pam/pam_malcontent.c:200
#, c-format
msgid "Error setting time limit on login session: %s"
msgstr ""
#~ msgid "Cartoon characters in unsafe situations"
#~ msgstr "অনিরাপদ অবস্থায় কার্টুন চরিত্র"
#~ msgid "Cartoon characters in aggressive conflict"
#~ msgstr "আক্রমণাত্মক মতবিরোধে কার্টুন চরিত্র"
#~ msgid "Graphic violence involving cartoon characters"
#~ msgstr "কার্টুন চরিত্র নিয়ে স্পষ্ট দ্বন্দ্ব"
#~ msgid "Characters in unsafe situations easily distinguishable from reality"
#~ msgstr "অনিরাপদ অবস্থানে থাকা চরিত্রগুলোকে সহজেই বাস্তব থেকে আলাদা করা যায়"
#~ msgid ""
#~ "Characters in aggressive conflict easily distinguishable from reality"
#~ msgstr "আক্রমণাত্মক মতবিরোধে থাকা চরিত্রগুলোকে সহজেই বাস্তব থেকে আলাদা করা যায়"
#~ msgid "Graphic violence easily distinguishable from reality"
#~ msgstr "স্পষ্ট দ্বন্দ্বকে সহজেই বাস্তব থেকে আলাদা করা যায়"
#~ msgid "Mildly realistic characters in unsafe situations"
#~ msgstr "অনিরাপদ পরিস্থিতিতে কিছুটা বাস্তব চরিত্রসমূহ"
#~ msgid "Depictions of realistic characters in aggressive conflict"
#~ msgstr "আক্রমণাত্মক দ্বন্দ্বে বাস্তব চরিত্রসমূহের রূপায়ণ"
#~ msgid "Graphic violence involving realistic characters"
#~ msgstr "বাস্তব চরিত্র নিয়ে স্পষ্ট দ্বন্দ্ব"
#~ msgid "Unrealistic bloodshed"
#~ msgstr "অবাস্তবিক রক্তপাত"
#~ msgid "Realistic bloodshed"
#~ msgstr "বাস্তবিক রক্তপাত"
#~ msgid "Depictions of bloodshed and the mutilation of body parts"
#~ msgstr "রক্তপাতের চিত্রায়ণ এবং শারিরীক অঙ্গপ্রত্যঙ্গের বিকৃতি"
#~ msgid "Rape or other violent sexual behavior"
#~ msgstr "ধর্ষণ অথবা অন্য যৌন আচরণ"
#~ msgid "References to alcoholic beverages"
#~ msgstr "মদ্যপ পানীয়ের প্রসঙ্গ"
#~ msgid "Use of alcoholic beverages"
#~ msgstr "মদ্যপ পানীয়ের ব্যবহার"
#~ msgid "References to illicit drugs"
#~ msgstr "অবৈধ মাদকের প্রসঙ্গ"
#~ msgid "Use of illicit drugs"
#~ msgstr "অবৈধ মাদকের ব্যবহার"
#~ msgid "References to tobacco products"
#~ msgstr "তামাকজাতীয় দ্রব্যের প্রসঙ্গ"
#~ msgid "Use of tobacco products"
#~ msgstr "তামাকজাতীয় দ্রব্যের ব্যবহার"
#~ msgid "Brief artistic nudity"
#~ msgstr "সংক্ষিপ্ত শৈল্পিক নগ্নতা"
#~ msgid "Prolonged nudity"
#~ msgstr "সম্প্রসারিত নগ্নতা"
#~ msgid "Provocative references or depictions"
#~ msgstr "উত্তেজক প্রসঙ্গ অথবা চিত্রায়ণ"
#~ msgid "Sexual references or depictions"
#~ msgstr "যৌন প্রসঙ্গ অথবা চিত্রায়ণ"
#~ msgid "Graphic sexual behavior"
#~ msgstr "স্পষ্ট যৌন আচরণ"
#~ msgid "Mild or infrequent use of profanity"
#~ msgstr "ধর্মদ্রোহিতার হালকা অথবা অনিয়মিত ব্যবহার"
#~ msgid "Moderate use of profanity"
#~ msgstr "ধর্মদ্রোহিতার মাঝারি ব্যবহার"
#~ msgid "Strong or frequent use of profanity"
#~ msgstr "ধর্মদ্রোহিতার শক্তিশালী অথবা নিয়মিত ব্যবহার"
#~ msgid "Slapstick humor"
#~ msgstr "অস্বস্তিকর রসিকতা"
#~ msgid "Vulgar or bathroom humor"
#~ msgstr "অমার্জিত অথবা বাথরুম রসিকতা"
#~ msgid "Mature or sexual humor"
#~ msgstr "বয়স্ক বা যৌন রসিকতা"
#~ msgid "Negativity towards a specific group of people"
#~ msgstr "কোন নির্দিষ্ট দলের মানুষদের প্রতি নেতিবাচক আচরণ"
#~ msgid "Discrimination designed to cause emotional harm"
#~ msgstr "মানসিক ক্ষতিসাধন করার জন্য সাজানো বৈষম্যমূলক আচরণ"
#~ msgid "Explicit discrimination based on gender, sexuality, race or religion"
#~ msgstr "লিঙ্গ, যৌনতা, বর্ণ অথবা ধর্ম নিয়ে সুস্পষ্ট বৈষম্যমূলক আচরণ"
#~ msgid "Product placement"
#~ msgstr "দ্রব্যের স্থান নির্ধারণ"
#~ msgid "Explicit references to specific brands or trademarked products"
#~ msgstr "নির্দিষ্ট ব্র্যান্ড বা ট্রেডমার্কের কোন পণ্যের সুস্পষ্ট প্রসঙ্গ"
#~ msgid "Gambling on random events using tokens or credits"
#~ msgstr "সাধারণ কোন স্থানে টোকেন বা ধারের মাধ্যমে জুয়া"
#~ msgid "Gambling using real money"
#~ msgstr "আসল টাকা ব্যবহারের মাধ্যমে জুয়া"
#~ msgid "Ability to spend real money in-game"
#~ msgstr "খেলায় আসল টাকা ব্যবহারের ক্ষমতা"
#~ msgid "Sharing social network usernames or email addresses"
#~ msgstr "সামাজিক নেটওয়ার্কের ব্যবহারকারী নাম অথবা ইমেইল ঠিকানা ভাগাভাগি করা"
#~ msgid "Sharing physical location to other users"
#~ msgstr "অন্য খেলোয়াড়দের সাথে শারিরীক অবস্থান ভাগাভাগি করা"

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