diff options
author | Matej Urbančič <mateju@svn.gnome.org> | 2018-05-15 21:03:11 +0200 |
---|---|---|
committer | Matej Urbančič <mateju@svn.gnome.org> | 2018-05-15 21:03:11 +0200 |
commit | 2acb520fc9b19118107916b4c89a041d1651df4d (patch) | |
tree | de915d27698f0f0ee89862dfce8c103c157df952 | |
parent | 2da5fd3b3dfb4a0f2885349dad2a8e2cc063119c (diff) | |
parent | f4433b3766bab48b85ae0e42e3e704bb7f380663 (diff) | |
download | gnome-control-center-2acb520fc9b19118107916b4c89a041d1651df4d.tar.gz |
Merge branch 'master' of gitlab.gnome.org:GNOME/gnome-control-center
179 files changed, 18883 insertions, 4715 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0c7ddc104 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +_build/ +**/*~
\ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 711923889..6d17c8dab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,24 +1,7 @@ -image: fedora:rawhide +image: claudioandre/settings:fedora.dev stages: - build - test - - deploy - -variables: - DEPENDENCIES: accountsservice-devel cheese-libs-devel chrpath clutter-gtk-devel colord-devel - colord-gtk-devel cups-devel desktop-file-utils docbook-style-xsl gdk-pixbuf2-devel - gettext git glib2-devel gnome-bluetooth-libs-devel gnome-desktop3-devel - gnome-online-accounts-devel gnome-settings-daemon-devel grilo-devel - gsettings-desktop-schemas-devel gtk3-devel ibus-devel intltool libcanberra-devel - libgtop2-devel libgudev-devel libnma-devel libpwquality-devel libsmbclient-devel - libsoup-devel libwacom-devel libX11-devel libXi-devel libxml2-devel libxslt - libXxf86misc-devel meson ModemManager-glib-devel NetworkManager-libnm-devel - polkit-devel pulseaudio-libs-devel upower-devel - - -before_script: - - dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES - ## # Stage: Build @@ -29,11 +12,25 @@ before_script: ## build: stage: build + artifacts: + name: builded + untracked: true + expire_in: 3h30min + script: + - echo "== Info ==" + - tests/ci-helper.sh "INFO" + - tests/ci-helper.sh "GIT_INFO" + + - echo "== Building ==" - meson . _build - - ninja -C _build + - ninja -C _build 2>&1 | tee compilation.log + + - echo "== Installing ==" - ninja -C _build install + - echo "== Report ==" + - tests/ci-helper.sh "WARNINGS" ## # Stage: Test @@ -42,24 +39,26 @@ build: ## test: stage: test - script: - - meson . _build - - ninja -C _build - - ninja -C _build install - - meson test -C _build --verbose --no-stdsplit + artifacts: + name: log + when: always + paths: + - $(pwd)/*.log + dependencies: + - build -## -# Stage: Deploy -# -# Checks if the released version is in a good shape. -## -deploy: - stage: deploy script: - - meson . _build - - ninja -C _build - - meson test -C _build - - ninja dist -C _build - only: - - tags
\ No newline at end of file + - echo "== Info ==" + - tests/ci-helper.sh "INFO" + - tests/ci-helper.sh "GIT_INFO" + + - | + if [[ -n "${CI_COMMIT_TAG}" ]]; then + echo "== Distro Test ==" + meson test -C _build + ninja dist -C _build + else + echo "== Testing ==" + meson test -C _build --verbose --no-stdsplit + fi diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md new file mode 100644 index 000000000..416478e1d --- /dev/null +++ b/.gitlab/issue_templates/Bug.md @@ -0,0 +1,8 @@ +Detailed description of the issue. Put as much information as you can, potentially +with images showing the issue. + +Steps to reproduce: + +1. Open GNOME Settings +2. Change X to something else +3. ... diff --git a/.gitlab/issue_templates/Epic.md b/.gitlab/issue_templates/Epic.md new file mode 100644 index 000000000..aa7c6a3b5 --- /dev/null +++ b/.gitlab/issue_templates/Epic.md @@ -0,0 +1,41 @@ +# Current problems +<!-- +What are the problems that the current project has? + +For example: +* User cannot use the keyboard to perform most common actions +or +* User cannot see documents from cloud services +--> + +# Goals & use cases +<!-- +What are the use cases that this proposal will cover? What are the end goals? + +For example: +* User needs to share a file with their friends. +or +* It should be easy to edit a picture within the app. +--> + +# Requirements +<!-- +What does the solution needs to ensure for being succesful? + +For example: +* Work on small form factors and touch +or +* Use the Meson build system and integrate with it +--> + +# Relevant art +<!-- +Is there any product that has implemented something similar? Put links to other +projects, pictures, links to other code, etc. +--> + +# Proposal & plan +<!-- What's the solution and how should be achieved? It can be split in smaller +tasks of minimum change, so they can be delivered across several releases. --> + +/label ~"1. Epic" diff --git a/.gitlab/issue_templates/Feature.md b/.gitlab/issue_templates/Feature.md new file mode 100644 index 000000000..d76486658 --- /dev/null +++ b/.gitlab/issue_templates/Feature.md @@ -0,0 +1,17 @@ +Detailed description of the feature. Put as much information as you can. + +Proposed Mockups: + +(Add mockups of the proposed feature) + +## Design Tasks + +* [ ] design tasks + +## Development Tasks + +* [ ] development tasks + +## QA Tasks + +* [ ] qa (quality assurance) tasks @@ -1,19 +1,21 @@ -GNOME Control Center -==================== +[![Build Status](https://gitlab.gnome.org/GNOME/gnome-control-center/badges/master/build.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/pipelines) +[![License](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://gitlab.gnome.org/GNOME/gnome-control-center/blob/master/COPYING) -About - +GNOME Settings +==================== -The control center is GNOME's main interface for configuration of various -aspects of your desktop. +GNOME Settings is GNOME's main interface for configuration of various aspects of +your desktop. -Installation - +## Contributing -See the file 'INSTALL' +See `docs/CONTRIBUTING.md` for details on the contribution process, and `docs/HACKING.md` +for the coding style guidelines. -How to report bugs - +## Reporting Bugs Bugs should be reported to the GNOME bug tracking system under the product -gnome-control-center. It is available at http://bugzilla.gnome.org. +gnome-control-center. It is available at https://gitlab.gnome.org. In the report please include the following information - @@ -23,7 +25,7 @@ In the report please include the following information - If the bug was a crash, include the exact text that was printed out A stacktrace where possible [see below] -How to get a stack trace - +### How to get a stack trace If the crash is reproducible, it is possible to get a stack trace and attach it to the bug report. The following steps are used to obtain a @@ -39,15 +41,3 @@ stack trace - Once you have the backtrace, copy and paste this either into the 'Comments' field or attach a file with it included. - - -Patches - - -Patches should be submitted to bugzilla.gnome.org or emailed to the -gnomecc-list@gnome.org list. If using bugzilla, attach -the patch to a new bug report [or preferably, check to see if there is -already a bug report that corresponds to your patch]. Bug reports -containing patches should include the 'PATCH' keyword. - -See https://wiki.gnome.org/Newcomers/CodeContributionWorkflow for how to -create patches. diff --git a/build-aux/flatpak/org.gnome.Settings.json b/build-aux/flatpak/org.gnome.Settings.json new file mode 100644 index 000000000..ea91887fc --- /dev/null +++ b/build-aux/flatpak/org.gnome.Settings.json @@ -0,0 +1,446 @@ +{ + "app-id" : "org.gnome.Settings", + "runtime" : "org.gnome.Platform", + "runtime-version" : "master", + "sdk" : "org.gnome.Sdk", + "command" : "gnome-control-center", + "tags" : [ + "devel" + ], + "desktop-file-name-prefix" : "(Development) ", + "finish-args" : [ + "--device=dri", + "--env=DCONF_USER_CONFIG_DIR=.config/dconf", + "--filesystem=host", + "--own-name=org.gnome.ControlCenter", + "--own-name=org.gnome.SessionManager", + "--share=ipc", + "--share=network", + "--socket=x11", + "--socket=pulseaudio", + "--socket=session-bus", + "--socket=system-bus", + "--socket=wayland" + ], + "build-options" : { + "cflags" : "-O2 -g", + "cxxflags" : "-O2 -g", + "env" : { + "V" : "1" + } + }, + "x-run-args" : [ + "--verbose" + ], + "cleanup" : [ + "/include", + "/share/aclocal", + "/man", + "/share/man", + "/share/gtk-doc", + "/share/vala", + "*.la", + "*.a" + ], + "modules" : [ + { + "name" : "pwquality", + "buildsystem" : "autotools", + "config-opts" : [ + ], + "sources" : [ + { + "type" : "git", + "url" : "https://github.com/libpwquality/libpwquality.git" + } + ] + }, + { + "name" : "polkit", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-introspection", + "--disable-libelogind" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://anongit.freedesktop.org/polkit" + } + ] + }, + { + "name" : "accountservice", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-systemd", + "--disable-elogind" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://anongit.freedesktop.org/accountsservice" + } + ] + }, + { + "name" : "libusb1", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-udev" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://github.com/libusb/libusb.git" + } + ] + }, + { + "name" : "gusb", + "buildsystem" : "meson", + "config-opts" : [ + "-Ddocs=false", + "-Dtests=false", + "-Dvapi=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://github.com/hughsie/libgusb.git" + } + ] + }, + { + "name" : "udev", + "config-opts" : [ + "--disable-hwdb", + "--disable-logging", + "--disable-gudev", + "--disable-introspection", + "--disable-keymap", + "--disable-mtd_probe" + ], + "cleanup" : [ + "/include", + "/etc", + "/libexec", + "/sbin", + "/lib/pkgconfig", + "/man", + "/share/aclocal", + "/share/doc", + "/share/gtk-doc", + "/share/man", + "/share/pkgconfig", + "*.la", + "*.a" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://github.com/gentoo/eudev.git" + } + ] + }, + { + "name" : "gudev", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-umockdev" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/libgudev" + } + ] + }, + { + "name" : "colord", + "buildsystem" : "meson", + "config-opts" : [ + "-Dargyllcms_sensor=false", + "-Dbash_completion=false", + "-Dman=false", + "-Dudev_rules=false", + "-Dsystemd=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://github.com/hughsie/colord.git" + } + ] + }, + { + "name" : "colord-gtk", + "buildsystem" : "autotools", + "config-opts" : [ + ], + "sources" : [ + { + "type" : "git", + "url" : "git://github.com/hughsie/colord-gtk.git" + } + ] + }, + { + "name" : "rest", + "buildsystem" : "autotools", + "sources" : [ + { + "type" : "git", + "branch" : "librest-0-7", + "url" : "https://git.gnome.org/browse/librest" + } + ] + }, + { + "name" : "gnome-online-accounts", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-telepathy", + "--disable-documentation" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/gnome-online-accounts" + } + ] + }, + { + "name" : "gnome-desktop", + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/gnome-desktop" + } + ] + }, + { + "name" : "geocode-glib", + "buildsystem" : "meson", + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/geocode-glib" + } + ] + }, + { + "name" : "libgweather", + "buildsystem" : "meson", + "sources" : [ + { + "type" : "git", + "url" : "https://gitlab.gnome.org/GNOME/libgweather.git" + } + ] + }, + { + "name" : "upower", + "buildsystem" : "autotools", + "sources" : [ + { + "type" : "git", + "url" : "git://anongit.freedesktop.org/upower" + } + ] + }, + { + "name" : "libwacom", + "buildsystem" : "autotools", + "sources" : [ + { + "type" : "git", + "url" : "https://github.com/linuxwacom/libwacom.git" + } + ] + }, + { + "name" : "libndp", + "buildsystem" : "autotools", + "sources" : [ + { + "type" : "archive", + "url" : " http://libndp.org/files/libndp-1.6.tar.gz", + "sha256" : "0c7dfa84e013bd5e569ef2c6292a6f72cfaf14f4ff77a77425e52edc33ffac0e" + } + ] + }, + { + "name" : "NetworkManager", + "buildsystem" : "meson", + "config-opts" : [ + "-Dlibaudit=no", + "-Ddbus_conf_dir=/app/etc/dbus-1/system.d", + "-Ddbus_ifaces_dir=/app/share/dbus-1/interfaces", + "-Ddbus_sys_dir=/app/share/dbus-1/system.d", + "-Ddnsmasq=/usr/bin/true", + "-Ddocs=false", + "-Dintrospection=false", + "-Diptables=/usr/bin/true", + "-Djson_validation=false", + "-Dlibnm_glib=false", + "-Dmodem_manager=false", + "-Dnmtui=false", + "-Dovs=false", + "-Dppp=false", + "-Dqt=false", + "-Dselinux=false", + "-Dsession_tracking=no", + "-Dsystemdsystemunitdir='no'", + "-Dsystemd_journal=false", + "-Dtests=no", + "-Dvapi=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://anongit.freedesktop.org/NetworkManager/NetworkManager" + } + ] + }, + { + "name" : "network-manager-applet", + "buildsystem" : "meson", + "config-opts" : [ + "-Dgtk_doc=false", + "-Dintrospection=false", + "-Dlibnm_gtk=false", + "-Dselinux=false", + "-Dteam=false", + "-Dwwan=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/network-manager-applet" + } + ] + }, + { + "name" : "ModemManager", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-introspection", + "--disable-vala", + "--with-udev-base-dir=/app/lib", + "--without-mbim", + "--without-qmi" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://anongit.freedesktop.org/ModemManager/ModemManager" + } + ] + }, + { + "name" : "gnome-settings-daemon", + "buildsystem" : "meson", + "sources" : [ + { + "type" : "git", + "url" : "https://gitlab.gnome.org/GNOME/gnome-settings-daemon.git" + } + ] + }, + { + "name" : "gnome-bluetooth", + "buildsystem" : "meson", + "config-opts" : [ + "-Dintrospection=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/gnome-bluetooth" + } + ] + }, + { + "name" : "grilo", + "buildsystem" : "meson", + "config-opts" : [ + "-Denable-grl-pls=false", + "-Denable-gtk-doc=false", + "-Denable-introspection=false", + "-Denable-test-ui=false", + "-Denable-vala=false" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/grilo" + } + ] + }, + { + "name" : "openldap", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-slapd" + ], + "sources" : [ + { + "type" : "archive", + "url" : "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.4.46.tgz", + "sha256" : "9a90dcb86b99ae790ccab93b7585a31fbcbeec8c94bf0f7ab0ca0a87ea0c4b2d" + } + ] + }, + { + "name" : "samba", + "buildsystem" : "autotools", + "sources" : [ + { + "type" : "archive", + "url" : "https://download.samba.org/pub/samba/stable/samba-4.8.1.tar.gz", + "sha256" : "8ef7367507f16b7a5e2f6aed5bcdbd1143feca79aa2a07c9b21292b17d7f789d" + } + ] + }, + { + "name" : "libgtop2", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-introspection" + ], + "sources" : [ + { + "type" : "git", + "url" : "https://gitlab.gnome.org/GNOME/libgtop.git" + } + ] + }, + { + "name" : "cheese", + "buildsystem" : "autotools", + "config-opts" : [ + "--disable-introspection" + ], + "sources" : [ + { + "type" : "git", + "url" : "git://git.gnome.org/cheese" + } + ] + }, + { + "name" : "gnome-control-center", + "buildsystem" : "meson", + "sources" : [ + { + "type" : "git", + "url" : "https://gitlab.gnome.org/GNOME/gnome-control-center.git" + } + ], + "config-opts" : [ + "-Dtracing=true" + ] + } + ] +}
\ No newline at end of file diff --git a/build-aux/meson.build b/build-aux/meson.build new file mode 100644 index 000000000..f3fdb40a8 --- /dev/null +++ b/build-aux/meson.build @@ -0,0 +1,5 @@ +update_from_gsd = find_program('meson/update-from-gsd.sh') +update_from_gsd_in = files('meson/update-from-gsd.in') +update_from_nma_in = files('meson/update-from-nma.in') + +meson.add_install_script('meson/meson_post_install.py', control_center_datadir) diff --git a/meson_post_install.py b/build-aux/meson/meson_post_install.py index f9119e1a7..f9119e1a7 100644 --- a/meson_post_install.py +++ b/build-aux/meson/meson_post_install.py diff --git a/update-from-gsd.in b/build-aux/meson/update-from-gsd.in index 29d06be8d..29d06be8d 100755 --- a/update-from-gsd.in +++ b/build-aux/meson/update-from-gsd.in diff --git a/update-from-gsd.sh b/build-aux/meson/update-from-gsd.sh index 9f2d6b79c..9f2d6b79c 100755 --- a/update-from-gsd.sh +++ b/build-aux/meson/update-from-gsd.sh diff --git a/update-from-nma.in b/build-aux/meson/update-from-nma.in index 76738b10b..76738b10b 100755 --- a/update-from-nma.in +++ b/build-aux/meson/update-from-nma.in diff --git a/data/icons/meson.build b/data/icons/meson.build index 0f9a7eb54..a6a6c221f 100644 --- a/data/icons/meson.build +++ b/data/icons/meson.build @@ -1,4 +1,4 @@ install_subdir( - 'hicolor', - install_dir: control_center_icondir + 'hicolor', + install_dir : control_center_icondir ) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 000000000..7e054da29 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# Contributing + +When contributing to the development of GNOME Settings, please first discuss the change you wish to +make via issue, email, or any other method with the maintainers before making a change. + +Please note we have a Code of Conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure your code compiles and doesn't break anything. Run `meson test -C <builddir>` before creating + the pull request. +2. If you're adding new API, it must be properly documented. +3. The commit message is formatted as follows: + ``` + component: <summary> + + A paragraph explaining the problem and its context. + + Another one explaining how you solved that. + + <link to the issue> + ``` +4. You may merge the pull request in once you have the sign-off of the maintainers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + +## Code of Conduct + +GNOME Settings is a project developed based on GNOME Code of Conduct. You can read it below: + +### Summary + +GNOME creates software for a better world. We achieve this by behaving well towards +each other. + +Therefore this document suggests what we consider ideal behaviour, so you know what +to expect when getting involved in GNOME. This is who we are and what we want to be. +There is no official enforcement of these principles, and this should not be interpreted +like a legal document. + +### Advice + + * **Be respectful and considerate**: Disagreement is no excuse for poor behaviour or personal + attacks. Remember that a community where people feel uncomfortable is not a productive one. + + * **Be patient and generous**: If someone asks for help it is because they need it. Do politely + suggest specific documentation or more appropriate venues where appropriate, but avoid + aggressive or vague responses such as "RTFM". + + * **Assume people mean well**: Remember that decisions are often a difficult choice between + competing priorities. If you disagree, please do so politely. If something seems outrageous, + check that you did not misinterpret it. Ask for clarification, but do not assume the worst. + + * **Try to be concise**: Avoid repeating what has been said already. Making a conversation larger + makes it difficult to follow, and people often feel personally attacked if they receive multiple + messages telling them the same thing. + + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file diff --git a/docs/HACKING.md b/docs/HACKING.md new file mode 100644 index 000000000..cf9265f50 --- /dev/null +++ b/docs/HACKING.md @@ -0,0 +1,213 @@ +# Style + +GNOME Settings has a coding style based on GTK Coding Style, but with a few more +rules. Please read them carefully and, if in doubt, ask a maintainer for directions. + +## General + +The most important rule is: **see the surrounding code, and copy its style**. + +Another rule that applies to function declarations is that all parameters are +aligned by the last '*'. There are plenty of examples below. + +## Comments + +Comment blocks should be formatted as following: + +```c +/* Single line comment */ + +/* Multiline comments start at the first line of the comment block, + * but have the closing slash a line after. Every line starts with + * an asterisk that is aligned with every the rest of the block. + */ +``` + +## Header (.h) files + +It is organized by the following structure: + + 1. GPL header + 2. Local includes + 3. System includes + 4. `G_BEGIN_DECLS` + 5. `#defines` + 6. `G_DECLARE_{FINAL,DERIVABLE}_TYPE` + 7. Public API + 8. `G_END_DECLS` + +The following style rules apply: + + * The '*' and the type come together, without any spaces in between. + * Function names are aligned by the widest return value. + * Parenthesis after function name is aligned by the widest function name + * The last '*' in parameters are aligned by the widest parameter type + * No new line at the end of the file + +As an example, this is how a header file should look like (extracted from +the `cc-object-storage.h` file): + +```c +/* cc-object-storage.h + * + * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +/* Default storage keys */ +#define CC_OBJECT_NMCLIENT "CcObjectStorage::nm-client" + + +#define CC_TYPE_OBJECT_STORAGE (cc_object_storage_get_type()) + +G_DECLARE_FINAL_TYPE (CcObjectStorage, cc_object_storage, CC, OBJECT_STORAGE, GObject) + +gboolean cc_object_storage_has_object (const gchar *key); + +void cc_object_storage_add_object (const gchar *key, + gpointer object); + +gpointer cc_object_storage_get_object (const gchar *key); + +gpointer cc_object_storage_create_dbus_proxy_sync (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GError **error); + +void cc_object_storage_create_dbus_proxy (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +G_END_DECLS +``` + +## Source code + +The source file keeps an order of methods. The order will be as following: + + 1. GPL header + 2. Structures + 3. Function prototypes + 4. G_DEFINE_TYPE() + 5. Enums + 6. Static variables + 7. Auxiliary methods + 8. Callbacks + 9. Interface implementations + 10. Parent class overrides + 11. class_init and init + 12. Public API + +### Structures + +The structures must have the first pointer asterisk aligned one space after the +widest type name. For example: + +```c +typedef struct +{ + GBusType bus_type; + GDBusProxyFlags flags; + gchar *name; + gchar *path; + gchar *interface; + gboolean cached; +} TaskData; + +``` + +### Function Prototypes + +Function prototypes must be formatted just like in header files. + +### Auxiliary Methods + +Auxiliary method names must have a verb in the dictionary form, and should always +perform an action over something. They don't have the `cc_` prefix. For example: + +```c +static void +execute_something_on_data (Foo *data, + Bar *bar) +{ + /* ... */ +} +``` + +### Callbacks + + * Callbacks always have the `_cb` suffix + * Signal callbacks always have the `on_<object_name>` prefix + * Callback names must have the name of the signal in the past + +For example: + +```c +static void +on_foo_size_allocated_cb (GtkWidget *widget, + GtkAllocation *allocation, + gpointer user_data) +{ + /* ... */ +} +``` + +### Line Splitting + +Line splitting works following the GTK code style, but legibility comes over above +all. If a function call looks unbalanced following the GTK style, it is fine to +slightly escape the rules. + +For example, this feels extremelly unbalanced: + +```c +foo_bar_do_somthing_sync (a, + 1, + object, + data, + something + cancellable, + &error); +``` + +Notice the empty space before the arguments, and how empty and odd it looks. In +comparison, it will look better if written like this: + +```c +foo_bar_do_somthing_sync (a, 1, object, data, + something + cancellable, + &error); +``` + +# Contributing guidelines + +See CONTRIBUTIONS.md file for the contribution guidelines, and the Code of Conduct +that contributors are expected to follow.
\ No newline at end of file diff --git a/gnome-control-center.doap b/gnome-control-center.doap index 08b1f9f87..a7ca2e001 100644 --- a/gnome-control-center.doap +++ b/gnome-control-center.doap @@ -4,38 +4,17 @@ xmlns:gnome="http://api.gnome.org/doap-extensions#" xmlns="http://usefulinc.com/ns/doap#"> - <name xml:lang="en">gnome-control-center</name> + <name xml:lang="en">GNOME Settings</name> <shortdesc xml:lang="en">GNOME's main interface to configure various aspects of the desktop</shortdesc> <description xml:lang="en">GNOME's main interface to configure various aspects of the desktop</description> <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnomecc-list" /> <download-page rdf:resource="http://download.gnome.org/sources/gnome-control-center/" /> - <bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-control-center" /> + <bug-database rdf:resource="http://gitlab.gnome.org/GNOME/gnome-control-center/issues" /> <category rdf:resource="http://api.gnome.org/doap-extensions#core" /> <programming-language>C</programming-language> <maintainer> <foaf:Person> - <foaf:name>Rui Matos</foaf:name> - <foaf:mbox rdf:resource="mailto:tiagomatos@gmail.com" /> - <gnome:userid>rtcm</gnome:userid> - </foaf:Person> - </maintainer> - <maintainer> - <foaf:Person> - <foaf:name>Richard Hughes</foaf:name> - <foaf:mbox rdf:resource="mailto:richard@hughsie.com" /> - <gnome:userid>rhughes</gnome:userid> - </foaf:Person> - </maintainer> - <maintainer> - <foaf:Person> - <foaf:name>Olivier Fourdan</foaf:name> - <foaf:mbox rdf:resource="mailto:ofourdan@redhat.com" /> - <gnome:userid>ofourdan</gnome:userid> - </foaf:Person> - </maintainer> - <maintainer> - <foaf:Person> <foaf:name>Georges Basile Stavracas Neto</foaf:name> <foaf:mbox rdf:resource="mailto:gbsneto@gnome.org" /> <gnome:userid>gbsneto</gnome:userid> diff --git a/man/meson.build b/man/meson.build index cab3fa945..1e9e08971 100644 --- a/man/meson.build +++ b/man/meson.build @@ -17,10 +17,10 @@ xsltproc_cmd = [ output = meson.project_name() + '.1' custom_target( - output, - input: meson.project_name() + '.xml', - output: output, - command: xsltproc_cmd, - install: true, - install_dir: join_paths(control_center_mandir, 'man1') + output, + input : meson.project_name() + '.xml', + output : output, + command : xsltproc_cmd, + install : true, + install_dir : join_paths(control_center_mandir, 'man1') ) diff --git a/meson.build b/meson.build index 20aeb9fc1..a61acc9c4 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,8 @@ project( 'gnome-control-center', 'c', - version: '3.29.0', - license: 'GPL2+', - meson_version: '>= 0.43.0' + version : '3.29.0', + license : 'GPL2+', + meson_version : '>= 0.43.0' ) control_center_prefix = get_option('prefix') @@ -25,8 +25,16 @@ host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390 cc = meson.get_compiler('c') +# Tracing +enable_tracing = get_option('tracing') + config_h = configuration_data() +py3 = import('python3') +python = py3.find_python() + +config_h.set_quoted('TEST_NM_PYTHON', python.path()) + # defines set_defines = [ # package @@ -41,7 +49,9 @@ foreach define: set_defines config_h.set_quoted(define[0], define[1]) endforeach -config_h.set('USER_DIR_MODE', 0700, +# meson does not support octal values, so it must be handled as a +# string. See: https://github.com/mesonbuild/meson/issues/2047 +config_h.set('USER_DIR_MODE', '0700', description: 'Permissions for creating the user\'s config, cache and data directories') # compiler flags @@ -55,7 +65,6 @@ optimized_src = ''' ''' control_center_optimized = get_option('buildtype').contains('optimized') and cc.compiles(optimized_src) -message('whether_optimization is enabled: ' + control_center_optimized.to_string()) if control_center_optimized common_flags += '-Wp,-D_FORTIFY_SOURCE=2' @@ -203,6 +212,7 @@ if host_is_linux_not_s390 description: 'Define to 1 if libwacom provides definition for 3D styli') else message('Bluetooth and Wacom panels will not be built (no USB support on this platform)') + message('Thunderbolt panel will not be built (not supported on this platform)') endif config_h.set('BUILD_BLUETOOTH', host_is_linux_not_s390, description: 'Define to 1 to build the Bluetooth panel') @@ -212,6 +222,8 @@ config_h.set('BUILD_WACOM', host_is_linux_not_s390, description: 'Define to 1 to build the Wacom panel') config_h.set('HAVE_WACOM', host_is_linux_not_s390, description: 'Define to 1 if Wacom is supportted') +config_h.set('BUILD_THUNDERBOLT', host_is_linux_not_s390, + description: 'Define to 1 to build the Thunderbolt panel') # Check for info panel gnome_session_libexecdir = get_option('gnome_session_libexecdir') @@ -237,15 +249,13 @@ install_subdir( top_inc = include_directories('.') shell_inc = include_directories('shell') -update_from_gsd = find_program('update-from-gsd.sh') -update_from_gsd_in = files('update-from-gsd.in') -update_from_nma_in = files('update-from-nma.in') - +subdir('build-aux') subdir('data/icons') subdir('po') subdir('panels') subdir('shell') subdir('search-provider') +subdir('tests') if get_option('documentation') subdir('man') @@ -256,18 +266,20 @@ configure_file( configuration: config_h ) -meson.add_install_script( - 'meson_post_install.py', - control_center_datadir -) - -output = meson.project_name() + ' was configured with the following options:\n' -output += '** gnome-bluetooth (Bluetooth panel): ' + host_is_linux_not_s390.to_string() + '\n' -output += '** Cheese (Users panel webcam support): ' + enable_cheese.to_string() + '\n' -output += '** IBus (Region panel IBus support): ' + enable_ibus.to_string() + '\n' -output += '** NetworkManager (Network panel): ' + host_is_linux.to_string() + '\n' -output += '** wacom (Wacom tablet panel): ' + host_is_linux_not_s390.to_string() + '\n' -output += '** Wayland: ' + enable_wayland.to_string() + '\n' -output += '** gnome-session libexecdir: ' + gnome_session_libexecdir + '\n' -output += 'End options' -message(output) +output = '' +output += '\n ' + meson.project_name() + ' - ' + meson.project_version() + '\n' +output += ' ===================================\n' +output += ' Options \n' +output += ' Documentation .............................. ' + get_option('documentation').to_string() + '\n' +output += ' Tracing .................................... ' + enable_tracing.to_string() + '\n' +output += ' gnome-session libexecdir ................... ' + gnome_session_libexecdir + '\n' +output += ' Optimized .................................. ' + control_center_optimized.to_string() + '\n' +output += ' Panels \n' +output += ' GNOME Bluetooth (Bluetooth panel) .......... ' + host_is_linux_not_s390.to_string() + '\n' +output += ' Cheese (Users panel webcam support) ........ ' + enable_cheese.to_string() + '\n' +output += ' IBus (Region panel IBus support) ........... ' + enable_ibus.to_string() + '\n' +output += ' NetworkManager (Network panel) ............. ' + host_is_linux.to_string() + '\n' +output += ' Wacom (Wacom tablet panel) ................. ' + host_is_linux_not_s390.to_string() + '\n' +output += ' Wayland .................................... ' + enable_wayland.to_string() + '\n' + +message(output)
\ No newline at end of file diff --git a/meson_options.txt b/meson_options.txt index 7498af4d6..a347168b7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,4 +2,5 @@ option('cheese', type: 'boolean', value: true, description: 'build with cheese w option('documentation', type: 'boolean', value: false, description: 'build documentation') option('gnome_session_libexecdir', type: 'string', value: '', description: 'Directory for gnome-session\'s libexecdir') option('ibus', type: 'boolean', value: true, description: 'build with IBus support') -option('wayland', type: 'boolean', value: true, description: 'build with Wayland support') +option('tracing', type: 'boolean', value: false, description: 'add extra debugging information') +option('wayland', type: 'boolean', value: true, description: 'build with Wayland support')
\ No newline at end of file diff --git a/panels/bluetooth/cc-bluetooth-panel.c b/panels/bluetooth/cc-bluetooth-panel.c index 36c58bf4d..5a60d70c8 100644 --- a/panels/bluetooth/cc-bluetooth-panel.c +++ b/panels/bluetooth/cc-bluetooth-panel.c @@ -24,6 +24,7 @@ #include <glib/gi18n-lib.h> #include <shell/cc-shell.h> +#include <shell/cc-object-storage.h> #include <bluetooth-settings-widget.h> #include "cc-bluetooth-panel.h" @@ -310,20 +311,18 @@ cc_bluetooth_panel_init (CcBluetoothPanel *self) self->cancellable = g_cancellable_new (); /* RFKill */ - self->rfkill = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - NULL, NULL); - self->properties = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.freedesktop.DBus.Properties", - NULL, NULL); + self->rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + NULL, NULL); + self->properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.freedesktop.DBus.Properties", + NULL, NULL); self->stack = gtk_stack_new (); gtk_stack_set_homogeneous (GTK_STACK (self->stack), TRUE); @@ -343,10 +342,10 @@ cc_bluetooth_panel_init (CcBluetoothPanel *self) gtk_container_add (GTK_CONTAINER (self), self->stack); airplane_mode_changed (NULL, NULL, NULL, self); - g_signal_connect (self->rfkill, "g-properties-changed", - G_CALLBACK (airplane_mode_changed), self); - g_signal_connect_swapped (G_OBJECT (self->widget), "adapter-status-changed", - G_CALLBACK (cc_bluetooth_panel_update_power), self); + g_signal_connect_object (self->rfkill, "g-properties-changed", + G_CALLBACK (airplane_mode_changed), self, 0); + g_signal_connect_object (G_OBJECT (self->widget), "adapter-status-changed", + G_CALLBACK (cc_bluetooth_panel_update_power), self, G_CONNECT_SWAPPED); g_signal_connect (G_OBJECT (WID ("switch_bluetooth")), "notify::active", G_CALLBACK (power_callback), self); diff --git a/panels/color/cc-color-calibrate.c b/panels/color/cc-color-calibrate.c index d21ad058f..9357eee72 100644 --- a/panels/color/cc-color-calibrate.c +++ b/panels/color/cc-color-calibrate.c @@ -28,6 +28,8 @@ #include <math.h> #include <colord-session/cd-session.h> +#include "shell/cc-object-storage.h" + #define GNOME_DESKTOP_USE_UNSTABLE_API #include <libgnome-desktop/gnome-rr.h> @@ -884,14 +886,13 @@ cc_color_calibrate_setup (CcColorCalibrate *calibrate, g_return_val_if_fail (calibrate->priv->device_kind != CD_SENSOR_CAP_UNKNOWN, FALSE); /* use logind to disable system state idle */ - priv->proxy_inhibit = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - NULL, - error); + priv->proxy_inhibit = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + NULL, + error); if (priv->proxy_inhibit == NULL) { ret = FALSE; @@ -899,27 +900,26 @@ cc_color_calibrate_setup (CcColorCalibrate *calibrate, } /* start the calibration session daemon */ - priv->proxy_helper = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - CD_SESSION_DBUS_SERVICE, - CD_SESSION_DBUS_PATH, - CD_SESSION_DBUS_INTERFACE_DISPLAY, - NULL, - error); + priv->proxy_helper = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + CD_SESSION_DBUS_SERVICE, + CD_SESSION_DBUS_PATH, + CD_SESSION_DBUS_INTERFACE_DISPLAY, + NULL, + error); if (priv->proxy_helper == NULL) { ret = FALSE; goto out; } - g_signal_connect (priv->proxy_helper, - "g-properties-changed", - G_CALLBACK (cc_color_calibrate_property_changed_cb), - calibrate); - g_signal_connect (priv->proxy_helper, - "g-signal", - G_CALLBACK (cc_color_calibrate_signal_cb), - calibrate); + g_signal_connect_object (priv->proxy_helper, + "g-properties-changed", + G_CALLBACK (cc_color_calibrate_property_changed_cb), + calibrate, 0); + g_signal_connect_object (priv->proxy_helper, + "g-signal", + G_CALLBACK (cc_color_calibrate_signal_cb), + calibrate, 0); out: return ret; } diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c index d901b623e..e9a65cf58 100644 --- a/panels/color/cc-color-panel.c +++ b/panels/color/cc-color-panel.c @@ -26,7 +26,7 @@ #include <gdk/gdkx.h> #include <libsoup/soup.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-color-calibrate.h" #include "cc-color-cell-renderer-text.h" #include "cc-color-panel.h" @@ -49,7 +49,6 @@ struct _CcColorPanelPrivate GPtrArray *devices; GPtrArray *sensors; GCancellable *cancellable; - GDBusProxy *proxy; GSettings *settings; GSettings *settings_colord; GtkBuilder *builder; diff --git a/panels/color/meson.build b/panels/color/meson.build index 36bd4be7d..54766a807 100644 --- a/panels/color/meson.build +++ b/panels/color/meson.build @@ -55,7 +55,7 @@ cflags += [ panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) diff --git a/panels/common/cc-common-language.c b/panels/common/cc-common-language.c index 028213acb..4ea4f06ad 100644 --- a/panels/common/cc-common-language.c +++ b/panels/common/cc-common-language.c @@ -33,6 +33,7 @@ #include <libgnome-desktop/gnome-languages.h> #include "cc-common-language.h" +#include "shell/cc-object-storage.h" static char *get_lang_for_user_object_path (const char *path); @@ -175,14 +176,13 @@ get_lang_for_user_object_path (const char *path) GVariant *props; char *lang; - user = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - path, - "org.freedesktop.Accounts.User", - NULL, - &error); + user = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + path, + "org.freedesktop.Accounts.User", + NULL, + &error); if (user == NULL) { g_warning ("Failed to get proxy for user '%s': %s", path, error->message); diff --git a/shell/cc-hostname-entry.c b/panels/common/cc-hostname-entry.c index 0b0d6d10c..0b0d6d10c 100644 --- a/shell/cc-hostname-entry.c +++ b/panels/common/cc-hostname-entry.c diff --git a/shell/cc-hostname-entry.h b/panels/common/cc-hostname-entry.h index a48177961..a48177961 100644 --- a/shell/cc-hostname-entry.h +++ b/panels/common/cc-hostname-entry.h diff --git a/panels/common/cc-language-chooser.c b/panels/common/cc-language-chooser.c index 961df5a0a..f0d2ecedc 100644 --- a/panels/common/cc-language-chooser.c +++ b/panels/common/cc-language-chooser.c @@ -29,7 +29,7 @@ #include <gio/gio.h> #include <gtk/gtk.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-common-language.h" #include "cc-util.h" diff --git a/shell/hostname-helper.c b/panels/common/hostname-helper.c index df596975e..df596975e 100644 --- a/shell/hostname-helper.c +++ b/panels/common/hostname-helper.c diff --git a/shell/hostname-helper.h b/panels/common/hostname-helper.h index 9f96c12f9..9f96c12f9 100644 --- a/shell/hostname-helper.h +++ b/panels/common/hostname-helper.h diff --git a/shell/list-box-helper.c b/panels/common/list-box-helper.c index 415cdde94..415cdde94 100644 --- a/shell/list-box-helper.c +++ b/panels/common/list-box-helper.c diff --git a/shell/list-box-helper.h b/panels/common/list-box-helper.h index c2a0acc97..c2a0acc97 100644 --- a/shell/list-box-helper.h +++ b/panels/common/list-box-helper.h diff --git a/panels/common/meson.build b/panels/common/meson.build index 561f42cf7..e9451e6d6 100644 --- a/panels/common/meson.build +++ b/panels/common/meson.build @@ -24,6 +24,23 @@ common_sources += gnome.mkenums( vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n' ) +sources = files( + 'cc-hostname-entry.c', + 'hostname-helper.c', + 'list-box-helper.c', +) + +libwidgets = static_library( + 'widgets', + sources: sources, + include_directories: top_inc, + dependencies: common_deps + [ polkit_gobject_dep ] +) +libwidgets_dep = declare_dependency( + include_directories: common_inc, + link_with: libwidgets +) + sources = common_sources + files( 'cc-common-language.c', 'cc-language-chooser.c', @@ -121,3 +138,4 @@ run_target( script_name, command: script ) + diff --git a/panels/datetime/backward b/panels/datetime/backward index f1f95a894..8594be65f 100644 --- a/panels/datetime/backward +++ b/panels/datetime/backward @@ -1,13 +1,12 @@ -# <pre> -# @(#)backward 8.9 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # This file provides links between current names for time zones # and their old names. Many names changed in late 1993. -Link Africa/Asmara Africa/Asmera -Link Africa/Bamako Africa/Timbuktu +# Link TARGET LINK-NAME +Link Africa/Nairobi Africa/Asmera +Link Africa/Abidjan Africa/Timbuktu Link America/Argentina/Catamarca America/Argentina/ComodRivadavia Link America/Adak America/Atka Link America/Argentina/Buenos_Aires America/Buenos_Aires @@ -21,17 +20,25 @@ Link America/Argentina/Jujuy America/Jujuy Link America/Indiana/Knox America/Knox_IN Link America/Kentucky/Louisville America/Louisville Link America/Argentina/Mendoza America/Mendoza +Link America/Toronto America/Montreal Link America/Rio_Branco America/Porto_Acre Link America/Argentina/Cordoba America/Rosario -Link America/St_Thomas America/Virgin +Link America/Tijuana America/Santa_Isabel +Link America/Denver America/Shiprock +Link America/Port_of_Spain America/Virgin +Link Pacific/Auckland Antarctica/South_Pole Link Asia/Ashgabat Asia/Ashkhabad -Link Asia/Chongqing Asia/Chungking +Link Asia/Kolkata Asia/Calcutta +Link Asia/Shanghai Asia/Chongqing +Link Asia/Shanghai Asia/Chungking Link Asia/Dhaka Asia/Dacca +Link Asia/Shanghai Asia/Harbin +Link Asia/Urumqi Asia/Kashgar Link Asia/Kathmandu Asia/Katmandu -Link Asia/Kolkata Asia/Calcutta Link Asia/Macau Asia/Macao -Link Asia/Jerusalem Asia/Tel_Aviv +Link Asia/Yangon Asia/Rangoon Link Asia/Ho_Chi_Minh Asia/Saigon +Link Asia/Jerusalem Asia/Tel_Aviv Link Asia/Thimphu Asia/Thimbu Link Asia/Makassar Asia/Ujung_Pandang Link Asia/Ulaanbaatar Asia/Ulan_Bator @@ -54,7 +61,9 @@ Link America/Sao_Paulo Brazil/East Link America/Manaus Brazil/West Link America/Halifax Canada/Atlantic Link America/Winnipeg Canada/Central -Link America/Regina Canada/East-Saskatchewan +# This line is commented out, as the name exceeded the 14-character limit +# and was an unused misnomer. +#Link America/Regina Canada/East-Saskatchewan Link America/Toronto Canada/Eastern Link America/Edmonton Canada/Mountain Link America/St_Johns Canada/Newfoundland @@ -89,10 +98,11 @@ Link Pacific/Auckland NZ Link Pacific/Chatham NZ-CHAT Link America/Denver Navajo Link Asia/Shanghai PRC +Link Pacific/Honolulu Pacific/Johnston +Link Pacific/Pohnpei Pacific/Ponape Link Pacific/Pago_Pago Pacific/Samoa -Link Pacific/Chuuk Pacific/Yap Link Pacific/Chuuk Pacific/Truk -Link Pacific/Pohnpei Pacific/Ponape +Link Pacific/Chuuk Pacific/Yap Link Europe/Warsaw Poland Link Europe/Lisbon Portugal Link Asia/Taipei ROC @@ -115,4 +125,4 @@ Link Pacific/Pago_Pago US/Samoa Link Etc/UTC UTC Link Etc/UTC Universal Link Europe/Moscow W-SU -Link Etc/UTC Zulu +Link Etc/UTC Zulu
\ No newline at end of file diff --git a/panels/datetime/cc-datetime-panel.c b/panels/datetime/cc-datetime-panel.c index 2ea385188..15f3dd8c3 100644 --- a/panels/datetime/cc-datetime-panel.c +++ b/panels/datetime/cc-datetime-panel.c @@ -25,7 +25,7 @@ #include <langinfo.h> #include <sys/time.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-timezone-map.h" #include "timedated.h" #include "date-endian.h" diff --git a/panels/datetime/meson.build b/panels/datetime/meson.build index ba82618f2..5073f263d 100644 --- a/panels/datetime/meson.build +++ b/panels/datetime/meson.build @@ -183,33 +183,14 @@ cflags += [ '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) ] -panels_libs += static_library( +datetime_panel_lib = static_library( cappletname, sources: sources + resources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) - -test_cflags = '-DSRCDIR="@0@"'.format(meson.current_source_dir()) - -test_units = [ - #['test-timezone', ['cc-timezone-map.c', 'tz.c'] + resources, [m_dep], []], - ['test-timezone-gfx', ['tz.c'] + resources, [m_dep], [test_cflags]], - ['test-endianess', ['date-endian.c'], [], []] -] - -foreach unit: test_units - exe = executable( - unit[0], - [unit[0] + '.c'] + unit[1], - include_directories: top_inc, - dependencies: deps + unit[2], - c_args: cflags + unit[3] - ) - - test(unit[0], exe) -endforeach +panels_libs += datetime_panel_lib subdir('po-timezones') subdir('icons') diff --git a/panels/datetime/test-timezone-gfx.c b/panels/datetime/test-timezone-gfx.c deleted file mode 100644 index 2beda3f7c..000000000 --- a/panels/datetime/test-timezone-gfx.c +++ /dev/null @@ -1,61 +0,0 @@ -#include <config.h> -#include <locale.h> - -#include "tz.h" - -static void -test_timezone_gfx (gconstpointer data) -{ - const char *pixmap_dir = data; - g_autoptr(TzDB) db = NULL; - GPtrArray *locs; - guint i; - - db = tz_load_db (); - locs = tz_get_locations (db); - for (i = 0; i < locs->len ; i++) { - TzLocation *loc = locs->pdata[i]; - TzInfo *info; - g_autofree gchar *filename = NULL; - g_autofree gchar *path = NULL; - gdouble selected_offset; - char buf[16]; - - info = tz_info_from_location (loc); - selected_offset = tz_location_get_utc_offset (loc) - / (60.0*60.0) + ((info->daylight) ? -1.0 : 0.0); - - filename = g_strdup_printf ("timezone_%s.png", - g_ascii_formatd (buf, sizeof (buf), - "%g", selected_offset)); - path = g_build_filename (pixmap_dir, filename, NULL); - - if (g_file_test (path, G_FILE_TEST_IS_REGULAR) == FALSE) { - g_message ("File '%s' missing for zone '%s'", filename, loc->zone); - g_test_fail (); - } - } -} - -int main (int argc, char **argv) -{ - char *pixmap_dir; - - setlocale (LC_ALL, ""); - g_test_init (&argc, &argv, NULL); - - g_setenv ("G_DEBUG", "fatal_warnings", FALSE); - - if (argc == 2) { - pixmap_dir = g_strdup (argv[1]); - } else if (argc == 1) { - pixmap_dir = g_strdup (SRCDIR "/data/"); - } else { - g_message ("Usage: %s [PIXMAP DIRECTORY]", argv[0]); - return 1; - } - - g_test_add_data_func ("/datetime/timezone-gfx", pixmap_dir, test_timezone_gfx); - - return g_test_run (); -} diff --git a/panels/datetime/test-timezone.c b/panels/datetime/test-timezone.c deleted file mode 100644 index ca9860118..000000000 --- a/panels/datetime/test-timezone.c +++ /dev/null @@ -1,108 +0,0 @@ -#include <locale.h> -#include <gtk/gtk.h> -#include "cc-timezone-map.h" - -#define TZ_DIR "/usr/share/zoneinfo/" - -static GList * -get_timezone_list (GList *tzs, - const char *top_path, - const char *subpath) -{ - GDir *dir; - char *fullpath; - const char *name; - - if (subpath == NULL) - fullpath = g_strdup (top_path); - else - fullpath = g_build_filename (top_path, subpath, NULL); - dir = g_dir_open (fullpath, 0, NULL); - if (dir == NULL) { - g_warning ("Could not open %s", fullpath); - return NULL; - } - while ((name = g_dir_read_name (dir)) != NULL) { - g_autofree gchar *path = NULL; - - if (g_str_has_suffix (name, ".tab")) - continue; - - if (subpath != NULL) - path = g_build_filename (top_path, subpath, name, NULL); - else - path = g_build_filename (top_path, name, NULL); - if (g_file_test (path, G_FILE_TEST_IS_DIR)) { - if (subpath == NULL) { - tzs = get_timezone_list (tzs, top_path, name); - } else { - g_autofree gchar *new_subpath = NULL; - new_subpath = g_strdup_printf ("%s/%s", subpath, name); - tzs = get_timezone_list (tzs, top_path, new_subpath); - } - } else if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) { - if (subpath == NULL) - tzs = g_list_prepend (tzs, g_strdup (name)); - else { - char *tz; - tz = g_strdup_printf ("%s/%s", subpath, name); - tzs = g_list_prepend (tzs, tz); - } - } - } - g_dir_close (dir); - - return tzs; -} - -static void -test_timezone (void) -{ - CcTimezoneMap *map; - TzDB *tz_db; - GList *tzs, *l; - GHashTable *ht; - - ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - map = cc_timezone_map_new (); - tz_db = tz_load_db (); - tzs = get_timezone_list (NULL, TZ_DIR, NULL); - for (l = tzs; l != NULL; l = l->next) { - const gchar *timezone = l->data; - g_autofree gchar *clean_tz = NULL; - - clean_tz = tz_info_get_clean_name (tz_db, timezone); - - if (cc_timezone_map_set_timezone (map, clean_tz) == FALSE) { - if (g_hash_table_lookup (ht, clean_tz) == NULL) { - if (g_strcmp0 (clean_tz, timezone) == 0) - g_print ("Failed to locate timezone '%s'\n", timezone); - else - g_print ("Failed to locate timezone '%s' (original name: '%s')\n", clean_tz, timezone); - g_hash_table_insert (ht, g_strdup (clean_tz), GINT_TO_POINTER (TRUE)); - g_test_fail (); - } - /* We don't warn for those two, we'll just fallback - * in the panel code */ - if (!g_str_equal (clean_tz, "posixrules") && - !g_str_equal (clean_tz, "Factory")) - g_test_fail (); - } - } - g_list_free_full (tzs, g_free); - tz_db_free (tz_db); - g_hash_table_destroy (ht); -} - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - gtk_init (NULL, NULL); - g_test_init (&argc, &argv, NULL); - - g_setenv ("G_DEBUG", "fatal_warnings", FALSE); - - g_test_add_func ("/datetime/timezone", test_timezone); - - return g_test_run (); -} diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c index 2f372fd7e..9488ca80b 100644 --- a/panels/display/cc-display-panel.c +++ b/panels/display/cc-display-panel.c @@ -29,7 +29,8 @@ #include <gdesktop-enums.h> #include <math.h> -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include <libupower-glib/upower.h> #include "cc-display-config-manager-dbus.h" @@ -87,6 +88,8 @@ struct _CcDisplayPanelPrivate GtkWidget *main_titlebar; GtkWidget *apply_titlebar; + GtkWidget *apply_titlebar_apply; + GtkWidget *apply_titlebar_warning; }; typedef struct @@ -283,6 +286,8 @@ reset_titlebar (CcDisplayPanel *self) } g_clear_object (&priv->apply_titlebar); + g_clear_object (&priv->apply_titlebar_apply); + g_clear_object (&priv->apply_titlebar_warning); } static void @@ -2590,47 +2595,59 @@ on_toplevel_key_press (GtkWidget *button, } static void -show_apply_titlebar (CcDisplayPanel *panel) +show_apply_titlebar (CcDisplayPanel *panel, gboolean is_applicable) { CcDisplayPanelPrivate *priv = panel->priv; - GtkWidget *header, *button, *toplevel; GtkSizeGroup *size_group; - if (priv->apply_titlebar) - return; + if (!priv->apply_titlebar) + { + GtkWidget *header, *button, *toplevel; + priv->apply_titlebar = header = gtk_header_bar_new (); - priv->apply_titlebar = header = gtk_header_bar_new (); - gtk_header_bar_set_title (GTK_HEADER_BAR (header), _("Apply Changes?")); + size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); - size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + button = gtk_button_new_with_mnemonic (_("_Cancel")); + gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button); + gtk_size_group_add_widget (size_group, button); + g_signal_connect_object (button, "clicked", G_CALLBACK (on_screen_changed), + panel, G_CONNECT_SWAPPED); - button = gtk_button_new_with_mnemonic (_("_Cancel")); - gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button); - gtk_size_group_add_widget (size_group, button); - g_signal_connect_object (button, "clicked", G_CALLBACK (on_screen_changed), - panel, G_CONNECT_SWAPPED); + toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel))); + g_signal_connect_object (toplevel, "key-press-event", G_CALLBACK (on_toplevel_key_press), + button, G_CONNECT_SWAPPED); - toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel))); - g_signal_connect_object (toplevel, "key-press-event", G_CALLBACK (on_toplevel_key_press), - button, G_CONNECT_SWAPPED); + priv->apply_titlebar_apply = button = gtk_button_new_with_mnemonic (_("_Apply")); + gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button); + gtk_size_group_add_widget (size_group, button); + g_signal_connect_object (button, "clicked", G_CALLBACK (apply_current_configuration), + panel, G_CONNECT_SWAPPED); + gtk_style_context_add_class (gtk_widget_get_style_context (button), + GTK_STYLE_CLASS_SUGGESTED_ACTION); - button = gtk_button_new_with_mnemonic (_("_Apply")); - gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button); - gtk_size_group_add_widget (size_group, button); - g_signal_connect_object (button, "clicked", G_CALLBACK (apply_current_configuration), - panel, G_CONNECT_SWAPPED); - gtk_style_context_add_class (gtk_widget_get_style_context (button), - GTK_STYLE_CLASS_SUGGESTED_ACTION); + gtk_widget_show_all (header); + g_object_unref (size_group); - gtk_widget_show_all (header); - g_object_unref (size_group); + header = gtk_window_get_titlebar (GTK_WINDOW (toplevel)); + if (header) + priv->main_titlebar = g_object_ref (header); - header = gtk_window_get_titlebar (GTK_WINDOW (toplevel)); - if (header) - priv->main_titlebar = g_object_ref (header); + gtk_window_set_titlebar (GTK_WINDOW (toplevel), priv->apply_titlebar); + g_object_ref (priv->apply_titlebar); + g_object_ref (priv->apply_titlebar_apply); + } - gtk_window_set_titlebar (GTK_WINDOW (toplevel), priv->apply_titlebar); - g_object_ref (priv->apply_titlebar); + if (is_applicable) + { + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->apply_titlebar), _("Apply Changes?")); + gtk_header_bar_set_subtitle (GTK_HEADER_BAR (priv->apply_titlebar), NULL); + } + else + { + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->apply_titlebar), _("Changes Cannot be Applied")); + gtk_header_bar_set_subtitle (GTK_HEADER_BAR (priv->apply_titlebar), _("This could be due to hardware limitations.")); + } + gtk_widget_set_sensitive (priv->apply_titlebar_apply, is_applicable); } static void @@ -2640,12 +2657,6 @@ update_apply_button (CcDisplayPanel *panel) gboolean config_equal; CcDisplayConfig *applied_config; - if (!cc_display_config_is_applicable (priv->current_config)) - { - reset_titlebar (panel); - return; - } - applied_config = cc_display_config_manager_get_current (priv->manager); config_equal = cc_display_config_equal (priv->current_config, @@ -2655,7 +2666,7 @@ update_apply_button (CcDisplayPanel *panel) if (config_equal) reset_titlebar (panel); else - show_apply_titlebar (panel); + show_apply_titlebar (panel, cc_display_config_is_applicable (priv->current_config)); } static void @@ -3107,7 +3118,7 @@ shell_proxy_ready (GObject *source, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (!proxy) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -3326,17 +3337,16 @@ cc_display_panel_init (CcDisplayPanel *self) g_signal_connect (self, "map", G_CALLBACK (mapped_cb), NULL); self->priv->shell_cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - "org.gnome.Shell", - "/org/gnome/Shell", - "org.gnome.Shell", - self->priv->shell_cancellable, - (GAsyncReadyCallback) shell_proxy_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + "org.gnome.Shell", + "/org/gnome/Shell", + "org.gnome.Shell", + self->priv->shell_cancellable, + (GAsyncReadyCallback) shell_proxy_ready, + self); g_bus_get (G_BUS_TYPE_SESSION, self->priv->shell_cancellable, diff --git a/panels/display/cc-night-light-dialog.c b/panels/display/cc-night-light-dialog.c index a2bbc683e..55fca2429 100644 --- a/panels/display/cc-night-light-dialog.c +++ b/panels/display/cc-night-light-dialog.c @@ -27,6 +27,8 @@ #include "cc-night-light-dialog.h" #include "cc-night-light-widget.h" +#include "shell/cc-object-storage.h" + struct _CcNightLightDialog { GObject parent; GtkBuilder *builder; @@ -77,11 +79,11 @@ cc_night_light_dialog_finalize (GObject *object) self->main_window = NULL; } - g_object_unref (self->builder); - g_object_unref (self->proxy_color); - g_object_unref (self->proxy_color_props); - g_object_unref (self->settings_display); - g_object_unref (self->settings_clock); + g_clear_object (&self->builder); + g_clear_object (&self->proxy_color); + g_clear_object (&self->proxy_color_props); + g_clear_object (&self->settings_display); + g_clear_object (&self->settings_clock); if (self->timer_id > 0) g_source_remove (self->timer_id); @@ -384,15 +386,21 @@ static void dialog_got_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcNightLightDialog *self = (CcNightLightDialog *) user_data; + GDBusProxy *proxy; g_autoptr(GError) error = NULL; - self->proxy_color = g_dbus_proxy_new_for_bus_finish (res, &error); - if (self->proxy_color == NULL) + + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); + if (proxy == NULL) { - g_warning ("failed to connect to g-s-d: %s", error->message); + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("failed to connect to g-s-d: %s", error->message); return; } - g_signal_connect (self->proxy_color, "g-properties-changed", - G_CALLBACK (dialog_color_properties_changed_cb), self); + + self->proxy_color = proxy; + + g_signal_connect_object (self->proxy_color, "g-properties-changed", + G_CALLBACK (dialog_color_properties_changed_cb), self, 0); dialog_update_state (self); self->timer_id = g_timeout_add_seconds (10, dialog_tick_cb, self); } @@ -401,13 +409,18 @@ static void dialog_got_proxy_props_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcNightLightDialog *self = (CcNightLightDialog *) user_data; + GDBusProxy *proxy; g_autoptr(GError) error = NULL; - self->proxy_color_props = g_dbus_proxy_new_for_bus_finish (res, &error); - if (self->proxy_color_props == NULL) + + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); + if (proxy == NULL) { - g_warning ("failed to connect to g-s-d: %s", error->message); + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("failed to connect to g-s-d: %s", error->message); return; } + + self->proxy_color_props = proxy; } static gboolean @@ -669,25 +682,23 @@ cc_night_light_dialog_init (CcNightLightDialog *self) gtk_box_pack_start (box, self->night_light_widget, FALSE, FALSE, 0); gtk_widget_show (self->night_light_widget); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Color", - "/org/gnome/SettingsDaemon/Color", - "org.gnome.SettingsDaemon.Color", - self->cancellable, - dialog_got_proxy_cb, - self); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Color", - "/org/gnome/SettingsDaemon/Color", - "org.freedesktop.DBus.Properties", - self->cancellable, - dialog_got_proxy_props_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Color", + "/org/gnome/SettingsDaemon/Color", + "org.gnome.SettingsDaemon.Color", + self->cancellable, + dialog_got_proxy_cb, + self); + + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Color", + "/org/gnome/SettingsDaemon/Color", + "org.freedesktop.DBus.Properties", + self->cancellable, + dialog_got_proxy_props_cb, + self); /* clock settings_display */ self->settings_clock = g_settings_new (CLOCK_SCHEMA); diff --git a/panels/display/meson.build b/panels/display/meson.build index ee33b4355..d341758f8 100644 --- a/panels/display/meson.build +++ b/panels/display/meson.build @@ -58,7 +58,7 @@ cflags += [ panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) diff --git a/panels/info/cc-info-overview-panel.c b/panels/info/cc-info-overview-panel.c index 411c1c905..19f785a36 100644 --- a/panels/info/cc-info-overview-panel.c +++ b/panels/info/cc-info-overview-panel.c @@ -21,7 +21,8 @@ #include <config.h> -#include "shell/cc-hostname-entry.h" +#include "shell/cc-object-storage.h" +#include "cc-hostname-entry.h" #include "cc-info-resources.h" #include "info-cleanup.h" @@ -235,13 +236,12 @@ get_renderer_from_session (void) char *renderer; g_autoptr(GError) error = NULL; - session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - NULL, &error); + session_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, &error); if (error != NULL) { g_warning ("Unable to connect to create a proxy for org.gnome.SessionManager: %s", @@ -302,13 +302,12 @@ has_dual_gpu (void) gboolean ret; g_autoptr(GError) error = NULL; - switcheroo_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "net.hadess.SwitcherooControl", - "/net/hadess/SwitcherooControl", - "net.hadess.SwitcherooControl", - NULL, &error); + switcheroo_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "net.hadess.SwitcherooControl", + "/net/hadess/SwitcherooControl", + "net.hadess.SwitcherooControl", + NULL, &error); if (switcheroo_proxy == NULL) { g_debug ("Unable to connect to create a proxy for net.hadess.SwitcherooControl: %s", @@ -720,14 +719,13 @@ info_overview_panel_setup_virt (CcInfoOverviewPanel *self) g_autoptr(GVariant) variant = NULL; GVariant *inner; - systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1", - NULL, - &error); + systemd_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1", + NULL, + &error); if (systemd_proxy == NULL) { diff --git a/panels/info/meson.build b/panels/info/meson.build index 13015b96c..dc1c11cb2 100644 --- a/panels/info/meson.build +++ b/panels/info/meson.build @@ -64,32 +64,14 @@ deps = common_deps + [ dependency('libgtop-2.0') ] -panels_libs += static_library( +info_panel_lib = static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) - -test_name = 'test-info-cleanup' - -sources = files( - 'info-cleanup.c', - test_name + '.c' -) - -cflags += ['-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir())] - -exe = executable( - test_name, - sources, - include_directories: top_inc, - dependencies: deps, - c_args: cflags -) - -test(name, exe) +panels_libs += info_panel_lib # FIXME: workaround for updating different sources code input_dir = join_paths(meson.source_root(), '..', 'gnome-settings-daemon', 'plugins', 'housekeeping') diff --git a/panels/keyboard/shortcut-editor.ui b/panels/keyboard/shortcut-editor.ui index 74898ab79..081552955 100644 --- a/panels/keyboard/shortcut-editor.ui +++ b/panels/keyboard/shortcut-editor.ui @@ -255,7 +255,7 @@ <child> <object class="GtkButton" id="change_custom_shortcut_button"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> <property name="label" translatable="yes">Set Shortcut…</property> <signal name="clicked" handler="change_custom_shortcut_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" /> </object> diff --git a/panels/meson.build b/panels/meson.build index d671c4775..37a343642 100644 --- a/panels/meson.build +++ b/panels/meson.build @@ -28,6 +28,7 @@ endif if host_is_linux_not_s390 panels += [ 'bluetooth', + 'thunderbolt', 'wacom' ] endif diff --git a/panels/mouse/gnome-mouse-properties.c b/panels/mouse/gnome-mouse-properties.c index 4d0920b2d..2a22b4815 100644 --- a/panels/mouse/gnome-mouse-properties.c +++ b/panels/mouse/gnome-mouse-properties.c @@ -35,7 +35,7 @@ #include "gnome-mouse-properties.h" #include "gsd-input-helper.h" #include "gsd-device-manager.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-mouse-caps-helper.h" #include <sys/types.h> diff --git a/panels/network/cc-network-panel.c b/panels/network/cc-network-panel.c index 51ea823f7..a03ab56da 100644 --- a/panels/network/cc-network-panel.c +++ b/panels/network/cc-network-panel.c @@ -23,6 +23,8 @@ #include <glib/gi18n.h> #include <stdlib.h> +#include "shell/cc-object-storage.h" + #include "cc-network-panel.h" #include "cc-network-resources.h" @@ -554,6 +556,8 @@ panel_remove_device (CcNetworkPanel *panel, NMDevice *device) if (object == NULL) return; + /* NMObject will not fire the "removed" signal, so handle the UI removal explicitly */ + object_removed_cb (object, panel); g_ptr_array_remove (panel->devices, object); /* update vpn widgets */ @@ -876,16 +880,24 @@ cc_network_panel_init (CcNetworkPanel *panel) /* add the virtual proxy device */ panel_add_proxy_device (panel); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) { + NMClient *client = nm_client_new (NULL, NULL); + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); + g_object_unref (client); + } + /* use NetworkManager client */ - panel->client = nm_client_new (NULL, NULL); - g_signal_connect (panel->client, "notify::nm-running" , - G_CALLBACK (manager_running), panel); - g_signal_connect (panel->client, "notify::active-connections", - G_CALLBACK (active_connections_changed), panel); - g_signal_connect (panel->client, "device-added", - G_CALLBACK (device_added_cb), panel); - g_signal_connect (panel->client, "device-removed", - G_CALLBACK (device_removed_cb), panel); + panel->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); + + g_signal_connect_object (panel->client, "notify::nm-running" , + G_CALLBACK (manager_running), panel, 0); + g_signal_connect_object (panel->client, "notify::active-connections", + G_CALLBACK (active_connections_changed), panel, 0); + g_signal_connect_object (panel->client, "device-added", + G_CALLBACK (device_added_cb), panel, 0); + g_signal_connect_object (panel->client, "device-removed", + G_CALLBACK (device_removed_cb), panel, 0); /* Setup ModemManager client */ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); @@ -907,8 +919,8 @@ cc_network_panel_init (CcNetworkPanel *panel) } /* add remote settings such as VPN settings as virtual devices */ - g_signal_connect (panel->client, NM_CLIENT_CONNECTION_ADDED, - G_CALLBACK (notify_connection_added_cb), panel); + g_signal_connect_object (panel->client, NM_CLIENT_CONNECTION_ADDED, + G_CALLBACK (notify_connection_added_cb), panel, 0); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel)); g_signal_connect_after (toplevel, "map", G_CALLBACK (on_toplevel_map), panel); diff --git a/panels/network/cc-wifi-panel.c b/panels/network/cc-wifi-panel.c index 2c1cd17b7..d785bad0d 100644 --- a/panels/network/cc-wifi-panel.c +++ b/panels/network/cc-wifi-panel.c @@ -23,7 +23,8 @@ #include "net-device-wifi.h" #include "network-dialogs.h" -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include <glib/gi18n.h> #include <NetworkManager.h> @@ -421,7 +422,7 @@ rfkill_proxy_acquired_cb (GObject *source_object, GError *error; error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (error) { @@ -618,37 +619,47 @@ cc_wifi_panel_init (CcWifiPanel *self) self->cancellable = g_cancellable_new (); self->devices = g_ptr_array_new_with_free_func (g_object_unref); - /* Load NetworkManager */ - self->client = nm_client_new (NULL, NULL); - - g_signal_connect (self->client, - "device-added", - G_CALLBACK (device_added_cb), - self); - - g_signal_connect (self->client, - "device-removed", - G_CALLBACK (device_removed_cb), - self); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) + { + NMClient *client = nm_client_new (NULL, NULL); + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); + g_object_unref (client); + } - g_signal_connect (self->client, - "notify::wireless-enabled", - G_CALLBACK (wireless_enabled_cb), - self); + /* Load NetworkManager */ + self->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); + + g_signal_connect_object (self->client, + "device-added", + G_CALLBACK (device_added_cb), + self, + 0); + + g_signal_connect_object (self->client, + "device-removed", + G_CALLBACK (device_removed_cb), + self, + 0); + + g_signal_connect_object (self->client, + "notify::wireless-enabled", + G_CALLBACK (wireless_enabled_cb), + self, + 0); /* Load Wi-Fi devices */ load_wifi_devices (self); /* Acquire Airplane Mode proxy */ - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - self->cancellable, - rfkill_proxy_acquired_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + self->cancellable, + rfkill_proxy_acquired_cb, + self); /* Handle comment-line arguments after loading devices */ handle_argv (self); diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c index 400dc433d..100a3b4e3 100644 --- a/panels/network/connection-editor/ce-page-ip4.c +++ b/panels/network/connection-editor/ce-page-ip4.c @@ -28,7 +28,7 @@ #include <glib/gi18n.h> #include <NetworkManager.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "ce-page-ip4.h" #include "ui-helpers.h" diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c index 995197504..35653f3a1 100644 --- a/panels/network/connection-editor/ce-page-ip6.c +++ b/panels/network/connection-editor/ce-page-ip6.c @@ -28,7 +28,7 @@ #include <glib/gi18n.h> #include <NetworkManager.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "ce-page-ip6.h" #include "ui-helpers.h" diff --git a/panels/network/connection-editor/meson.build b/panels/network/connection-editor/meson.build index 616bafdb1..9ba9b3784 100644 --- a/panels/network/connection-editor/meson.build +++ b/panels/network/connection-editor/meson.build @@ -40,7 +40,7 @@ sources += gnome.compile_resources( libconnection_editor = static_library( name, sources: sources, - include_directories: [top_inc, wireless_security_inc], + include_directories: [top_inc, common_inc, wireless_security_inc], dependencies: deps, c_args: cflags, link_with: libwireless_security diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c index 1b268044a..556b57fb8 100644 --- a/panels/network/connection-editor/net-connection-editor.c +++ b/panels/network/connection-editor/net-connection-editor.c @@ -26,7 +26,7 @@ #include <NetworkManager.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "net-connection-editor.h" #include "net-connection-editor-resources.h" #include "ce-page-details.h" diff --git a/panels/network/meson.build b/panels/network/meson.build index 8036d79f8..2ec4fbf71 100644 --- a/panels/network/meson.build +++ b/panels/network/meson.build @@ -69,11 +69,12 @@ sources += gnome.compile_resources( cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) -panels_libs += static_library( +network_panel_lib = static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [top_inc, common_inc], dependencies: deps, c_args: cflags, link_with: libconnection_editor ) +panels_libs += network_panel_lib diff --git a/panels/network/net-device-ethernet.c b/panels/network/net-device-ethernet.c index 603ad6c86..afb544352 100644 --- a/panels/network/net-device-ethernet.c +++ b/panels/network/net-device-ethernet.c @@ -28,7 +28,7 @@ #include "panel-common.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "connection-editor/net-connection-editor.h" #include "connection-editor/ce-page.h" @@ -551,8 +551,8 @@ device_ethernet_constructed (GObject *object) G_CALLBACK (add_profile), device); client = net_object_get_client (NET_OBJECT (object)); - g_signal_connect (client, NM_CLIENT_CONNECTION_ADDED, - G_CALLBACK (client_connection_added_cb), object); + g_signal_connect_object (client, NM_CLIENT_CONNECTION_ADDED, + G_CALLBACK (client_connection_added_cb), object, 0); g_signal_connect_object (client, NM_CLIENT_CONNECTION_REMOVED, G_CALLBACK (connection_removed), device, 0); diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index 313e9ab8c..5b9a77a1f 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -29,8 +29,8 @@ #include <NetworkManager.h> #include <polkit/polkit.h> -#include "shell/list-box-helper.h" -#include "shell/hostname-helper.h" +#include "list-box-helper.h" +#include "hostname-helper.h" #include "network-dialogs.h" #include "panel-common.h" diff --git a/panels/notifications/cc-edit-dialog.c b/panels/notifications/cc-edit-dialog.c index 778c18c86..bdac5a4f9 100644 --- a/panels/notifications/cc-edit-dialog.c +++ b/panels/notifications/cc-edit-dialog.c @@ -26,7 +26,7 @@ #include <gio/gio.h> #include <gio/gdesktopappinfo.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-notifications-panel.h" #include "cc-edit-dialog.h" diff --git a/panels/notifications/cc-notifications-panel.c b/panels/notifications/cc-notifications-panel.c index 1265b5b6f..9baa5a80e 100644 --- a/panels/notifications/cc-notifications-panel.c +++ b/panels/notifications/cc-notifications-panel.c @@ -25,7 +25,8 @@ #include <gio/gio.h> #include <gio/gdesktopappinfo.h> -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include "cc-notifications-panel.h" #include "cc-notifications-resources.h" #include "cc-edit-dialog.h" @@ -150,7 +151,7 @@ on_perm_store_ready (GObject *source_object, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -241,15 +242,14 @@ cc_notifications_panel_init (CcNotificationsPanel *panel) gtk_widget_show (w); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.impl.portal.PermissionStore", - "/org/freedesktop/impl/portal/PermissionStore", - "org.freedesktop.impl.portal.PermissionStore", - panel->apps_load_cancellable, - on_perm_store_ready, - panel); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.impl.portal.PermissionStore", + "/org/freedesktop/impl/portal/PermissionStore", + "org.freedesktop.impl.portal.PermissionStore", + panel->apps_load_cancellable, + on_perm_store_ready, + panel); } static const char * diff --git a/panels/notifications/meson.build b/panels/notifications/meson.build index 97a623fcb..55adee3b5 100644 --- a/panels/notifications/meson.build +++ b/panels/notifications/meson.build @@ -40,7 +40,7 @@ cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: common_deps, c_args: cflags ) diff --git a/panels/online-accounts/cc-online-accounts-panel.c b/panels/online-accounts/cc-online-accounts-panel.c index 835810003..a89d249c0 100644 --- a/panels/online-accounts/cc-online-accounts-panel.c +++ b/panels/online-accounts/cc-online-accounts-panel.c @@ -32,7 +32,7 @@ #include "cc-online-accounts-panel.h" #include "cc-online-accounts-resources.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" struct _CcGoaPanel { @@ -402,6 +402,22 @@ cc_goa_panel_finalize (GObject *object) { CcGoaPanel *panel = CC_GOA_PANEL (object); + if (panel->removed_object != NULL) + { + g_autoptr(GError) error = NULL; + goa_account_call_remove_sync (goa_object_peek_account (panel->removed_object), + NULL, /* GCancellable */ + &error); + + if (error != NULL) + { + g_warning ("Error removing account: %s (%s, %d)", + error->message, + g_quark_to_string (error->domain), + error->code); + } + } + g_clear_object (&panel->client); G_OBJECT_CLASS (cc_goa_panel_parent_class)->finalize (object); diff --git a/panels/online-accounts/meson.build b/panels/online-accounts/meson.build index eea6f89ec..1f899e881 100644 --- a/panels/online-accounts/meson.build +++ b/panels/online-accounts/meson.build @@ -39,7 +39,7 @@ cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index f9b67a458..7b7c4a24d 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -29,7 +29,8 @@ #include <NetworkManager.h> #endif -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include "cc-power-panel.h" #include "cc-power-resources.h" @@ -567,6 +568,18 @@ kind_to_description (UpDeviceKind kind) g_assert_not_reached (); } +static UpDeviceLevel +get_battery_level (UpDevice *device) +{ + UpDeviceLevel battery_level; + + if (!g_object_class_find_property (G_OBJECT_CLASS (G_OBJECT_GET_CLASS (device)), "battery-level")) + return UP_DEVICE_LEVEL_NONE; + + g_object_get (device, "battery-level", &battery_level, NULL); + return battery_level; +} + static void add_device (CcPowerPanel *panel, UpDevice *device) { @@ -581,9 +594,9 @@ add_device (CcPowerPanel *panel, UpDevice *device) GString *description; gdouble percentage; gchar *name; - gchar *s; gboolean show_caution = FALSE; gboolean is_present; + UpDeviceLevel battery_level; name = NULL; g_object_get (device, @@ -593,6 +606,7 @@ add_device (CcPowerPanel *panel, UpDevice *device) "model", &name, "is-present", &is_present, NULL); + battery_level = get_battery_level (device); if (!is_present) { @@ -667,9 +681,20 @@ add_device (CcPowerPanel *panel, UpDevice *device) box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_widget_set_margin_start (box2, 20); gtk_widget_set_margin_end (box2, 20); - s = g_strdup_printf ("%d%%", (int)percentage); - widget = gtk_label_new (s); - g_free (s); + + if (battery_level == UP_DEVICE_LEVEL_NONE) + { + gchar *s; + + s = g_strdup_printf ("%d%%", (int)(percentage + 0.5)); + widget = gtk_label_new (s); + g_free (s); + } + else + { + widget = gtk_label_new (""); + } + gtk_widget_set_halign (widget, GTK_ALIGN_END); gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL); gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, TRUE, 0); @@ -1083,7 +1108,7 @@ got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_da CcPowerPanel *self; GDBusProxy *screen_proxy; - screen_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + screen_proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (screen_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1096,8 +1121,8 @@ got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_da self->priv->screen_proxy = screen_proxy; /* we want to change the bar if the user presses brightness buttons */ - g_signal_connect (screen_proxy, "g-properties-changed", - G_CALLBACK (on_screen_property_change), self); + g_signal_connect_object (screen_proxy, "g-properties-changed", + G_CALLBACK (on_screen_property_change), self, 0); sync_screen_brightness (self); als_enabled_state_changed (self); @@ -1120,7 +1145,7 @@ got_kbd_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) CcPowerPanel *self; GDBusProxy *kbd_proxy; - kbd_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + kbd_proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (kbd_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1133,8 +1158,8 @@ got_kbd_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) self->priv->kbd_proxy = kbd_proxy; /* we want to change the bar if the user presses brightness buttons */ - g_signal_connect (kbd_proxy, "g-properties-changed", - G_CALLBACK (on_kbd_property_change), self); + g_signal_connect_object (kbd_proxy, "g-properties-changed", + G_CALLBACK (on_kbd_property_change), self, 0); sync_kbd_brightness (self); } @@ -1163,6 +1188,51 @@ combo_time_changed_cb (GtkWidget *widget, CcPowerPanel *self) g_settings_set_int (self->priv->gsd_settings, key, value); } +/* Copied from src/properties/bacon-video-widget-properties.c + * in totem */ +static char * +time_to_string_text (gint64 msecs) +{ + char *secs, *mins, *hours, *string; + int sec, min, hour, _time; + + _time = (int) (msecs / 1000); + sec = _time % 60; + _time = _time - sec; + min = (_time % (60*60)) / 60; + _time = _time - (min * 60); + hour = _time / (60*60); + + hours = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d hour", "%d hours", hour), hour); + + mins = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", + "%d minutes", min), min); + + secs = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d second", + "%d seconds", sec), sec); + + if (hour > 0) + { + /* 5 hours 2 minutes 12 seconds */ + string = g_strdup_printf (C_("time", "%s %s %s"), hours, mins, secs); + } else if (min > 0) { + /* 2 minutes 12 seconds */ + string = g_strdup_printf (C_("time", "%s %s"), mins, secs); + } else if (sec > 0) { + /* 10 seconds */ + string = g_strdup (secs); + } else { + /* 0 seconds */ + string = g_strdup (_("0 seconds")); + } + + g_free (hours); + g_free (mins); + g_free (secs); + + return string; +} + static void set_value_for_combo (GtkComboBox *combo_box, gint value) { @@ -1184,11 +1254,27 @@ set_value_for_combo (GtkComboBox *combo_box, gint value) gtk_tree_model_get (model, &iter, ACTION_MODEL_VALUE, &value_tmp, -1); - if (value == value_tmp) + if (value_tmp == value) { gtk_combo_box_set_active_iter (combo_box, &iter); return; } + else if (value_tmp > value) + { + GtkTreeIter new; + char *text; + + /* This is an unlisted value, add it to the drop-down */ + gtk_list_store_insert_before (GTK_LIST_STORE (model), &new, &iter); + text = time_to_string_text (value * 1000); + gtk_list_store_set (GTK_LIST_STORE (model), &new, + ACTION_MODEL_TEXT, text, + ACTION_MODEL_VALUE, value, + -1); + g_free (text); + gtk_combo_box_set_active_iter (combo_box, &new); + return; + } last = iter; } while (gtk_tree_model_iter_next (model, &iter)); @@ -1441,12 +1527,30 @@ nm_device_changed (NMClient *client, } static void +setup_nm_client (CcPowerPanel *self, + NMClient *client) +{ + CcPowerPanelPrivate *priv = self->priv; + + priv->nm_client = client; + + g_signal_connect_object (priv->nm_client, "notify", + G_CALLBACK (nm_client_state_changed), self, 0); + g_signal_connect_object (priv->nm_client, "device-added", + G_CALLBACK (nm_device_changed), self, 0); + g_signal_connect_object (priv->nm_client, "device-removed", + G_CALLBACK (nm_device_changed), self, 0); + + nm_client_state_changed (priv->nm_client, NULL, self); + nm_device_changed (priv->nm_client, NULL, self); +} + +static void nm_client_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcPowerPanel *self; - CcPowerPanelPrivate *priv; NMClient *client; GError *error = NULL; @@ -1467,18 +1571,12 @@ nm_client_ready_cb (GObject *source_object, } self = user_data; - priv = self->priv; - priv->nm_client = client; - g_signal_connect (priv->nm_client, "notify", - G_CALLBACK (nm_client_state_changed), self); - g_signal_connect (priv->nm_client, "device-added", - G_CALLBACK (nm_device_changed), self); - g_signal_connect (priv->nm_client, "device-removed", - G_CALLBACK (nm_device_changed), self); + /* Setup the client */ + setup_nm_client (self, client); - nm_client_state_changed (priv->nm_client, NULL, self); - nm_device_changed (priv->nm_client, NULL, self); + /* Store the object in the cache too */ + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); } #endif @@ -1648,13 +1746,12 @@ iio_proxy_appeared_cb (GDBusConnection *connection, GError *error = NULL; self->priv->iio_proxy = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "net.hadess.SensorProxy", - "/net/hadess/SensorProxy", - "net.hadess.SensorProxy", - NULL, &error); + cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "net.hadess.SensorProxy", + "/net/hadess/SensorProxy", + "net.hadess.SensorProxy", + NULL, &error); if (error != NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1887,29 +1984,35 @@ add_power_saving_section (CcPowerPanel *self) g_signal_connect (G_OBJECT (priv->mobile_switch), "notify::active", G_CALLBACK (mobile_switch_changed), self); - nm_client_new_async (priv->cancellable, nm_client_ready_cb, self); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) + setup_nm_client (self, cc_object_storage_get_object (CC_OBJECT_NMCLIENT)); + else + nm_client_new_async (priv->cancellable, nm_client_ready_cb, self); g_signal_connect (G_OBJECT (priv->wifi_switch), "notify::active", G_CALLBACK (wifi_switch_changed), self); #endif #ifdef HAVE_BLUETOOTH - priv->bt_rfkill = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - NULL, NULL); + + priv->bt_rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + NULL, + NULL); + if (priv->bt_rfkill) { - priv->bt_properties = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.freedesktop.DBus.Properties", - NULL, NULL); + priv->bt_properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.freedesktop.DBus.Properties", + NULL, + NULL); } row = no_prelight_row_new (); @@ -1944,8 +2047,8 @@ add_power_saving_section (CcPowerPanel *self) gtk_widget_show_all (box); gtk_widget_set_no_show_all (row, TRUE); priv->bt_row = row; - g_signal_connect_swapped (G_OBJECT (priv->bt_rfkill), "g-properties-changed", - G_CALLBACK (bt_powered_state_changed), self); + g_signal_connect_object (priv->bt_rfkill, "g-properties-changed", + G_CALLBACK (bt_powered_state_changed), self, G_CONNECT_SWAPPED); g_signal_connect (G_OBJECT (priv->bt_switch), "notify::active", G_CALLBACK (bt_switch_changed), self); @@ -2509,24 +2612,22 @@ cc_power_panel_init (CcPowerPanel *self) priv->cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Power", - "/org/gnome/SettingsDaemon/Power", - "org.gnome.SettingsDaemon.Power.Screen", - priv->cancellable, - got_screen_proxy_cb, - self); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Power", - "/org/gnome/SettingsDaemon/Power", - "org.gnome.SettingsDaemon.Power.Keyboard", - priv->cancellable, - got_kbd_proxy_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Screen", + priv->cancellable, + got_screen_proxy_cb, + self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Keyboard", + priv->cancellable, + got_kbd_proxy_cb, + self); priv->chassis_type = get_chassis_type (priv->cancellable); diff --git a/panels/power/meson.build b/panels/power/meson.build index 9a27e93bd..d4091eaa1 100644 --- a/panels/power/meson.build +++ b/panels/power/meson.build @@ -47,7 +47,7 @@ endif panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c index 55a1682b4..877028863 100644 --- a/panels/printers/cc-printers-panel.c +++ b/panels/printers/cc-printers-panel.c @@ -18,6 +18,8 @@ #include <config.h> +#include "shell/cc-object-storage.h" + #include "cc-printers-panel.h" #include "cc-printers-resources.h" #include "pp-printer.h" @@ -608,14 +610,13 @@ attach_to_cups_notifier_cb (GObject *source_object, priv->subscription_renewal_id = g_timeout_add_seconds (RENEW_INTERVAL, renew_subscription, self); - priv->cups_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - 0, - NULL, - CUPS_DBUS_NAME, - CUPS_DBUS_PATH, - CUPS_DBUS_INTERFACE, - NULL, - &error); + priv->cups_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + CUPS_DBUS_NAME, + CUPS_DBUS_PATH, + CUPS_DBUS_INTERFACE, + NULL, + &error); if (!priv->cups_proxy) { @@ -1229,14 +1230,13 @@ connection_test_cb (GObject *source_object, gpointer user_data) { CcPrintersPanelPrivate *priv; - CcPrintersPanel *self = (CcPrintersPanel*) user_data; + CcPrintersPanel *self; gboolean success; PpCups *cups = PP_CUPS (source_object); g_autoptr(GError) error = NULL; - priv = self->priv; - success = pp_cups_connection_test_finish (cups, result, &error); + g_object_unref (cups); if (error != NULL) { @@ -1244,15 +1244,18 @@ connection_test_cb (GObject *source_object, { g_warning ("Could not test connection: %s", error->message); } + + return; } + self = CC_PRINTERS_PANEL (user_data); + priv = self->priv; + if (!success) { priv->cups_status_check_id = g_timeout_add_seconds (CUPS_STATUS_CHECK_INTERVAL, cups_status_check, self); } - - g_object_unref (cups); } static void diff --git a/panels/printers/meson.build b/panels/printers/meson.build index 6be8590c7..e3d1e8414 100644 --- a/panels/printers/meson.build +++ b/panels/printers/meson.build @@ -66,34 +66,12 @@ deps = common_deps + [ cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) -panels_libs += static_library( +printers_panel_lib = static_library( cappletname, sources: sources, include_directories: [top_inc, common_inc, shell_inc], dependencies: deps, c_args: cflags ) +panels_libs += [ printers_panel_lib ] -test_units = [ - 'test-canonicalization', - 'test-shift' -] - -sources = files( - 'pp-print-device.c', - 'pp-utils.c' -) - -cflags += '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()) - -foreach unit: test_units - exe = executable( - unit, - [unit + '.c'] + sources, - include_directories: top_inc, - dependencies: deps, - c_args: cflags - ) - - test(unit, exe) -endforeach diff --git a/panels/printers/new-printer-dialog.ui b/panels/printers/new-printer-dialog.ui index 0e9a8110a..437220542 100644 --- a/panels/printers/new-printer-dialog.ui +++ b/panels/printers/new-printer-dialog.ui @@ -153,6 +153,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="transition-type">none</property> + <property name="has_focus">True</property> <style> <class name="view"/> </style> diff --git a/panels/printers/pp-details-dialog.c b/panels/printers/pp-details-dialog.c index 5db3798ad..d5a56f168 100644 --- a/panels/printers/pp-details-dialog.c +++ b/panels/printers/pp-details-dialog.c @@ -33,7 +33,6 @@ #include <cups/cups.h> #include <cups/ppd.h> -#include "cc-editable-entry.h" #include "pp-details-dialog.h" #include "pp-ppd-selection-dialog.h" #include "pp-printer.h" diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c index dfab7eb42..f1331d6d6 100644 --- a/panels/printers/pp-jobs-dialog.c +++ b/panels/printers/pp-jobs-dialog.c @@ -31,7 +31,7 @@ #include <cups/cups.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "pp-jobs-dialog.h" #include "pp-utils.h" #include "pp-job.h" diff --git a/panels/printers/pp-new-printer-dialog.c b/panels/printers/pp-new-printer-dialog.c index 7a15a455f..e7857fc01 100644 --- a/panels/printers/pp-new-printer-dialog.c +++ b/panels/printers/pp-new-printer-dialog.c @@ -506,6 +506,20 @@ authenticate_samba_server (GtkButton *button, } } +static gboolean +stack_key_press_cb (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + PpNewPrinterDialog *dialog = (PpNewPrinterDialog *) user_data; + PpNewPrinterDialogPrivate *priv = dialog->priv; + + gtk_widget_grab_focus (WID ("search-entry")); + gtk_main_do_event (event); + + return TRUE; +} + static void pp_new_printer_dialog_init (PpNewPrinterDialog *dialog) { @@ -556,6 +570,8 @@ pp_new_printer_dialog_init (PpNewPrinterDialog *dialog) widget = WID ("unlock-button"); g_signal_connect (widget, "clicked", G_CALLBACK (authenticate_samba_server), dialog); + g_signal_connect (WID ("stack"), "key-press-event", G_CALLBACK (stack_key_press_cb), dialog); + /* Authentication form widgets */ g_signal_connect (WID ("username-entry"), "changed", G_CALLBACK (auth_entries_changed), dialog); g_signal_connect (WID ("password-entry"), "changed", G_CALLBACK (auth_entries_changed), dialog); diff --git a/panels/privacy/cc-privacy-panel.c b/panels/privacy/cc-privacy-panel.c index 428dafef7..8735e33d0 100644 --- a/panels/privacy/cc-privacy-panel.c +++ b/panels/privacy/cc-privacy-panel.c @@ -18,7 +18,8 @@ * Author: Matthias Clasen <mclasen@redhat.com> */ -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include "cc-privacy-panel.h" #include "cc-privacy-resources.h" #include "cc-util.h" @@ -463,7 +464,7 @@ on_gclue_manager_ready (GObject *source_object, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -475,10 +476,11 @@ on_gclue_manager_ready (GObject *source_object, self = user_data; self->priv->gclue_manager = proxy; - g_signal_connect (self->priv->gclue_manager, - "g-properties-changed", - G_CALLBACK (on_gclue_manager_props_changed), - self); + g_signal_connect_object (self->priv->gclue_manager, + "g-properties-changed", + G_CALLBACK (on_gclue_manager_props_changed), + self, + 0); update_location_label (self); } @@ -783,7 +785,7 @@ on_perm_store_ready (GObject *source_object, GVariant *params; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -842,25 +844,23 @@ add_location (CcPrivacyPanel *self) g_free, g_object_unref); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.GeoClue2", - "/org/freedesktop/GeoClue2/Manager", - "org.freedesktop.GeoClue2.Manager", - priv->cancellable, - on_gclue_manager_ready, - self); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.impl.portal.PermissionStore", - "/org/freedesktop/impl/portal/PermissionStore", - "org.freedesktop.impl.portal.PermissionStore", - priv->cancellable, - on_perm_store_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.GeoClue2", + "/org/freedesktop/GeoClue2/Manager", + "org.freedesktop.GeoClue2.Manager", + priv->cancellable, + on_gclue_manager_ready, + self); + + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.impl.portal.PermissionStore", + "/org/freedesktop/impl/portal/PermissionStore", + "org.freedesktop.impl.portal.PermissionStore", + priv->cancellable, + on_perm_store_ready, + self); } static void diff --git a/panels/region/cc-format-chooser.c b/panels/region/cc-format-chooser.c index 4998de99d..2fed3f10e 100644 --- a/panels/region/cc-format-chooser.c +++ b/panels/region/cc-format-chooser.c @@ -27,7 +27,7 @@ #include <string.h> #include <glib/gi18n.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-common-language.h" #include "cc-util.h" diff --git a/panels/region/cc-input-chooser.c b/panels/region/cc-input-chooser.c index a5156ccbf..9f882cdb3 100644 --- a/panels/region/cc-input-chooser.c +++ b/panels/region/cc-input-chooser.c @@ -22,7 +22,7 @@ #define GNOME_DESKTOP_USE_UNSTABLE_API #include <libgnome-desktop/gnome-languages.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-common-language.h" #include "cc-util.h" #include "cc-input-chooser.h" diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c index 48c0d7ac0..5fdb35a25 100644 --- a/panels/region/cc-region-panel.c +++ b/panels/region/cc-region-panel.c @@ -26,7 +26,8 @@ #include <gtk/gtk.h> #include <polkit/polkit.h> -#include "shell/list-box-helper.h" +#include "shell/cc-object-storage.h" +#include "list-box-helper.h" #include "cc-region-panel.h" #include "cc-region-resources.h" #include "cc-language-chooser.h" @@ -1796,7 +1797,7 @@ session_proxy_ready (GObject *source, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (!proxy) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1832,15 +1833,14 @@ cc_region_panel_init (CcRegionPanel *self) priv->cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - priv->cancellable, - session_proxy_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + priv->cancellable, + session_proxy_ready, + self); setup_login_button (self); setup_language_section (self); diff --git a/panels/search/cc-search-locations-dialog.c b/panels/search/cc-search-locations-dialog.c index 3d2ec8a47..132754722 100644 --- a/panels/search/cc-search-locations-dialog.c +++ b/panels/search/cc-search-locations-dialog.c @@ -19,7 +19,7 @@ */ #include "cc-search-locations-dialog.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include <glib/gi18n.h> diff --git a/panels/search/cc-search-panel.c b/panels/search/cc-search-panel.c index 67e722556..7c5051ae2 100644 --- a/panels/search/cc-search-panel.c +++ b/panels/search/cc-search-panel.c @@ -21,7 +21,7 @@ #include "cc-search-panel.h" #include "cc-search-locations-dialog.h" #include "cc-search-resources.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include <gio/gdesktopappinfo.h> #include <glib/gi18n.h> diff --git a/panels/search/meson.build b/panels/search/meson.build index 0081674c4..f8663fb65 100644 --- a/panels/search/meson.build +++ b/panels/search/meson.build @@ -43,7 +43,7 @@ cflags += [ panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: common_deps, c_args: cflags ) diff --git a/panels/sharing/cc-sharing-networks.c b/panels/sharing/cc-sharing-networks.c index d703af5bc..672ac98d6 100644 --- a/panels/sharing/cc-sharing-networks.c +++ b/panels/sharing/cc-sharing-networks.c @@ -26,7 +26,7 @@ #include "cc-sharing-networks.h" #include "org.gnome.SettingsDaemon.Sharing.h" #include "gsd-sharing-enums.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" struct _CcSharingNetworksPrivate { GtkWidget *listbox; @@ -232,6 +232,7 @@ cc_sharing_networks_new_row (const char *uuid, /* Label */ w = gtk_label_new (network_name); + gtk_widget_set_margin_end (w, 12); gtk_container_add (GTK_CONTAINER (box), w); /* Remove button */ @@ -273,6 +274,7 @@ cc_sharing_networks_new_current_row (CcSharingNetworks *self) /* Label */ w = gtk_label_new (""); gtk_container_add (GTK_CONTAINER (box), w); + gtk_widget_set_margin_end (w, 12); self->priv->current_label = w; w = gtk_switch_new (); diff --git a/panels/sharing/cc-sharing-panel.c b/panels/sharing/cc-sharing-panel.c index 8b35c9a31..1352f7e8f 100644 --- a/panels/sharing/cc-sharing-panel.c +++ b/panels/sharing/cc-sharing-panel.c @@ -20,9 +20,9 @@ */ #include "cc-sharing-panel.h" -#include "shell/cc-hostname-entry.h" +#include "cc-hostname-entry.h" -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-sharing-resources.h" #include "vino-preferences.h" #include "cc-remote-login.h" diff --git a/panels/sharing/meson.build b/panels/sharing/meson.build index 5caac36c0..236458171 100644 --- a/panels/sharing/meson.build +++ b/panels/sharing/meson.build @@ -78,7 +78,7 @@ cflags += [ panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: common_deps, c_args: cflags ) diff --git a/panels/thunderbolt/bolt-client.c b/panels/thunderbolt/bolt-client.c new file mode 100644 index 000000000..0ebc360b1 --- /dev/null +++ b/panels/thunderbolt/bolt-client.c @@ -0,0 +1,697 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "bolt-client.h" + +#include "bolt-device.h" +#include "bolt-error.h" +#include "bolt-names.h" + +#include <gio/gio.h> + +static void handle_dbus_device_added (GObject *self, + GDBusProxy *bus_proxy, + GVariant *params); +static void handle_dbus_device_removed (GObject *self, + GDBusProxy *bus_proxy, + GVariant *params); + +struct _BoltClient +{ + BoltProxy parent; +}; + +enum { + PROP_0, + + /* D-Bus Props */ + PROP_VERSION, + PROP_PROBING, + PROP_SECURITY, + PROP_AUTHMODE, + + PROP_LAST +}; + +static GParamSpec *props[PROP_LAST] = {NULL, }; + +enum { + SIGNAL_DEVICE_ADDED, + SIGNAL_DEVICE_REMOVED, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = {0}; + + +G_DEFINE_TYPE (BoltClient, + bolt_client, + BOLT_TYPE_PROXY); + + +static void +bolt_client_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + if (bolt_proxy_get_dbus_property (object, pspec, value)) + return; + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +} + +static const BoltProxySignal * +bolt_client_get_dbus_signals (guint *n) +{ + static BoltProxySignal dbus_signals[] = { + {"DeviceAdded", handle_dbus_device_added}, + {"DeviceRemoved", handle_dbus_device_removed}, + }; + + *n = G_N_ELEMENTS (dbus_signals); + + return dbus_signals; +} + + +static void +bolt_client_class_init (BoltClientClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + BoltProxyClass *proxy_class = BOLT_PROXY_CLASS (klass); + + gobject_class->get_property = bolt_client_get_property; + + proxy_class->get_dbus_signals = bolt_client_get_dbus_signals; + + props[PROP_VERSION] + = g_param_spec_uint ("version", + "Version", NULL, + 0, G_MAXUINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME); + + props[PROP_PROBING] + = g_param_spec_boolean ("probing", + "Probing", NULL, + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME); + + props[PROP_SECURITY] + = g_param_spec_enum ("security-level", + "SecurityLevel", NULL, + BOLT_TYPE_SECURITY, + BOLT_SECURITY_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME); + + props[PROP_AUTHMODE] = + g_param_spec_flags ("auth-mode", "AuthMode", NULL, + BOLT_TYPE_AUTH_MODE, + BOLT_AUTH_ENABLED, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + props); + + /* signals */ + signals[SIGNAL_DEVICE_ADDED] = + g_signal_new ("device-added", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_STRING); + + signals[SIGNAL_DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_STRING); +} + + +static void +bolt_client_init (BoltClient *cli) +{ +} + +/* dbus signals */ + +static void +handle_dbus_device_added (GObject *self, GDBusProxy *bus_proxy, GVariant *params) +{ + BoltClient *cli = BOLT_CLIENT (self); + const char *opath = NULL; + + g_variant_get_child (params, 0, "&o", &opath); + g_signal_emit (cli, signals[SIGNAL_DEVICE_ADDED], 0, opath); +} + +static void +handle_dbus_device_removed (GObject *self, GDBusProxy *bus_proxy, GVariant *params) +{ + BoltClient *cli = BOLT_CLIENT (self); + const char *opath = NULL; + + g_variant_get_child (params, 0, "&o", &opath); + g_signal_emit (cli, signals[SIGNAL_DEVICE_REMOVED], 0, opath); +} + +/* public methods */ + +BoltClient * +bolt_client_new (GError **error) +{ + BoltClient *cli; + GDBusConnection *bus; + + bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); + if (bus == NULL) + { + g_prefix_error (error, "Error connecting to D-Bus: "); + return FALSE; + } + + cli = g_initable_new (BOLT_TYPE_CLIENT, + NULL, error, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-connection", bus, + "g-name", BOLT_DBUS_NAME, + "g-object-path", BOLT_DBUS_PATH, + "g-interface-name", BOLT_DBUS_INTERFACE, + NULL); + + g_object_unref (bus); + + return cli; +} + +static void +got_the_client (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + GTask *task = user_data; + GObject *obj; + + obj = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, &error); + + if (obj == NULL) + { + g_task_return_error (task, error); + return; + } + + g_task_return_pointer (task, obj, g_object_unref); + g_object_unref (task); +} + +static void +got_the_bus (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + GTask *task = user_data; + GCancellable *cancellable; + GDBusConnection *bus; + + bus = g_bus_get_finish (res, &error); + if (bus == NULL) + { + g_prefix_error (&error, "could not connect to D-Bus: "); + g_task_return_error (task, error); + return; + } + + cancellable = g_task_get_cancellable (task); + g_async_initable_new_async (BOLT_TYPE_CLIENT, + G_PRIORITY_DEFAULT, + cancellable, + got_the_client, task, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-connection", bus, + "g-name", BOLT_DBUS_NAME, + "g-object-path", BOLT_DBUS_PATH, + "g-interface-name", BOLT_DBUS_INTERFACE, + NULL); + g_object_unref (bus); +} + +void +bolt_client_new_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (NULL, cancellable, callback, user_data); + g_bus_get (G_BUS_TYPE_SYSTEM, cancellable, got_the_bus, task); +} + +BoltClient * +bolt_client_new_finish (GAsyncResult *res, + GError **error) +{ + g_return_val_if_fail (G_IS_TASK (res), NULL); + + return g_task_propagate_pointer (G_TASK (res), error); +} + +GPtrArray * +bolt_client_list_devices (BoltClient *client, + GCancellable *cancel, + GError **error) +{ + g_autoptr(GVariant) val = NULL; + g_autoptr(GPtrArray) devices = NULL; + g_autoptr(GVariantIter) iter = NULL; + GDBusConnection *bus = NULL; + const char *d; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL); + + val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client), + "ListDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancel, + error); + if (val == NULL) + return NULL; + + bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client)); + + devices = g_ptr_array_new_with_free_func (g_object_unref); + + g_variant_get (val, "(ao)", &iter); + while (g_variant_iter_loop (iter, "&o", &d, NULL)) + { + BoltDevice *dev; + + dev = bolt_device_new_for_object_path (bus, d, cancel, error); + if (dev == NULL) + return NULL; + + g_ptr_array_add (devices, dev); + } + + return g_steal_pointer (&devices); +} + +BoltDevice * +bolt_client_get_device (BoltClient *client, + const char *uid, + GCancellable *cancel, + GError **error) +{ + g_autoptr(GVariant) val = NULL; + g_autoptr(GError) err = NULL; + BoltDevice *dev = NULL; + GDBusConnection *bus = NULL; + const char *opath = NULL; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL); + + val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client), + "DeviceByUid", + g_variant_new ("(s)", uid), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancel, + &err); + + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return NULL; + } + + bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client)); + g_variant_get (val, "(&o)", &opath); + + if (opath == NULL) + return NULL; + + dev = bolt_device_new_for_object_path (bus, opath, cancel, error); + return dev; +} + +BoltDevice * +bolt_client_enroll_device (BoltClient *client, + const char *uid, + BoltPolicy policy, + BoltAuthCtrl flags, + GError **error) +{ + g_autoptr(GVariant) val = NULL; + g_autoptr(GError) err = NULL; + g_autofree char *fstr = NULL; + BoltDevice *dev = NULL; + GDBusConnection *bus = NULL; + GVariant *params = NULL; + const char *opath = NULL; + const char *pstr; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL); + + pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, error); + if (pstr == NULL) + return NULL; + + fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, error); + if (fstr == NULL) + return NULL; + + params = g_variant_new ("(sss)", uid, pstr, fstr); + val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client), + "EnrollDevice", + params, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err); + + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return NULL; + } + + bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client)); + g_variant_get (val, "(&o)", &opath); + + if (opath == NULL) + return NULL; + + dev = bolt_device_new_for_object_path (bus, opath, NULL, error); + return dev; +} + +void +bolt_client_enroll_device_async (BoltClient *client, + const char *uid, + BoltPolicy policy, + BoltAuthCtrl flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autofree char *fstr = NULL; + GError *err = NULL; + GVariant *params; + const char *pstr; + + g_return_if_fail (BOLT_IS_CLIENT (client)); + g_return_if_fail (uid != NULL); + + pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err); + if (pstr == NULL) + { + g_task_report_error (client, callback, user_data, NULL, err); + return; + } + + fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err); + if (fstr == NULL) + { + g_task_report_error (client, callback, user_data, NULL, err); + return; + } + + params = g_variant_new ("(sss)", uid, pstr, fstr); + g_dbus_proxy_call (G_DBUS_PROXY (client), + "EnrollDevice", + params, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +gboolean +bolt_client_enroll_device_finish (BoltClient *client, + GAsyncResult *res, + char **path, + GError **error) +{ + GVariant *val = NULL; + + g_autoptr(GError) err = NULL; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE); + + val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err); + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return FALSE; + } + + if (path != NULL) + g_variant_get (val, "(o)", path); + + return TRUE; +} + +gboolean +bolt_client_forget_device (BoltClient *client, + const char *uid, + GError **error) +{ + g_autoptr(GVariant) val = NULL; + g_autoptr(GError) err = NULL; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE); + + val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client), + "ForgetDevice", + g_variant_new ("(s)", uid), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err); + + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return FALSE; + } + + return TRUE; +} + +void +bolt_client_forget_device_async (BoltClient *client, + const char *uid, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (BOLT_IS_CLIENT (client)); + + g_dbus_proxy_call (G_DBUS_PROXY (client), + "ForgetDevice", + g_variant_new ("(s)", uid), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +gboolean +bolt_client_forget_device_finish (BoltClient *client, + GAsyncResult *res, + GError **error) +{ + g_autoptr(GVariant) val = NULL; + g_autoptr(GError) err = NULL; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE); + + val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err); + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return FALSE; + } + + return TRUE; +} + +/* getter */ +guint +bolt_client_get_version (BoltClient *client) +{ + const char *key; + guint val = 0; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), val); + + key = g_param_spec_get_name (props[PROP_VERSION]); + ok = bolt_proxy_get_property_uint32 (BOLT_PROXY (client), key, &val); + + if (!ok) + g_warning ("failed to get property '%s'", key); + + return val; +} + +gboolean +bolt_client_is_probing (BoltClient *client) +{ + const char *key; + gboolean val = FALSE; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), val); + + key = g_param_spec_get_name (props[PROP_PROBING]); + ok = bolt_proxy_get_property_bool (BOLT_PROXY (client), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltSecurity +bolt_client_get_security (BoltClient *client) +{ + const char *key; + gboolean ok; + gint val = BOLT_SECURITY_UNKNOWN; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), val); + + key = g_param_spec_get_name (props[PROP_SECURITY]); + ok = bolt_proxy_get_property_enum (BOLT_PROXY (client), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltAuthMode +bolt_client_get_authmode (BoltClient *client) +{ + const char *key; + gboolean ok; + guint val = BOLT_AUTH_DISABLED; + + g_return_val_if_fail (BOLT_IS_CLIENT (client), val); + + key = g_param_spec_get_name (props[PROP_AUTHMODE]); + ok = bolt_proxy_get_property_flags (BOLT_PROXY (client), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +void +bolt_client_set_authmode_async (BoltClient *client, + BoltAuthMode mode, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autofree char *str = NULL; + GError *err = NULL; + GParamSpec *pspec; + GParamSpecFlags *flags_pspec; + GFlagsClass *flags_class; + + pspec = props[PROP_AUTHMODE]; + flags_pspec = G_PARAM_SPEC_FLAGS (pspec); + flags_class = flags_pspec->flags_class; + str = bolt_flags_class_to_string (flags_class, mode, &err); + + if (str == NULL) + { + g_task_report_error (client, callback, user_data, NULL, err); + return; + } + + bolt_proxy_set_property_async (BOLT_PROXY (client), + g_param_spec_get_nick (pspec), + g_variant_new ("s", str), + cancellable, + callback, + user_data); +} + +gboolean +bolt_client_set_authmode_finish (BoltClient *client, + GAsyncResult *res, + GError **error) +{ + return bolt_proxy_set_property_finish (res, error); +} + +/* utility functions */ +static gint +device_sort_by_syspath (gconstpointer ap, + gconstpointer bp, + gpointer data) +{ + BoltDevice *a = BOLT_DEVICE (*((BoltDevice **) ap)); + BoltDevice *b = BOLT_DEVICE (*((BoltDevice **) bp)); + gint sort_order = GPOINTER_TO_INT (data); + const char *pa; + const char *pb; + + pa = bolt_device_get_syspath (a); + pb = bolt_device_get_syspath (b); + + return sort_order * g_strcmp0 (pa, pb); +} + +void +bolt_devices_sort_by_syspath (GPtrArray *devices, + gboolean reverse) +{ + gpointer sort_order = GINT_TO_POINTER (reverse ? -1 : 1); + + if (devices == NULL) + return; + + g_ptr_array_sort_with_data (devices, + device_sort_by_syspath, + sort_order); +} diff --git a/panels/thunderbolt/bolt-client.h b/panels/thunderbolt/bolt-client.h new file mode 100644 index 000000000..853823011 --- /dev/null +++ b/panels/thunderbolt/bolt-client.h @@ -0,0 +1,107 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include "bolt-enums.h" +#include "bolt-device.h" +#include "bolt-proxy.h" + +G_BEGIN_DECLS + +#define BOLT_TYPE_CLIENT bolt_client_get_type () +G_DECLARE_FINAL_TYPE (BoltClient, bolt_client, BOLT, CLIENT, BoltProxy); + +BoltClient * bolt_client_new (GError **error); + +void bolt_client_new_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +BoltClient * bolt_client_new_finish (GAsyncResult *res, + GError **error); + +GPtrArray * bolt_client_list_devices (BoltClient *client, + GCancellable *cancellable, + GError **error); + +BoltDevice * bolt_client_get_device (BoltClient *client, + const char *uid, + GCancellable *cancellable, + GError **error); + +BoltDevice * bolt_client_enroll_device (BoltClient *client, + const char *uid, + BoltPolicy policy, + BoltAuthCtrl flags, + GError **error); + +void bolt_client_enroll_device_async (BoltClient *client, + const char *uid, + BoltPolicy policy, + BoltAuthCtrl flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean bolt_client_enroll_device_finish (BoltClient *client, + GAsyncResult *res, + char **path, + GError **error); + +gboolean bolt_client_forget_device (BoltClient *client, + const char *uid, + GError **error); + +void bolt_client_forget_device_async (BoltClient *client, + const char *uid, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean bolt_client_forget_device_finish (BoltClient *client, + GAsyncResult *res, + GError **error); + +/* getter */ +guint bolt_client_get_version (BoltClient *client); + +gboolean bolt_client_is_probing (BoltClient *client); + +BoltSecurity bolt_client_get_security (BoltClient *client); + +BoltAuthMode bolt_client_get_authmode (BoltClient *client); + +/* setter */ + +void bolt_client_set_authmode_async (BoltClient *client, + BoltAuthMode mode, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean bolt_client_set_authmode_finish (BoltClient *client, + GAsyncResult *res, + GError **error); + +/* utility functions */ +void bolt_devices_sort_by_syspath (GPtrArray *devices, + gboolean reverse); + +G_END_DECLS diff --git a/panels/thunderbolt/bolt-device.c b/panels/thunderbolt/bolt-device.c new file mode 100644 index 000000000..b316950d3 --- /dev/null +++ b/panels/thunderbolt/bolt-device.c @@ -0,0 +1,604 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "config.h" + +#include "bolt-device.h" + +#include "bolt-enums.h" +#include "bolt-error.h" +#include "bolt-names.h" + +#include <gio/gio.h> + +struct _BoltDevice +{ + BoltProxy parent; +}; + +enum { + PROP_0, + + /* D-Bus Props */ + PROP_UID, + PROP_NAME, + PROP_VENDOR, + PROP_TYPE, + PROP_STATUS, + PROP_AUTHFLAGS, + PROP_PARENT, + PROP_SYSPATH, + PROP_CONNTIME, + PROP_AUTHTIME, + + PROP_STORED, + PROP_POLICY, + PROP_KEY, + PROP_STORETIME, + PROP_LABEL, + + PROP_LAST +}; + +static GParamSpec *props[PROP_LAST] = {NULL, }; + +G_DEFINE_TYPE (BoltDevice, + bolt_device, + BOLT_TYPE_PROXY); + +static void +bolt_device_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + if (bolt_proxy_get_dbus_property (object, pspec, value)) + return; +} + + + +static void +bolt_device_class_init (BoltDeviceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = bolt_device_get_property; + + props[PROP_UID] = + g_param_spec_string ("uid", + "Uid", NULL, + "unknown", + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_NAME] = + g_param_spec_string ("name", + "Name", NULL, + "unknown", + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_VENDOR] = + g_param_spec_string ("vendor", + "Vendor", NULL, + "unknown", + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_TYPE] = + g_param_spec_enum ("type", + "Type", NULL, + BOLT_TYPE_DEVICE_TYPE, + BOLT_DEVICE_PERIPHERAL, + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_STATUS] = + g_param_spec_enum ("status", + "Status", NULL, + BOLT_TYPE_STATUS, + BOLT_STATUS_DISCONNECTED, + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_AUTHFLAGS] = + g_param_spec_flags ("authflags", + "AuthFlags", NULL, + BOLT_TYPE_AUTH_FLAGS, + BOLT_AUTH_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + props[PROP_PARENT] = + g_param_spec_string ("parent", + "Parent", NULL, + "unknown", + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_SYSPATH] = + g_param_spec_string ("syspath", + "SysfsPath", NULL, + "unknown", + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_CONNTIME] = + g_param_spec_uint64 ("conntime", + "ConnectTime", NULL, + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + props[PROP_AUTHTIME] = + g_param_spec_uint64 ("authtime", + "AuthorizeTime", NULL, + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + props[PROP_STORED] = + g_param_spec_boolean ("stored", + "Stored", NULL, + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_POLICY] = + g_param_spec_enum ("policy", + "Policy", NULL, + BOLT_TYPE_POLICY, + BOLT_POLICY_DEFAULT, + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_KEY] = + g_param_spec_enum ("key", + "Key", NULL, + BOLT_TYPE_KEY_STATE, + BOLT_KEY_MISSING, + G_PARAM_READABLE | + G_PARAM_STATIC_NICK); + + props[PROP_STORETIME] = + g_param_spec_uint64 ("storetime", + "StoreTime", NULL, + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + props[PROP_LABEL] = + g_param_spec_string ("label", + "Label", NULL, + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + props); + +} + +static void +bolt_device_init (BoltDevice *mgr) +{ +} + +/* public methods */ + +BoltDevice * +bolt_device_new_for_object_path (GDBusConnection *bus, + const char *path, + GCancellable *cancel, + GError **error) +{ + BoltDevice *dev; + + dev = g_initable_new (BOLT_TYPE_DEVICE, + cancel, error, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-connection", bus, + "g-name", BOLT_DBUS_NAME, + "g-object-path", path, + "g-interface-name", BOLT_DBUS_DEVICE_INTERFACE, + NULL); + + return dev; +} + +gboolean +bolt_device_authorize (BoltDevice *dev, + BoltAuthCtrl flags, + GCancellable *cancel, + GError **error) +{ + g_autoptr(GError) err = NULL; + g_autofree char *fstr = NULL; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), FALSE); + + fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, error); + if (fstr == NULL) + return FALSE; + + g_dbus_proxy_call_sync (G_DBUS_PROXY (dev), + "Authorize", + g_variant_new ("(s)", fstr), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancel, + &err); + + if (err != NULL) + return bolt_error_propagate_stripped (error, &err); + + return TRUE; +} + +void +bolt_device_authorize_async (BoltDevice *dev, + BoltAuthCtrl flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GError *err = NULL; + g_autofree char *fstr = NULL; + + g_return_if_fail (BOLT_IS_DEVICE (dev)); + + fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err); + if (fstr == NULL) + { + g_task_report_error (dev, callback, user_data, NULL, err); + return; + } + + g_dbus_proxy_call (G_DBUS_PROXY (dev), + "Authorize", + g_variant_new ("(s)", fstr), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +gboolean +bolt_device_authorize_finish (BoltDevice *dev, + GAsyncResult *res, + GError **error) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GVariant) val = NULL; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), FALSE); + + val = g_dbus_proxy_call_finish (G_DBUS_PROXY (dev), res, &err); + if (val == NULL) + { + bolt_error_propagate_stripped (error, &err); + return FALSE; + } + + return TRUE; +} + +const char * +bolt_device_get_uid (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_UID]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +const char * +bolt_device_get_name (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_NAME]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +const char * +bolt_device_get_vendor (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_VENDOR]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +BoltDeviceType +bolt_device_get_device_type (BoltDevice *dev) +{ + const char *key; + gboolean ok; + gint val = BOLT_DEVICE_PERIPHERAL; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_TYPE]); + ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltStatus +bolt_device_get_status (BoltDevice *dev) +{ + const char *key; + gboolean ok; + gint val = BOLT_STATUS_UNKNOWN; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_STATUS]); + ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltAuthFlags +bolt_device_get_authflags (BoltDevice *dev) +{ + const char *key; + gboolean ok; + guint val = BOLT_AUTH_NONE; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_AUTHFLAGS]); + ok = bolt_proxy_get_property_flags (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +const char * +bolt_device_get_parent (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_PARENT]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +const char * +bolt_device_get_syspath (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_SYSPATH]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +guint64 +bolt_device_get_conntime (BoltDevice *dev) +{ + const char *key; + guint64 val = 0; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_CONNTIME]); + ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +guint64 +bolt_device_get_authtime (BoltDevice *dev) +{ + const char *key; + guint64 val = 0; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_AUTHTIME]); + ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +gboolean +bolt_device_is_stored (BoltDevice *dev) +{ + const char *key; + gboolean val = FALSE; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_STORED]); + ok = bolt_proxy_get_property_bool (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltPolicy +bolt_device_get_policy (BoltDevice *dev) +{ + const char *key; + gboolean ok; + gint val = BOLT_POLICY_DEFAULT; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_POLICY]); + ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +BoltKeyState +bolt_device_get_keystate (BoltDevice *dev) +{ + const char *key; + gboolean ok; + gint val = BOLT_KEY_MISSING; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_KEY]); + ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +guint64 +bolt_device_get_storetime (BoltDevice *dev) +{ + const char *key; + guint64 val = 0; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), val); + + key = g_param_spec_get_name (props[PROP_STORETIME]); + ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val); + + if (!ok) + g_warning ("failed to get enum property '%s'", key); + + return val; +} + +const char * +bolt_device_get_label (BoltDevice *dev) +{ + const char *key; + const char *str; + + g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL); + + key = g_param_spec_get_name (props[PROP_LABEL]); + str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key); + + return str; +} + +char * +bolt_device_get_display_name (BoltDevice *dev) +{ + const char *label; + const char *name; + const char *vendor; + + label = bolt_device_get_label (dev); + if (label != NULL) + return g_strdup (label); + + name = bolt_device_get_name (dev); + vendor = bolt_device_get_vendor (dev); + + return g_strdup_printf ("%s %s", vendor, name); +} + +guint64 +bolt_device_get_timestamp (BoltDevice *dev) +{ + BoltStatus status; + guint64 timestamp = 0; + + status = bolt_device_get_status (dev); + + switch (status) + { + case BOLT_STATUS_AUTHORIZING: + case BOLT_STATUS_AUTH_ERROR: + case BOLT_STATUS_CONNECTING: + case BOLT_STATUS_CONNECTED: + timestamp = bolt_device_get_conntime (dev); + break; + + case BOLT_STATUS_DISCONNECTED: + /* implicit: device is stored */ + timestamp = bolt_device_get_storetime (dev); + break; + + case BOLT_STATUS_AUTHORIZED: + case BOLT_STATUS_AUTHORIZED_DPONLY: + case BOLT_STATUS_AUTHORIZED_NEWKEY: + case BOLT_STATUS_AUTHORIZED_SECURE: + timestamp = bolt_device_get_authtime (dev); + break; + + case BOLT_STATUS_UNKNOWN: + timestamp = 0; + break; + } + + return timestamp; +} diff --git a/panels/thunderbolt/bolt-device.h b/panels/thunderbolt/bolt-device.h new file mode 100644 index 000000000..ffd09f9a8 --- /dev/null +++ b/panels/thunderbolt/bolt-device.h @@ -0,0 +1,87 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include "bolt-enums.h" +#include "bolt-proxy.h" + +G_BEGIN_DECLS + +#define BOLT_TYPE_DEVICE bolt_device_get_type () +G_DECLARE_FINAL_TYPE (BoltDevice, bolt_device, BOLT, DEVICE, BoltProxy); + +BoltDevice * bolt_device_new_for_object_path (GDBusConnection *bus, + const char *path, + GCancellable *cancellable, + GError **error); + +gboolean bolt_device_authorize (BoltDevice *dev, + BoltAuthCtrl flags, + GCancellable *cancellable, + GError **error); + +void bolt_device_authorize_async (BoltDevice *dev, + BoltAuthCtrl flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean bolt_device_authorize_finish (BoltDevice *dev, + GAsyncResult *res, + GError **error); + +/* getter */ +const char * bolt_device_get_uid (BoltDevice *dev); + +const char * bolt_device_get_name (BoltDevice *dev); + +const char * bolt_device_get_vendor (BoltDevice *dev); + +BoltDeviceType bolt_device_get_device_type (BoltDevice *dev); + +BoltStatus bolt_device_get_status (BoltDevice *dev); + +BoltAuthFlags bolt_device_get_authflags (BoltDevice *dev); + +const char * bolt_device_get_parent (BoltDevice *dev); + +const char * bolt_device_get_syspath (BoltDevice *dev); + +guint64 bolt_device_get_conntime (BoltDevice *dev); + +guint64 bolt_device_get_authtime (BoltDevice *dev); + +gboolean bolt_device_is_stored (BoltDevice *dev); + +BoltPolicy bolt_device_get_policy (BoltDevice *dev); + +BoltKeyState bolt_device_get_keystate (BoltDevice *dev); + +guint64 bolt_device_get_storetime (BoltDevice *dev); + +const char * bolt_device_get_label (BoltDevice *dev); + +/* derived getter */ +char * bolt_device_get_display_name (BoltDevice *dev); + +guint64 bolt_device_get_timestamp (BoltDevice *dev); + +G_END_DECLS diff --git a/panels/thunderbolt/bolt-enums.c b/panels/thunderbolt/bolt-enums.c new file mode 100644 index 000000000..de77737f8 --- /dev/null +++ b/panels/thunderbolt/bolt-enums.c @@ -0,0 +1,395 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "config.h" + +#include "bolt-enums.h" +#include "bolt-error.h" + +#include <gio/gio.h> + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref); + +gboolean +bolt_enum_class_validate (GEnumClass *enum_class, + gint value, + GError **error) +{ + const char *name; + gboolean oob; + + if (enum_class == NULL) + { + name = g_type_name_from_class ((GTypeClass *) enum_class); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "could not determine enum class for '%s'", + name); + + return FALSE; + } + + oob = value < enum_class->minimum || value > enum_class->maximum; + + if (oob) + { + name = g_type_name_from_class ((GTypeClass *) enum_class); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "enum value '%d' is out of bounds for '%s'", + value, name); + return FALSE; + } + + return TRUE; +} + +gboolean +bolt_enum_validate (GType enum_type, + gint value, + GError **error) +{ + g_autoptr(GEnumClass) klass = g_type_class_ref (enum_type); + return bolt_enum_class_validate (klass, value, error); +} + +const char * +bolt_enum_to_string (GType enum_type, + gint value, + GError **error) +{ + g_autoptr(GEnumClass) klass = NULL; + GEnumValue *ev; + + klass = g_type_class_ref (enum_type); + + if (!bolt_enum_class_validate (klass, value, error)) + return NULL; + + ev = g_enum_get_value (klass, value); + return ev->value_nick; +} + +gint +bolt_enum_from_string (GType enum_type, + const char *string, + GError **error) +{ + g_autoptr(GEnumClass) klass = NULL; + const char *name; + GEnumValue *ev; + + klass = g_type_class_ref (enum_type); + + if (klass == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "could not determine enum class"); + return -1; + } + + if (string == NULL) + { + name = g_type_name_from_class ((GTypeClass *) klass); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "empty string passed for enum class for '%s'", + name); + return -1; + } + + ev = g_enum_get_value_by_nick (klass, string); + + if (ev == NULL) + { + name = g_type_name (enum_type); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "invalid string '%s' for enum '%s'", string, name); + return -1; + } + + return ev->value; +} + +char * +bolt_flags_class_to_string (GFlagsClass *flags_class, + guint value, + GError **error) +{ + g_autoptr(GString) str = NULL; + const char *name; + GFlagsValue *fv; + + if (flags_class == NULL) + { + name = g_type_name_from_class ((GTypeClass *) flags_class); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "could not determine flags class for '%s'", + name); + + return FALSE; + } + + fv = g_flags_get_first_value (flags_class, value); + if (fv == NULL) + { + if (value == 0) + return g_strdup (""); + + name = g_type_name_from_class ((GTypeClass *) flags_class); + + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "invalid value '%u' for flags '%s'", value, name); + return NULL; + } + + value &= ~fv->value; + str = g_string_new (fv->value_nick); + + while (value != 0 && + (fv = g_flags_get_first_value (flags_class, value)) != NULL) + { + g_string_append (str, " | "); + g_string_append (str, fv->value_nick); + + value &= ~fv->value; + } + + if (value != 0) + { + name = g_type_name_from_class ((GTypeClass *) flags_class); + + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "unhandled value '%u' for flags '%s'", value, name); + return NULL; + } + + return g_string_free (g_steal_pointer (&str), FALSE); +} + +gboolean +bolt_flags_class_from_string (GFlagsClass *flags_class, + const char *string, + guint *flags_out, + GError **error) +{ + g_auto(GStrv) vals = NULL; + const char *name; + guint flags = 0; + + if (flags_class == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "could not determine flags class"); + + return FALSE; + } + + if (string == NULL) + { + name = g_type_name_from_class ((GTypeClass *) flags_class); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "empty string passed for flags class for '%s'", + name); + return FALSE; + } + + vals = g_strsplit (string, "|", -1); + + for (guint i = 0; vals[i]; i++) + { + GFlagsValue *fv; + char *nick; + + nick = g_strstrip (vals[i]); + fv = g_flags_get_value_by_nick (flags_class, nick); + + if (fv == NULL) + { + name = g_type_name_from_class ((GTypeClass *) flags_class); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "invalid flag '%s' for flags '%s'", string, name); + + return FALSE; + } + + flags |= fv->value; + } + + if (flags_out != NULL) + *flags_out = flags; + + return TRUE; +} + +char * +bolt_flags_to_string (GType flags_type, + guint value, + GError **error) +{ + g_autoptr(GFlagsClass) klass = NULL; + + klass = g_type_class_ref (flags_type); + return bolt_flags_class_to_string (klass, value, error); +} + +gboolean +bolt_flags_from_string (GType flags_type, + const char *string, + guint *flags_out, + GError **error) +{ + g_autoptr(GFlagsClass) klass = NULL; + + klass = g_type_class_ref (flags_type); + return bolt_flags_class_from_string (klass, string, flags_out, error); +} + +gboolean +bolt_flags_update (guint from, + guint *to, + guint mask) +{ + guint val; + gboolean chg; + + g_return_val_if_fail (to != NULL, FALSE); + + val = *to & ~mask; /* clear all bits in mask */ + val = val | (from & mask); /* set all bits in from and mask */ + chg = *to != val; + *to = val; + + return chg; +} + +const char * +bolt_status_to_string (BoltStatus status) +{ + return bolt_enum_to_string (BOLT_TYPE_STATUS, status, NULL); +} + +gboolean +bolt_status_is_authorized (BoltStatus status) +{ + return status == BOLT_STATUS_AUTHORIZED || + status == BOLT_STATUS_AUTHORIZED_SECURE || + status == BOLT_STATUS_AUTHORIZED_NEWKEY; +} + +gboolean +bolt_status_is_pending (BoltStatus status) +{ + return status == BOLT_STATUS_AUTH_ERROR || + status == BOLT_STATUS_CONNECTED; +} + +gboolean +bolt_status_validate (BoltStatus status) +{ + return bolt_enum_validate (BOLT_TYPE_STATUS, status, NULL); +} + +gboolean +bolt_status_is_connected (BoltStatus status) +{ + return status > BOLT_STATUS_DISCONNECTED; +} + +BoltSecurity +bolt_security_from_string (const char *str) +{ + return bolt_enum_from_string (BOLT_TYPE_SECURITY, str, NULL); +} + +const char * +bolt_security_to_string (BoltSecurity security) +{ + return bolt_enum_to_string (BOLT_TYPE_SECURITY, security, NULL); +} + +gboolean +bolt_security_validate (BoltSecurity security) +{ + return bolt_enum_validate (BOLT_TYPE_SECURITY, security, NULL); +} + +gboolean +bolt_security_allows_pcie (BoltSecurity security) +{ + gboolean pcie = FALSE; + + switch (security) + { + case BOLT_SECURITY_NONE: + case BOLT_SECURITY_USER: + case BOLT_SECURITY_SECURE: + pcie = TRUE; + break; + + case BOLT_SECURITY_DPONLY: + case BOLT_SECURITY_USBONLY: + case BOLT_SECURITY_UNKNOWN: + pcie = FALSE; + break; + } + + return pcie; +} + +BoltPolicy +bolt_policy_from_string (const char *str) +{ + return bolt_enum_from_string (BOLT_TYPE_POLICY, str, NULL); +} + +const char * +bolt_policy_to_string (BoltPolicy policy) +{ + return bolt_enum_to_string (BOLT_TYPE_POLICY, policy, NULL); +} + +gboolean +bolt_policy_validate (BoltPolicy policy) +{ + return bolt_enum_validate (BOLT_TYPE_POLICY, policy, NULL); +} + +BoltDeviceType +bolt_device_type_from_string (const char *str) +{ + return bolt_enum_from_string (BOLT_TYPE_DEVICE_TYPE, str, NULL); +} + +const char * +bolt_device_type_to_string (BoltDeviceType type) +{ + return bolt_enum_to_string (BOLT_TYPE_DEVICE_TYPE, type, NULL); +} + +gboolean +bolt_device_type_validate (BoltDeviceType type) +{ + return bolt_enum_validate (BOLT_TYPE_DEVICE_TYPE, type, NULL); +} + +gboolean +bolt_device_type_is_host (BoltDeviceType type) +{ + return type == BOLT_DEVICE_HOST; +} diff --git a/panels/thunderbolt/bolt-enums.h b/panels/thunderbolt/bolt-enums.h new file mode 100644 index 000000000..6e2953fa2 --- /dev/null +++ b/panels/thunderbolt/bolt-enums.h @@ -0,0 +1,249 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include "bolt-names.h" +#include "bolt-enum-types.h" + + +gboolean bolt_enum_validate (GType enum_type, + gint value, + GError **error); + +gboolean bolt_enum_class_validate (GEnumClass *enum_class, + gint value, + GError **error); + +const char * bolt_enum_to_string (GType enum_type, + gint value, + GError **error); + +gint bolt_enum_from_string (GType enum_type, + const char *string, + GError **error); + + +char * bolt_flags_class_to_string (GFlagsClass *flags_class, + guint value, + GError **error); + +gboolean bolt_flags_class_from_string (GFlagsClass *flags_class, + const char *string, + guint *flags_out, + GError **error); + +char * bolt_flags_to_string (GType flags_type, + guint value, + GError **error); + +gboolean bolt_flags_from_string (GType flags_type, + const char *string, + guint *flags_out, + GError **error); + +gboolean bolt_flags_update (guint from, + guint *to, + guint mask); + +#define bolt_flag_isset(flags_, flag_) (!!(flags_ & flag_)) +#define bolt_flag_isclear(flags_, flag_) (!(flags_ & flag_)) + +/** + * BoltStatus: + * @BOLT_STATUS_UNKNOWN: Device is in an unknown state (should normally not happen). + * @BOLT_STATUS_DISCONNECTED: Device is not connected. + * @BOLT_STATUS_CONNECTING: Device is currently being connected. + * @BOLT_STATUS_CONNECTED: Device is connected, but not authorized. + * @BOLT_STATUS_AUTHORIZING: Device is currently authorizing. + * @BOLT_STATUS_AUTH_ERROR: Failed to authorize a device via a key. + * @BOLT_STATUS_AUTHORIZED: Device connected and authorized. + * @BOLT_STATUS_AUTHORIZED_SECURE: Device connected and securely authorized via a key (deprecated). + * @BOLT_STATUS_AUTHORIZED_NEWKEY: Device connected and authorized via a new key (deprecated). + * @BOLT_STATUS_AUTHORIZED_DPONLY: Device authorized but with thunderbolt disabled (deprecated). + * + * The current status of the device. + */ +typedef enum { + + BOLT_STATUS_UNKNOWN = -1, + BOLT_STATUS_DISCONNECTED = 0, + BOLT_STATUS_CONNECTING, + BOLT_STATUS_CONNECTED, + BOLT_STATUS_AUTHORIZING, + BOLT_STATUS_AUTH_ERROR, + BOLT_STATUS_AUTHORIZED, + + /* deprecated, do not use */ + BOLT_STATUS_AUTHORIZED_SECURE, + BOLT_STATUS_AUTHORIZED_NEWKEY, + BOLT_STATUS_AUTHORIZED_DPONLY + +} BoltStatus; + +const char * bolt_status_to_string (BoltStatus status); +gboolean bolt_status_is_authorized (BoltStatus status); +gboolean bolt_status_is_connected (BoltStatus status); +gboolean bolt_status_is_pending (BoltStatus status); +gboolean bolt_status_validate (BoltStatus status); + +/** + * BoltAuthFlags: + * @BOLT_AUTH_NONE: No specific authorization. + * @BOLT_AUTH_NOPCIE: PCIe tunnels are *not* authorized. + * @BOLT_AUTH_SECURE: Device is securely authorized. + * @BOLT_AUTH_NOKEY: Device does *not* support key verification. + * @BOLT_AUTH_BOOT: Device was already authorized during pre-boot. + * + * More specific information about device authorization. + */ +typedef enum { /*< flags >*/ + + BOLT_AUTH_NONE = 0, + BOLT_AUTH_NOPCIE = 1 << 0, + BOLT_AUTH_SECURE = 1 << 1, + BOLT_AUTH_NOKEY = 1 << 2, + BOLT_AUTH_BOOT = 1 << 3, + +} BoltAuthFlags; + +/** + * BoltKeyState: + * @BOLT_KEY_UNKNOWN: unknown key state + * @BOLT_KEY_MISSING: no key + * @BOLT_KEY_HAVE: key exists + * @BOLT_KEY_NEW: key is new + * + * The state of the key. + */ + +typedef enum { + + BOLT_KEY_UNKNOWN = -1, + BOLT_KEY_MISSING = 0, + BOLT_KEY_HAVE = 1, + BOLT_KEY_NEW = 2 + +} BoltKeyState; + +/** + * BoltSecurity: + * @BOLT_SECURITY_UNKNOWN : Unknown security. + * @BOLT_SECURITY_NONE : No security, all devices are automatically connected. + * @BOLT_SECURITY_DPONLY : Display Port only devices only. + * @BOLT_SECURITY_USER : User needs to authorize devices. + * @BOLT_SECURITY_SECURE : User needs to authorize devices. Authorization can + * be done via key exchange to verify the device identity. + * @BOLT_SECURITY_USBONLY : Only create a PCIe tunnel to the USB controller in a + * connected thunderbolt dock, allowing no downstream PCIe tunnels. + * + * The security level of the thunderbolt domain. + */ +typedef enum { + + BOLT_SECURITY_UNKNOWN = -1, + BOLT_SECURITY_NONE = 0, + BOLT_SECURITY_DPONLY = 1, + BOLT_SECURITY_USER = '1', + BOLT_SECURITY_SECURE = '2', + BOLT_SECURITY_USBONLY = 4, + +} BoltSecurity; + + +BoltSecurity bolt_security_from_string (const char *str); +const char * bolt_security_to_string (BoltSecurity security); +gboolean bolt_security_validate (BoltSecurity security); +gboolean bolt_security_allows_pcie (BoltSecurity security); + +/** + * BoltPolicy: + * @BOLT_POLICY_UNKNOWN: Unknown policy. + * @BOLT_POLICY_DEFAULT: Default policy. + * @BOLT_POLICY_MANUAL: Manual authorization of the device. + * @BOLT_POLICY_AUTO: Connect the device automatically, + * with the best possible security level supported + * by the domain controller. + * + * What do to for connected devices. + */ +typedef enum { + + BOLT_POLICY_UNKNOWN = -1, + BOLT_POLICY_DEFAULT = 0, + BOLT_POLICY_MANUAL = 1, + BOLT_POLICY_AUTO = 2, + +} BoltPolicy; + + +BoltPolicy bolt_policy_from_string (const char *str); +const char * bolt_policy_to_string (BoltPolicy policy); +gboolean bolt_policy_validate (BoltPolicy policy); + +/** + * BoltAuthCtrl: + * @BOLT_AUTHCTRL_NONE: No authorization flags. + * + * Control authorization. + */ +typedef enum { /*< flags >*/ + + BOLT_AUTHCTRL_NONE = 0 + +} BoltAuthCtrl; + +/** + * BoltDeviceType: + * @BOLT_DEVICE_UNKNOWN_TYPE: Unknown device type + * @BOLT_DEVICE_HOST: The device representing the host + * @BOLT_DEVICE_PERIPHERAL: A generic thunderbolt peripheral + * + * The type of the device. + */ +typedef enum { + + BOLT_DEVICE_UNKNOWN_TYPE = -1, + BOLT_DEVICE_HOST = 0, + BOLT_DEVICE_PERIPHERAL + +} BoltDeviceType; + +BoltDeviceType bolt_device_type_from_string (const char *str); +const char * bolt_device_type_to_string (BoltDeviceType type); +gboolean bolt_device_type_validate (BoltDeviceType type); +gboolean bolt_device_type_is_host (BoltDeviceType type); + +/** + * BoltAuthMode: + * @BOLT_AUTH_DISABLED: Authorization is disabled + * @BOLT_AUTH_ENABLED: Authorization is enabled. + * + * Control authorization. + */ +typedef enum { /*< flags >*/ + + BOLT_AUTH_DISABLED = 0, + BOLT_AUTH_ENABLED = 1 + +} BoltAuthMode; + +#define bolt_auth_mode_is_enabled(auth) ((auth & BOLT_AUTH_ENABLED) != 0) +#define bolt_auth_mode_is_disabled(auth) (!bolt_auth_mode_is_enabled (auth)) diff --git a/panels/thunderbolt/bolt-error.c b/panels/thunderbolt/bolt-error.c new file mode 100644 index 000000000..37d844e4a --- /dev/null +++ b/panels/thunderbolt/bolt-error.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "config.h" + +#include "bolt-error.h" + +#include "bolt-names.h" + +#include <gio/gio.h> + +/** + * SECTION:bolt-error + * @Title: Error codes + * + */ + +static const GDBusErrorEntry bolt_error_entries[] = { + {BOLT_ERROR_FAILED, BOLT_DBUS_NAME ".Error.Failed"}, + {BOLT_ERROR_UDEV, BOLT_DBUS_NAME ".Error.UDev"}, +}; + + +GQuark +bolt_error_quark (void) +{ + static volatile gsize quark_volatile = 0; + + g_dbus_error_register_error_domain ("bolt-error-quark", + &quark_volatile, + bolt_error_entries, + G_N_ELEMENTS (bolt_error_entries)); + return (GQuark) quark_volatile; +} + +gboolean +bolt_err_notfound (const GError *error) +{ + return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) || + g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) || + g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND) || + g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); +} + +gboolean +bolt_err_exists (const GError *error) +{ + return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS) || + g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_EXIST); +} + +gboolean +bolt_err_inval (const GError *error) +{ + return g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE); +} + +gboolean +bolt_err_cancelled (const GError *error) +{ + return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); +} + +gboolean +bolt_error_propagate_stripped (GError **dest, + GError **source) +{ + GError *src; + + g_return_val_if_fail (source != NULL, FALSE); + + src = *source; + + if (src == NULL) + return TRUE; + + if (g_dbus_error_is_remote_error (src)) + g_dbus_error_strip_remote_error (src); + + g_propagate_error (dest, g_steal_pointer (source)); + return FALSE; +} diff --git a/panels/thunderbolt/bolt-error.h b/panels/thunderbolt/bolt-error.h new file mode 100644 index 000000000..39b3eee98 --- /dev/null +++ b/panels/thunderbolt/bolt-error.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include <glib.h> + +G_BEGIN_DECLS + +/** + * BoltError: + * @BOLT_ERROR_FAILED: Generic error code + * @BOLT_ERROR_UDEV: UDev error + * + * Error codes used inside Bolt. + */ +enum { + BOLT_ERROR_FAILED = 0, + BOLT_ERROR_UDEV, + BOLT_ERROR_NOKEY, + BOLT_ERROR_BADKEY, + BOLT_ERROR_CFG, +} BoltError; + + +GQuark bolt_error_quark (void); +#define BOLT_ERROR (bolt_error_quark ()) + +/* helper function to check for certain error types */ +gboolean bolt_err_notfound (const GError *error); +gboolean bolt_err_exists (const GError *error); +gboolean bolt_err_inval (const GError *error); +gboolean bolt_err_cancelled (const GError *error); + +gboolean bolt_error_propagate_stripped (GError **dest, + GError **source); + +G_END_DECLS diff --git a/panels/thunderbolt/bolt-names.h b/panels/thunderbolt/bolt-names.h new file mode 100644 index 000000000..2c0a97b24 --- /dev/null +++ b/panels/thunderbolt/bolt-names.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2018 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +/* D-Bus API revision (here for the lack of a better place) */ +#define BOLT_DBUS_API_VERSION 1U + +/* logging */ + +#define BOLT_LOG_DEVICE_UID "BOLT_DEVICE_UID" +#define BOLT_LOG_DEVICE_NAME "BOLT_DEVICE_NAME" +#define BOLT_LOG_DEVICE_STATE "BOLT_DEVICE_STATE" + +#define BOLT_LOG_ERROR_DOMAIN "ERROR_DOMAIN" +#define BOLT_LOG_ERROR_CODE "ERROR_CODE" +#define BOLT_LOG_ERROR_MESSAGE "ERROR_MESSAGE" + +#define BOLT_LOG_TOPIC "BOLT_TOPIC" +#define BOLT_LOG_VERSION "BOLT_VERSION" +#define BOLT_LOG_CONTEXT "BOLT_LOG_CONTEXT" + +/* logging - message ids */ +#define BOLT_LOG_MSG_ID_STARTUP "dd11929c788e48bdbb6276fb5f26b08a" + + +/* dbus */ + +#define BOLT_DBUS_NAME "org.freedesktop.bolt" +#define BOLT_DBUS_PATH "/org/freedesktop/bolt" +#define BOLT_DBUS_INTERFACE "org.freedesktop.bolt1.Manager" + +#define BOLT_DBUS_DEVICE_INTERFACE "org.freedesktop.bolt1.Device" diff --git a/panels/thunderbolt/bolt-proxy.c b/panels/thunderbolt/bolt-proxy.c new file mode 100644 index 000000000..e044c871f --- /dev/null +++ b/panels/thunderbolt/bolt-proxy.c @@ -0,0 +1,514 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "bolt-proxy.h" + +#include "bolt-enums.h" +#include "bolt-error.h" +#include "bolt-names.h" +#include "bolt-str.h" + +static void bolt_proxy_handle_props_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data); + +static void bolt_proxy_handle_dbus_signal (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, + GVariant *params, + gpointer user_data); + +G_DEFINE_TYPE (BoltProxy, bolt_proxy, G_TYPE_DBUS_PROXY); + + +static void +bolt_proxy_constructed (GObject *object) +{ + G_OBJECT_CLASS (bolt_proxy_parent_class)->constructed (object); + + g_signal_connect (object, "g-properties-changed", + G_CALLBACK (bolt_proxy_handle_props_changed), object); + + g_signal_connect (object, "g-signal", + G_CALLBACK (bolt_proxy_handle_dbus_signal), object); +} + +static const BoltProxySignal * +bolt_proxy_get_dbus_signals (guint *n) +{ + *n = 0; + return NULL; +} + +static void +bolt_proxy_class_init (BoltProxyClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = bolt_proxy_constructed; + + klass->get_dbus_signals = bolt_proxy_get_dbus_signals; + +} + +static void +bolt_proxy_init (BoltProxy *object) +{ +} + +static void +bolt_proxy_handle_props_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + g_autoptr(GVariantIter) iter = NULL; + gboolean handled; + GParamSpec **pp; + const char *key; + guint n; + + pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n); + + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + handled = FALSE; + for (guint i = 0; !handled && i < n; i++) + { + GParamSpec *pspec = pp[i]; + const char *nick; + const char *name; + + nick = g_param_spec_get_nick (pspec); + name = g_param_spec_get_name (pspec); + + handled = bolt_streq (nick, key); + + if (handled) + g_object_notify (G_OBJECT (user_data), name); + } + } + + g_free (pp); +} + +static void +bolt_proxy_handle_dbus_signal (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, + GVariant *params, + gpointer user_data) +{ + const BoltProxySignal *ps; + guint n; + + if (signal_name == NULL) + return; + + ps = BOLT_PROXY_GET_CLASS (proxy)->get_dbus_signals (&n); + + for (guint i = 0; i < n; i++) + { + const BoltProxySignal *sig = &ps[i]; + + if (g_str_equal (sig->theirs, signal_name)) + { + sig->handle (G_OBJECT (proxy), proxy, params); + break; + } + } + +} + +/* public methods */ + +gboolean +bolt_proxy_get_dbus_property (GObject *proxy, + GParamSpec *spec, + GValue *value) +{ + g_autoptr(GVariant) val = NULL; + const GVariantType *vt; + gboolean handled = FALSE; + const char *nick; + + nick = g_param_spec_get_nick (spec); + val = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), nick); + + if (val == NULL) + return FALSE; + + vt = g_variant_get_type (val); + + if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) && + G_IS_PARAM_SPEC_ENUM (spec)) + { + GParamSpecEnum *enum_spec = G_PARAM_SPEC_ENUM (spec); + GEnumValue *ev; + const char *str; + + str = g_variant_get_string (val, NULL); + ev = g_enum_get_value_by_nick (enum_spec->enum_class, str); + + handled = ev != NULL; + + if (handled) + g_value_set_enum (value, ev->value); + else + g_value_set_enum (value, enum_spec->default_value); + } + else if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) && + G_IS_PARAM_SPEC_FLAGS (spec)) + { + GParamSpecFlags *flags_spec = G_PARAM_SPEC_FLAGS (spec); + GFlagsClass *flags_class = flags_spec->flags_class; + const char *str; + guint v; + + str = g_variant_get_string (val, NULL); + handled = bolt_flags_class_from_string (flags_class, str, &v, NULL); + + if (handled) + g_value_set_flags (value, v); + else + g_value_set_flags (value, flags_spec->default_value); + } + else + { + g_dbus_gvariant_to_gvalue (val, value); + } + + return handled; +} + +gboolean +bolt_proxy_has_name_owner (BoltProxy *proxy) +{ + const char *name_owner; + + g_return_val_if_fail (proxy != NULL, FALSE); + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + + return name_owner != NULL; +} + +static GParamSpec * +find_property (BoltProxy *proxy, + const char *name, + GError **error) +{ + GParamSpec *res = NULL; + GParamSpec **pp; + guint n; + + pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n); + + for (guint i = 0; i < n; i++) + { + GParamSpec *pspec = pp[i]; + + if (bolt_streq (pspec->name, name)) + { + res = pspec; + break; + } + } + + if (pp == NULL) + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, + "could not find property '%s'", name); + + g_free (pp); + return res; +} + +static GVariant * +bolt_proxy_get_cached_property (BoltProxy *proxy, + const char *name) +{ + const char *bus_name = NULL; + GParamSpec *pspec; + GVariant *var; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL) + return NULL; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + + return var; +} + +gboolean +bolt_proxy_get_property_bool (BoltProxy *proxy, + const char *name, + gboolean *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_boolean (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_enum (BoltProxy *proxy, + const char *name, + gint *value) +{ + g_autoptr(GVariant) var = NULL; + const char *str = NULL; + const char *bus_name = NULL; + GParamSpec *pspec; + GEnumValue *ev; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL) + return FALSE; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + if (var == NULL) + return FALSE; + + str = g_variant_get_string (var, NULL); + + if (str == NULL) + return FALSE; + + ev = g_enum_get_value_by_nick (G_PARAM_SPEC_ENUM (pspec)->enum_class, str); + + if (ev == NULL) + return FALSE; + + if (value) + *value = ev->value; + + return TRUE; +} + +gboolean +bolt_proxy_get_property_flags (BoltProxy *proxy, + const char *name, + guint *value) +{ + g_autoptr(GVariant) var = NULL; + const char *str = NULL; + const char *bus_name = NULL; + GFlagsClass *flags_class; + GParamSpec *pspec; + guint v; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL || !G_IS_PARAM_SPEC_FLAGS (pspec)) + return FALSE; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + if (var == NULL) + return FALSE; + + str = g_variant_get_string (var, NULL); + + if (str == NULL) + return FALSE; + + flags_class = G_PARAM_SPEC_FLAGS (pspec)->flags_class; + ok = bolt_flags_class_from_string (flags_class, str, &v, NULL); + + if (ok && value) + *value = v; + + return ok; +} + +gboolean +bolt_proxy_get_property_uint32 (BoltProxy *proxy, + const char *name, + guint *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_uint32 (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_int64 (BoltProxy *proxy, + const char *name, + gint64 *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_int64 (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_uint64 (BoltProxy *proxy, + const char *name, + guint64 *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_uint64 (var); + + return TRUE; +} + +const char * +bolt_proxy_get_property_string (BoltProxy *proxy, + const char *name) +{ + g_autoptr(GVariant) var = NULL; + const char *val = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var != NULL) + val = g_variant_get_string (var, NULL); + + if (val && *val == '\0') + val = NULL; + + return val; +} + +gboolean +bolt_proxy_set_property (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GError **error) +{ + GParamSpec *pp; + const char *iface; + gboolean ok = FALSE; + GVariant *res; + + pp = find_property (proxy, name, NULL); + if (pp != NULL) + name = g_param_spec_get_nick (pp); + + iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy)); + + res = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + iface, + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + + if (res) + { + g_variant_unref (res); + ok = TRUE; + } + + return ok; +} + +void +bolt_proxy_set_property_async (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GParamSpec *pp; + const char *iface; + + pp = find_property (proxy, name, NULL); + + if (pp != NULL) + name = g_param_spec_get_nick (pp); + + iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy)); + + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + iface, + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +gboolean +bolt_proxy_set_property_finish (GAsyncResult *res, + GError **error) +{ + BoltProxy *proxy; + GVariant *val = NULL; + + proxy = (BoltProxy *) g_async_result_get_source_object (res); + val = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + + if (val == NULL) + return FALSE; + + g_variant_unref (val); + return TRUE; +} diff --git a/panels/thunderbolt/bolt-proxy.h b/panels/thunderbolt/bolt-proxy.h new file mode 100644 index 000000000..c05eb8c88 --- /dev/null +++ b/panels/thunderbolt/bolt-proxy.h @@ -0,0 +1,97 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include <gio/gio.h> + +G_BEGIN_DECLS + +typedef struct BoltProxySignal +{ + + const char *theirs; + void (*handle)(GObject *self, + GDBusProxy *bus_proxy, + GVariant *params); + +} BoltProxySignal; + +#define BOLT_TYPE_PROXY (bolt_proxy_get_type ()) +G_DECLARE_DERIVABLE_TYPE (BoltProxy, bolt_proxy, BOLT, PROXY, GDBusProxy) + +struct _BoltProxyClass +{ + GDBusProxyClass parent; + + /* virtuals */ + const BoltProxySignal * (*get_dbus_signals) (guint *n); +}; + +gboolean bolt_proxy_get_dbus_property (GObject *proxy, + GParamSpec *spec, + GValue *value); + +gboolean bolt_proxy_has_name_owner (BoltProxy *proxy); + +gboolean bolt_proxy_get_property_bool (BoltProxy *proxy, + const char *name, + gboolean *value); + +gboolean bolt_proxy_get_property_enum (BoltProxy *proxy, + const char *name, + gint *value); + +gboolean bolt_proxy_get_property_flags (BoltProxy *proxy, + const char *name, + guint *value); + +gboolean bolt_proxy_get_property_uint32 (BoltProxy *proxy, + const char *name, + guint *value); + +gboolean bolt_proxy_get_property_int64 (BoltProxy *proxy, + const char *name, + gint64 *value); + +gboolean bolt_proxy_get_property_uint64 (BoltProxy *proxy, + const char *name, + guint64 *value); + +const char * bolt_proxy_get_property_string (BoltProxy *proxy, + const char *name); + +gboolean bolt_proxy_set_property (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GError **error); + +void bolt_proxy_set_property_async (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean bolt_proxy_set_property_finish (GAsyncResult *res, + GError **error); + +G_END_DECLS diff --git a/panels/thunderbolt/bolt-str.c b/panels/thunderbolt/bolt-str.c new file mode 100644 index 000000000..fe0580d48 --- /dev/null +++ b/panels/thunderbolt/bolt-str.c @@ -0,0 +1,117 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "config.h" + +#include "bolt-str.h" + +#include <string.h> + +typedef void (* zero_fn_t) (void *s, + size_t n); +void +bolt_erase_n (void *data, gsize n) +{ +#if !HAVE_FN_EXPLICIT_BZERO + #warning no explicit bzero, using fallback + static volatile zero_fn_t explicit_bzero = bzero; +#endif + + explicit_bzero (data, n); +} + +void +bolt_str_erase (char *str) +{ + if (str == NULL) + return; + + bolt_erase_n (str, strlen (str)); +} + +void +bolt_str_erase_clear (char **str) +{ + g_return_if_fail (str != NULL); + if (*str == NULL) + return; + + bolt_str_erase (*str); + g_free (*str); + *str = NULL; +} + +GStrv +bolt_strv_from_ptr_array (GPtrArray **array) +{ + GPtrArray *a; + + if (array == NULL || *array == NULL) + return NULL; + + a = *array; + + if (a->len == 0 || a->pdata[a->len - 1] != NULL) + g_ptr_array_add (a, NULL); + + *array = NULL; + return (GStrv) g_ptr_array_free (a, FALSE); +} + +char * +bolt_strdup_validate (const char *string) +{ + g_autofree char *str = NULL; + gboolean ok; + gsize l; + + if (string == NULL) + return NULL; + + str = g_strdup (string); + str = g_strstrip (str); + + l = strlen (str); + if (l == 0) + return NULL; + + ok = g_utf8_validate (str, l, NULL); + + if (!ok) + return NULL; + + return g_steal_pointer (&str); +} + +char * +bolt_strstrip (char *string) +{ + char *str; + + if (string == NULL) + return NULL; + + str = g_strstrip (string); + + if (strlen (str) == 0) + g_clear_pointer (&str, g_free); + + return str; +} diff --git a/panels/thunderbolt/bolt-str.h b/panels/thunderbolt/bolt-str.h new file mode 100644 index 000000000..ecf95a7ed --- /dev/null +++ b/panels/thunderbolt/bolt-str.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include <glib.h> +#include <string.h> + +G_BEGIN_DECLS + +void bolt_erase_n (void *data, + gsize n); +void bolt_str_erase (char *str); +void bolt_str_erase_clear (char **str); + +#define bolt_streq(s1, s2) (g_strcmp0 (s1, s2) == 0) + +GStrv bolt_strv_from_ptr_array (GPtrArray **array); + +#define bolt_yesno(val) val ? "yes" : "no" + +char *bolt_strdup_validate (const char *string); + +char *bolt_strstrip (char *string); + +G_END_DECLS diff --git a/panels/thunderbolt/bolt-time.c b/panels/thunderbolt/bolt-time.c new file mode 100644 index 000000000..606aed69a --- /dev/null +++ b/panels/thunderbolt/bolt-time.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2018 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "config.h" + +#include "bolt-time.h" + +char * +bolt_epoch_format (guint64 seconds, const char *format) +{ + g_autoptr(GDateTime) dt = NULL; + + dt = g_date_time_new_from_unix_utc ((gint64) seconds); + + if (dt == NULL) + return NULL; + + return g_date_time_format (dt, format); +} + +guint64 +bolt_now_in_seconds (void) +{ + gint64 now = g_get_real_time (); + + return (guint64) now / G_USEC_PER_SEC; +} diff --git a/panels/thunderbolt/bolt-time.h b/panels/thunderbolt/bolt-time.h new file mode 100644 index 000000000..fc3ed9741 --- /dev/null +++ b/panels/thunderbolt/bolt-time.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2018 Red Hat, Inc + * + * This program 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, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#pragma once + +#include <glib.h> + +G_BEGIN_DECLS + +char * bolt_epoch_format (guint64 seconds, + const char *format); + +guint64 bolt_now_in_seconds (void); + +G_END_DECLS diff --git a/panels/thunderbolt/cc-bolt-device-dialog.c b/panels/thunderbolt/cc-bolt-device-dialog.c new file mode 100644 index 000000000..11469d46c --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-dialog.c @@ -0,0 +1,476 @@ +/* Copyright (C) 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * + */ + +#include <config.h> + +#include <glib/gi18n.h> + +#include "bolt-device.h" +#include "bolt-error.h" +#include "bolt-time.h" + +#include "cc-thunderbolt-resources.h" + +#include "cc-bolt-device-dialog.h" + +struct _CcBoltDeviceDialog +{ + GtkDialog parent; + + BoltClient *client; + BoltDevice *device; + GCancellable *cancel; + + /* main ui */ + GtkHeaderBar *header_bar; + + /* notifications */ + GtkLabel *notify_label; + GtkRevealer *notify_revealer; + + /* device details */ + GtkLabel *name_label; + GtkLabel *status_label; + GtkLabel *uuid_label; + + GtkLabel *time_title; + GtkLabel *time_label; + + /* actions */ + GtkWidget *button_box; + GtkSpinner *spinner; + GtkButton *connect_button; + GtkButton *forget_button; +}; + +static void on_notify_button_clicked_cb (GtkButton *button, + CcBoltDeviceDialog *panel); + +static void on_forget_button_clicked_cb (CcBoltDeviceDialog *dialog); +static void on_connect_button_clicked_cb (CcBoltDeviceDialog *dialog); + +G_DEFINE_TYPE (CcBoltDeviceDialog, cc_bolt_device_dialog, GTK_TYPE_DIALOG); + +#define RESOURCE_UI "/org/gnome/control-center/thunderbolt/cc-bolt-device-dialog.ui" + +static const char * +status_to_string_for_ui (BoltDevice *dev) +{ + BoltStatus status; + BoltAuthFlags aflags; + gboolean nopcie; + + status = bolt_device_get_status (dev); + aflags = bolt_device_get_authflags(dev); + nopcie = bolt_flag_isset (aflags, BOLT_AUTH_NOPCIE); + + switch (status) + { + case BOLT_STATUS_DISCONNECTED: + return C_("Thunderbolt Device Status", "Disconnected"); + + case BOLT_STATUS_CONNECTING: + return C_("Thunderbolt Device Status", "Connecting"); + + case BOLT_STATUS_CONNECTED: + return C_("Thunderbolt Device Status", "Connected"); + + case BOLT_STATUS_AUTH_ERROR: + return C_("Thunderbolt Device Status", "Authorization Error"); + + case BOLT_STATUS_AUTHORIZING: + return C_("Thunderbolt Device Status", "Authorizing"); + + case BOLT_STATUS_AUTHORIZED: + case BOLT_STATUS_AUTHORIZED_NEWKEY: + case BOLT_STATUS_AUTHORIZED_SECURE: + case BOLT_STATUS_AUTHORIZED_DPONLY: + if (nopcie) + return C_("Thunderbolt Device Status", "Reduced Functionality"); + else + return C_("Thunderbolt Device Status", "Connected & Authorized"); + + case BOLT_STATUS_UNKNOWN: + break; /* use default return value, i.e. Unknown */ + } + + return C_("Thunderbolt Device Status", "Unknown"); +} + +static void +dialog_update_from_device (CcBoltDeviceDialog *dialog) +{ + g_autofree char *generated = NULL; + g_autofree char *timestr = NULL; + const char *label; + const char *uuid; + const char *status_brief; + BoltStatus status; + gboolean stored; + BoltDevice *dev; + guint timestamp; + + if (gtk_widget_in_destruction (GTK_WIDGET (dialog))) + return; + + dev = dialog->device; + + uuid = bolt_device_get_uid (dev); + label = bolt_device_get_label (dev); + + stored = bolt_device_is_stored (dev); + status = bolt_device_get_status (dev); + + if (label == NULL) + { + const char *name = bolt_device_get_name (dev); + const char *vendor = bolt_device_get_vendor (dev); + + generated = g_strdup_printf ("%s %s", name, vendor); + label = generated; + } + + gtk_label_set_label (dialog->name_label, label); + gtk_header_bar_set_title (dialog->header_bar, label); + + status_brief = status_to_string_for_ui (dev); + gtk_label_set_label (dialog->status_label, status_brief); + gtk_widget_set_visible (GTK_WIDGET (dialog->forget_button), stored); + + /* while we are having an ongoing operation we are setting the buttons + * to be in-sensitive. In that case, if the button was visible + * before it will be hidden when the operation is finished by the + * dialog_operation_done() function */ + if (gtk_widget_is_sensitive (GTK_WIDGET (dialog->connect_button))) + gtk_widget_set_visible (GTK_WIDGET (dialog->connect_button), + status == BOLT_STATUS_CONNECTED); + + gtk_label_set_label (dialog->uuid_label, uuid); + + if (bolt_status_is_authorized (status)) + { + /* Translators: The time point the device was authorized. */ + gtk_label_set_label (dialog->time_title, _("Authorized at:")); + timestamp = bolt_device_get_authtime (dev); + } + else if (bolt_status_is_connected (status)) + { + /* Translators: The time point the device was connected. */ + gtk_label_set_label (dialog->time_title, _("Connected at:")); + timestamp = bolt_device_get_conntime (dev); + } + else + { + /* Translators: The time point the device was enrolled, + * i.e. authorized and stored in the device database. */ + gtk_label_set_label (dialog->time_title, _("Enrolled at:")); + timestamp = bolt_device_get_storetime (dev); + } + + timestr = bolt_epoch_format (timestamp, "%c"); + gtk_label_set_label (dialog->time_label, timestr); + +} + +static void +on_device_notify_cb (GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data); + + dialog_update_from_device (dialog); +} + +static void +dialog_operation_start (CcBoltDeviceDialog *dialog) +{ + gtk_widget_set_sensitive (GTK_WIDGET (dialog->connect_button), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (dialog->forget_button), FALSE); + gtk_spinner_start (dialog->spinner); +} + +static void +dialog_operation_done (CcBoltDeviceDialog *dialog, + GtkWidget *sender, + GError *error) +{ + GtkWidget *cb = GTK_WIDGET (dialog->connect_button); + GtkWidget *fb = GTK_WIDGET (dialog->forget_button); + + /* don' do anything if we are being destroyed */ + if (gtk_widget_in_destruction (GTK_WIDGET (dialog))) + return; + + /* also don't do anything if the op was canceled */ + if (error != NULL && bolt_err_cancelled (error)) + return; + + gtk_spinner_stop (dialog->spinner); + + if (error != NULL) + { + gtk_label_set_label (dialog->notify_label, error->message); + gtk_revealer_set_reveal_child (dialog->notify_revealer, TRUE); + + /* set the *other* button to sensitive */ + gtk_widget_set_sensitive (cb, cb != sender); + gtk_widget_set_sensitive (fb, fb != sender); + } + else + { + gtk_widget_set_visible (sender, FALSE); + gtk_widget_set_sensitive (cb, TRUE); + gtk_widget_set_sensitive (fb, TRUE); + } +} + +static void +dialog_authorize_done (CcBoltDeviceDialog *dialog, + gboolean ok, + GError *error) +{ + if (!ok) + g_prefix_error (&error, _("Failed to authorize device: ")); + + dialog_operation_done (dialog, GTK_WIDGET (dialog->connect_button), error); +} + +static void +on_device_authorized (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data); + gboolean ok; + + ok = bolt_device_authorize_finish (BOLT_DEVICE (source), res, &err); + dialog_authorize_done (dialog, ok, err); +} + +static void +on_device_enrolled (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data); + gboolean ok; + + ok = bolt_client_enroll_device_finish (dialog->client, res, NULL, &err); + dialog_authorize_done (dialog, ok, err); +} + +static void +on_connect_button_clicked_cb (CcBoltDeviceDialog *dialog) +{ + BoltDevice *device = dialog->device; + gboolean stored; + + g_return_if_fail (device != NULL); + + dialog_operation_start (dialog); + + stored = bolt_device_is_stored (device); + if (stored) + { + bolt_device_authorize_async (device, + BOLT_AUTHCTRL_NONE, + dialog->cancel, + on_device_authorized, + dialog); + } + else + { + const char *uid = bolt_device_get_uid (device); + + bolt_client_enroll_device_async (dialog->client, + uid, + BOLT_POLICY_DEFAULT, + BOLT_AUTHCTRL_NONE, + dialog->cancel, + on_device_enrolled, + dialog); + } + +} + +static void +on_forget_device_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data); + gboolean ok; + + ok = bolt_client_forget_device_finish (dialog->client, res, &err); + + if (!ok) + g_prefix_error (&err, _("Failed to forget device: ")); + + dialog_operation_done (dialog, GTK_WIDGET (dialog->forget_button), err); +} + +static void +on_forget_button_clicked_cb (CcBoltDeviceDialog *dialog) +{ + const char *uid = NULL; + + g_return_if_fail (dialog->device != NULL); + + uid = bolt_device_get_uid (dialog->device); + dialog_operation_start (dialog); + + bolt_client_forget_device_async (dialog->client, + uid, + dialog->cancel, + on_forget_device_done, + dialog); +} + +static void +on_notify_button_clicked_cb (GtkButton *button, + CcBoltDeviceDialog *dialog) +{ + gtk_revealer_set_reveal_child (dialog->notify_revealer, FALSE); +} + + +static void +cc_bolt_device_dialog_finalize (GObject *object) +{ + CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (object); + + g_clear_object (&dialog->device); + g_cancellable_cancel (dialog->cancel); + g_clear_object (&dialog->cancel); + g_clear_object (&dialog->client); + + G_OBJECT_CLASS (cc_bolt_device_dialog_parent_class)->finalize (object); +} + +static void +cc_bolt_device_dialog_class_init (CcBoltDeviceDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = cc_bolt_device_dialog_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, RESOURCE_UI); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, header_bar); + + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, notify_label); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, notify_revealer); + + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, name_label); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, status_label); + + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, uuid_label); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_title); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_label); + + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, button_box); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, spinner); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, connect_button); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, forget_button); + + gtk_widget_class_bind_template_callback (widget_class, on_notify_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, on_connect_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, on_forget_button_clicked_cb); +} + +static void +cc_bolt_device_dialog_init (CcBoltDeviceDialog *dialog) +{ + g_resources_register (cc_thunderbolt_get_resource ()); + gtk_widget_init_template (GTK_WIDGET (dialog)); +} + +/* public functions */ +CcBoltDeviceDialog * +cc_bolt_device_dialog_new (void) +{ + CcBoltDeviceDialog *dialog; + + dialog = g_object_new (CC_TYPE_BOLT_DEVICE_DIALOG, + "use-header-bar", TRUE, + NULL); + return dialog; +} + +void +cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialog, + BoltClient *client) +{ + g_clear_object (&dialog->client); + dialog->client = g_object_ref (client); +} + +void +cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog, + BoltDevice *device) +{ + if (device == dialog->device) + return; + + if (dialog->device) + { + g_cancellable_cancel (dialog->cancel); + g_clear_object (&dialog->cancel); + dialog->cancel = g_cancellable_new (); + + g_signal_handlers_disconnect_by_func (dialog->device, + G_CALLBACK (on_device_notify_cb), + dialog); + g_clear_object (&dialog->device); + } + + if (device == NULL) + return; + + dialog->device = g_object_ref (device); + g_signal_connect_object (dialog->device, + "notify", + G_CALLBACK (on_device_notify_cb), + dialog, + 0); + + /* reset the sensitivity of the buttons, because + * dialog_update_from_device, because it can't know */ + gtk_widget_set_sensitive (GTK_WIDGET (dialog->connect_button), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (dialog->forget_button), TRUE); + + dialog_update_from_device (dialog); +} + +BoltDevice * +cc_bolt_device_dialog_peek_device (CcBoltDeviceDialog *dialog) +{ + return dialog->device; +} + +gboolean +cc_bolt_device_dialog_device_equal (CcBoltDeviceDialog *dialog, + BoltDevice *device) +{ + return dialog->device != NULL && device == dialog->device; +} diff --git a/panels/thunderbolt/cc-bolt-device-dialog.h b/panels/thunderbolt/cc-bolt-device-dialog.h new file mode 100644 index 000000000..bd91eac71 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-dialog.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * + */ + +#pragma once + +#include <gtk/gtk.h> + +#include "bolt-client.h" +#include "bolt-device.h" + +G_BEGIN_DECLS + +#define CC_TYPE_BOLT_DEVICE_DIALOG cc_bolt_device_dialog_get_type () + +G_DECLARE_FINAL_TYPE (CcBoltDeviceDialog, cc_bolt_device_dialog, CC, BOLT_DEVICE_DIALOG, GtkDialog); + +CcBoltDeviceDialog * cc_bolt_device_dialog_new (void); + +void cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialog, + BoltClient *client); + +void cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog, + BoltDevice *device); +BoltDevice * cc_bolt_device_dialog_peek_device (CcBoltDeviceDialog *dialog); + +gboolean cc_bolt_device_dialog_device_equal (CcBoltDeviceDialog *dialog, + BoltDevice *device); + +G_END_DECLS diff --git a/panels/thunderbolt/cc-bolt-device-dialog.ui b/panels/thunderbolt/cc-bolt-device-dialog.ui new file mode 100644 index 000000000..584915a31 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-dialog.ui @@ -0,0 +1,359 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.20.0 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <template class="CcBoltDeviceDialog" parent="GtkDialog"> + <property name="can_focus">False</property> + <property name="type_hint">dialog</property> + <property name="use_header_bar">1</property> + <property name="resizable">False</property> + <property name="modal">True</property> + + <child internal-child="headerbar"> + <object class="GtkHeaderBar" id="header_bar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="show_close_button">True</property> + <property name="title">Device Identifier</property> + <property name="subtitle"></property> + <property name="has-subtitle">False</property> + </object> + </child> + + <child internal-child="vbox"> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="margin-bottom">24</property> + <property name="border-width">0</property> + <child> + <object class="GtkOverlay"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child type="overlay"> + <object class="GtkRevealer" id="notify_revealer"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">start</property> + <property name="transition_type">slide-down</property> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel" id="notify_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </object> + </child> + <child> + <object class="GtkButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">none</property> + <signal name="clicked" + handler="on_notify_button_clicked_cb" + object="CcBoltDeviceDialog" + swapped="no" /> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon-name">window-close-symbolic</property> + </object> + </child> + </object> + </child> + </object> + </child> + <style> + <class name="app-notification" /> + </style> + </object> + </child> + </object> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="expand">True</property> + <property name="orientation">vertical</property> + + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin-left">72</property> + <property name="margin-right">72</property> + <property name="margin-top">24</property> + <property name="margin-bottom">0</property> + <property name="row_spacing">12</property> + <property name="column_spacing">24</property> + <child> + <object class="GtkLabel" id="name_title_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label" translatable="yes">Name:</property> + <property name="justify">right</property> + <property name="xalign">1</property> + <property name="mnemonic_widget">name_label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="name_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="label">Device identifier</property> + <property name="use_markup">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="status_title_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label" translatable="yes">Status:</property> + <property name="justify">right</property> + <property name="xalign">1</property> + <property name="mnemonic_widget">status_label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="status_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="label">Status</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + + <child> + <object class="GtkLabel" id="uuid_title_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label" translatable="yes">UUID:</property> + <property name="justify">right</property> + <property name="xalign">1</property> + <property name="mnemonic_widget">uuid_label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="uuid_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="label">Status</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + + <child> + <object class="GtkLabel" id="time_title"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label">Timestamp:</property> + <property name="justify">right</property> + <property name="xalign">1</property> + <property name="mnemonic_widget">time_label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="time_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="label">Status</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">1</property> + <property name="position">1</property> + </packing> + <object class="GtkSizeGroup" id="device_titles_sizegroup"> + <widgets> + <widget name="name_title_label"/> + <widget name="status_title_label"/> + <widget name="uuid_title_label"/> + <widget name="time_title"/> + </widgets> + </object> + <object class="GtkSizeGroup" id="device_labels_sizegroup"> + <widgets> + <widget name="name_label"/> + <widget name="status_label"/> + <widget name="uuid_label"/> + <widget name="time_label"/> + </widgets> + </object> + </child> + <!-- end of grid --> + <child> + <object class="GtkBox" id="button_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">12</property> + <property name="margin-left">72</property> + <property name="margin-right">72</property> + <property name="margin-top">36</property> + <property name="margin-bottom">0</property> + <property name="halign">fill</property> + <child> + <object class="GtkSpinner" id="spinner"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="active">False</property> + </object> + </child> + + <child> + <object class="GtkButton" id="connect_button"> + <property name="label" translatable="yes">Authorize and Connect</property> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">fill</property> + + <signal name="clicked" + handler="on_connect_button_clicked_cb" + object="CcBoltDeviceDialog" + swapped="yes" /> + <style> + <class name="suggested-action"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <object class="GtkButton" id="forget_button"> + <property name="label" translatable="yes">Forget Device</property> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="halign">fill</property> + <signal name="clicked" + handler="on_forget_button_clicked_cb" + object="CcBoltDeviceDialog" + swapped="yes" /> + <style> + <class name="destructive-action"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkBox" id="spinner_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + </object> + + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + + <object class="GtkSizeGroup" id="actions_sizegroup"> + <widgets> + <widget name="forget_button"/> + <widget name="connect_button"/> + </widgets> + </object> + + <object class="GtkSizeGroup" id="spinner_sizegroup"> + <widgets> + <widget name="spinner"/> + <widget name="spinner_box"/> + </widgets> + </object> + + </child> + </object> + </child> + + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/panels/thunderbolt/cc-bolt-device-entry.c b/panels/thunderbolt/cc-bolt-device-entry.c new file mode 100644 index 000000000..27beaddea --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-entry.c @@ -0,0 +1,218 @@ +/* Copyright (C) 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * + */ + +#include <config.h> + +#include "bolt-str.h" + +#include "cc-bolt-device-entry.h" + +#include "cc-thunderbolt-resources.h" + +#include <glib/gi18n.h> + +#define RESOURCE_UI "/org/gnome/control-center/thunderbolt/cc-bolt-device-entry.ui" + +struct _CcBoltDeviceEntry +{ + GtkListBoxRow parent; + + BoltDevice *device; + + /* main ui */ + GtkLabel *name_label; + GtkLabel *status_label; +}; + +static const char * device_status_to_brief_for_ui (BoltDevice *dev); + +G_DEFINE_TYPE (CcBoltDeviceEntry, cc_bolt_device_entry, GTK_TYPE_LIST_BOX_ROW); + +enum +{ + SIGNAL_STATUS_CHANGED, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = { 0, }; + +static void +entry_set_name (CcBoltDeviceEntry *entry) +{ + g_autofree char *name = NULL; + BoltDevice *dev = entry->device; + + g_return_if_fail (dev != NULL); + + name = bolt_device_get_display_name (dev); + + gtk_label_set_label (entry->name_label, name); +} + +static void +entry_update_status (CcBoltDeviceEntry *entry) +{ + const char *brief; + BoltStatus status; + + status = bolt_device_get_status (entry->device); + brief = device_status_to_brief_for_ui (entry->device); + + gtk_label_set_label (entry->status_label, brief); + + g_signal_emit (entry, + signals[SIGNAL_STATUS_CHANGED], + 0, + status); +} + +static void +on_device_notify_cb (GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + CcBoltDeviceEntry *entry = CC_BOLT_DEVICE_ENTRY (user_data); + const char *what; + + what = g_param_spec_get_name (pspec); + + if (bolt_streq (what, "status")) + entry_update_status (entry); + else if (bolt_streq (what, "label") || + bolt_streq (what, "name") || + bolt_streq (what, "vendor")) + entry_set_name (entry); +} + +/* device helpers */ + +static const char * +device_status_to_brief_for_ui (BoltDevice *dev) +{ + BoltStatus status; + BoltAuthFlags aflags; + gboolean nopcie; + + status = bolt_device_get_status (dev); + aflags = bolt_device_get_authflags(dev); + nopcie = bolt_flag_isset (aflags, BOLT_AUTH_NOPCIE); + + switch (status) + { + case BOLT_STATUS_DISCONNECTED: + return C_("Thunderbolt Device Status", "Disconnected"); + + case BOLT_STATUS_CONNECTING: + return C_("Thunderbolt Device Status", "Connecting"); + + case BOLT_STATUS_CONNECTED: + case BOLT_STATUS_AUTHORIZED_DPONLY: + return C_("Thunderbolt Device Status", "Connected"); + + case BOLT_STATUS_AUTH_ERROR: + return C_("Thunderbolt Device Status", "Error"); + + case BOLT_STATUS_AUTHORIZING: + return C_("Thunderbolt Device Status", "Authorizing"); + + case BOLT_STATUS_AUTHORIZED: + case BOLT_STATUS_AUTHORIZED_NEWKEY: + case BOLT_STATUS_AUTHORIZED_SECURE: + if (nopcie) + return C_("Thunderbolt Device Status", "Connected"); + else + return C_("Thunderbolt Device Status", "Authorized"); + + case BOLT_STATUS_UNKNOWN: + break; /* use function default */ + } + + return C_("Thunderbolt Device Status", "Unknown"); +} + +static void +cc_bolt_device_entry_finalize (GObject *object) +{ + CcBoltDeviceEntry *entry = CC_BOLT_DEVICE_ENTRY (object); + + g_clear_object (&entry->device); + + G_OBJECT_CLASS (cc_bolt_device_entry_parent_class)->finalize (object); +} + +static void +cc_bolt_device_entry_class_init (CcBoltDeviceEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = cc_bolt_device_entry_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, RESOURCE_UI); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceEntry, name_label); + gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceEntry, status_label); + + signals[SIGNAL_STATUS_CHANGED] = + g_signal_new ("status-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, + 1, BOLT_TYPE_STATUS); +} + +static void +cc_bolt_device_entry_init (CcBoltDeviceEntry *entry) +{ + g_resources_register (cc_thunderbolt_get_resource ()); + gtk_widget_init_template (GTK_WIDGET (entry)); +} + +/* public function */ + +CcBoltDeviceEntry * +cc_bolt_device_entry_new (BoltDevice *device) +{ + CcBoltDeviceEntry *entry; + + entry = g_object_new (CC_TYPE_BOLT_DEVICE_ENTRY, NULL); + entry->device = g_object_ref (device); + + entry_set_name (entry); + entry_update_status (entry); + + g_signal_connect_object (entry->device, + "notify", + G_CALLBACK (on_device_notify_cb), + entry, + 0); + + return entry; +} + +BoltDevice * +cc_bolt_device_entry_get_device (CcBoltDeviceEntry *entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (CC_IS_BOLT_DEVICE_ENTRY (entry), NULL); + + return entry->device; +} diff --git a/panels/thunderbolt/cc-bolt-device-entry.h b/panels/thunderbolt/cc-bolt-device-entry.h new file mode 100644 index 000000000..f93cee5f8 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-entry.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * + */ + +#pragma once + +#include <gtk/gtk.h> +#include "bolt-device.h" + +G_BEGIN_DECLS + +#define CC_TYPE_BOLT_DEVICE_ENTRY cc_bolt_device_entry_get_type () +G_DECLARE_FINAL_TYPE (CcBoltDeviceEntry, cc_bolt_device_entry, CC, BOLT_DEVICE_ENTRY, GtkListBoxRow); + + +CcBoltDeviceEntry * cc_bolt_device_entry_new (BoltDevice *device); +BoltDevice * cc_bolt_device_entry_get_device (CcBoltDeviceEntry *entry); + +G_END_DECLS diff --git a/panels/thunderbolt/cc-bolt-device-entry.ui b/panels/thunderbolt/cc-bolt-device-entry.ui new file mode 100644 index 000000000..d1ada1856 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-device-entry.ui @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.20"/> + + <template class="CcBoltDeviceEntry" parent="GtkListBoxRow"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="activatable">True</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="border-width">12</property> + <property name="margin_left">6</property> + <property name="margin_right">6</property> + <property name="column-spacing">12</property> + <property name="row-spacing">2</property> + <child> + <object class="GtkLabel" id="name_label"> + <property name="ellipsize">end</property> + <property name="use-markup">True</property> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="label">Device Name</property> + <property name="xalign">0.0</property> + <property name="valign">center</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="status_label"> + <property name="visible">True</property> + <property name="hexpand">False</property> + <property name="label">Status</property> + <property name="halign">end</property> + <property name="valign">center</property> + <property name="xalign">1.0</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">0</property> + </packing> + </child> + </object> + </child> + </template> +</interface> diff --git a/panels/thunderbolt/cc-bolt-panel.c b/panels/thunderbolt/cc-bolt-panel.c new file mode 100644 index 000000000..a4face5b3 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-panel.c @@ -0,0 +1,959 @@ +/* Copyright © 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * + */ + +#include <config.h> + +#include <shell/cc-panel.h> +#include <list-box-helper.h> + +#include <glib/gi18n.h> +#include <polkit/polkit.h> + +#include "cc-bolt-device-dialog.h" +#include "cc-bolt-device-entry.h" + +#include "bolt-client.h" +#include "bolt-str.h" + +#include "cc-bolt-panel.h" +#include "cc-thunderbolt-resources.h" + +struct _CcBoltPanel +{ + CcPanel parent; + + BoltClient *client; + GCancellable *cancel; + + /* headerbar menu */ + GtkBox *headerbar_box; + GtkLockButton *lock_button; + + /* main ui */ + GtkStack *container; + + /* empty state */ + GtkLabel *notb_caption; + GtkLabel *notb_details; + + /* notifications */ + GtkLabel *notification_label; + GtkRevealer *notification_revealer; + + /* authmode */ + GtkSwitch *authmode_switch; + GtkSpinner *authmode_spinner; + GtkStack *authmode_mode; + + /* device list */ + GHashTable *devices; + + GtkStack *devices_stack; + GtkBox *devices_box; + GtkBox *pending_box; + + GtkListBox *devices_list; + GtkListBox *pending_list; + + /* device details dialog */ + CcBoltDeviceDialog *device_dialog; + + /* polkit integration */ + GPermission *permission; +}; + +/* initialization */ +static void bolt_client_ready (GObject *source, + GAsyncResult *res, + gpointer user_data); + +/* panel functions */ +static void cc_bolt_panel_set_no_thunderbolt (CcBoltPanel *panel, + const char *custom_msg); + +static void cc_bolt_panel_name_owner_changed (CcBoltPanel *panel); + +static CcBoltDeviceEntry * cc_bolt_panel_add_device (CcBoltPanel *panel, + BoltDevice *dev); + +static void cc_bolt_panel_del_device_entry (CcBoltPanel *panel, + CcBoltDeviceEntry *entry); + +static void cc_bolt_panel_authmode_sync (CcBoltPanel *panel); + +static void cc_panel_list_box_migrate (CcBoltPanel *panel, + GtkListBox *from, + GtkListBox *to, + CcBoltDeviceEntry *entry); + +/* bolt client signals */ +static void on_bolt_name_owner_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data); + +static void on_bolt_device_added_cb (BoltClient *cli, + const char *path, + CcBoltPanel *panel); + +static void on_bolt_device_removed_cb (BoltClient *cli, + const char *opath, + CcBoltPanel *panel); + +static void on_bolt_notify_authmode_cb (GObject *gobject, + GParamSpec *pspec, + gpointer user_data); + +/* panel signals */ +static gboolean on_authmode_state_set_cb (CcBoltPanel *panel, + gboolean state, + GtkSwitch *toggle); + +static void on_device_entry_row_activated_cb (CcBoltPanel *panel, + GtkListBoxRow *row); + +static gboolean on_device_dialog_delete_event_cb (GtkWidget *widget, + GdkEvent *event, + CcBoltPanel *panel); + +static void on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry, + BoltStatus new_status, + CcBoltPanel *panel); + +static void on_notification_button_clicked_cb (GtkButton *button, + CcBoltPanel *panel); + + +/* polkit */ +static void on_permission_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data); + +static void on_permission_notify_cb (GPermission *permission, + GParamSpec *pspec, + CcBoltPanel *panel); + +CC_PANEL_REGISTER (CcBoltPanel, cc_bolt_panel); + +static void +bolt_client_ready (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + g_autoptr(CcBoltPanel) panel = NULL; + BoltClient *client; + + panel = CC_BOLT_PANEL (user_data); + client = bolt_client_new_finish (res, &err); + + if (client == NULL) + { + const char *text; + + /* operation got cancelled because the panel got destroyed */ + if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + g_error_matches (err, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED)) + return; + + g_warning ("Could not create client: %s", err->message); + text = _("The Thunderbolt subsystem (boltd) is not installed or " + "not set up properly."); + + gtk_label_set_label (panel->notb_details, text); + gtk_stack_set_visible_child_name (panel->container, "no-thunderbolt"); + + return; + } + + g_signal_connect_object (client, + "notify::g-name-owner", + G_CALLBACK (on_bolt_name_owner_changed_cb), + panel, + 0); + + g_signal_connect_object (client, + "device-added", + G_CALLBACK (on_bolt_device_added_cb), + panel, + 0); + + g_signal_connect_object (client, + "device-removed", + G_CALLBACK (on_bolt_device_removed_cb), + panel, + 0); + + g_signal_connect_object (client, + "notify::auth-mode", + G_CALLBACK (on_bolt_notify_authmode_cb), + panel, + 0); + + panel->client = client; + + cc_bolt_device_dialog_set_client (panel->device_dialog, client); + + cc_bolt_panel_authmode_sync (panel); + + g_object_bind_property (panel->authmode_switch, + "active", + panel->devices_box, + "sensitive", + G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + + g_object_bind_property (panel->authmode_switch, + "active", + panel->pending_box, + "sensitive", + G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + + gtk_stack_set_visible_child_name (panel->devices_stack, "no-devices"); + cc_bolt_panel_name_owner_changed (panel); +} + +static gboolean +devices_table_transfer_entry (GHashTable *from, + GHashTable *to, + gconstpointer key) +{ + gpointer k, v; + gboolean found; + + found = g_hash_table_lookup_extended (from, key, &k, &v); + + if (found) + { + g_hash_table_steal (from, key); + g_hash_table_insert (to, k, v); + } + + return found; +} + +static void +devices_table_clear_entries (GHashTable *table, + CcBoltPanel *panel) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, table); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + CcBoltDeviceEntry *entry = value; + + cc_bolt_panel_del_device_entry (panel, entry); + g_hash_table_iter_remove (&iter); + } +} + +static void +devices_table_synchronize (CcBoltPanel *panel) +{ + g_autoptr(GHashTable) old = NULL; + g_autoptr(GPtrArray) devices = NULL; + g_autoptr(GError) err = NULL; + guint i; + + devices = bolt_client_list_devices (panel->client, panel->cancel, &err); + + if (!devices) + { + g_warning ("Could not list devices: %s", err->message); + devices = g_ptr_array_new_with_free_func (g_object_unref); + } + + old = panel->devices; + panel->devices = g_hash_table_new (g_str_hash, g_str_equal); + + for (i = 0; i < devices->len; i++) + { + BoltDevice *dev = g_ptr_array_index (devices, i); + const char *path; + gboolean found; + + path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev)); + found = devices_table_transfer_entry (old, panel->devices, path); + + if (found) + continue; + + cc_bolt_panel_add_device (panel, dev); + } + + devices_table_clear_entries (old, panel); + gtk_stack_set_visible_child_name (panel->container, "devices-listing"); +} + +static gboolean +list_box_sync_visible (GtkListBox *lstbox) +{ + g_autoptr(GList) children = NULL; + gboolean show; + + children = gtk_container_get_children (GTK_CONTAINER (lstbox)); + show = g_list_length (children) > 0; + + gtk_widget_set_visible (GTK_WIDGET (lstbox), show); + + return show; +} + +static GtkWidget * +cc_bolt_panel_box_for_listbox (CcBoltPanel *panel, + GtkListBox *lstbox) +{ + if ((gpointer) lstbox == panel->devices_list) + return GTK_WIDGET (panel->devices_box); + else if ((gpointer) lstbox == panel->pending_list) + return GTK_WIDGET (panel->pending_box); + + g_return_val_if_reached (NULL); +} + +static CcBoltDeviceEntry * +cc_bolt_panel_add_device (CcBoltPanel *panel, + BoltDevice *dev) +{ + CcBoltDeviceEntry *entry; + BoltDeviceType type; + BoltStatus status; + const char *path; + + type = bolt_device_get_device_type (dev); + + if (type != BOLT_DEVICE_PERIPHERAL) + return FALSE; + + entry = cc_bolt_device_entry_new (dev); + path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev)); + + /* add to the list box */ + gtk_widget_show_all (GTK_WIDGET (entry)); + + status = bolt_device_get_status (dev); + + if (bolt_status_is_pending (status)) + { + gtk_container_add (GTK_CONTAINER (panel->pending_list), GTK_WIDGET (entry)); + gtk_widget_show_all (GTK_WIDGET (panel->pending_list)); + gtk_widget_show_all (GTK_WIDGET (panel->pending_box)); + } + else + { + gtk_container_add (GTK_CONTAINER (panel->devices_list), GTK_WIDGET (entry)); + gtk_widget_show_all (GTK_WIDGET (panel->devices_list)); + gtk_widget_show_all (GTK_WIDGET (panel->devices_box)); + } + + g_signal_connect_object (entry, + "status-changed", + G_CALLBACK (on_device_entry_status_changed_cb), + panel, + 0); + + gtk_stack_set_visible_child_name (panel->devices_stack, "have-devices"); + g_hash_table_insert (panel->devices, (gpointer) path, entry); + + return entry; +} + +static void +cc_bolt_panel_del_device_entry (CcBoltPanel *panel, + CcBoltDeviceEntry *entry) +{ + BoltDevice *dev; + GtkWidget *box; + GtkWidget *p; + gboolean show; + + dev = cc_bolt_device_entry_get_device (entry); + if (cc_bolt_device_dialog_device_equal (panel->device_dialog, dev)) + { + gtk_widget_hide (GTK_WIDGET (panel->device_dialog)); + cc_bolt_device_dialog_set_device (panel->device_dialog, NULL); + } + + p = gtk_widget_get_parent (GTK_WIDGET (entry)); + gtk_widget_destroy (GTK_WIDGET (entry)); + + box = cc_bolt_panel_box_for_listbox (panel, GTK_LIST_BOX (p)); + show = list_box_sync_visible (GTK_LIST_BOX (p)); + gtk_widget_set_visible (box, show); + + if (!gtk_widget_is_visible (GTK_WIDGET (panel->pending_list)) && + !gtk_widget_is_visible (GTK_WIDGET (panel->devices_list))) + { + gtk_stack_set_visible_child_name (panel->devices_stack, "no-devices"); + } +} + +static void +cc_bolt_panel_authmode_sync (CcBoltPanel *panel) +{ + BoltClient *client = panel->client; + BoltAuthMode mode; + gboolean enabled; + const char *name; + + mode = bolt_client_get_authmode (client); + enabled = (mode & BOLT_AUTH_ENABLED) != 0; + + g_signal_handlers_block_by_func (panel->authmode_switch, on_authmode_state_set_cb, panel); + + gtk_switch_set_state (panel->authmode_switch, enabled); + + g_signal_handlers_unblock_by_func (panel->authmode_switch, on_authmode_state_set_cb, panel); + + name = enabled ? "enabled" : "disabled"; + gtk_stack_set_visible_child_name (panel->authmode_mode, name); +} + +static void +cc_panel_list_box_migrate (CcBoltPanel *panel, + GtkListBox *from, + GtkListBox *to, + CcBoltDeviceEntry *entry) +{ + GtkWidget *from_box; + GtkWidget *to_box; + gboolean show; + GtkWidget *target; + + target = GTK_WIDGET (entry); + + gtk_container_remove (GTK_CONTAINER (from), target); + gtk_container_add (GTK_CONTAINER (to), target); + gtk_widget_show_all (GTK_WIDGET (to)); + + from_box = cc_bolt_panel_box_for_listbox (panel, from); + to_box = cc_bolt_panel_box_for_listbox (panel, to); + + show = list_box_sync_visible (from); + gtk_widget_set_visible (from_box, show); + gtk_widget_set_visible (to_box, TRUE); +} + +/* bolt client signals */ +static void +cc_bolt_panel_set_no_thunderbolt (CcBoltPanel *panel, + const char *msg) +{ + if (!msg) + { + msg = _("Thunderbolt could not be detected.\n" + "Either the system lacks Thunderbolt support, " + "it has been disabled in the BIOS or is set to " + "an unsupported security level in the BIOS."); + } + + gtk_label_set_label (panel->notb_details, msg); + gtk_stack_set_visible_child_name (panel->container, "no-thunderbolt"); +} + +static void +cc_bolt_panel_name_owner_changed (CcBoltPanel *panel) +{ + BoltClient *client = panel->client; + BoltSecurity sl; + gboolean notb = TRUE; + const char *text = NULL; + const char *name_owner; + + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (panel->client)); + + if (name_owner == NULL) + { + cc_bolt_panel_set_no_thunderbolt (panel, NULL); + devices_table_clear_entries (panel->devices, panel); + gtk_widget_hide (GTK_WIDGET (panel->headerbar_box)); + return; + } + + gtk_stack_set_visible_child_name (panel->container, "loading"); + + sl = bolt_client_get_security (client); + + switch (sl) + { + case BOLT_SECURITY_NONE: + case BOLT_SECURITY_SECURE: + case BOLT_SECURITY_USER: + /* we fetch the device list and show them here */ + notb = FALSE; + break; + + case BOLT_SECURITY_DPONLY: + case BOLT_SECURITY_USBONLY: + text = _("Thunderbolt support has been disabled in the BIOS."); + break; + + case BOLT_SECURITY_UNKNOWN: + text = NULL; + break; + } + + if (notb) + { + /* security level is unknown or un-handled */ + cc_bolt_panel_set_no_thunderbolt (panel, text); + return; + } + + if (panel->permission) + { + gtk_widget_show (GTK_WIDGET (panel->headerbar_box)); + } + else + { + polkit_permission_new ("org.freedesktop.bolt.manage", + NULL, + panel->cancel, + on_permission_ready, + g_object_ref (panel)); + } + + devices_table_synchronize (panel); +} + +/* bolt client signals */ +static void +on_bolt_name_owner_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + cc_bolt_panel_name_owner_changed (CC_BOLT_PANEL (user_data)); +} + +static void +on_bolt_device_added_cb (BoltClient *cli, + const char *path, + CcBoltPanel *panel) +{ + g_autoptr(GError) err = NULL; + GDBusConnection *bus; + BoltDevice *dev; + gboolean found; + + found = g_hash_table_contains (panel->devices, path); + + if (found) + return; + + bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (panel->client)); + dev = bolt_device_new_for_object_path (bus, path, panel->cancel, &err); + + if (!dev) + { + g_warning ("Could not create proxy for %s", path); + return; + } + + cc_bolt_panel_add_device (panel, dev); +} + +static void +on_bolt_device_removed_cb (BoltClient *cli, + const char *path, + CcBoltPanel *panel) +{ + CcBoltDeviceEntry *entry; + + entry = g_hash_table_lookup (panel->devices, path); + + if (!entry) + return; + + cc_bolt_panel_del_device_entry (panel, entry); + g_hash_table_remove (panel->devices, path); +} + +static void +on_bolt_notify_authmode_cb (GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + cc_bolt_panel_authmode_sync (CC_BOLT_PANEL (user_data)); +} + +/* panel signals */ + +static void +on_authmode_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + CcBoltPanel *panel = CC_BOLT_PANEL (user_data); + gboolean ok; + + ok = bolt_client_set_authmode_finish (BOLT_CLIENT (source_object), res, &error); + if (!ok) + { + g_autofree char *text; + + g_warning ("Could not set authmode: %s", error->message); + + text = g_strdup_printf (_("Error switching direct mode: %s"), error->message); + gtk_label_set_markup (panel->notification_label, text); + gtk_revealer_set_reveal_child (panel->notification_revealer, TRUE); + + /* make sure we are reflecting the correct state */ + cc_bolt_panel_authmode_sync (panel); + } + + gtk_spinner_stop (panel->authmode_spinner); + gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), TRUE); +} + +static gboolean +on_authmode_state_set_cb (CcBoltPanel *panel, + gboolean enable, + GtkSwitch *toggle) +{ + BoltClient *client = panel->client; + BoltAuthMode mode; + + gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), FALSE); + gtk_spinner_start (panel->authmode_spinner); + + mode = bolt_client_get_authmode (client); + + if (enable) + mode = mode | BOLT_AUTH_ENABLED; + else + mode = mode & ~BOLT_AUTH_ENABLED; + + bolt_client_set_authmode_async (client, mode, NULL, on_authmode_ready, panel); + + return TRUE; +} + +static void +on_device_entry_row_activated_cb (CcBoltPanel *panel, + GtkListBoxRow *row) +{ + CcBoltDeviceEntry *entry; + BoltDevice *device; + + if (!CC_IS_BOLT_DEVICE_ENTRY (row)) + return; + + entry = CC_BOLT_DEVICE_ENTRY (row); + device = cc_bolt_device_entry_get_device (entry); + + cc_bolt_device_dialog_set_device (panel->device_dialog, device); + gtk_window_resize (GTK_WINDOW (panel->device_dialog), 1, 1); + gtk_widget_show (GTK_WIDGET (panel->device_dialog)); +} + +static gboolean +on_device_dialog_delete_event_cb (GtkWidget *widget, + GdkEvent *event, + CcBoltPanel *panel) +{ + CcBoltDeviceDialog *dialog; + + dialog = CC_BOLT_DEVICE_DIALOG (widget); + + cc_bolt_device_dialog_set_device (dialog, NULL); + gtk_widget_hide (widget); + + return TRUE; +} + +static void +on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry, + BoltStatus new_status, + CcBoltPanel *panel) +{ + GtkListBox *from = NULL; + GtkListBox *to = NULL; + GtkWidget *p; + gboolean is_pending; + gboolean parent_pending; + + /* if we are doing some active work, then lets not change + * the list the entry is in; otherwise we might just hop + * from one box to the other and back again. + */ + if (new_status == BOLT_STATUS_CONNECTING || new_status == BOLT_STATUS_AUTHORIZING) + return; + + is_pending = bolt_status_is_pending (new_status); + + p = gtk_widget_get_parent (GTK_WIDGET (entry)); + parent_pending = (gpointer) p == panel->pending_list; + + /* */ + if (is_pending && !parent_pending) + { + from = panel->devices_list; + to = panel->pending_list; + } + else if (!is_pending && parent_pending) + { + from = panel->pending_list; + to = panel->devices_list; + } + + if (from && to) + cc_panel_list_box_migrate (panel, from, to, entry); +} + + +static void +on_notification_button_clicked_cb (GtkButton *button, + CcBoltPanel *panel) +{ + gtk_revealer_set_reveal_child (panel->notification_revealer, FALSE); +} + +/* polkit */ + +static void +on_permission_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(CcBoltPanel) panel = user_data; + g_autoptr(GError) err = NULL; + GPermission *permission; + gboolean is_allowed; + const char *name; + + permission = polkit_permission_new_finish (res, &err); + panel->permission = permission; + + if (!panel->permission) + { + g_warning ("Could not get polkit permissions: %s", err->message); + return; + } + + g_signal_connect_object (permission, + "notify", + G_CALLBACK (on_permission_notify_cb), + panel, + G_CONNECT_AFTER); + + is_allowed = g_permission_get_allowed (permission); + gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), is_allowed); + gtk_lock_button_set_permission (panel->lock_button, permission); + + name = gtk_stack_get_visible_child_name (panel->container); + + gtk_widget_set_visible (GTK_WIDGET (panel->headerbar_box), + bolt_streq (name, "devices-listing")); +} + +static void +on_permission_notify_cb (GPermission *permission, + GParamSpec *pspec, + CcBoltPanel *panel) +{ + gboolean is_allowed = g_permission_get_allowed (permission); + + gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), is_allowed); +} + +static gint +device_entries_sort_by_recency_cb (GtkListBoxRow *a_row, + GtkListBoxRow *b_row, + gpointer user_data) +{ + CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row); + CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row); + BoltDevice *a = cc_bolt_device_entry_get_device (a_entry); + BoltDevice *b = cc_bolt_device_entry_get_device (b_entry); + BoltStatus status; + gint64 a_ts, b_ts; + gint64 score; + + a_ts = (gint64) bolt_device_get_timestamp (a); + b_ts = (gint64) bolt_device_get_timestamp (b); + + score = b_ts - a_ts; + + if (score != 0) + return score; + + status = bolt_device_get_status (a); + + if (bolt_status_is_connected (status)) + { + const char *a_path; + const char *b_path; + + a_path = bolt_device_get_syspath (a); + b_path = bolt_device_get_syspath (b); + + return g_strcmp0 (a_path, b_path); + } + else + { + const char *a_name; + const char *b_name; + + a_name = bolt_device_get_name (a); + b_name = bolt_device_get_name (b); + + return g_strcmp0 (a_name, b_name); + } + + return 0; +} + +static gint +device_entries_sort_by_syspath_cb (GtkListBoxRow *a_row, + GtkListBoxRow *b_row, + gpointer user_data) +{ + CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row); + CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row); + BoltDevice *a = cc_bolt_device_entry_get_device (a_entry); + BoltDevice *b = cc_bolt_device_entry_get_device (b_entry); + + const char *a_path; + const char *b_path; + + a_path = bolt_device_get_syspath (a); + b_path = bolt_device_get_syspath (b); + + return g_strcmp0 (a_path, b_path); +} + +/* GObject overrides */ + +static void +cc_bolt_panel_finalize (GObject *object) +{ + CcBoltPanel *panel = CC_BOLT_PANEL (object); + + g_clear_object (&panel->client); + g_clear_pointer (&panel->devices, g_hash_table_unref); + g_clear_object (&panel->permission); + + G_OBJECT_CLASS (cc_bolt_panel_parent_class)->finalize (object); +} + +static void +cc_bolt_panel_dispose (GObject *object) +{ + CcBoltPanel *panel = CC_BOLT_PANEL (object); + + /* cancel any ongoing operation */ + g_cancellable_cancel (panel->cancel); + + /* Must be destroyed in dispose, not finalize. */ + g_clear_pointer (&panel->device_dialog, gtk_widget_destroy); + + G_OBJECT_CLASS (cc_bolt_panel_parent_class)->dispose (object); +} + +static void +cc_bolt_panel_constructed (GObject *object) +{ + CcBoltPanel *panel = CC_BOLT_PANEL (object); + GtkWindow *parent; + CcShell *shell; + + parent = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel)))); + gtk_window_set_transient_for (GTK_WINDOW (panel->device_dialog), parent); + + G_OBJECT_CLASS (cc_bolt_panel_parent_class)->constructed (object); + + shell = cc_panel_get_shell (CC_PANEL (panel)); + cc_shell_embed_widget_in_header (shell, GTK_WIDGET (panel->headerbar_box)); +} + +static void +cc_bolt_panel_class_init (CcBoltPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->constructed = cc_bolt_panel_constructed; + object_class->dispose = cc_bolt_panel_dispose; + object_class->finalize = cc_bolt_panel_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/thunderbolt/cc-bolt-panel.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, authmode_mode); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, authmode_spinner); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, authmode_switch); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, container); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_list); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_box); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_stack); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, headerbar_box); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, lock_button); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notb_caption); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notb_details); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notification_label); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notification_revealer); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, pending_box); + gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, pending_list); + + gtk_widget_class_bind_template_callback (widget_class, on_notification_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, on_authmode_state_set_cb); + gtk_widget_class_bind_template_callback (widget_class, on_device_entry_row_activated_cb); +} + +static void +cc_bolt_panel_init (CcBoltPanel *panel) +{ + g_resources_register (cc_thunderbolt_get_resource ()); + + gtk_widget_init_template (GTK_WIDGET (panel)); + + gtk_stack_set_visible_child_name (panel->container, "loading"); + + gtk_list_box_set_header_func (panel->devices_list, + cc_list_box_update_header_func, + NULL, + NULL); + + gtk_list_box_set_header_func (panel->pending_list, + cc_list_box_update_header_func, + NULL, + NULL); + + gtk_list_box_set_sort_func (panel->devices_list, + device_entries_sort_by_recency_cb, + panel, + NULL); + + gtk_list_box_set_sort_func (panel->pending_list, + device_entries_sort_by_syspath_cb, + panel, + NULL); + + panel->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); + + panel->device_dialog = cc_bolt_device_dialog_new (); + g_signal_connect_object (panel->device_dialog, + "delete-event", + G_CALLBACK (on_device_dialog_delete_event_cb), + panel, 0); + + panel->cancel = g_cancellable_new (); + bolt_client_new_async (panel->cancel, bolt_client_ready, g_object_ref (panel)); + +} diff --git a/shell/cc-shell-log.h b/panels/thunderbolt/cc-bolt-panel.h index 132a19dcf..5901044e8 100644 --- a/shell/cc-shell-log.h +++ b/panels/thunderbolt/cc-bolt-panel.h @@ -1,6 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2009 Red Hat, Inc. +/* Copyright © 2018 Red Hat, Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,18 +13,18 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. * + * Authors: Christian J. Kellner <ckellner@redhat.com> + * */ -#ifndef __CC_SHELL_LOG_H -#define __CC_SHELL_LOG_H +#pragma once -#include <glib.h> +#include <glib-object.h> G_BEGIN_DECLS -void cc_shell_log_init (void); -void cc_shell_log_set_debug (gboolean debug); +#define CC_TYPE_BOLT_PANEL cc_bolt_panel_get_type () -G_END_DECLS +G_DECLARE_FINAL_TYPE (CcBoltPanel, cc_bolt_panel, CC, BOLT_PANEL, CcPanel); -#endif /* __CC_SHELL_LOG_H */ +G_END_DECLS diff --git a/panels/thunderbolt/cc-bolt-panel.ui b/panels/thunderbolt/cc-bolt-panel.ui new file mode 100644 index 000000000..226353c64 --- /dev/null +++ b/panels/thunderbolt/cc-bolt-panel.ui @@ -0,0 +1,594 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.20"/> + + <template class="CcBoltPanel" parent="CcPanel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + + <child> + <object class="GtkOverlay"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child type="overlay"> + <object class="GtkRevealer" id="notification_revealer"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">start</property> + <property name="transition_type">slide-down</property> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel" id="notification_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </object> + </child> + <child> + <object class="GtkButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">none</property> + <signal name="clicked" + handler="on_notification_button_clicked_cb" + object="CcBoltPanel" + swapped="no" /> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon-name">window-close-symbolic</property> + </object> + </child> + </object> + </child> + </object> + </child> + <style> + <class name="app-notification" /> + </style> + </object> + </child> + </object> + </child> + + <child> + <object class="GtkStack" id="container"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="homogeneous">False</property> + <property name="transition_type">crossfade</property> + + <!-- Spinner for when we are creating --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="expand">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="orientation">vertical</property> + <property name="spacing">10</property> + <property name="margin">18</property> + <child type="center"> + <object class="GtkSpinner" id="loading-spinner"> + <property name="visible">True</property> + <property name="active">True</property> + <property name="expand">True</property> + </object> + </child> + </object> + <packing> + <property name="name">loading</property> + </packing> + </child> + + <!-- No tunderbolt --> + + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="expand">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="orientation">vertical</property> + <property name="spacing">10</property> + <property name="margin">18</property> + <child type="center" > + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="margin_end">6</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</property> + <property name="row_spacing">12</property> + <property name="column_spacing">24</property> + + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">thunderbolt-symbolic</property> + <property name="pixel_size">96</property> + <property name="yalign">0</property> + <style> + <class name="dim-label" /> + </style> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="height">2</property> + </packing> + </child> + + <child> + <object class="GtkLabel" id="notb_caption"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="wrap">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">No Thunderbolt support</property> + <attributes> + <attribute name="scale" value="1.2" /> + </attributes> + <style> + <class name="dim-label" /> + </style> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + + <child> + <object class="GtkLabel" id="notb_details"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="max-width-chars">40</property> + <property name="use_markup">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="wrap">True</property> + <property name="label" translatable="no">Could not connect to the thunderbolt subsystem.</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + + </object> + </child> + + </object> + <packing> + <property name="name">no-thunderbolt</property> + </packing> + </child> + + <!-- Normal operation mode (show list of devices) --> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hscrollbar-policy">never</property> + + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="shadow-type">none</property> + + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">horizontal</property> + <property name="valign">start</property> + + <!-- Stub box --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + </object> + </child> + + <!-- center/content box --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="spacing">32</property> + <property name="margin_top">32</property> + <property name="margin_bottom">32</property> + <property name="margin_left">18</property> + <property name="margin_right">18</property> + <property name="orientation">vertical</property> + + <!-- Auth Mode --> + <child> + <object class="GtkBox" id="authmode_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">12</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">False</property> + <property name="halign">start</property> + <property name="xalign">0.0</property> + <property name="label" translatable="yes">Direct Access</property> + <property name="mnemonic_widget">authmode_switch</property> + <attributes> + <attribute name="weight" value="bold" /> + </attributes> + </object> + </child> + + <child> + <object class="GtkStack" id="authmode_mode"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="transition-type">crossfade</property> + <property name="homogeneous">True</property> + + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_left">0</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label" translatable="yes" >Allow direct access to devices such as docks and external GPUs.</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + <property name="xalign">0.0</property> + <property name="yalign">0.0</property> + <property name="max-width-chars">45</property> + </object> + <packing> + <property name="name">enabled</property> + </packing> + </child> + + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_left">0</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="label" translatable="yes" >Only USB and Display Port devices can attach.</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + <property name="xalign">0.0</property> + <property name="yalign">0.0</property> + <property name="max-width-chars">45</property> + </object> + <packing> + <property name="name">disabled</property> + </packing> + </child> + + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">6</property> + <property name="halign">center</property> + <property name="valign">start</property> + + <child> + <object class="GtkSpinner" id="authmode_spinner"> + <property name="visible">True</property> + <property name="active">False</property> + </object> + </child> + + <child> + <object class="GtkSwitch" id="authmode_switch"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="halign">end</property> + <property name="valign">start</property> + <property name="active">True</property> + <signal name="state-set" + handler="on_authmode_state_set_cb" + object="CcBoltPanel" + swapped="yes" /> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + <property name="pack-type">end</property> + </packing> + </child> + </object> + </child> + + <!-- Stack: devices/no-devices --> + <child> + <object class="GtkStack" id="devices_stack"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="transition-type">crossfade</property> + + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">32</property> + + <!-- Pending Device List --> + <child> + <object class="GtkBox" id="pending_box"> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + + <!-- Pending Device List: Header --> + <child> + <object class="GtkBox" id="pending_header"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">start</property> + <property name="spacing">6</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">dialog-warning-symbolic</property> + <property name="icon_size">1</property> + <property name="margin_left">0</property> + <property name="xalign">0.0</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Pending Devices</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkSpinner" id="pending_spinner"> + <property name="hexpand">True</property> + <property name="visible">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + + <!-- Pending List: Devices --> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="valign">start</property> + <property name="vexpand">False</property> + <style> + <class name="view" /> + </style> + <child> + <object class="GtkListBox" id="pending_list"> + <property name="visible">True</property> + <property name="selection-mode">none</property> + <property name="can_focus">True</property> + <signal name="row-activated" + handler="on_device_entry_row_activated_cb" + object="CcBoltPanel" + swapped="yes" /> + </object> + </child> + </object> + </child> + </object> + </child> + + <!-- Device List --> + <child> + <object class="GtkBox" id="devices_box"> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + + <!-- Device List: Header --> + <child> + <object class="GtkBox" id="devices_header"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">start</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Devices</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + <child> + <object class="GtkSpinner" id="probing_spinner"> + <property name="hexpand">True</property> + <property name="visible">True</property> + </object> + </child> + </object> + </child> + + <!-- Device List: Devices --> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="valign">start</property> + <property name="vexpand">False</property> + <style> + <class name="view" /> + </style> + <child> + <object class="GtkListBox" id="devices_list"> + <property name="visible">True</property> + <property name="selection-mode">none</property> + <property name="can_focus">True</property> + <signal name="row-activated" + handler="on_device_entry_row_activated_cb" + object="CcBoltPanel" + swapped="yes" /> + </object> + </child> + </object> + </child> + + </object> + </child> + + </object> + <packing> + <property name="name">have-devices</property> + </packing> + </child> + + <!-- No Devices --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">start</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Devices</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">No devices attached</property> + <property name="xalign">0.0</property> + </object> + </child> + </object> + <packing> + <property name="name">no-devices</property> + </packing> + </child> <!-- End of: No Devices --> + + </object> + </child> <!-- End of Stack: devices/no-devices --> + + </object> + </child> <!-- End of enter/content box --> + + + <!-- Stub box --> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + </object> + </child> + + <!-- End of content --> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">devices-listing</property> + </packing> + </child> + + <!-- End of 'container' --> + </object> + </child> + + <!-- End of overlay --> + </object> + </child> + </template> + + <!-- Headerbar entries --> + <object class="GtkBox" id="headerbar_box"> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <property name="halign">end</property> + <child> + <object class="GtkLockButton" id="lock_button"> + <property name="visible">True</property> + </object> + </child> + </object> + +</interface> diff --git a/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in b/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in new file mode 100644 index 000000000..12ba0330c --- /dev/null +++ b/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in @@ -0,0 +1,18 @@ +[Desktop Entry] +Name=Thunderbolt +Comment=Manage Thunderbolt devices +Exec=gnome-control-center thunderbolt +# Translators: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=thunderbolt +Terminal=false +Type=Application +NoDisplay=true +StartupNotify=true +Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;HardwareSettings;X-GNOME-DevicesSettings; +OnlyShowIn=GNOME;Unity; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-control-center +X-GNOME-Bugzilla-Component=thunderbolt +X-GNOME-Bugzilla-Version=@VERSION@ +# Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +Keywords=Thunderbolt; diff --git a/panels/thunderbolt/meson.build b/panels/thunderbolt/meson.build new file mode 100644 index 000000000..17e125b5f --- /dev/null +++ b/panels/thunderbolt/meson.build @@ -0,0 +1,74 @@ +panels_list += cappletname + +desktop = 'gnome-@0@-panel.desktop'.format(cappletname) +desktop_in = configure_file( + input: desktop + '.in.in', + output: desktop + '.in', + configuration: desktop_conf +) + +i18n.merge_file( + desktop, + type: 'desktop', + input: desktop_in, + output: desktop, + po_dir: po_dir, + install: true, + install_dir: control_center_desktopdir +) + +sources = files( + 'bolt-client.c', + 'bolt-device.c', + 'bolt-enums.c', + 'bolt-error.c', + 'bolt-proxy.c', + 'bolt-str.c', + 'bolt-time.c', + 'cc-bolt-panel.c', + 'cc-bolt-device-dialog.c', + 'cc-bolt-device-entry.c', +) + +enum_headers = [ + 'bolt-enums.h', + 'bolt-error.h' +] + +sources += gnome.mkenums_simple( + 'bolt-enum-types', + sources: enum_headers) + +resource_data = files( + 'cc-bolt-device-dialog.ui', + 'cc-bolt-device-entry.ui', + 'cc-bolt-panel.ui' +) + +sources += gnome.compile_resources( + 'cc-' + cappletname + '-resources', + cappletname + '.gresource.xml', + source_dir: '.', + c_name: 'cc_' + cappletname, + dependencies: resource_data, + export: true +) + +deps = common_deps + [ + gnome_desktop_dep, + polkit_gobject_dep, + m_dep, +] + +cflags += [ + '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir), + '-DBINDIR="@0@"'.format(control_center_bindir) +] + +panels_libs += static_library( + cappletname, + sources: sources, + include_directories: [top_inc, common_inc], + dependencies: deps, + c_args: cflags +) diff --git a/panels/thunderbolt/thunderbolt.gresource.xml b/panels/thunderbolt/thunderbolt.gresource.xml new file mode 100644 index 000000000..8953d6243 --- /dev/null +++ b/panels/thunderbolt/thunderbolt.gresource.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/gnome/control-center/thunderbolt"> + <file preprocess="xml-stripblanks">cc-bolt-device-dialog.ui</file> + <file preprocess="xml-stripblanks">cc-bolt-device-entry.ui</file> + <file preprocess="xml-stripblanks">cc-bolt-panel.ui</file> + </gresource> +</gresources> + diff --git a/panels/thunderbolt/update-from-bolt.sh b/panels/thunderbolt/update-from-bolt.sh new file mode 100755 index 000000000..8b22f0831 --- /dev/null +++ b/panels/thunderbolt/update-from-bolt.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +if [ $# -ne 1 ]; then + echo "$0: usage: <BOLT-SOURCE>" + exit 1 +fi + +boltsrc="$1" + +function die() { + echo $* + exit 1 +} + +function copyone() { + dst=$1 + src="$boltsrc/$dst" + + search=(common cli) + for base in ${search[*]} + do + path="$boltsrc/$base/$dst" + if [ -f $path ]; then + src=$path + break; + fi + done + + if [ ! -f $src ]; then + echo -e "$dst \t[ skipped ] $src (ENOENT)" + elif cmp -s $src $dst; then + echo -e "$dst \t[ unchanged ]" + else + cp $src $dst || die "$dst [failed] source: $src" + echo -e "$dst \t[ updated ] $src" + git add $dst + fi +} + +names=(client device enums error names proxy str time) + +for fn in ${names[*]} +do + header="bolt-$fn.h" + source="bolt-$fn.c" + + copyone $header + copyone $source +done + diff --git a/panels/universal-access/cc-ua-panel.c b/panels/universal-access/cc-ua-panel.c index 23e7d8a56..7a56ee1f3 100644 --- a/panels/universal-access/cc-ua-panel.c +++ b/panels/universal-access/cc-ua-panel.c @@ -27,7 +27,7 @@ #include <glib/gi18n-lib.h> #include <gdesktop-enums.h> -#include "shell/list-box-helper.h" +#include "list-box-helper.h" #include "cc-ua-panel.h" #include "cc-ua-resources.h" diff --git a/panels/universal-access/meson.build b/panels/universal-access/meson.build index d7983f200..119143654 100644 --- a/panels/universal-access/meson.build +++ b/panels/universal-access/meson.build @@ -47,7 +47,7 @@ cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) panels_libs += static_library( cappletname, sources: sources, - include_directories: top_inc, + include_directories: [ top_inc, common_inc ], dependencies: deps, c_args: cflags ) diff --git a/panels/user-accounts/data/account-dialog.ui b/panels/user-accounts/data/account-dialog.ui index a508ecd30..50dad028e 100644 --- a/panels/user-accounts/data/account-dialog.ui +++ b/panels/user-accounts/data/account-dialog.ui @@ -538,7 +538,7 @@ </packing> </child> <child> - <object class="GtkLabel" id="enterprise-hint"> + <object class="GtkLabel" id="enterprise_hint"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="yalign">0</property> @@ -810,7 +810,7 @@ <widget name="enterprise_domain_hint"/> <widget name="enterprise_login"/> <widget name="enterprise_password"/> - <widget name="enterprise-hint"/> + <widget name="enterprise_hint"/> </widgets> </object> <object class="GtkSizeGroup"> diff --git a/panels/user-accounts/um-account-dialog.c b/panels/user-accounts/um-account-dialog.c index 9ca2c6d9d..ba4c24375 100644 --- a/panels/user-accounts/um-account-dialog.c +++ b/panels/user-accounts/um-account-dialog.c @@ -70,7 +70,7 @@ static void um_account_dialog_response (GtkDialog *dialog, struct _UmAccountDialog { GtkDialog parent; GtkWidget *stack; - GSimpleAsyncResult *async; + GTask *task; GCancellable *cancellable; GPermission *permission; GtkSpinner *spinner; @@ -181,14 +181,13 @@ static void complete_dialog (UmAccountDialog *self, ActUser *user) { - if (user != NULL) { - g_simple_async_result_set_op_res_gpointer (self->async, - g_object_ref (user), - g_object_unref); - } - - g_simple_async_result_complete_in_idle (self->async); gtk_widget_hide (GTK_WIDGET (self)); + + if (user != NULL) + g_object_ref (user); + + g_task_return_pointer (self->task, user, g_object_unref); + g_clear_object (&self->task); } static void @@ -895,7 +894,7 @@ on_join_login (GObject *source, return; } - um_realm_login_finish (result, &creds, &error); + creds = um_realm_login_finish (result, &error); /* Logged in as admin successfully, use creds to join domain */ if (error == NULL) { @@ -1001,7 +1000,7 @@ on_realm_login (GObject *source, return; } - um_realm_login_finish (result, &creds, &error); + creds = um_realm_login_finish (result, &error); /* * User login is valid, but cannot authenticate right now (eg: user needs @@ -1581,6 +1580,7 @@ um_account_dialog_class_init (UmAccountDialogClass *klass) gtk_widget_class_bind_template_child (widget_class, UmAccountDialog, enterprise_login); gtk_widget_class_bind_template_child (widget_class, UmAccountDialog, enterprise_password); gtk_widget_class_bind_template_child (widget_class, UmAccountDialog, enterprise_domain_hint); + gtk_widget_class_bind_template_child (widget_class, UmAccountDialog, enterprise_hint); } UmAccountDialog * @@ -1599,15 +1599,15 @@ um_account_dialog_show (UmAccountDialog *self, g_return_if_fail (UM_IS_ACCOUNT_DIALOG (self)); /* Make sure not already doing an operation */ - g_return_if_fail (self->async == NULL); - - self->async = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - um_account_dialog_show); + g_return_if_fail (self->task == NULL); if (self->cancellable) g_object_unref (self->cancellable); self->cancellable = g_cancellable_new (); + self->task = g_task_new (G_OBJECT (self), self->cancellable, callback, user_data); + g_task_set_source_tag (self->task, um_account_dialog_show); + g_clear_object (&self->permission); self->permission = permission ? g_object_ref (permission) : NULL; @@ -1626,17 +1626,10 @@ ActUser * um_account_dialog_finish (UmAccountDialog *self, GAsyncResult *result) { - ActUser *user; - g_return_val_if_fail (UM_IS_ACCOUNT_DIALOG (self), NULL); - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), - um_account_dialog_show), NULL); - g_return_val_if_fail (result == G_ASYNC_RESULT (self->async), NULL); - - user = g_simple_async_result_get_op_res_gpointer (self->async); - if (user != NULL) - g_object_ref (user); + g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (self)), NULL); + g_return_val_if_fail (g_async_result_is_tagged (result, um_account_dialog_show), NULL); + g_return_val_if_fail (result == G_ASYNC_RESULT (self->task), NULL); - g_clear_object (&self->async); - return user; + return g_task_propagate_pointer (self->task, NULL); } diff --git a/panels/user-accounts/um-realm-manager.c b/panels/user-accounts/um-realm-manager.c index 26391486f..36fe48206 100644 --- a/panels/user-accounts/um-realm-manager.c +++ b/panels/user-accounts/um-realm-manager.c @@ -166,42 +166,25 @@ on_realm_diagnostics (GDBusConnection *connection, } } -typedef struct { - GCancellable *cancellable; - UmRealmManager *manager; -} NewClosure; - -static void -new_closure_free (gpointer data) -{ - NewClosure *closure = data; - g_clear_object (&closure->cancellable); - g_clear_object (&closure->manager); - g_slice_free (NewClosure, closure); -} - static void on_provider_new (GObject *source, GAsyncResult *result, gpointer user_data) { - GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data); - NewClosure *closure = g_simple_async_result_get_op_res_gpointer (async); + GTask *task = G_TASK (user_data); + UmRealmManager *manager = g_task_get_task_data (task); GError *error = NULL; - UmRealmProvider *provider; - - provider = um_realm_provider_proxy_new_finish (result, &error); - closure->manager->provider = provider; + manager->provider = um_realm_provider_proxy_new_finish (result, &error); if (error == NULL) { - g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (closure->manager->provider), -1); + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (manager->provider), -1); g_debug ("Created realm manager"); + g_task_return_pointer (task, g_object_ref (manager), g_object_unref); } else { - g_simple_async_result_take_error (async, error); + g_task_return_error (task, error); } - g_simple_async_result_complete (async); - g_object_unref (async); + g_object_unref (task); } static void @@ -209,8 +192,8 @@ on_manager_new (GObject *source, GAsyncResult *result, gpointer user_data) { - GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data); - NewClosure *closure = g_simple_async_result_get_op_res_gpointer (async); + GTask *task = G_TASK (user_data); + UmRealmManager *manager; GDBusConnection *connection; GError *error = NULL; GObject *object; @@ -218,7 +201,7 @@ on_manager_new (GObject *source, object = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error); if (error == NULL) { - closure->manager = UM_REALM_MANAGER (object); + manager = UM_REALM_MANAGER (object); connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object)); g_debug ("Connected to realmd"); @@ -233,20 +216,20 @@ on_manager_new (GObject *source, on_realm_diagnostics, NULL, NULL); - closure->manager->diagnostics_sig = sig; + manager->diagnostics_sig = sig; + + g_task_set_task_data (task, manager, g_object_unref); um_realm_provider_proxy_new (connection, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, "org.freedesktop.realmd", "/org/freedesktop/realmd", - closure->cancellable, - on_provider_new, g_object_ref (async)); + g_task_get_cancellable (task), + on_provider_new, task); } else { - g_simple_async_result_take_error (async, error); - g_simple_async_result_complete (async); + g_task_return_error (task, error); + g_object_unref (task); } - - g_object_unref (async); } void @@ -254,61 +237,37 @@ um_realm_manager_new (GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *async; - NewClosure *closure; + GTask *task; g_debug ("Connecting to realmd..."); - async = g_simple_async_result_new (NULL, callback, user_data, - um_realm_manager_new); - closure = g_slice_new (NewClosure); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - g_simple_async_result_set_op_res_gpointer (async, closure, new_closure_free); + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_source_tag (task, um_realm_manager_new); g_async_initable_new_async (UM_TYPE_REALM_MANAGER, G_PRIORITY_DEFAULT, - cancellable, on_manager_new, g_object_ref (async), + cancellable, on_manager_new, task, "flags", G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "name", "org.freedesktop.realmd", "bus-type", G_BUS_TYPE_SYSTEM, "object-path", "/org/freedesktop/realmd", "get-proxy-type-func", um_realm_object_manager_client_get_proxy_type, NULL); - - g_object_unref (async); } UmRealmManager * um_realm_manager_new_finish (GAsyncResult *result, GError **error) { - GSimpleAsyncResult *async; - NewClosure *closure; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, - um_realm_manager_new), NULL); + g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); + g_return_val_if_fail (g_async_result_is_tagged (result, um_realm_manager_new), NULL); - async = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (async, error)) - return NULL; - - closure = g_simple_async_result_get_op_res_gpointer (async); - return g_object_ref (closure->manager); + return g_task_propagate_pointer (G_TASK (result), error); } -typedef struct { - GDBusObjectManager *manager; - GCancellable *cancellable; - GList *realms; -} DiscoverClosure; - static void -discover_closure_free (gpointer data) +realms_free (gpointer data) { - DiscoverClosure *discover = data; - g_object_unref (discover->manager); - g_clear_object (&discover->cancellable); - g_list_free_full (discover->realms, g_object_unref); - g_slice_free (DiscoverClosure, discover); + g_list_free_full (data, g_object_unref); } static void @@ -316,26 +275,27 @@ on_provider_discover (GObject *source, GAsyncResult *result, gpointer user_data) { - GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data); - DiscoverClosure *discover = g_simple_async_result_get_op_res_gpointer (async); + GTask *task = G_TASK (user_data); + UmRealmManager *manager = g_task_get_source_object (task); GDBusObject *object; GError *error = NULL; gboolean no_membership = FALSE; gchar **realms; gint relevance; gint i; + GList *kerberos_realms = NULL; um_realm_provider_call_discover_finish (UM_REALM_PROVIDER (source), &relevance, &realms, result, &error); if (error == NULL) { for (i = 0; realms[i]; i++) { - object = g_dbus_object_manager_get_object (discover->manager, realms[i]); + object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (manager), realms[i]); if (object == NULL) { g_warning ("Realm is not in object manager: %s", realms[i]); } else { if (is_realm_with_kerberos_and_membership (object)) { g_debug ("Discovered realm: %s", realms[i]); - discover->realms = g_list_prepend (discover->realms, object); + kerberos_realms = g_list_prepend (kerberos_realms, object); } else { g_debug ("Realm does not support kerberos membership: %s", realms[i]); no_membership = TRUE; @@ -345,16 +305,21 @@ on_provider_discover (GObject *source, } g_strfreev (realms); - if (!discover->realms && no_membership) { - g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, - _("Cannot automatically join this type of domain")); + if (!kerberos_realms && no_membership) { + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, + _("Cannot automatically join this type of domain")); + } else if (!kerberos_realms) { + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, + _("No such domain or realm found")); + } else { + kerberos_realms = g_list_reverse (kerberos_realms); + g_task_return_pointer (task, kerberos_realms, realms_free); } } else { - g_simple_async_result_take_error (async, error); + g_task_return_error (task, error); } - g_simple_async_result_complete (async); - g_object_unref (async); + g_object_unref (task); } void @@ -364,8 +329,7 @@ um_realm_manager_discover (UmRealmManager *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; - DiscoverClosure *discover; + GTask *task; GVariant *options; g_return_if_fail (UM_IS_REALM_MANAGER (self)); @@ -374,19 +338,13 @@ um_realm_manager_discover (UmRealmManager *self, g_debug ("Discovering realms for: %s", input); - res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - um_realm_manager_discover); - discover = g_slice_new0 (DiscoverClosure); - discover->manager = g_object_ref (self); - discover->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - g_simple_async_result_set_op_res_gpointer (res, discover, discover_closure_free); + task = g_task_new (G_OBJECT (self), cancellable, callback, user_data); + g_task_set_source_tag (task, um_realm_manager_discover); options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); um_realm_provider_call_discover (self->provider, input, options, cancellable, - on_provider_discover, g_object_ref (res)); - - g_object_unref (res); + on_provider_discover, task); } GList * @@ -394,29 +352,12 @@ um_realm_manager_discover_finish (UmRealmManager *self, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *async; - DiscoverClosure *discover; - GList *realms; - g_return_val_if_fail (UM_IS_REALM_MANAGER (self), NULL); - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), - um_realm_manager_discover), NULL); + g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (self)), NULL); + g_return_val_if_fail (g_async_result_is_tagged (result, um_realm_manager_discover), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - async = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (async, error)) - return NULL; - - discover = g_simple_async_result_get_op_res_gpointer (async); - if (!discover->realms) { - g_set_error (error, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, - _("No such domain or realm found")); - return NULL; - } - - realms = g_list_reverse (discover->realms); - discover->realms = NULL; - return realms; + return g_task_propagate_pointer (G_TASK (result), error); } GList * @@ -516,20 +457,6 @@ find_supported_credentials (UmRealmKerberosMembership *membership, return NULL; } -static void -on_realm_join_complete (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data); - - g_debug ("Completed Join() method call"); - - g_simple_async_result_set_op_res_gpointer (async, g_object_ref (result), g_object_unref); - g_simple_async_result_complete_in_idle (async); - g_object_unref (async); -} - static gboolean realm_join_as_owner (UmRealmObject *realm, const gchar *owner, @@ -541,7 +468,6 @@ realm_join_as_owner (UmRealmObject *realm, gpointer user_data) { UmRealmKerberosMembership *membership; - GSimpleAsyncResult *async; GVariant *contents; GVariant *options; GVariant *option; @@ -558,9 +484,6 @@ realm_join_as_owner (UmRealmObject *realm, return FALSE; } - async = g_simple_async_result_new (G_OBJECT (realm), callback, user_data, - realm_join_as_owner); - if (g_str_equal (type, "ccache")) { g_debug ("Using a kerberos credential cache to join the realm"); contents = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), @@ -583,10 +506,7 @@ realm_join_as_owner (UmRealmObject *realm, g_debug ("Calling the Join() method with %s credentials", owner); um_realm_kerberos_membership_call_join (membership, creds, options, - cancellable, on_realm_join_complete, - g_object_ref (async)); - - g_object_unref (async); + cancellable, callback, user_data); g_object_unref (membership); return TRUE; @@ -640,7 +560,6 @@ um_realm_join_finish (UmRealmObject *realm, UmRealmKerberosMembership *membership; GError *call_error = NULL; gchar *dbus_error; - GAsyncResult *async; g_return_val_if_fail (UM_REALM_IS_OBJECT (realm), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -648,12 +567,13 @@ um_realm_join_finish (UmRealmObject *realm, membership = um_realm_object_get_kerberos_membership (realm); g_return_val_if_fail (membership != NULL, FALSE); - async = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)); - um_realm_kerberos_membership_call_join_finish (membership, async, &call_error); + um_realm_kerberos_membership_call_join_finish (membership, result, &call_error); g_object_unref (membership); - if (call_error == NULL) + if (call_error == NULL) { + g_debug ("Completed Join() method call"); return TRUE; + } dbus_error = g_dbus_error_get_remote_error (call_error); if (dbus_error == NULL) { @@ -683,7 +603,6 @@ typedef struct { gchar *realm; gchar *user; gchar *password; - GBytes *credentials; } LoginClosure; static void @@ -694,7 +613,6 @@ login_closure_free (gpointer data) g_free (login->realm); g_free (login->user); g_free (login->password); - g_bytes_unref (login->credentials); g_slice_free (LoginClosure, login); } @@ -763,11 +681,12 @@ login_perform_kinit (krb5_context k5, } static void -kinit_thread_func (GSimpleAsyncResult *async, - GObject *object, +kinit_thread_func (GTask *task, + gpointer object, + gpointer task_data, GCancellable *cancellable) { - LoginClosure *login = g_simple_async_result_get_op_res_gpointer (async); + LoginClosure *login = task_data; krb5_context k5 = NULL; krb5_error_code code; GError *error = NULL; @@ -799,40 +718,41 @@ kinit_thread_func (GSimpleAsyncResult *async, if (filename != NULL) { g_file_get_contents (filename, &contents, &length, &error); if (error == NULL) { - login->credentials = g_bytes_new_take (contents, length); g_debug ("Read in credential cache: %s", filename); } else { g_warning ("Couldn't read credential cache: %s: %s", filename, error->message); g_error_free (error); } + + g_task_return_pointer (task, g_bytes_new_take (contents, length), (GDestroyNotify) g_bytes_unref); } break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: case KRB5KDC_ERR_POLICY: - g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN, - _("Cannot log in as %s at the %s domain"), - login->user, login->domain); + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN, + _("Cannot log in as %s at the %s domain"), + login->user, login->domain); break; case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KRB_AP_ERR_BAD_INTEGRITY: - g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD, - _("Invalid password, please try again")); + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD, + _("Invalid password, please try again")); break; case KRB5_PREAUTH_FAILED: case KRB5KDC_ERR_KEY_EXP: case KRB5KDC_ERR_CLIENT_REVOKED: case KRB5KDC_ERR_ETYPE_NOSUPP: case KRB5_PROG_ETYPE_NOSUPP: - g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH, - _("Cannot log in as %s at the %s domain"), - login->user, login->domain); + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH, + _("Cannot log in as %s at the %s domain"), + login->user, login->domain); break; default: - g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, - _("Couldn’t connect to the %s domain: %s"), - login->domain, krb5_get_error_message (k5, code)); + g_task_return_new_error (task, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC, + _("Couldn’t connect to the %s domain: %s"), + login->domain, krb5_get_error_message (k5, code)); break; } @@ -844,6 +764,8 @@ kinit_thread_func (GSimpleAsyncResult *async, if (k5) krb5_free_context (k5); + + g_object_unref (task); } void @@ -854,7 +776,7 @@ um_realm_login (UmRealmObject *realm, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *async; + GTask *task; LoginClosure *login; UmRealmKerberos *kerberos; @@ -866,46 +788,29 @@ um_realm_login (UmRealmObject *realm, kerberos = um_realm_object_get_kerberos (realm); g_return_if_fail (kerberos != NULL); - async = g_simple_async_result_new (NULL, callback, user_data, - um_realm_login); + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_source_tag (task, um_realm_login); + login = g_slice_new0 (LoginClosure); login->domain = g_strdup (um_realm_kerberos_get_domain_name (kerberos)); login->realm = g_strdup (um_realm_kerberos_get_realm_name (kerberos)); login->user = g_strdup (user); login->password = g_strdup (password); - g_simple_async_result_set_op_res_gpointer (async, login, login_closure_free); + g_task_set_task_data (task, login, login_closure_free); - g_simple_async_result_set_handle_cancellation (async, TRUE); - g_simple_async_result_run_in_thread (async, kinit_thread_func, - G_PRIORITY_DEFAULT, cancellable); + g_task_set_return_on_cancel (task, TRUE); + g_task_run_in_thread (task, kinit_thread_func); - g_object_unref (async); g_object_unref (kerberos); } -gboolean +GBytes * um_realm_login_finish (GAsyncResult *result, - GBytes **credentials, GError **error) { - GSimpleAsyncResult *async; - LoginClosure *login; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, - um_realm_login), FALSE); + g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE); + g_return_val_if_fail (g_async_result_is_tagged (result, um_realm_login), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - async = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (async, error)) - return FALSE; - - login = g_simple_async_result_get_op_res_gpointer (async); - if (credentials) { - if (login->credentials) - *credentials = g_bytes_ref (login->credentials); - else - *credentials = NULL; - } - - return TRUE; + return g_task_propagate_pointer (G_TASK (result), error); } diff --git a/panels/user-accounts/um-realm-manager.h b/panels/user-accounts/um-realm-manager.h index 2bf61e6cb..34d67a635 100644 --- a/panels/user-accounts/um-realm-manager.h +++ b/panels/user-accounts/um-realm-manager.h @@ -70,8 +70,7 @@ void um_realm_login (UmRealmObject *realm, GAsyncReadyCallback callback, gpointer user_data); -gboolean um_realm_login_finish (GAsyncResult *result, - GBytes **credentials, +GBytes * um_realm_login_finish (GAsyncResult *result, GError **error); gboolean um_realm_join_as_user (UmRealmObject *realm, diff --git a/panels/wacom/meson.build b/panels/wacom/meson.build index d323a818a..e206b00e9 100644 --- a/panels/wacom/meson.build +++ b/panels/wacom/meson.build @@ -15,19 +15,19 @@ panels_list += cappletname desktop = 'gnome-@0@-panel.desktop'.format(cappletname) desktop_in = configure_file( - input: desktop + '.in.in', - output: desktop + '.in', - configuration: desktop_conf + input : desktop + '.in.in', + output : desktop + '.in', + configuration : desktop_conf ) i18n.merge_file( - desktop, - type: 'desktop', - input: desktop_in, - output: desktop, - po_dir: po_dir, - install: true, - install_dir: control_center_desktopdir + desktop, + type : 'desktop', + input : desktop_in, + output : desktop, + po_dir : po_dir, + install : true, + install_dir : control_center_desktopdir ) common_sources = files( @@ -62,10 +62,10 @@ resource_data = files( common_sources += gnome.compile_resources( 'cc-' + cappletname + '-resources', cappletname + '.gresource.xml', - source_dir: '.', - c_name: 'cc_' + cappletname, - dependencies: resource_data, - export: true + source_dir : '.', + c_name : 'cc_' + cappletname, + dependencies : resource_data, + export : true ) sources = common_sources + files( @@ -82,13 +82,11 @@ incs = [ panels_libs += static_library( cappletname + '-properties', - sources: sources, - include_directories: incs, - dependencies: deps, - c_args: cflags, - link_with: [ - libwacom_calibrator - ] + sources : sources, + include_directories : incs, + dependencies : deps, + c_args : cflags, + link_with : [ libwacom_calibrator ] ) name = 'test-wacom' @@ -96,12 +94,10 @@ name = 'test-wacom' sources = common_sources + files(name + '.c') executable( - name, - sources, - include_directories: incs, - dependencies: deps, - c_args: test_cflags, - link_with: [ - libwacom_calibrator_test - ] + name, + sources, + include_directories : incs, + dependencies : deps, + c_args : test_cflags, + link_with : [ libwacom_calibrator_test ] ) diff --git a/po/POTFILES.in b/po/POTFILES.in index dfd8ccff0..a05df8a7f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -20,6 +20,7 @@ panels/color/gnome-color-panel.desktop.in.in panels/common/cc-common-language.c panels/common/cc-language-chooser.c panels/common/cc-util.c +panels/common/hostname-helper.c panels/common/language-chooser.ui panels/datetime/big.ui panels/datetime/cc-datetime-panel.c @@ -183,6 +184,12 @@ panels/sound/gvc-mixer-dialog.c panels/sound/gvc-sound-theme-chooser.c panels/sound/gvc-speaker-test.c panels/sound/sound-theme-file-utils.c +panels/thunderbolt/cc-bolt-device-dialog.c +panels/thunderbolt/cc-bolt-device-dialog.ui +panels/thunderbolt/cc-bolt-device-entry.c +panels/thunderbolt/cc-bolt-panel.c +panels/thunderbolt/cc-bolt-panel.ui +panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in panels/universal-access/cc-ua-panel.c panels/universal-access/gnome-universal-access-panel.desktop.in.in panels/universal-access/uap.ui @@ -226,7 +233,6 @@ shell/cc-application.c shell/cc-window.c shell/gnome-control-center.desktop.in.in shell/help-overlay.ui -shell/hostname-helper.c shell/org.gnome.ControlCenter.gschema.xml shell/panel-list.ui shell/window.ui @@ -24,8 +24,8 @@ msgstr "" "Project-Id-Version: gnome-control-center\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-23 19:10+0000\n" -"PO-Revision-Date: 2018-02-26 19:26+0100\n" +"POT-Creation-Date: 2018-04-19 13:00+0000\n" +"PO-Revision-Date: 2018-05-04 14:13+0200\n" "Last-Translator: Marek Černocký <marek@manet.cz>\n" "Language-Team: čeština <gnome-cs-list@gnome.org>\n" "Language: cs\n" @@ -118,16 +118,16 @@ msgid "You can add images to your %s folder and they will show up here" msgstr "Můžete obrázky přidat do své složky %s a potom se zde objeví" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 #: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 #: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -136,10 +136,10 @@ msgstr "Můžete obrázky přidat do své složky %s a potom se zde objeví" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_Zrušit" @@ -184,39 +184,39 @@ msgstr "preferences-desktop-wallpaper" msgid "Wallpaper;Screen;Desktop;" msgstr "tapeta;obrazovka;plocha;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Vypnout režim „letadlo“" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Nebylo nalezeno žádné Bluetooth" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Připojte adaptér, aby šlo používat Bluetooth." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth vypnuto" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Zapnout, aby se připojila zařízení a obdržela přenosy souborů." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Režim „letadlo“ je zapnutý" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "Když je zapnutý režim „letadlo“, je Bluetooth zakázané." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Hardwarový režim „letadlo“ je zapnutý" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Vypněte přepínač režimu „letadlo“, aby se povolilo Bluetooth." @@ -241,14 +241,14 @@ msgid "share;sharing;bluetooth;obex;" msgstr "sdílet;sdílení;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "Umístěte kalibrační zařízení na čtverec a zmáčkněte „Začít“" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -257,7 +257,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -266,54 +266,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Zavřete víko notebooku" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Došlo k vnitřní chybě, z které už se nelze obnovit." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "Nástroje vyžadované pro kalibraci nejsou nainstalované." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "Profil nemohl být vygenerován." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "Cílový bílý bod nebyl dosažitelný." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Dokončeno!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Kalibrace selhala!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Můžete oddělat kalibrační zařízení." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "Nestrkejte do kalibračního zařízení během procesu kalibrace" @@ -375,48 +375,48 @@ msgstr "Nezkalibrováno" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Výchozí:" #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Prostor barev:" #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Testovací profil: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Výběr souboru s profilem ICC" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Importovat" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Podporované profily ICC" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Všechny soubory" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Obrazovka" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Selhalo odeslání souboru: %s" @@ -424,40 +424,40 @@ msgstr "Selhalo odeslání souboru: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "Profil byl odeslán na:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Zapište si tuto adresu URL." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "Restartujte tento počítač a zaveďte svůj normální operační systém." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "" "Zadejte adresu URL do svého prohlížeče, aby se stáhl a nainstaloval profil." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Uložit profil" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Uložit" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Vytvořit barevný profil pro vybrané zařízení" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -466,12 +466,12 @@ msgstr "" "a zapnutá." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "Měřící sonda nepodporuje profilování tiskáren." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Typ zařízení není v současnosti podporován." @@ -920,6 +920,12 @@ msgstr "%e. %B" msgid "%b %e, %Y" msgstr "%e. %B %Y" +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Přístupový bod" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Jazyk" @@ -1116,58 +1122,58 @@ msgstr "Změnit nastavení systémového času a data" msgid "To change time or date settings, you need to authenticate." msgstr "Abyste mohli měnit nastavení času a data, musíte se autentizovat." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Na šířku" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Na výšku vpravo" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Na výšku vlevo" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Na šířku (překlopené)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Orientace" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Rozlišení" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Obnovovací frekvence" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Škálování" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "Přizpůsobit televizi" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Hlavní displej" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Uspořádání displejů" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1175,59 +1181,67 @@ msgstr "" "Přesuňte displeje tak, aby odpovídaly vašemu rozestavení. Horní pruh je v " "místě hlavního displeje." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Režim displeje" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Sloučit displeje" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Duplikovat" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Samostatný displej" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Použít změny?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Použít" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Použít změny?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "Změny nelze použít" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Může to být dáno omezeními hardwaru." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1991 panels/power/cc-power-panel.c:1998 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Zapnuto" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1985 panels/power/cc-power-panel.c:1996 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1235,11 +1249,11 @@ msgstr "Zapnuto" msgid "Off" msgstr "Vypnuto" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "_Noční světlo" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "Nelze získat informace o obrazovce" @@ -1279,7 +1293,7 @@ msgstr "Od soumraku do rozbřesku" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Ruční" @@ -1329,8 +1343,8 @@ msgstr "" "východ;západ;slunce;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Není známo" @@ -1338,24 +1352,24 @@ msgstr "Není známo" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; ID sestavení: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64bitový" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32bitový" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Verze %s" @@ -1690,8 +1704,8 @@ msgstr "Spouštěče" msgid "Launch help browser" msgstr "Spustit prohlížeč nápovědy" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Nastavení" @@ -1800,7 +1814,7 @@ msgstr "Zapnout nebo vypnout vysoký kontrast" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Vlastní zkratky" @@ -1811,7 +1825,7 @@ msgstr "Vlastní zkratky" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -2110,7 +2124,7 @@ msgid "Single click, secondary button" msgstr "Kliknutí, vedlejší tlačítko" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:581 msgid "Network proxy" msgstr "Proxy sítě" @@ -2118,23 +2132,23 @@ msgstr "Proxy sítě" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:717 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "VPN %s" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:781 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "Problém, něco se stalo špatně. Kontaktujte prosím vyrobce softwaru." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:787 msgid "NetworkManager needs to be running." msgstr "Je zapotřebí, aby běžel program NetworkManager." -#: panels/network/cc-wifi-panel.c:213 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Wi-Fi" @@ -2283,7 +2297,7 @@ msgid "Remove VPN" msgstr "Odebrat VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Podrobnosti" @@ -2418,7 +2432,7 @@ msgstr "Určeno pro připojení, u kterých jsou přenosy účtované nebo omeze #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automatické" @@ -2616,9 +2630,9 @@ msgid "Select file to import" msgstr "Vybrat soubor pro import" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Otevřít" @@ -3041,19 +3055,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Heslo" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Zapnout Wi-Fi" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "Přip_ojit se ke skryté síti…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "Zapnou_t bezdrátový přístupový bod…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "Známé sítě Wi-_Fi" @@ -3362,23 +3376,23 @@ msgstr "Schází firmware" msgid "Cable unplugged" msgstr "Odpojen kabel" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "nedefinovaná chyba v zabezpečení 802.1X (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "není vybrán žádný soubor" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "blíže neurčená chyba při ověřování souboru s metodou eap" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "Soukromé klíče DER, PEM, nebo PKCS#12 (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "Certifikáty DER nebo PEM (*.der, *.pem, *.crt, *.cer)" @@ -3799,19 +3813,19 @@ msgstr "Jiný" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "Účet %s" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Chyba při odebírání účtu" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> byl odebrán" @@ -3863,11 +3877,11 @@ msgstr "Přidat účet" msgid "Remove Account" msgstr "Odebrat účet" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Neznámý čas" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -3875,7 +3889,7 @@ msgstr[0] "%i minuta" msgstr[1] "%i minuty" msgstr[2] "%i minut" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3885,19 +3899,19 @@ msgstr[2] "%i hodin" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "hodina" msgstr[1] "hodiny" msgstr[2] "hodin" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "minuta" @@ -3905,240 +3919,284 @@ msgstr[1] "minuty" msgstr[2] "minut" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s do plného nabití" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Pozor, zbývá %s" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "Zbývá %s" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Plně nabito" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Vybitá" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Nabíjí se" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Vybíjí se" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Hlavní" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Přídavná" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Bezdrátová myš" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Bezdrátová klávesnice" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Záložní zdroj napájení" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Osobní digitální asistent (PDA)" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Mobilní telefon" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Multimediální přehrávač" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tablet" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Počítač" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Herní vstupní zařízení" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2377 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Baterie" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "Nabíjí se" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Pozor" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Nízká" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "Dobrá" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Plně nabitá" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Vybitá" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Baterie" -#: panels/power/cc-power-panel.c:1239 +#: panels/power/cc-power-panel.c:1206 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hodiny" +msgstr[1] "%d hodin" +msgstr[2] "%d hodin" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuty" +msgstr[1] "%d minut" +msgstr[2] "%d minut" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d sekundy" +msgstr[1] "%d sekund" +msgstr[2] "%d sekund" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +msgctxt "time" +msgid "%s %s" +msgstr "%s %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +msgid "0 seconds" +msgstr "0 sekund" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Při _nečinnosti" -#: panels/power/cc-power-panel.c:1693 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Šetření energií" -#: panels/power/cc-power-panel.c:1724 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "_Jas obrazovky" -#: panels/power/cc-power-panel.c:1743 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Automatický jas" -#: panels/power/cc-power-panel.c:1763 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "_Jas klávesnice" -#: panels/power/cc-power-panel.c:1773 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "_Ztlumit jas obrazovky při neaktivitě" -#: panels/power/cc-power-panel.c:1798 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" -msgstr "_Vypnout obrazovku" +msgstr "_Vypnout obrazovku po uplynutí" -#: panels/power/cc-power-panel.c:1835 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1840 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Vypněte Wi-Fi, když chcete šetřit energii." -#: panels/power/cc-power-panel.c:1865 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "_Mobilní připojení" -#: panels/power/cc-power-panel.c:1870 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "" "Vypnout mobilní širokopásmová zařízení (3G, 4G, LTE atd.), aby se šetřila " "energie." -#: panels/power/cc-power-panel.c:1923 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1928 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Vypněte Bluetooth, když chcete šetřit energii." -#: panels/power/cc-power-panel.c:1987 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "Při napájení z baterie" -#: panels/power/cc-power-panel.c:1989 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Při napájení ze sítě" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Uspat do paměti" -#: panels/power/cc-power-panel.c:2085 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Vypnout" -#: panels/power/cc-power-panel.c:2086 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Uspat na disk" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Nic nedělat" #. Frame header -#: panels/power/cc-power-panel.c:2201 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Uspávání a vypínací tlačítko" -#: panels/power/cc-power-panel.c:2240 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "_Automaticky uspat" -#: panels/power/cc-power-panel.c:2241 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Automaticky uspat" -#: panels/power/cc-power-panel.c:2308 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "_Když je zmáčknuto vypínací tlačítko" -#: panels/power/cc-power-panel.c:2427 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Zařízení" @@ -4273,18 +4331,18 @@ msgid "Authentication Required" msgstr "Požadováno ověření totožnosti" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "Tiskárna „%s“ byla odebrána" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Selhalo přidání nové tiskárny." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "Nelze načíst uživatelské rozhraní: %s" @@ -4397,21 +4455,21 @@ msgid "Test Page" msgstr "Testovací stránka" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "Podrobnosti o tiskárně %s" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "Nenalezen vyhovující ovladač" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "Vyberte soubor PPD" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4424,7 +4482,7 @@ msgid "Select Printer Driver" msgstr "Vyberte ovladač tiskárny" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Vybrat" @@ -4481,55 +4539,55 @@ msgid "Reverse portrait" msgstr "Obráceně na výšku" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Čeká" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Pozastaveno" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Požadováno ověření" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "Zpracovává se" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Zastaveno" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Zrušeno" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Přerušeno" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Dokončeno" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" @@ -4538,14 +4596,14 @@ msgstr[1] "%u úlohy vyžadují ověření" msgstr[2] "%u úloh vyžaduje ověření" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s – aktivní úlohy" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "Zadejte pověření pro tisk z tiskárny %s." @@ -4913,25 +4971,25 @@ msgstr "" "Bohužel to vypadá, že systémová\n" "služba tisku není dostupná." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Zamykání obrazovky" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "Používá se" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Zapnuto" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Vypnuto" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Služby určování polohy" @@ -5191,11 +5249,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Další" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Není vybrán žádný vstupní zdroj" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "Při_hlašovací obrazovka" @@ -5801,34 +5859,204 @@ msgstr "Subwoofer" msgid "Custom" msgstr "Vlastní" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Odpojeno" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Připojuje se" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Připojeno" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Chyba ověřování" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Ověřuje se" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Omezená funkcionalita" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Připojeno a ověřeno" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Neznámý" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Ověřeno:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Připojeno:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Registrováno:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "Selhalo ověření zařízení: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "Zapomenutí zařízení selhalo: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Název:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Stav:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Ověřit a připojit" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Zapomenout zařízení" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Chyba" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Ověřeno" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"Subsystém Thunderbolt (boltd) není nainstalovaný, nebo není správně " +"nastavený." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"Thunderbolt se nezdařilo nalézt.\n" +"Buď systém postrádá podporu pro Thunderbolt, nebo je vypnutá přes BIOS, nebo " +"je v něm nastavená nepodporovaná úroveň zabezpečení." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "Podpora pro Thunderbolt je vypnutá přes BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Chyba při přepínání přímého režimu: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Bez podpory pro Thunderbolt" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Přímý přístup" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "" +"Umožňuje přímý přístup k zařízením, jako jsou dokovací stanice nebo externí " +"GPU." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Připojeny mohou být jen zařízení USB a Display Port." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Čekající zařízení" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Nejsou připojena žádná zařízení" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Spravujte zařízení Thunderbolt" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Výchozí" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Střední" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Velký" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Větší" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "Největší" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5878,7 +6106,7 @@ msgid "C_ursor Size" msgstr "Velikost k_urzoru" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Přiblížení" @@ -6169,27 +6397,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Vysoký" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Krátká" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ obrazovky" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ obrazovky" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ obrazovky" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Dlouhá" @@ -6214,134 +6442,134 @@ msgstr "Levá polovina" msgid "Right Half" msgstr "Pravá polovina" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Volby přiblížení" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "Zvětšení _lupou:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Následovat ukazatel myši" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "Část o_brazovky:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "Lupa se rozšiřuj_e mimo obrazovku" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "Udržovat u_kazatel lupy na středu" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "Ukazatel lu_py odsouvá okolní obsah" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "Ukazatel lupy se přesouvá s o_bsahem" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Poloha lupy:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Lupa" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Tloušťka:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Tenký" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Tlustý" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "Dé_lka:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "_Barva:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "Zaměřovací _kříž:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "Překrývat ukazat_el myši" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Zaměřovací kříž" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "_Bílá na černém:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Jas:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Kontrast:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "_Barva" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Žádná" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Plná" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Nízký" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Vysoký" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Nízký" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Vysoký" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Ovlivnění barev:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Ovlivnění barev" @@ -6934,7 +7162,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6942,7 +7170,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6979,7 +7207,7 @@ msgstr "Heslo nelze změnit" msgid "The passwords do not match." msgstr "Hesla si neodpovídají." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Procházet další obrázky" @@ -7007,30 +7235,30 @@ msgstr "Neplatné heslo, zkuste to, prosím, znovu" msgid "Couldn’t connect to the %s domain: %s" msgstr "Nelze se připojit k doméně „%s“: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Váš účet" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Selhalo smazání účtu" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Selhalo zneplatnění vzdáleně spravovaného uživatele" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Nemůžete smazat svůj vlastní účet." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "Uživatel %s je doposud přihlášen" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -7038,12 +7266,12 @@ msgstr "" "Smazání účtu, zatímco je dotyčný uživatel přihlášen, může přivést systém do " "nekonzistentního stavu." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "Chcete zachovat soubory uživatele %s?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7051,47 +7279,47 @@ msgstr "" "Je možné zachovat domovskou složku, poštovní schránku a dočasné soubory, i " "když bude uživatelský účet smazán." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "O_dstranit soubory" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "Zacho_vat soubory" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "Opravdu chcete zneplatnit vzdáleně spravovaný účet uživatele %s?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "O_dstranit" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Účet zakázán" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Bude nastaveno při příštím přihlášení" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Žádné" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "právě přihlášený" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Selhalo kontaktování účtovací služby" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "" "Zkontrolujte prosím, že je účtovací služba AccountService nainstalovaná a " @@ -7101,7 +7329,7 @@ msgstr "" #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7109,12 +7337,12 @@ msgstr "" "Abyste mohli provést změny,\n" "klikněte nejprve na ikonu *" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Vytvořit uživatelský účet" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7122,12 +7350,12 @@ msgstr "" "Pro vytvoření uživatelského účtu\n" "nejprve klikněte na ikonu *" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Odstranit vybraný uživatelský účet" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7404,35 +7632,35 @@ msgstr "" "Ovládací centrum je hlavní rozhraní GNOME pro nastavení různých vlastností " "vašeho pracovního prostředí." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Zobrazit číslo verze" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Zapnout podrobný režim" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Zobrazit přehled" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Hledat řetězec" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Vypsat všechny možné názvy panelů a skončit" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Panel, který se má zobrazit" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGUMENT…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Dostupné panely:" @@ -7484,12 +7712,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Zrušit vyhledávání" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Přístupový bod" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "Identifikátor naposledy otevřeného panelu Nastavení" @@ -20,8 +20,8 @@ msgstr "" "Project-Id-Version: gnome-control-center master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-20 09:14+0000\n" -"PO-Revision-Date: 2018-02-21 17:01+0100\n" +"POT-Creation-Date: 2018-04-19 13:00+0000\n" +"PO-Revision-Date: 2018-04-23 15:03+0200\n" "Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n" "Language-Team: es <gnome-es-list@gnome.org>\n" "Language: es\n" @@ -113,16 +113,16 @@ msgid "You can add images to your %s folder and they will show up here" msgstr "Puede añadir imágenes a su carpeta %s y se mostrarán aquí" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 -#: panels/network/net-device-wifi.c:1371 panels/network/net-device-wifi.c:1451 -#: panels/network/net-device-wifi.c:1690 panels/network/network-wifi.ui:24 +#: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 +#: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -131,10 +131,10 @@ msgstr "Puede añadir imágenes a su carpeta %s y se mostrarán aquí" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_Cancelar" @@ -169,49 +169,50 @@ msgstr "Fondo" msgid "Change your background image to a wallpaper or photo" msgstr "Cambiar la imagen de fondo de escritorio por un tapiz o una foto" -#: panels/background/gnome-background-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/background/gnome-background-panel.desktop.in.in:7 msgid "preferences-desktop-wallpaper" msgstr "preferences-desktop-wallpaper" -#. Translators: those are keywords for the background control-center panel -#: panels/background/gnome-background-panel.desktop.in.in:14 +#. Translators: Search terms to find the Background panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/background/gnome-background-panel.desktop.in.in:15 msgid "Wallpaper;Screen;Desktop;" msgstr "Fondo de pantalla;Pantalla;Escritorio;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Apagar el modo avión" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "No se encontraron adaptadores Bluetooth" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Conectar a un dongle para usar el Bluetooth." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth apagado" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "" "Encender para conectar dispositivos y recibir transferencias de archivos." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "El modo avión está activado" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "El Bluetooth está apagado cuando el modo avión está activado." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "El hardware en modo avión está activado" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Apague el modo avión para activar el Bluetooth." @@ -225,17 +226,18 @@ msgstr "Bluetooth" msgid "Turn Bluetooth on and off and connect your devices" msgstr "Activar y desactivar Bluetooth y conectar sus dispositivos" -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:5 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:6 msgid "bluetooth" msgstr "bluetooth" -#. Translators: those are keywords for the bluetooth control-center panel -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:18 +#. Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:19 msgid "share;sharing;bluetooth;obex;" msgstr "compartir;compartición;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "" "Coloque su dispositivo de calibración sobre el cuadrado y pulse «Iniciar»" @@ -243,7 +245,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -253,7 +255,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -263,54 +265,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Apagar la tapa del portátil" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Ocurrió un error interno y no se pudo recuperar." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "Las herramientas requeridas para la calibración no están instaladas." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "No se puede generar el perfil." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "No se pudo obtener el punto blanco del objetivo." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Completado" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Falló la configuración." #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Puede quitar el dispositivo de calibración." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "No interrumpir al dispositivo de calibración cuando está en progreso" @@ -372,48 +374,48 @@ msgstr "Sin calibrar" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Predeterminado: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Espacio de color: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Perfil de color: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Seleccionar archivo de perfil ICC" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Importar" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Perfiles ICC soportados" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Todos los archivos" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Pantalla" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Falló al subir el archivo: %s" @@ -421,39 +423,39 @@ msgstr "Falló al subir el archivo: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "El perfil se ha subido a:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Anote este URL." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "Reinicie el equipo y arranque su sistema operativo normal." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "Escriba el URL en su navegador para descargar e instalar el perfil." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Guardar perfil" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Guardar" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Crear un perfil de color para el dispositivo seleccionado" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -462,12 +464,12 @@ msgstr "" "correctamente conectado." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "El instrumento de medida no soporta perfilado de impresoras." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "El tipo de dispositivo actualmente no está soportado." @@ -877,12 +879,13 @@ msgid "" msgstr "" "Calibrar el color de sus dispositivos, como pantallas, cámaras o impresoras" -#: panels/color/gnome-color-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/color/gnome-color-panel.desktop.in.in:7 msgid "preferences-color" msgstr "preferences-color" -#. Translators: those are keywords for the color control-center panel -#: panels/color/gnome-color-panel.desktop.in.in:18 +#. Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/color/gnome-color-panel.desktop.in.in:19 msgid "Color;ICC;Profile;Calibrate;Printer;Display;" msgstr "Color;ICC;Perfil;Calibrado;Impresora;Pantalla;" @@ -919,6 +922,12 @@ msgstr "%e de %b" msgid "%b %e, %Y" msgstr "%e de %b, %Y" +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Hotspot" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Idioma" @@ -1097,12 +1106,13 @@ msgstr "AM / PM" msgid "Change the date and time, including time zone" msgstr "Cambiar la fecha y la hora, incluyendo la zona horaria" -#: panels/datetime/gnome-datetime-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:7 msgid "preferences-system-time" msgstr "preferences-system-time" -#. Translators: those are keywords for the date and time control-center panel -#: panels/datetime/gnome-datetime-panel.desktop.in.in:14 +#. Translators: Search terms to find the Date and Time panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:15 msgid "Clock;Timezone;Location;" msgstr "Reloj;Zona horaria;Ubicación;" @@ -1115,59 +1125,59 @@ msgid "To change time or date settings, you need to authenticate." msgstr "" "Para cambiar la configuración de la fecha o de la hora, debe autenticarse." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Horizontal" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Vertical derecha" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Vertical izquierda" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Horizontal (dada la vuelta)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Orientación" -#: panels/display/cc-display-panel.c:870 -#: panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 +#: panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Resolución" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Tasa de refresco" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Escala" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "Ajustes para TV" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Pantalla primaria" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Distribución de las pantallas" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1175,59 +1185,67 @@ msgstr "" "Arrastre las pantallas para que coincidan con su configuración. La barra " "superior se mostrará en la pantalla primaria." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Modo de la pantalla" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Unir pantallas" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Espejo" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Pantalla única" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "¿Aplicar los cambios?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Aplicar" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "¿Aplicar los cambios?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "No se pueden aplicar los cambios" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Esto puede deber a limitaciones hardware." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1995 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Encendido" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1982 panels/power/cc-power-panel.c:1993 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 #: panels/universal-access/uap.ui:334 panels/universal-access/uap.ui:380 #: panels/universal-access/uap.ui:426 panels/universal-access/uap.ui:532 #: panels/universal-access/uap.ui:685 panels/universal-access/uap.ui:731 @@ -1235,11 +1253,11 @@ msgstr "Encendido" msgid "Off" msgstr "Apagado" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "Luz _nocturna" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "No se pudo obtener la información de la pantalla" @@ -1279,7 +1297,7 @@ msgstr "Desde el amanecer hasta la puesta del sol" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Manual" @@ -1313,12 +1331,13 @@ msgstr "Pantallas" msgid "Choose how to use connected monitors and projectors" msgstr "Elegir cómo usar las pantallas y los proyectores conectados" -#: panels/display/gnome-display-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/display/gnome-display-panel.desktop.in.in:7 msgid "preferences-desktop-display" msgstr "preferences-desktop-display" -#. Translators: those are keywords for the display control-center panel -#: panels/display/gnome-display-panel.desktop.in.in:18 +#. Translators: Search terms to find the Displays panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/display/gnome-display-panel.desktop.in.in:19 msgid "" "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" "redshift;color;sunset;sunrise;" @@ -1327,8 +1346,8 @@ msgstr "" "color;amanecer;atardecer;ocaso;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Desconocido" @@ -1336,24 +1355,24 @@ msgstr "Desconocido" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; ID de construcción: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64 bits" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32 bits" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Versión %s" @@ -1457,12 +1476,13 @@ msgstr "Aplicaciones predeterminadas" msgid "Configure Default Applications" msgstr "Configurar aplicaciones predeterminadas" -#: panels/info/gnome-default-apps-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-default-apps-panel.desktop.in.in:7 msgid "starred" msgstr "destacado" -#. Translators: those are keywords for the Default Applications panel -#: panels/info/gnome-default-apps-panel.desktop.in.in:18 +#. Translators: Search terms to find the Default Applications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-default-apps-panel.desktop.in.in:19 msgid "default;application;preferred;media;" msgstr "predeterminado;aplicación;preferida;medios;" @@ -1474,14 +1494,17 @@ msgstr "Acerca de" msgid "View information about your system" msgstr "Ver información sobre su sistema" -#: panels/info/gnome-info-overview-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-info-overview-panel.desktop.in.in:7 msgid "help-about" msgstr "help-about" -#. Translators: those are keywords for the System Information panel +#. Translators: Search terms to find the About panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. "Preferred Applications" is the old name for the preference, so make #. sure that you use the same "translation" for those keywords -#: panels/info/gnome-info-overview-panel.desktop.in.in:20 +#: panels/info/gnome-info-overview-panel.desktop.in.in:23 msgid "" "device;system;information;memory;processor;version;default;application;" "preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" @@ -1498,12 +1521,13 @@ msgstr "Soportes extraíbles" msgid "Configure Removable Media settings" msgstr "Configurar soportes extraíbles" -#: panels/info/gnome-removable-media-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-removable-media-panel.desktop.in.in:7 msgid "media-removable" msgstr "media-removable" -#. Translators: those are keywords for the Removable Media panel -#: panels/info/gnome-removable-media-panel.desktop.in.in:18 +#. Translators: Search terms to find the Removable Media panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-removable-media-panel.desktop.in.in:19 msgid "" "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" "removable;media;autorun;" @@ -1683,8 +1707,8 @@ msgstr "Lanzadores" msgid "Launch help browser" msgstr "Lanzar el visor de ayuda" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Configuración" @@ -1793,7 +1817,7 @@ msgstr "Contraste alto activado o desactivado" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Combinación personalizada" @@ -1804,7 +1828,7 @@ msgstr "Combinación personalizada" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -1894,12 +1918,13 @@ msgstr "" "Ver y cambiar los atajos del teclado y establecer sus preferencias de " "escritura" -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:7 msgid "input-keyboard" msgstr "input-keyboard" -#. Translators: those are keywords for the keyboard control-center panel -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:18 +#. Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 msgid "" "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" msgstr "" @@ -1990,12 +2015,13 @@ msgstr "" "Cambiar la sensibilidad de su ratón o su «touchpad» y configurarlos para " "zurdos o diestros" -#: panels/mouse/gnome-mouse-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:7 msgid "input-mouse" msgstr "input-mouse" -#. Translators: those are keywords for the mouse and touchpad control-center panel -#: panels/mouse/gnome-mouse-panel.desktop.in.in:18 +#. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:19 msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" msgstr "" "trackpad;puntero;pulsar;pulsación;doble;botón;trackball;desplazamiento;" @@ -2100,7 +2126,7 @@ msgid "Single click, secondary button" msgstr "Una sola pulsación, botón secundario" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:581 msgid "Network proxy" msgstr "Proxy de la red" @@ -2108,23 +2134,23 @@ msgstr "Proxy de la red" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:717 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "VPN «%s»" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:781 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "Algo ha fallado. Contacte con el fabricante del software." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:787 msgid "NetworkManager needs to be running." msgstr "NetworkManager debe estar en ejecución." -#: panels/network/cc-wifi-panel.c:212 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Inalámbrica" @@ -2175,31 +2201,31 @@ msgstr "Perfil %d" #. TRANSLATORS: this WEP WiFi security #: panels/network/connection-editor/ce-page-details.c:56 -#: panels/network/net-device-wifi.c:231 panels/network/net-device-wifi.c:453 +#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:468 msgid "WEP" msgstr "WEP" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:60 -#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:458 +#: panels/network/net-device-wifi.c:239 panels/network/net-device-wifi.c:473 #: panels/network/network-wifi.ui:593 msgid "WPA" msgstr "WPA" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:64 -#: panels/network/net-device-wifi.c:239 +#: panels/network/net-device-wifi.c:243 msgid "WPA2" msgstr "WPA2" #. TRANSLATORS: this Enterprise WiFi security #: panels/network/connection-editor/ce-page-details.c:69 -#: panels/network/net-device-wifi.c:244 +#: panels/network/net-device-wifi.c:248 msgid "Enterprise" msgstr "Empresa" #: panels/network/connection-editor/ce-page-details.c:74 -#: panels/network/net-device-wifi.c:249 panels/network/net-device-wifi.c:443 +#: panels/network/net-device-wifi.c:253 panels/network/net-device-wifi.c:458 msgctxt "Wifi security" msgid "None" msgstr "Ninguna" @@ -2211,7 +2237,7 @@ msgstr "Nunca" #: panels/network/connection-editor/ce-page-details.c:110 #: panels/network/net-device-ethernet.c:121 -#: panels/network/net-device-wifi.c:552 +#: panels/network/net-device-wifi.c:567 #, c-format msgid "%i day ago" msgid_plural "%i days ago" @@ -2221,37 +2247,37 @@ msgstr[1] "hace %i días" #. Translators: network device speed #: panels/network/connection-editor/ce-page-details.c:225 #: panels/network/net-device-ethernet.c:50 -#: panels/network/net-device-wifi.c:608 +#: panels/network/net-device-wifi.c:646 #, c-format msgid "%d Mb/s" msgstr "%d Mb/s" #: panels/network/connection-editor/ce-page-details.c:251 -#: panels/network/net-device-wifi.c:637 +#: panels/network/net-device-wifi.c:675 msgctxt "Signal strength" msgid "None" msgstr "Ninguna" #: panels/network/connection-editor/ce-page-details.c:253 -#: panels/network/net-device-wifi.c:639 +#: panels/network/net-device-wifi.c:677 msgctxt "Signal strength" msgid "Weak" msgstr "Débil" #: panels/network/connection-editor/ce-page-details.c:255 -#: panels/network/net-device-wifi.c:641 +#: panels/network/net-device-wifi.c:679 msgctxt "Signal strength" msgid "Ok" msgstr "Aceptar" #: panels/network/connection-editor/ce-page-details.c:257 -#: panels/network/net-device-wifi.c:643 +#: panels/network/net-device-wifi.c:681 msgctxt "Signal strength" msgid "Good" msgstr "Buena" #: panels/network/connection-editor/ce-page-details.c:259 -#: panels/network/net-device-wifi.c:645 +#: panels/network/net-device-wifi.c:683 msgctxt "Signal strength" msgid "Excellent" msgstr "Excelente" @@ -2269,7 +2295,7 @@ msgid "Remove VPN" msgstr "Quitar VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Detalles" @@ -2404,7 +2430,7 @@ msgstr "Adecuado para conexiones que consumen o limitan los datos." #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automático" @@ -2602,9 +2628,9 @@ msgid "Select file to import" msgstr "Seleccione el archivo que importar" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Abrir" @@ -2669,12 +2695,13 @@ msgstr "Red" msgid "Control how you connect to the Internet" msgstr "Controlar cómo se conecta a Internet" -#: panels/network/gnome-network-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-network-panel.desktop.in.in:7 msgid "network-workgroup" msgstr "network-workgroup" -#. Translators: those are keywords for the network control-center panel -#: panels/network/gnome-network-panel.desktop.in.in:18 +#. Translators: Search terms to find the Network panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-network-panel.desktop.in.in:19 msgid "" "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;" "DNS;" @@ -2686,27 +2713,28 @@ msgstr "" msgid "Control how you connect to Wi-Fi networks" msgstr "Controlar cómo se conecta a redes inalámbricas" -#: panels/network/gnome-wifi-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-wifi-panel.desktop.in.in:7 msgid "network-wireless" msgstr "network-wireless" -#. Translators: those are keywords for the wi-fi control-center panel -#: panels/network/gnome-wifi-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wi-Fi panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-wifi-panel.desktop.in.in:19 msgid "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;" msgstr "Red;Inalámbrica;Wireless;Wi-Fi;Wifi;IP;LAN;Banda;ancha;DNS;" #: panels/network/net-device-ethernet.c:107 -#: panels/network/net-device-wifi.c:538 +#: panels/network/net-device-wifi.c:553 msgid "never" msgstr "nunca" #: panels/network/net-device-ethernet.c:117 -#: panels/network/net-device-wifi.c:548 +#: panels/network/net-device-wifi.c:563 msgid "today" msgstr "hoy" #: panels/network/net-device-ethernet.c:119 -#: panels/network/net-device-wifi.c:550 +#: panels/network/net-device-wifi.c:565 msgid "yesterday" msgstr "ayer" @@ -2731,7 +2759,7 @@ msgid "Wired" msgstr "Cableada" #: panels/network/net-device-ethernet.c:344 -#: panels/network/net-device-wifi.c:1849 +#: panels/network/net-device-wifi.c:1895 #: panels/network/network-ethernet.ui:120 panels/network/network-mobile.ui:394 #: panels/network/network-simple.ui:75 panels/network/network-vpn.ui:79 msgid "Options…" @@ -2741,12 +2769,12 @@ msgstr "Opciones…" msgid "Add new connection" msgstr "Añadir una conexión nueva" -#: panels/network/net-device-wifi.c:1328 +#: panels/network/net-device-wifi.c:1368 #, c-format msgid "Switching on the wireless hotspot will disconnect you from <b>%s</b>." msgstr "Cambiar al «hotspot» inalámbrico le desconectará de <b>%s</b>." -#: panels/network/net-device-wifi.c:1332 +#: panels/network/net-device-wifi.c:1372 msgid "" "It is not possible to access the Internet through your wireless while the " "hotspot is active." @@ -2754,11 +2782,11 @@ msgstr "" "No es posible acceder a Internet usando la conexión inalámbrica mientras el " "«hotspot» está activado." -#: panels/network/net-device-wifi.c:1339 +#: panels/network/net-device-wifi.c:1379 msgid "Turn On Wi-Fi Hotspot?" msgstr "¿Activar el punto de acceso inalámbrico?" -#: panels/network/net-device-wifi.c:1361 +#: panels/network/net-device-wifi.c:1401 msgid "" "Wi-Fi hotspots are usually used to share an additional Internet connection " "over Wi-Fi." @@ -2766,27 +2794,27 @@ msgstr "" "Los puntos de acceso inalámbricos se usan habitualmente para compartir una " "conexión a Internet adicional mediante Wi-Fi." -#: panels/network/net-device-wifi.c:1372 +#: panels/network/net-device-wifi.c:1412 msgid "_Turn On" msgstr "_Activar" -#: panels/network/net-device-wifi.c:1449 +#: panels/network/net-device-wifi.c:1489 msgid "Stop hotspot and disconnect any users?" msgstr "¿Detener el «hotspot» y desconectar a los usuarios?" -#: panels/network/net-device-wifi.c:1452 +#: panels/network/net-device-wifi.c:1492 msgid "_Stop Hotspot" msgstr "_Detener «hotspot»" -#: panels/network/net-device-wifi.c:1552 +#: panels/network/net-device-wifi.c:1592 msgid "System policy prohibits use as a Hotspot" msgstr "La política del sistema prohíbe usarlo como punto de acceso" -#: panels/network/net-device-wifi.c:1555 +#: panels/network/net-device-wifi.c:1595 msgid "Wireless device does not support Hotspot mode" msgstr "El dispositivo inalámbrico no soporta el modo de punto de acceso" -#: panels/network/net-device-wifi.c:1687 +#: panels/network/net-device-wifi.c:1733 msgid "" "Network details for the selected networks, including passwords and any " "custom configuration will be lost." @@ -2794,16 +2822,16 @@ msgstr "" "Se perderán los detalles de las redes seleccionadas, incluyendo la " "contraseña y cualquier configuración personalizada." -#: panels/network/net-device-wifi.c:1691 panels/network/network-wifi.ui:1362 +#: panels/network/net-device-wifi.c:1737 panels/network/network-wifi.ui:1362 msgid "_Forget" msgstr "_Olvidar" -#: panels/network/net-device-wifi.c:2000 panels/network/net-device-wifi.c:2007 +#: panels/network/net-device-wifi.c:2046 panels/network/net-device-wifi.c:2053 msgid "Known Wi-Fi Networks" msgstr "Redes inalámbricas conocidas" #. translators: This is the label for the "Forget wireless network" functionality -#: panels/network/net-device-wifi.c:2040 +#: panels/network/net-device-wifi.c:2086 msgctxt "Wi-Fi Network" msgid "_Forget" msgstr "_Olvidar" @@ -3022,19 +3050,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Contraseña" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Apagar la Wi-Fi" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "Conectar a una red oculta…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "_Activar el punto de acceso inalámbrico…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "Redes inalámbricas _conocidas" @@ -3343,23 +3371,23 @@ msgstr "falta el «firmware»" msgid "Cable unplugged" msgstr "Cable desconectado" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "error no definido en la seguridad 802.1X (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "no se ha seleccionado ningún archivo" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "error no especificado al validar el archivo del método eap" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "Claves privadas DER, PEM, o PKCS#12 (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "Certificados DER o PEM (*.der, *.pem, *.crt, *.cer)" @@ -3750,12 +3778,13 @@ msgstr "Notificaciones" msgid "Control which notifications are displayed and what they show" msgstr "Controlar qué notificaciones se muestran" -#: panels/notifications/gnome-notifications-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:7 msgid "preferences-system-notifications" msgstr "preferences-system-notifications" -#. Translators: those are keywords for the notifications control-center panel -#: panels/notifications/gnome-notifications-panel.desktop.in.in:19 +#. Translators: Search terms to find the Notifications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:20 msgid "Notifications;Banner;Message;Tray;Popup;" msgstr "notificaciones;banner;mensaje;bandeja;emergente;" @@ -3780,19 +3809,19 @@ msgstr "Otra" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "Cuenta de %s" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Error al quitar la cuenta" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> eliminado" @@ -3805,13 +3834,16 @@ msgstr "Cuentas en línea" msgid "Connect to your online accounts and decide what to use them for" msgstr "Conectarse a sus cuentas en línea y decidir para qué usarlas" -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:7 msgid "goa-panel" msgstr "goa-panel" -#. Translators: those are keywords for the online-accounts control-center panel +#. Translators: Search terms to find the Online Accounts panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. For ReadItLater and Pocket, see http://en.wikipedia.org/wiki/Pocket_(application) -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:19 +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:22 msgid "" "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" @@ -3841,18 +3873,18 @@ msgstr "Añadir una cuenta" msgid "Remove Account" msgstr "Quitar cuenta" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Tiempo desconocido" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i minuto" msgstr[1] "%i minutos" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3861,256 +3893,305 @@ msgstr[1] "%i horas" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "hora" msgstr[1] "horas" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "minuto" msgstr[1] "minutos" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s hasta que se cargue del todo" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Advertencia: quedan %s" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "%s restante" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Cargada completamente" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Vacía" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Cargando" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Descargando" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Principal" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Adicional" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Ratón inalámbrico" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Teclado inalámbrico" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Fuente de alimentación no interrumplible" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Asistente digital personal" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Teléfono móvil" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Reproductor multimedia" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tableta" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Equipo" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Mando de juegos" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2374 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Batería" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "Cargando" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Precaución" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Baja" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "Bien" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Cargada completamente" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Vacía" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Baterías" -#: panels/power/cc-power-panel.c:1236 +#: panels/power/cc-power-panel.c:1206 +#, c-format +#| msgid "%i hour" +#| msgid_plural "%i hours" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d horas" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +#| msgid "%i minute" +#| msgid_plural "%i minutes" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +#| msgid "30 seconds" +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d segundo" +msgstr[1] "%d segundos" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +#| msgid "%i %s %i %s" +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +#| msgid "%i %s %i %s" +msgctxt "time" +msgid "%s %s" +msgstr "%s %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +#| msgid "30 seconds" +msgid "0 seconds" +msgstr "0 seconds" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Cuando esté _inactivo" -#: panels/power/cc-power-panel.c:1690 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Ahorro de energía" -#: panels/power/cc-power-panel.c:1721 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "_Brillo de la pantalla" -#: panels/power/cc-power-panel.c:1740 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Brillo automático" -#: panels/power/cc-power-panel.c:1760 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "_Brillo del teclado" -#: panels/power/cc-power-panel.c:1770 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "_Oscurecer la pantalla cuando esté inactiva" -#: panels/power/cc-power-panel.c:1795 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" msgstr "_Apagar la pantalla" -#: panels/power/cc-power-panel.c:1832 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1837 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Apagar la Wi-Fi para ahorrar energía." -#: panels/power/cc-power-panel.c:1862 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "Banda ancha _móvil" -#: panels/power/cc-power-panel.c:1867 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "Apagar la banda ancha móvil (3G, 4G, LTE, etc.) para ahorrar energía." -#: panels/power/cc-power-panel.c:1920 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1925 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Apagar el Bluetooth para ahorrar energía." -#: panels/power/cc-power-panel.c:1984 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "En modo batería" -#: panels/power/cc-power-panel.c:1986 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Cuando está conectado a la red" -#: panels/power/cc-power-panel.c:2081 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Suspender" -#: panels/power/cc-power-panel.c:2082 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Apagar" -#: panels/power/cc-power-panel.c:2083 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Hibernar" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Nada" #. Frame header -#: panels/power/cc-power-panel.c:2198 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Botón de suspender y apagar" -#: panels/power/cc-power-panel.c:2237 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "Suspender _automáticamente" -#: panels/power/cc-power-panel.c:2238 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Suspender automáticamente" -#: panels/power/cc-power-panel.c:2305 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "Al pulsar el b_otón de encendido" -#: panels/power/cc-power-panel.c:2424 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Dispositivos" @@ -4124,12 +4205,13 @@ msgid "View your battery status and change power saving settings" msgstr "" "Ver el estado de la batería y cambiar la configuración de ahorro de energía" -#: panels/power/gnome-power-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/power/gnome-power-panel.desktop.in.in:7 msgid "gnome-power-manager" msgstr "gnome-power-manager" -#. Translators: those are keywords for the power control-center panel -#: panels/power/gnome-power-panel.desktop.in.in:18 +#. Translators: Search terms to find the Power panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/power/gnome-power-panel.desktop.in.in:19 msgid "" "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" msgstr "" @@ -4245,18 +4327,18 @@ msgid "Authentication Required" msgstr "Se requiere autenticación" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "Se ha eliminado la impresora «%s»" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Falló al añadir una impresora nueva." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "No se pudo cargar la IU: %s" @@ -4297,18 +4379,18 @@ msgstr "" "Añadir impresoras, ver los trabajos de la impresora y decidir cuál quiere " "imprimir" -#: panels/printers/gnome-printers-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/printers/gnome-printers-panel.desktop.in.in:7 msgid "printer" msgstr "impresora" -#. Translators: those are keywords for the printing control-center panel -#: panels/printers/gnome-printers-panel.desktop.in.in:15 +#. Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/printers/gnome-printers-panel.desktop.in.in:16 msgid "Printer;Queue;Print;Paper;Ink;Toner;" msgstr "Impresora;Cola;Imprimir;Papel;Tinta;Tóner;" #. Translators: This is a windows domain used with SMB protocol. #: panels/printers/jobs-dialog.ui:44 -#| msgid "_Domain" msgid "Domain" msgstr "Dominio" @@ -4324,7 +4406,6 @@ msgstr "Limpiar todos" #. Translators: This button pop up authentication dialog for print jobs which need credentials. #: panels/printers/jobs-dialog.ui:225 -#| msgid "Authenticate" msgid "_Authenticate" msgstr "_Autenticar" @@ -4371,21 +4452,21 @@ msgid "Test Page" msgstr "Página de prueba" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "Detalles de %s" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "No se ha encontrado ningún controlador adecuado" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "Seleccionar archivo PPD" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4398,7 +4479,7 @@ msgid "Select Printer Driver" msgstr "Seleccionar el controlador de la impresora" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Seleccionar" @@ -4455,74 +4536,71 @@ msgid "Reverse portrait" msgstr "Vertical invertido" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Pendiente" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Pausado" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 -#| msgid "Authentication required" +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Autenticación requerida" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "Procesando" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Detenido" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Cancelado" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Abortado" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Completado" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format -#| msgid "Server requires authentication" msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" msgstr[0] "%u trabajo requiere autenticación" msgstr[1] "%u trabajos requieren autenticación" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s - trabajos activos" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format -#| msgid "Enter username and password to view printers on %s." msgid "Enter credentials to print from %s." msgstr "Introduzca las credenciales para imprimir desde %s." @@ -4889,25 +4967,25 @@ msgstr "" "El servicio del sistema de impresión\n" "parece no estar disponible." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Bloqueo de pantalla" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "En uso" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Activado" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Desactivado" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Servicios de ubicación" @@ -4974,12 +5052,13 @@ msgid "Protect your personal information and control what others might see" msgstr "Proteger su información personal y controlar qué pueden ver otros" #. FIXME -#: panels/privacy/gnome-privacy-panel.desktop.in.in:7 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:8 msgid "preferences-system-privacy" msgstr "preferences-system-privacy" -#. Translators: those are keywords for the privacy control-center panel -#: panels/privacy/gnome-privacy-panel.desktop.in.in:19 +#. Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:20 msgid "" "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" "network;identity;" @@ -5166,11 +5245,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Otra" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "No se ha seleccionado ninguna fuente de entrada" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "Pantalla de inicio de _sesión" @@ -5217,12 +5296,13 @@ msgstr "" "Seleccione su idioma, formatos, distribuciones de teclado y fuentes de " "entrada" -#: panels/region/gnome-region-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/region/gnome-region-panel.desktop.in.in:7 msgid "preferences-desktop-locale" msgstr "preferences-desktop-locale" -#. Translators: those are keywords for the region control-center panel -#: panels/region/gnome-region-panel.desktop.in.in:18 +#. Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/region/gnome-region-panel.desktop.in.in:19 msgid "Language;Layout;Keyboard;Input;" msgstr "Idioma;Distribución;Teclado;Entrada;" @@ -5357,12 +5437,13 @@ msgstr "" "Controlar qué aplicaciones muestran resultados de búsqueda en la vista de " "actividades" -#: panels/search/gnome-search-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/search/gnome-search-panel.desktop.in.in:7 msgid "preferences-system-search" msgstr "preferences-system-search" -#. Translators: those are keywords for the search control-center panel -#: panels/search/gnome-search-panel.desktop.in.in:18 +#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/search/gnome-search-panel.desktop.in.in:19 msgid "Search;Find;Index;Hide;Privacy;Results;" msgstr "buscar;búsqueda;índice;ocultar;privacidad;resultados;" @@ -5466,12 +5547,13 @@ msgstr "Compartir" msgid "Control what you want to share with others" msgstr "Controla qué quiere compartir con otros" -#: panels/sharing/gnome-sharing-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:7 msgid "preferences-system-sharing" msgstr "preferences-system-sharing" -#. Translators: those are keywords for the sharing control-center panel -#: panels/sharing/gnome-sharing-panel.desktop.in.in:15 +#. Translators: Search terms to find the Sharing panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:16 msgid "" "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" "movies;server;renderer;" @@ -5577,12 +5659,13 @@ msgstr "Sonido" msgid "Change sound levels, inputs, outputs, and alert sounds" msgstr "Cambiar el volumen de entrada y salida de sonido y las alertas sonoras" -#: panels/sound/data/gnome-sound-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:7 msgid "multimedia-volume-control" msgstr "multimedia-volume-control" -#. Translators: those are keywords for the sound control-center panel -#: panels/sound/data/gnome-sound-panel.desktop.in.in:19 +#. Translators: Search terms to find the Sound panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:20 msgid "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;" msgstr "" "tarjeta;micrófono;volumen;desvanecer;balance;bluetooth;cascos;auriculares;" @@ -5775,34 +5858,223 @@ msgstr "Subwoofer" msgid "Custom" msgstr "Personalizado" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +#| msgid "Disconnected" +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Desconectado" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +#| msgid "Connecting" +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Conectando" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +#| msgid "Connected" +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Conectado" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +#| msgid "Authentication required" +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Error de autorización" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Autorizando" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Funcionalidad reducida" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +#| msgid "Connected Devices" +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Conectado y autorizado" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +#| msgid "Unknown" +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Desconocido" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Autorizado a las:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +#| msgid "Connected" +msgid "Connected at:" +msgstr "Conectado a las:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +#| msgid "_Enroll" +msgid "Enrolled at:" +msgstr "Unido a las:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +#| msgid "Failed to upload file: %s" +msgid "Failed to authorize device: " +msgstr "Falló al autorizar el dispositivo: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +#| msgid "Failed to upload file: %s" +msgid "Failed to forget device: " +msgstr "Falló al olvidar el dispositivo: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +#| msgid "_Name:" +msgid "Name:" +msgstr "Nombre:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Estado:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +#| msgid "Automatic _Connect" +msgid "Authorize and Connect" +msgstr "Autorizar y conectar" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +#| msgid "Remove Device" +msgid "Forget Device" +msgstr "Olvidar dispositivo" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +#| msgid "Mirror" +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Error" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +#| msgid "Authenticated" +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Autorizado" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"El subsistema de Thunderbolt (boltd) no está instalado o no se ha " +"configurado correctamente." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"No se pudo detectar Thunderbolt.\n" +"El sistema carece de soporte para Thunderbolt, se ha desactivado en la BIOS " +"o se ha configurado con un nivel de seguridad no soportado en la BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "El soporte de Thunderbolt se ha desactivado en la BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +#| msgid "Error setting default mailer: %s" +msgid "Error switching direct mode: %s" +msgstr "Error al cambiar al modo directo: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Si soporte para Thunderbolt" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +#| msgid "Universal Access" +msgid "Direct Access" +msgstr "Acceso directo" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "Permitir el acceso a dispositivos como soportes y GPU externas." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Sólo se pueden conectar dispositivos USB y Display Port" + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +#| msgid "Getting devices..." +msgid "Pending Devices" +msgstr "Dispositivos pendientes" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "No hay dispositivos conectados" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +#| msgid "Thunderbird" +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Gestionar dispositivos Thunderbolt" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +#| msgid "Thunderbird" +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +#| msgid "Thunderbird" +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Predeterminado" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Mediano" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Grande" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Más grande" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "El más grande" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5813,12 +6085,13 @@ msgstr[1] "%d píxeles" msgid "Make it easier to see, hear, type, point and click" msgstr "Hacer más sencillo de ver, escuchar, escribir y apuntar y pulsar" -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:7 msgid "preferences-desktop-accessibility" msgstr "preferences-desktop-accessibility" -#. Translators: those are keywords for the universal access control-center panel -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:18 +#. Translators: Search terms to find the Universal Access panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 msgid "" "Keyboard;Mouse;a11y;Accessibility;Contrast;Zoom;Screen;Reader;text;font;size;" "AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;click;Delay;Assist;Repeat;Blink;" @@ -5848,7 +6121,7 @@ msgid "C_ursor Size" msgstr "T_amaño del cursor" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Ampliación" @@ -6142,27 +6415,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Grande" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Corta" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ de pantalla" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ pantalla" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ de pantalla" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Larga" @@ -6187,134 +6460,134 @@ msgstr "Mitad izquierda" msgid "Right Half" msgstr "Mitad derecha" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Opciones de ampliación" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "_Magnificación:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Seguir el cursor del ratón" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "_Parte de la pantalla:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "El magnificador se _extiende fuera de la pantalla" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "_Mantener centrado el cursor del magnificador" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "El cursor del magnificador _empuja el contenido a su alrededor" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "El cursor del magnificador se mueve con el _contenido" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Posición del magnificador:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Magnificador" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Grosor:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Fino" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Grueso" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "_Longitud:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "Co_lor:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "_Cruces:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "_Solapa el cursor del ratón" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Cruces" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "_Blanco sobre negro:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Brillo:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Contraste:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "Co_lor" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Ninguno" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Completo" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Bajo" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Alto" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Bajo" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Alto" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Efectos de color:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Efectos de color" @@ -6457,12 +6730,13 @@ msgstr "Usuarios" msgid "Add or remove users and change your password" msgstr "Añadir o quitar usuarios y cambiar su contraseña" -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:7 msgid "system-users" msgstr "system-users" -#. Translators: those are keywords for the user accounts control-center panel -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:19 +#. Translators: Search terms to find the Users panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:20 msgid "Login;Name;Fingerprint;Avatar;Logo;Face;Password;" msgstr "inicio;sesión;nombre;huella;avatar;logo;cara;contraseña;" @@ -6909,7 +7183,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6917,7 +7191,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6954,7 +7228,7 @@ msgstr "No se pudo cambiar la contraseña" msgid "The passwords do not match." msgstr "Las contraseñas no coinciden." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Examinar para buscar más imágenes" @@ -6982,30 +7256,30 @@ msgstr "Contraseña no válida, inténtelo de nuevo" msgid "Couldn’t connect to the %s domain: %s" msgstr "No se pudo conectar al dominio %s: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Su cuenta" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Falló al eliminar el usuario" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Falló al revocar remotamente el usuario gestionado" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "No puede eliminar su propia cuenta." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s aún está registrado en el sistema" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -7013,12 +7287,12 @@ msgstr "" "Eliminar un usuario mientras está registrado en el sistema puede dejar el " "sistema en un estado inconsistente." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "¿Quiere mantener los archivos de %s?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7026,48 +7300,48 @@ msgstr "" "Es posible mantener la carpeta personal, el «spool» del correo y los " "archivos temporales al eliminar una cuenta de usuario." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "_Eliminar archivos" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "_Mantener archivos" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "" "¿Está seguro de que quiere revocar remotamente la cuenta gestionada de %s?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Eliminar" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Cuenta desactivada" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Para configurar en el siguiente inicio de sesión" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Ninguno" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Sesión iniciada" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Falló al contactar con el servicio de cuentas" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Asegúrese de que el servicio de cuentas está instalado y activado." @@ -7075,7 +7349,7 @@ msgstr "Asegúrese de que el servicio de cuentas está instalado y activado." #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7083,12 +7357,12 @@ msgstr "" "Para realizar los cambios\n" "pulse primero el icono *" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Crear una cuenta de usuario" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7096,12 +7370,12 @@ msgstr "" "Para crear un usuario\n" "pulse primero el icono *" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Quitar la cuenta de usuario seleccionada" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7235,12 +7509,13 @@ msgstr "" "Establecer el mapeado de botones y ajustar la sensibilidad del lápiz para " "tabletas gráficas" -#: panels/wacom/gnome-wacom-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:7 msgid "input-tablet" msgstr "input-tablet" -#. Translators: those are keywords for the wacom tablet control-center panel -#: panels/wacom/gnome-wacom-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wacom Tablet panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:19 msgid "Tablet;Wacom;Stylus;Eraser;Mouse;" msgstr "Tableta;Wacom;Stylus;Borrador;Ratón;" @@ -7376,35 +7651,35 @@ msgstr "" "El centro de control es la interfaz principal de GNOME para la configuración " "de diversos aspectos de su escritorio." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Mostrar el número de versión" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Activar el modo detallado" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Mostrar la visión general" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Buscar la cadena" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Listar todos los nombres de paneles posibles y salir" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Panel que mostrar" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGUMENTO…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Paneles disponibles:" @@ -7416,11 +7691,13 @@ msgstr "Ayuda" msgid "Quit" msgstr "Salir" -#: shell/gnome-control-center.desktop.in.in:4 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: shell/gnome-control-center.desktop.in.in:5 msgid "gnome-control-center" msgstr "gnome-control-center" -#: shell/gnome-control-center.desktop.in.in:15 +#. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: shell/gnome-control-center.desktop.in.in:17 msgid "Preferences;Settings;" msgstr "Preferencias;Configuración;" @@ -7454,12 +7731,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Cancelar búsqueda" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Hotspot" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "El identificador del último panel de Configuración que abrir" @@ -7869,9 +8140,6 @@ msgstr "Sonidos del sistema" #~ msgid "Add Device" #~ msgstr "Añadir dispositivo" -#~ msgid "Remove Device" -#~ msgstr "Quitar dispositivo" - #~ msgid "VPN Type" #~ msgstr "Tipo de VPN" @@ -8212,9 +8480,6 @@ msgstr "Sonidos del sistema" #~ msgid "_Sign In" #~ msgstr "Iniciar _sesión" -#~ msgid "_Name:" -#~ msgstr "_Nombre:" - #~ msgid "C_ommand:" #~ msgstr "C_omando:" @@ -9350,9 +9615,6 @@ msgstr "Sonidos del sistema" #~ msgid "_Settings…" #~ msgstr "_Configuración…" -#~ msgid "Disconnected" -#~ msgstr "Desconectada" - #~ msgid "Unspecified" #~ msgstr "Sin especificar" @@ -9652,9 +9914,6 @@ msgstr "Sonidos del sistema" #~ msgid "_Search by Address" #~ msgstr "Bu_scar por dirección" -#~ msgid "Getting devices..." -#~ msgstr "Obteniendo dispositivos…" - #~ msgid "" #~ "FirewallD is not running. Network printer detection needs services mdns, " #~ "ipp, ipp-client and samba-client enabled on firewall." @@ -10548,9 +10807,6 @@ msgstr "Sonidos del sistema" #~ msgid "Error setting default browser: %s" #~ msgstr "Error al establecer el navegador predeterminado: %s" -#~ msgid "Error setting default mailer: %s" -#~ msgstr "Error al establecer el programa de correo-e predeterminado: %s" - #~ msgid "Could not load the main interface" #~ msgstr "No es posible cargar el interfaz principal" @@ -10858,9 +11114,6 @@ msgstr "Sonidos del sistema" #~ msgid "Sylpheed-Claws" #~ msgstr "Sylpheed-Claws" -#~ msgid "Thunderbird" -#~ msgstr "Thunderbird" - #~ msgid "_Include Top Menu Bar" #~ msgstr "_Incluir barra de menú superior" @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: gnome-control-center master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-23 19:10+0000\n" -"PO-Revision-Date: 2018-02-24 06:09+0100\n" +"POT-Creation-Date: 2018-05-04 12:16+0000\n" +"PO-Revision-Date: 2018-05-05 16:53+0200\n" "Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n" "Language-Team: Friulian <f.t.public@gmail.com>\n" "Language: fur\n" @@ -18,7 +18,7 @@ msgstr "" "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.0.3\n" +"X-Generator: Poedit 2.0.7\n" #: panels/background/background.ui:49 msgid "_Background" @@ -103,16 +103,16 @@ msgstr "" "Al è pussibil zontâ imagjins ae tô cartele %s e a vegnaran mostradis a chi" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 #: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 #: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -121,10 +121,10 @@ msgstr "" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_Anule" @@ -169,39 +169,39 @@ msgstr "preferences-desktop-wallpaper" msgid "Wallpaper;Screen;Desktop;" msgstr "Rivestiment;Sfont;Scrivanie;Desktop;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Distude Modalitât Avion" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Nissun Bluetooth cjatât" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Tache une clâf par doprâ il Bluetooth." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth distudât" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Impie par coneti dispositîfs e ricevi trasferiments file." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Modalitât Avion impiade" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "Il Bluetooth nol è abilitât cuant che la modalitât avion e je impiade." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Modalitât avion hardware impiade" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Distude il cric de modalitât Avion par abilitâ il Bluetooth." @@ -226,7 +226,7 @@ msgid "share;sharing;bluetooth;obex;" msgstr "condividi;condivision;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "" "Place il tô dispositîf di calibrazion parsore dal cuadrât e sclice «Start»" @@ -234,7 +234,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -244,7 +244,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -254,54 +254,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Siere il tapon (visôr) dal portatil" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Al è vignût fûr un erôr interni impussibil di recuperâ." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "I struments necessaris pe calibradure no son instalâts." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "Impussibil gjenerâ il profîl." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "Impussibil vê il pont blanc prefissât." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Completât!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Calibrazion falide!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Al è pussibil gjavâ il dispositîf di calibrazion." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "No sta disturbâ il dispositîf di calibrazion intant che al lavore" @@ -363,48 +363,48 @@ msgstr "No calibrât" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Predefinît: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Spazi colôr: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " -msgstr "Profîl di test: " +msgstr "Profîl di prove: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Selezionâ file profîl ICC" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Impuarte" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Profîi ICC supuartâts" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Ducj i file" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Schermi" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Falît tal cjariâ il file: %s" @@ -412,40 +412,40 @@ msgstr "Falît tal cjariâ il file: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "Il profîl al è stât cjariât su:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Cjape note di cheste URL." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "" "Torne invie il computer e eseguìs il boot dal abituâl sisteme operatîf." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "Scrîf l'URL tal browser par scjariâ e instalâ il profîl." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Salve Profîl" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Salve" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Cree un profîl di colôr pal dispositîf selezionât" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -454,12 +454,12 @@ msgstr "" "tacât te juste maniere." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "Il strument di misure nol supuarte il profiling de stampant." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Il gjenar di dispositîf nol è al moment supuartât." @@ -869,7 +869,6 @@ msgstr "" #. Translators: Do NOT translate or transliterate this text (this is an icon file name)! #: panels/color/gnome-color-panel.desktop.in.in:7 -#| msgid "Preferences" msgid "preferences-color" msgstr "preferences-color" @@ -911,6 +910,12 @@ msgstr "%e %b" msgid "%b %e, %Y" msgstr "%e %b %Y" +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Hotspot" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Lenghe" @@ -1108,58 +1113,58 @@ msgid "To change time or date settings, you need to authenticate." msgstr "" "Par cambiâ lis impostazions de ore e de date al è necessari autenticâsi." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Orizontâl" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Verticâl diestre" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Verticâl çampe" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Orizontâl (invertît)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Orientament" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Risoluzion" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Frecuence di inzornament" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Scjale" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "Juste par TV" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Visôr primari" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Disposizion dai visôrs" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1167,59 +1172,67 @@ msgstr "" "Strissine i visôrs par fâ in mût che a corispuindin ae to configurazion. La " "sbare superiôr e je metude tal visôr primari." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Modalitât visôr" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Unìs visôrs" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Duplicât" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Visôr ugnul" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Aplicâ lis modifichis?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Apliche" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Aplicâ lis modifichis?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "Lis modifichis no puedin jessi aplicadis" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Chest al podarès jessi par vie di limitazions hardware." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1991 panels/power/cc-power-panel.c:1998 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Impiât" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1985 panels/power/cc-power-panel.c:1996 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1227,11 +1240,11 @@ msgstr "Impiât" msgid "Off" msgstr "Distudât" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "Lûs _noturne" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "Impussibil vê informazions sul schermi" @@ -1271,7 +1284,7 @@ msgstr "Tramont a cricâ dì" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Manuâl" @@ -1320,8 +1333,8 @@ msgstr "" "colôr;tramont;cricâ;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "No cognossût" @@ -1329,24 +1342,24 @@ msgstr "No cognossût" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; ID di costruzion: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64-bit" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32-bit" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Version %s" @@ -1487,7 +1500,7 @@ msgstr "" #: panels/info/gnome-removable-media-panel.desktop.in.in:3 msgid "Removable Media" -msgstr "Dispositîfs rimovibil" +msgstr "Dispositîfs estraibii" #: panels/info/gnome-removable-media-panel.desktop.in.in:4 msgid "Configure Removable Media settings" @@ -1677,8 +1690,8 @@ msgstr "Inviadôrs" msgid "Launch help browser" msgstr "Fâs partî il visualizadôr di manuâi" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Impostazions" @@ -1787,7 +1800,7 @@ msgstr "Ative o disative il contrast elevât" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Scurtis personalizadis" @@ -1798,7 +1811,7 @@ msgstr "Scurtis personalizadis" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -1972,7 +1985,7 @@ msgstr "Met" #: panels/mouse/cc-mouse-panel.c:82 panels/wacom/cc-wacom-panel.c:402 msgid "Test Your _Settings" -msgstr "Test _impostazions" +msgstr "Prove lis _impostazions" #: panels/mouse/gnome-mouse-panel.desktop.in.in:3 msgid "Mouse & Touchpad" @@ -2096,7 +2109,7 @@ msgid "Single click, secondary button" msgstr "Clic singul, boton secondari" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:583 msgid "Network proxy" msgstr "Proxy di rêt" @@ -2104,25 +2117,25 @@ msgstr "Proxy di rêt" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:719 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "VPN %s" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:783 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "" "Orpo, al semee che alc al sedi lât par stuart. Contate il furnidôr di " "software." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:789 msgid "NetworkManager needs to be running." msgstr "NetworkManager al à di jessi in esecuzion." -#: panels/network/cc-wifi-panel.c:213 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Wi-Fi" @@ -2266,7 +2279,7 @@ msgid "Remove VPN" msgstr "Gjave VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Detais" @@ -2401,7 +2414,7 @@ msgstr "Indicât par conessions cun adebit o limits di dâts." #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automatic" @@ -2599,9 +2612,9 @@ msgid "Select file to import" msgstr "Selezione un file di impuartâ" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Vierç" @@ -3021,19 +3034,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Password" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Distude Wi-Fi" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "_Conet a rêt platade…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "_Impie hotspot Wi-Fi…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "Rêts Wi-Fi _cognossudis" @@ -3342,23 +3355,23 @@ msgstr "Firmware mancjant" msgid "Cable unplugged" msgstr "Fil stacât" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "erôr no definît inte sigurece 802.1X (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "nissun file selezionât" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "erôr no specificât tal validâ il file dal metodi eap" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "Clâfs privadis DER, PEM, o PKCS#12 (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "Certificâts DER o PEM (*.der, *.pem, *.crt, *.cer)" @@ -3747,7 +3760,6 @@ msgstr "Controle cualis notifichis mostrâ e ce che a mostrin" #. Translators: Do NOT translate or transliterate this text (this is an icon file name)! #: panels/notifications/gnome-notifications-panel.desktop.in.in:7 -#| msgid "Preferences;Settings;" msgid "preferences-system-notifications" msgstr "preferences-system-notifications" @@ -3777,19 +3789,19 @@ msgstr "Altri" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "Account di %s" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Erôr tal gjava l'account" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> gjavât" @@ -3842,18 +3854,18 @@ msgstr "Zonte un account" msgid "Remove Account" msgstr "Gjave account" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Timp no cognossût" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i minût" msgstr[1] "%i minûts" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3862,256 +3874,297 @@ msgstr[1] "%i oris" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s e %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "ore" msgstr[1] "oris" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "minût" msgstr[1] "minûts" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s ae cjarie plene" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Atenzion: ancjemò %s" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "ancjemò %s" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Cjarie" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Scjarie" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "In cjarie" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "In scjarie" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Principâl" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Adizionâl" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Mouse cence fîl" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Tastiere cence fîl" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "UPS" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "PDA" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Celulâr" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Letôr multimediâl" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tablet" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Computer" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Dispositîf di input par zuiâ" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2377 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Batarie" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "In cjarie" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Atenzion" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Basse" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "Buine" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Cjarie" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Scjarie" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Batariis" -#: panels/power/cc-power-panel.c:1239 +#: panels/power/cc-power-panel.c:1206 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ore" +msgstr[1] "%d oris" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minût" +msgstr[1] "%d minûts" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d secont" +msgstr[1] "%d seconts" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s e %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +msgctxt "time" +msgid "%s %s" +msgstr "%s e %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +msgid "0 seconds" +msgstr "0 seconts" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Cuant _inatîf" -#: panels/power/cc-power-panel.c:1693 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Risparmi energjetic" -#: panels/power/cc-power-panel.c:1724 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "Luminositât dal _schermi" -#: panels/power/cc-power-panel.c:1743 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Luminositât automatiche" -#: panels/power/cc-power-panel.c:1763 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "Luminositât de _tastiere" -#: panels/power/cc-power-panel.c:1773 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "_Scurî il schermi cuant che al è inatîf" -#: panels/power/cc-power-panel.c:1798 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" msgstr "Schermi _neri" -#: panels/power/cc-power-panel.c:1835 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1840 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Distude Wi-Fi par sparagnâ curint." -#: panels/power/cc-power-panel.c:1865 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "Bande largje _mobil" -#: panels/power/cc-power-panel.c:1870 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "Distude bande largje mobil (3G, 4G, LTE, ecc.) par sparagnâ energjie." -#: panels/power/cc-power-panel.c:1923 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1928 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Distude il Bluetooth par sparagnâ curint." -#: panels/power/cc-power-panel.c:1987 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "Cuant che si dopre la batarie" -#: panels/power/cc-power-panel.c:1989 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Cuant che al è alimentât" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Sospindi" -#: panels/power/cc-power-panel.c:2085 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Distudâ" -#: panels/power/cc-power-panel.c:2086 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Ibernâ" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Nissune azion" #. Frame header -#: panels/power/cc-power-panel.c:2201 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Sospension e boton par distudâ" -#: panels/power/cc-power-panel.c:2240 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "Sospension _Automatiche" -#: panels/power/cc-power-panel.c:2241 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Sospension automatiche" -#: panels/power/cc-power-panel.c:2308 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "_Cuant che si frache il boton Distude" -#: panels/power/cc-power-panel.c:2427 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Dispositîfs" @@ -4246,18 +4299,18 @@ msgid "Authentication Required" msgstr "Autenticazion necessarie" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "La stampant “%s” e je stade eliminade" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Zonte de gnove stampant falide." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "Impussibil cjariâ la interface: %s" @@ -4364,24 +4417,24 @@ msgstr "" #. Translators: Name of job which makes printer to print test page #: panels/printers/options-dialog.ui:22 panels/printers/pp-options-dialog.c:893 msgid "Test Page" -msgstr "Pagjine di test" +msgstr "Pagjine di prove" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "Detais di %s" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "Nissun driver adat cjatât" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "Selezione file PPD" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4394,7 +4447,7 @@ msgid "Select Printer Driver" msgstr "Selezione driver stampant" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Selezione" @@ -4451,71 +4504,70 @@ msgid "Reverse portrait" msgstr "Verticâl invertît" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "In atese" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "In pause" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Autenticazion necessarie" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "In elaborazion" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Fermât" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Anulât" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Interot" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Finît" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format -#| msgid "Server requires authentication" msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" msgstr[0] "%u lavôr al domande autenticazion" msgstr[1] "%u lavôrs a domandin autenticazion" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s — Lavôrs Atîfs" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "Inserìs lis credenziâls par stampâ di %s." @@ -4653,7 +4705,7 @@ msgstr "Avanzadis" #. Translators: Name of job which makes printer to print test page #: panels/printers/pp-options-dialog.c:908 msgid "Test page" -msgstr "Pagjine di test" +msgstr "Pagjine di prove" #. Translators: this is an option of "Paper Source" #: panels/printers/pp-ppd-option-widget.c:76 @@ -4881,25 +4933,25 @@ msgstr "" "Il servizi di sisteme pe stampe\n" "nol semee jessi disponibil." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Bloc schermi" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "In ûs" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "On" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Off" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Servizis su la posizion" @@ -5161,11 +5213,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Altri" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Nissune sorzint input selezionade" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "_Schermade di acès" @@ -5391,7 +5443,7 @@ msgid "Preferences" msgstr "Preferencis" #. Label -#: panels/sharing/cc-sharing-networks.c:305 +#: panels/sharing/cc-sharing-networks.c:307 msgid "No networks selected for sharing" msgstr "Nissune rêt selezionade pe condivision" @@ -5665,7 +5717,7 @@ msgstr "_Profîl:" #: panels/sound/gvc-mixer-dialog.c:255 msgid "_Test Speakers" -msgstr "_Test cassis" +msgstr "_Prove cassis" #: panels/sound/gvc-mixer-dialog.c:424 msgid "Peak detect" @@ -5678,7 +5730,7 @@ msgstr "Dispositîf" #: panels/sound/gvc-mixer-dialog.c:1562 #, c-format msgid "Speaker Testing for %s" -msgstr "Test cassis par %s" +msgstr "Prove cassis par %s" #: panels/sound/gvc-mixer-dialog.c:1617 msgid "_Output volume:" @@ -5738,7 +5790,7 @@ msgstr "Preferencis sun" #: panels/sound/gvc-sound-theme-chooser.c:460 #: panels/sound/gvc-sound-theme-chooser.c:472 msgid "Testing event sound" -msgstr "Test event sonôr" +msgstr "Prove event sonôr" #: panels/sound/gvc-sound-theme-chooser.c:544 #: panels/wacom/wacom-stylus-page.ui:25 @@ -5759,7 +5811,7 @@ msgstr "Ferme" #: panels/sound/gvc-speaker-test.c:229 panels/sound/gvc-speaker-test.c:341 msgid "Test" -msgstr "Test" +msgstr "Prove" #: panels/sound/gvc-speaker-test.c:237 msgid "Subwoofer" @@ -5769,34 +5821,203 @@ msgstr "Subwoofer" msgid "Custom" msgstr "Personalizât" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Daûr a disconeti" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Daûr a coneti" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Conetût" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Erôr di autorizazion" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Daûr a autorizâ" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Funzionalitât ridote" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Conetût e autorizât" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "No cognossût" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Autorizât aes:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Conetût aes:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Regjistrât aes:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "No i è rivâts a autorizâ il dispositîf: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "No si è rivâts a dismenteâ il dispositîf: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Non:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Stât:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Autorize e conet" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Dismentee dispositîf" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Erôr" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Autorizât" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"Il sot-sisteme Thunderbolt (boltd) nol è instalât o nol è stât configurât in " +"maniere adate." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"Nol è stât pussibil rilevât Thunderbolt.\n" +"O al mancje tal sisteme il supuart par Thunderbolt, o al è stât disabilitât " +"tal BIOS o al è stât configurât tal BIOS a un nivel di sigurece no supuartât." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "Il supuart a Thunderbolt al è stât disabilitât tal BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Erôr tal passâ ae modalitât direte: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Nissun supuart par Thunderbolt" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Acès diret" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "" +"Permet l'acès diret a dispositîfs come supuarts (docks) e GPU esternis." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Dome i dispositîfs USB e Display Port a puedin tacâsi." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Dispositîf in pîts in spiete" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Nissun dispositîf tacât" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Gjestìs i dispositîfs Thunderbolt" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Predefinide" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Medie" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Grant" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Plui grant" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "Il plui grant" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5843,7 +6064,7 @@ msgid "C_ursor Size" msgstr "Dimension c_ursôr" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Ingrandiment" @@ -6134,27 +6355,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Grant" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Curt" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ di schermi" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ schermi" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ di schermi" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Lungje" @@ -6179,134 +6400,134 @@ msgstr "Metât çampe" msgid "Right Half" msgstr "Metât diestre" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Opzions di ingrandiment" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "In_grandiment:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Cor daûr dal cursôr dal mouse" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "Part di _schermi:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "L'ingranditôr si _slargje fûr dal visôr" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "_Tegnî il cursôr dal ingranditôr tal mieç" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "Il cursôr dal ingranditôr al _sburte il contignût" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "Il cursôr dal ingranditôr si sposte cui _contignûts" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Posizion dal ingranditôr:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Ingranditôr" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Spessôr:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Fin" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Spes" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "_Lungjece:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "Co_lôr:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "S_mire:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "_Al sta parsore dal cursôr dal mouse" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Smiris" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "Blanc su _neri:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "L_uminositât:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Contrast:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "Co_lôr" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Nissun" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Plen" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Basse" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Alte" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Ridot" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Elevât" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Efiets colôr:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Efiets colôr" @@ -6721,29 +6942,29 @@ msgstr "Erôr no cognossût" msgid "Should match the web address of your login provider." msgstr "Al varès di corispuindi ae direzion web dal to furnidôr di acès." -#: panels/user-accounts/um-account-dialog.c:229 +#: panels/user-accounts/um-account-dialog.c:228 msgid "Failed to add account" msgstr "Zonte dal account falide" -#: panels/user-accounts/um-account-dialog.c:462 +#: panels/user-accounts/um-account-dialog.c:461 msgid "Passwords do not match." msgstr "Lis password no corispuindin." -#: panels/user-accounts/um-account-dialog.c:717 -#: panels/user-accounts/um-account-dialog.c:763 -#: panels/user-accounts/um-account-dialog.c:784 +#: panels/user-accounts/um-account-dialog.c:716 +#: panels/user-accounts/um-account-dialog.c:762 +#: panels/user-accounts/um-account-dialog.c:783 msgid "Failed to register account" msgstr "Regjistrazion account falide" -#: panels/user-accounts/um-account-dialog.c:907 +#: panels/user-accounts/um-account-dialog.c:906 msgid "No supported way to authenticate with this domain" msgstr "Nissun mût supuartât par autenticâsi cun chest domini" -#: panels/user-accounts/um-account-dialog.c:980 +#: panels/user-accounts/um-account-dialog.c:979 msgid "Failed to join domain" msgstr "Falît a unîsi al domini" -#: panels/user-accounts/um-account-dialog.c:1041 +#: panels/user-accounts/um-account-dialog.c:1040 msgid "" "That login name didn’t work.\n" "Please try again." @@ -6751,7 +6972,7 @@ msgstr "" "Non di acès no valit.\n" "Prove une altre volte." -#: panels/user-accounts/um-account-dialog.c:1048 +#: panels/user-accounts/um-account-dialog.c:1047 msgid "" "That login password didn’t work.\n" "Please try again." @@ -6759,11 +6980,11 @@ msgstr "" "Password no valide.\n" "Prove une altre volte." -#: panels/user-accounts/um-account-dialog.c:1056 +#: panels/user-accounts/um-account-dialog.c:1055 msgid "Failed to log into domain" msgstr "Acès al domini falît" -#: panels/user-accounts/um-account-dialog.c:1114 +#: panels/user-accounts/um-account-dialog.c:1113 msgid "Unable to find the domain. Maybe you misspelled it?" msgstr "Impussibil cjatâ il domini. Isal stât scrit mâl?" @@ -6898,7 +7119,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%H:%M" @@ -6906,7 +7127,7 @@ msgstr "%H:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6943,58 +7164,57 @@ msgstr "Impussibil cambiâ la password" msgid "The passwords do not match." msgstr "Lis password no corispuindin." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Esplore altris imagjins" -#: panels/user-accounts/um-realm-manager.c:350 +#: panels/user-accounts/um-realm-manager.c:310 msgid "Cannot automatically join this type of domain" msgstr "Impussibil unîsi in automatic a chest gjenar di domini" -#: panels/user-accounts/um-realm-manager.c:413 -#, c-format +#: panels/user-accounts/um-realm-manager.c:313 msgid "No such domain or realm found" msgstr "Nissun domini o ream cjatâts" -#: panels/user-accounts/um-realm-manager.c:815 -#: panels/user-accounts/um-realm-manager.c:829 +#: panels/user-accounts/um-realm-manager.c:735 +#: panels/user-accounts/um-realm-manager.c:749 #, c-format msgid "Cannot log in as %s at the %s domain" msgstr "Impussibil acedi come %s al domini %s" -#: panels/user-accounts/um-realm-manager.c:821 +#: panels/user-accounts/um-realm-manager.c:741 msgid "Invalid password, please try again" msgstr "Password no valide, prove di gnûf" -#: panels/user-accounts/um-realm-manager.c:834 +#: panels/user-accounts/um-realm-manager.c:754 #, c-format msgid "Couldn’t connect to the %s domain: %s" msgstr "Impussibil tacâsi al domini %s: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Il to account" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Eliminazion utent falide" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Revoche dal utent gjestît di rimot falide" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Nol è permetût eliminâ il propri account." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s nol à ancjemò terminât la session" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -7002,12 +7222,12 @@ msgstr "" "Eliminâ un utent intant che la sô session e je ancjemò in cors, al pues " "lassâ il sisteme in stât incoerent." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "Tignî i file di %s?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7015,47 +7235,47 @@ msgstr "" "Al è pussibil tegnî la cartele home, la code di pueste e i varis file " "temporanis cuant che si elimine un account utent." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "_Scancele file" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "_Ten file" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "Sigûrs di revocâ l'account di %s gjestît di rimot?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Elimine" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Account disabilitât" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Di stabilî al prossim acès" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Nissun" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Acès eseguît" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Comunicazion cun servizi account falide" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Sigurâsi che AccountService al sedi instalât e abilitât." @@ -7063,7 +7283,7 @@ msgstr "Sigurâsi che AccountService al sedi instalât e abilitât." #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7071,12 +7291,12 @@ msgstr "" "Par aplicâ cambiaments,\n" "fâs prime clic su la icone *" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Cree un account utent" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7084,12 +7304,12 @@ msgstr "" "Par creâ un account utent,\n" "fas prime clic su la icone *" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Elimine l'account utent selezionât" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7367,35 +7587,35 @@ msgstr "" "Il centri di control GNOME e je la interface principâl par configurâ diviers " "aspiets dal to scritori." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Mostre numar version" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Abilite modalitât lungje/fetose" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Mostre la panoramiche" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Cîr la stringhe" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Liste i nons dai panei disponibii e jes" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Panel di mostrâ" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGOMENT…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Panei disponibii:" @@ -7447,12 +7667,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Anule ricercje" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Hotspot" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "L'identificadôr pal ultin panel di Impostazions di vierzi" @@ -7665,12 +7879,6 @@ msgstr "Suns di sisteme" #~ msgid "_Method" #~ msgstr "_Maniere" -#~ msgid "Add Device" -#~ msgstr "Zonte dispositîf" - -#~ msgid "Remove Device" -#~ msgstr "Gjave dispositîf" - #~ msgid "VPN Type" #~ msgstr "Gjenar di VPN" @@ -8001,9 +8209,6 @@ msgstr "Suns di sisteme" #~ msgid "_Sign In" #~ msgstr "_Jentre" -#~ msgid "_Name:" -#~ msgstr "_Non:" - #~ msgid "Add Shortcut" #~ msgstr "Zonte scurte" @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: gnome-control-center 2.0\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-20 09:14+0000\n" -"PO-Revision-Date: 2018-02-20 12:18+0100\n" +"POT-Creation-Date: 2018-04-16 12:25+0000\n" +"PO-Revision-Date: 2018-04-16 14:27+0200\n" "Last-Translator: gogo <trebelnik2@gmail.com>\n" "Language-Team: Croatian <lokalizacija@linux.hr>\n" "Language: hr\n" @@ -102,14 +102,14 @@ msgid "You can add images to your %s folder and they will show up here" msgstr "Možete dodati slike u vašu %s mapu i zatim će se prikazati ovdje gore" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 -#: panels/network/net-device-wifi.c:1371 panels/network/net-device-wifi.c:1451 -#: panels/network/net-device-wifi.c:1690 panels/network/network-wifi.ui:24 +#: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 +#: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 #: panels/printers/pp-details-dialog.c:331 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 @@ -120,10 +120,10 @@ msgstr "Možete dodati slike u vašu %s mapu i zatim će se prikazati ovdje gore #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_Odustani" @@ -158,48 +158,49 @@ msgstr "Pozadina" msgid "Change your background image to a wallpaper or photo" msgstr "Promijenite vašu pozadinsku sliku u sliku pozadine ili fotografiju" -#: panels/background/gnome-background-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/background/gnome-background-panel.desktop.in.in:7 msgid "preferences-desktop-wallpaper" msgstr "osobitosti-pozadine-radne površine" -#. Translators: those are keywords for the background control-center panel -#: panels/background/gnome-background-panel.desktop.in.in:14 +#. Translators: Search terms to find the Background panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/background/gnome-background-panel.desktop.in.in:15 msgid "Wallpaper;Screen;Desktop;" msgstr "Slika pozadine;Zaslon;Radna površina;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Isključi način rada u zrakoplovu" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Nema pronađenih Bluetooth uređaja" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Priključite uređaj kako bi mogli koristiti Bluetooth." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth je isključen" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Uključite za povezivanje uređaja i prijenos datoteka." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Način rada u zrakoplovu je uključen" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "Bluetooth je onemogućen kada je način rada u zrakoplovu uključen." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Hardverski način rada u zrakoplovu je uključen" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Isključite način rada u zrakoplovu kako bi mogli kristiti Bluetooth." @@ -213,17 +214,18 @@ msgstr "Bluetooth" msgid "Turn Bluetooth on and off and connect your devices" msgstr "Uključite ili isključite Bluetooth i povežite svoje uređaje" -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:5 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:6 msgid "bluetooth" msgstr "bluetooth" -#. Translators: those are keywords for the bluetooth control-center panel -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:18 +#. Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:19 msgid "share;sharing;bluetooth;obex;" msgstr "dijeli;dijeljenje;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "" "Smjestite vaš uređaj za kalibraciju preko četverokuta i pritisnite ”Pokreni”" @@ -231,7 +233,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -241,7 +243,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -251,54 +253,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Spusti zaslon prijenosnika" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Dogodila se unutrašnja greška koja se ne može oporaviti." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "Alati potrebni za kalibraciju nisu instalirani." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "Profil se ne može stvoriti." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "Odredišna bijela točka je dostižna." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Završeno!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Kalibracija nije uspjela!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Možete ukloniti uređaj za kalibraciju." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "Nemojte ometati uređaj tijekom kalibracije" @@ -360,48 +362,48 @@ msgstr "Nije kalibriran" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Uobičajeno: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Raspon boja: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Testni profil: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Odaberi ICC datoteku profila" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Uvezi" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Podržani ICC profili" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Sve datoteke" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Zaslon" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Neuspjelo slanje datoteke: %s" @@ -409,40 +411,40 @@ msgstr "Neuspjelo slanje datoteke: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "Profil je poslan na:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Zapišite ovaj URL." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "" "Ponovno pokrenite ovo računalo i pokrenite vaš uobičajeni operativni sustav." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "Upišite URL u vaš preglednik za preuzimanje i instalaciju profila." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Spremi profil" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Spremi" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Napravi profil boje za odabrani uređaj" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -450,12 +452,12 @@ msgstr "" "Mjerni uređaj nije pronađen. Provjerite je li uključen i ispravno spojen." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "Mjerni uređaj ne podržava profiliranje pisača." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Vrsta uređaja trenutno nije podržana." @@ -861,12 +863,13 @@ msgid "" "Calibrate the color of your devices, such as displays, cameras or printers" msgstr "Kalibrirajte boju vašeg uređaja, poput zalona, kamera i pisača" -#: panels/color/gnome-color-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/color/gnome-color-panel.desktop.in.in:7 msgid "preferences-color" msgstr "osobitosti-boje" -#. Translators: those are keywords for the color control-center panel -#: panels/color/gnome-color-panel.desktop.in.in:18 +#. Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/color/gnome-color-panel.desktop.in.in:19 msgid "Color;ICC;Profile;Calibrate;Printer;Display;" msgstr "Boja;ICC;Profil;Kalibriraj;Pisač;Zaslon;" @@ -1081,12 +1084,13 @@ msgstr "12-satno" msgid "Change the date and time, including time zone" msgstr "Promijenite datum i vrijeme, uključujući vremensku zonu" -#: panels/datetime/gnome-datetime-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:7 msgid "preferences-system-time" msgstr "osobitosti-vremena-sustava" -#. Translators: those are keywords for the date and time control-center panel -#: panels/datetime/gnome-datetime-panel.desktop.in.in:14 +#. Translators: Search terms to find the Date and Time panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:15 msgid "Clock;Timezone;Location;" msgstr "Sat;vremenska zona;lokacija;" @@ -1098,58 +1102,58 @@ msgstr "Promijeni postavke vremena i datuma sustava" msgid "To change time or date settings, you need to authenticate." msgstr "Morate se ovjeriti kako bi promijenili postavke vremena ili datuma." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Položeno" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Uspravno desno" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Uspravno lijevo" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Obrnuto položeno" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Orijentacija" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Razlučivost" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Frekvencija" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Prilagodba veličine" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "Prilagodi za TV" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Glavni zaslon" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Razmještaj zaslona" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1157,59 +1161,67 @@ msgstr "" "Povlačite zaslone kako bi se prilagodili vašim postavkama. Gornja traka je " "smještena na glavnom zaslonu." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Način rada zalona" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Spojeni zasloni" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Zrcalo" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Jednostruki zaslon" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Primijeni promjene?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Primijeni" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Primijeni promjene?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "Promjene se ne mogu primijeniti" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "To može biti uzrokovano ograničenjem hardvera." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1995 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2012 panels/power/cc-power-panel.c:2019 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Uključeno" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1982 panels/power/cc-power-panel.c:1993 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2006 panels/power/cc-power-panel.c:2017 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1217,11 +1229,11 @@ msgstr "Uključeno" msgid "Off" msgstr "Isključeno" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "_Noćno svjetlo" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "Nemoguće dobivanje informacije zaslona" @@ -1261,7 +1273,7 @@ msgstr "Zalazak prema izlasku sunca" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Ručno" @@ -1295,12 +1307,13 @@ msgstr "Zasloni" msgid "Choose how to use connected monitors and projectors" msgstr "Odaberite kako koristiti monitore i projektore" -#: panels/display/gnome-display-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/display/gnome-display-panel.desktop.in.in:7 msgid "preferences-desktop-display" msgstr "osobitosti-zaslona-radne površine" -#. Translators: those are keywords for the display control-center panel -#: panels/display/gnome-display-panel.desktop.in.in:18 +#. Translators: Search terms to find the Displays panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/display/gnome-display-panel.desktop.in.in:19 msgid "" "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" "redshift;color;sunset;sunrise;" @@ -1309,8 +1322,8 @@ msgstr "" "crveni pomak; boja;zalazak;izlazak;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Nepoznato" @@ -1318,24 +1331,24 @@ msgstr "Nepoznato" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; ID izgradnje: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64-bitni" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32-bitni" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Inačica %s" @@ -1438,12 +1451,13 @@ msgstr "Zadane aplikacije" msgid "Configure Default Applications" msgstr "Prilagodite zadane aplikacije" -#: panels/info/gnome-default-apps-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-default-apps-panel.desktop.in.in:7 msgid "starred" msgstr "označeno" -#. Translators: those are keywords for the Default Applications panel -#: panels/info/gnome-default-apps-panel.desktop.in.in:18 +#. Translators: Search terms to find the Default Applications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-default-apps-panel.desktop.in.in:19 msgid "default;application;preferred;media;" msgstr "zadano;aplikacija;poželjno;medij;" @@ -1455,14 +1469,17 @@ msgstr "O sustavu" msgid "View information about your system" msgstr "Prikaži informacije ovog sustava" -#: panels/info/gnome-info-overview-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-info-overview-panel.desktop.in.in:7 msgid "help-about" msgstr "pomoć-o sustavu" -#. Translators: those are keywords for the System Information panel +#. Translators: Search terms to find the About panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. "Preferred Applications" is the old name for the preference, so make #. sure that you use the same "translation" for those keywords -#: panels/info/gnome-info-overview-panel.desktop.in.in:20 +#: panels/info/gnome-info-overview-panel.desktop.in.in:23 msgid "" "device;system;information;memory;processor;version;default;application;" "preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" @@ -1478,12 +1495,13 @@ msgstr "Prijenosni mediji" msgid "Configure Removable Media settings" msgstr "Prilagodite prijenosne medije" -#: panels/info/gnome-removable-media-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-removable-media-panel.desktop.in.in:7 msgid "media-removable" msgstr "prijenosni-mediji" -#. Translators: those are keywords for the Removable Media panel -#: panels/info/gnome-removable-media-panel.desktop.in.in:18 +#. Translators: Search terms to find the Removable Media panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-removable-media-panel.desktop.in.in:19 msgid "" "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" "removable;media;autorun;" @@ -1661,8 +1679,8 @@ msgstr "Pokretači" msgid "Launch help browser" msgstr "Pokreni preglednik pomoći" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Postavke" @@ -1771,7 +1789,7 @@ msgstr "Uključi ili isključi visoki kontrast" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Prilagođeni prečaci" @@ -1782,7 +1800,7 @@ msgstr "Prilagođeni prečaci" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -1872,12 +1890,13 @@ msgid "View and change keyboard shortcuts and set your typing preferences" msgstr "" "Pogledajte i promijenite prečace tipkovnice i postavite osobitosti tipkanja" -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:7 msgid "input-keyboard" msgstr "način unosa-tipkovnice" -#. Translators: those are keywords for the keyboard control-center panel -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:18 +#. Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 msgid "" "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" msgstr "" @@ -1966,12 +1985,13 @@ msgid "" msgstr "" "Promijenite osjetljivost touchpada i miša i odaberite lijevu ili desnu ruku" -#: panels/mouse/gnome-mouse-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:7 msgid "input-mouse" msgstr "način unosa-miša" -#. Translators: those are keywords for the mouse and touchpad control-center panel -#: panels/mouse/gnome-mouse-panel.desktop.in.in:18 +#. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:19 msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" msgstr "" "Klizna površina;Pokazivač;Klik;Dodir;Dvostruk;Tipka;Klizna kugla;Pomakni;" @@ -2075,7 +2095,7 @@ msgid "Single click, secondary button" msgstr "Jednostruki klik, druga tipka" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:581 msgid "Network proxy" msgstr "Mrežni proxy" @@ -2083,24 +2103,24 @@ msgstr "Mrežni proxy" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:717 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "%s VPN" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:781 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "" "Ups, nešto je pošlo po krivu. Kontaktirajte svojeg dobavljača softvera." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:787 msgid "NetworkManager needs to be running." msgstr "Mrežni upravitelj mora biti pokrenut." -#: panels/network/cc-wifi-panel.c:212 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Bežična mreža" @@ -2151,31 +2171,31 @@ msgstr "Profil %d" #. TRANSLATORS: this WEP WiFi security #: panels/network/connection-editor/ce-page-details.c:56 -#: panels/network/net-device-wifi.c:231 panels/network/net-device-wifi.c:453 +#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:468 msgid "WEP" msgstr "WEP" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:60 -#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:458 +#: panels/network/net-device-wifi.c:239 panels/network/net-device-wifi.c:473 #: panels/network/network-wifi.ui:593 msgid "WPA" msgstr "WPA" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:64 -#: panels/network/net-device-wifi.c:239 +#: panels/network/net-device-wifi.c:243 msgid "WPA2" msgstr "WPA2" #. TRANSLATORS: this Enterprise WiFi security #: panels/network/connection-editor/ce-page-details.c:69 -#: panels/network/net-device-wifi.c:244 +#: panels/network/net-device-wifi.c:248 msgid "Enterprise" msgstr "Poslovanje" #: panels/network/connection-editor/ce-page-details.c:74 -#: panels/network/net-device-wifi.c:249 panels/network/net-device-wifi.c:443 +#: panels/network/net-device-wifi.c:253 panels/network/net-device-wifi.c:458 msgctxt "Wifi security" msgid "None" msgstr "Nepoznata" @@ -2187,7 +2207,7 @@ msgstr "Nikada" #: panels/network/connection-editor/ce-page-details.c:110 #: panels/network/net-device-ethernet.c:121 -#: panels/network/net-device-wifi.c:552 +#: panels/network/net-device-wifi.c:567 #, c-format msgid "%i day ago" msgid_plural "%i days ago" @@ -2197,37 +2217,37 @@ msgstr[2] "prije %i dana" #. Translators: network device speed #: panels/network/connection-editor/ce-page-details.c:225 -#: panels/network/net-device-ethernet.c:50 panels/network/net-device-wifi.c:608 +#: panels/network/net-device-ethernet.c:50 panels/network/net-device-wifi.c:646 #, c-format msgid "%d Mb/s" msgstr "%d Mb/s" #: panels/network/connection-editor/ce-page-details.c:251 -#: panels/network/net-device-wifi.c:637 +#: panels/network/net-device-wifi.c:675 msgctxt "Signal strength" msgid "None" msgstr "Nepoznata" #: panels/network/connection-editor/ce-page-details.c:253 -#: panels/network/net-device-wifi.c:639 +#: panels/network/net-device-wifi.c:677 msgctxt "Signal strength" msgid "Weak" msgstr "Slaba" #: panels/network/connection-editor/ce-page-details.c:255 -#: panels/network/net-device-wifi.c:641 +#: panels/network/net-device-wifi.c:679 msgctxt "Signal strength" msgid "Ok" msgstr "U redu" #: panels/network/connection-editor/ce-page-details.c:257 -#: panels/network/net-device-wifi.c:643 +#: panels/network/net-device-wifi.c:681 msgctxt "Signal strength" msgid "Good" msgstr "Dobra" #: panels/network/connection-editor/ce-page-details.c:259 -#: panels/network/net-device-wifi.c:645 +#: panels/network/net-device-wifi.c:683 msgctxt "Signal strength" msgid "Excellent" msgstr "Izvrsna" @@ -2245,7 +2265,7 @@ msgid "Remove VPN" msgstr "Ukloni VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Pojedinosti" @@ -2380,7 +2400,7 @@ msgstr "Prikladno za povezivanja s naplatom ili ograničenjem podataka." #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automatski" @@ -2580,7 +2600,7 @@ msgstr "Odaberi datoteku za uvoz" #: panels/network/connection-editor/vpn-helpers.c:182 #: panels/printers/pp-details-dialog.c:332 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Otvori" @@ -2645,12 +2665,13 @@ msgstr "Mreža" msgid "Control how you connect to the Internet" msgstr "Upravljajte načinom povezivanja na Internet" -#: panels/network/gnome-network-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-network-panel.desktop.in.in:7 msgid "network-workgroup" msgstr "mrežna-radna grupa" -#. Translators: those are keywords for the network control-center panel -#: panels/network/gnome-network-panel.desktop.in.in:18 +#. Translators: Search terms to find the Network panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-network-panel.desktop.in.in:19 msgid "" "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;" "DNS;" @@ -2662,27 +2683,28 @@ msgstr "" msgid "Control how you connect to Wi-Fi networks" msgstr "Upravljajte načinom povezivanja na bežične mreže" -#: panels/network/gnome-wifi-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-wifi-panel.desktop.in.in:7 msgid "network-wireless" msgstr "bežična-mreža" -#. Translators: those are keywords for the wi-fi control-center panel -#: panels/network/gnome-wifi-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wi-Fi panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-wifi-panel.desktop.in.in:19 msgid "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;" msgstr "Mreža;Bežično;Bežična mreža;IP;Žično;Širokopojasni internet;DNS;" #: panels/network/net-device-ethernet.c:107 -#: panels/network/net-device-wifi.c:538 +#: panels/network/net-device-wifi.c:553 msgid "never" msgstr "nikada" #: panels/network/net-device-ethernet.c:117 -#: panels/network/net-device-wifi.c:548 +#: panels/network/net-device-wifi.c:563 msgid "today" msgstr "danas" #: panels/network/net-device-ethernet.c:119 -#: panels/network/net-device-wifi.c:550 +#: panels/network/net-device-wifi.c:565 msgid "yesterday" msgstr "jučer" @@ -2707,7 +2729,7 @@ msgid "Wired" msgstr "Žična mreža" #: panels/network/net-device-ethernet.c:344 -#: panels/network/net-device-wifi.c:1849 panels/network/network-ethernet.ui:120 +#: panels/network/net-device-wifi.c:1895 panels/network/network-ethernet.ui:120 #: panels/network/network-mobile.ui:394 panels/network/network-simple.ui:75 #: panels/network/network-vpn.ui:79 msgid "Options…" @@ -2717,12 +2739,12 @@ msgstr "Mogućnosti…" msgid "Add new connection" msgstr "Dodaj novu mrežu" -#: panels/network/net-device-wifi.c:1328 +#: panels/network/net-device-wifi.c:1368 #, c-format msgid "Switching on the wireless hotspot will disconnect you from <b>%s</b>." msgstr "Prebacivanje na bežičnu pristupnu točku odspojiti će vas s <b>%s</b>." -#: panels/network/net-device-wifi.c:1332 +#: panels/network/net-device-wifi.c:1372 msgid "" "It is not possible to access the Internet through your wireless while the " "hotspot is active." @@ -2730,11 +2752,11 @@ msgstr "" "Pristup Internetu nije moguć putem vašeg bežičnog povezivanja dok je " "pristupna točka aktivna." -#: panels/network/net-device-wifi.c:1339 +#: panels/network/net-device-wifi.c:1379 msgid "Turn On Wi-Fi Hotspot?" msgstr "Uključi bežičnu pristupnu točku?" -#: panels/network/net-device-wifi.c:1361 +#: panels/network/net-device-wifi.c:1401 msgid "" "Wi-Fi hotspots are usually used to share an additional Internet connection " "over Wi-Fi." @@ -2742,27 +2764,27 @@ msgstr "" "Bežične pristupne točke uobičajeno se koriste za dijeljenje dodatnog " "pristupa internetu putem bežične mreže." -#: panels/network/net-device-wifi.c:1372 +#: panels/network/net-device-wifi.c:1412 msgid "_Turn On" msgstr "_Uključi" -#: panels/network/net-device-wifi.c:1449 +#: panels/network/net-device-wifi.c:1489 msgid "Stop hotspot and disconnect any users?" msgstr "Zaustaviti pristupnu točku i odspojiti sve korisnike?" -#: panels/network/net-device-wifi.c:1452 +#: panels/network/net-device-wifi.c:1492 msgid "_Stop Hotspot" msgstr "_Zaustavi pristupnu točku" -#: panels/network/net-device-wifi.c:1552 +#: panels/network/net-device-wifi.c:1592 msgid "System policy prohibits use as a Hotspot" msgstr "Pravila sustava ne dopuštaju korištenje kao pristupne točke" -#: panels/network/net-device-wifi.c:1555 +#: panels/network/net-device-wifi.c:1595 msgid "Wireless device does not support Hotspot mode" msgstr "Bežični uređaj ne podržava način pristupne točke" -#: panels/network/net-device-wifi.c:1687 +#: panels/network/net-device-wifi.c:1733 msgid "" "Network details for the selected networks, including passwords and any " "custom configuration will be lost." @@ -2770,16 +2792,16 @@ msgstr "" "Mrežne pojedinosti za odabrane mreže, uključujući lozinke i sve prilagođene " "postavke će biti izgubljene." -#: panels/network/net-device-wifi.c:1691 panels/network/network-wifi.ui:1362 +#: panels/network/net-device-wifi.c:1737 panels/network/network-wifi.ui:1362 msgid "_Forget" msgstr "_Zaboravi" -#: panels/network/net-device-wifi.c:2000 panels/network/net-device-wifi.c:2007 +#: panels/network/net-device-wifi.c:2046 panels/network/net-device-wifi.c:2053 msgid "Known Wi-Fi Networks" msgstr "Poznate bežične mreže" #. translators: This is the label for the "Forget wireless network" functionality -#: panels/network/net-device-wifi.c:2040 +#: panels/network/net-device-wifi.c:2086 msgctxt "Wi-Fi Network" msgid "_Forget" msgstr "_Zaboravi" @@ -2998,19 +3020,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Lozinka" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Isključi bežičnu mrežu" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "_Poveži se na skrivenu mrežu…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "_Uključi bežičnu pristupnu točku…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "_Poznate bežične mreže" @@ -3319,23 +3341,23 @@ msgstr "Nedostaje firmver" msgid "Cable unplugged" msgstr "Kabel je odspojen" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "neodređena greška u 802.1x sigurnosti (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "nema odabrane datoteke" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "neodređena greška provjeravanja datoteke eap-načina" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM, ili PKCS#12 privatni ključevi (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "DER ili PEM vjerodajnice (*.der, *.pem, *.crt, *.cer)" @@ -3719,12 +3741,13 @@ msgstr "Obavijesti" msgid "Control which notifications are displayed and what they show" msgstr "Upravljajte koje će poruke biti prikazane i što će prikazivati" -#: panels/notifications/gnome-notifications-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:7 msgid "preferences-system-notifications" msgstr "osobitosti-obavijesti-sustava" -#. Translators: those are keywords for the notifications control-center panel -#: panels/notifications/gnome-notifications-panel.desktop.in.in:19 +#. Translators: Search terms to find the Notifications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:20 msgid "Notifications;Banner;Message;Tray;Popup;" msgstr "Obavijesti;Transparent;Poruka;Statusna traka;Skočni prozor;" @@ -3749,19 +3772,19 @@ msgstr "Ostalo" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "%s račun" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Greška pri uklanjanju računa" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> je uklonjen" @@ -3775,13 +3798,16 @@ msgid "Connect to your online accounts and decide what to use them for" msgstr "" "Povežite se sa svojim mrežnim računima i odredite za što ih želite koristiti" -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:7 msgid "goa-panel" msgstr "goa-panel" -#. Translators: those are keywords for the online-accounts control-center panel +#. Translators: Search terms to find the Online Accounts panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. For ReadItLater and Pocket, see http://en.wikipedia.org/wiki/Pocket_(application) -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:19 +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:22 msgid "" "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" @@ -3811,11 +3837,11 @@ msgstr "Dodaj račun" msgid "Remove Account" msgstr "Ukloni račun" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Nepoznato vrijeme" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -3823,7 +3849,7 @@ msgstr[0] "%i minuta" msgstr[1] "%i minute" msgstr[2] "%i minuta" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3833,19 +3859,19 @@ msgstr[2] "%i sati" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "sat" msgstr[1] "sata" msgstr[2] "sati" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "minuta" @@ -3853,240 +3879,241 @@ msgstr[1] "minute" msgstr[2] "minuta" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s do potpune napunjenosti" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Upozorenje: %s preostalo" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "%s preostalo" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Potpuno napunjeno" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Prazna" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Punjenje" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Pražnjenje" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Glavna" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Dodatna" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Bežični miš" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Bežična tipkovnica" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Neprekinuta opskrba energijom (UPS)" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Osobni digitalni pomagač (PDA)" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Mobitel" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Medijski reproduktor" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tablet" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Računalo" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Uređaj za igranje" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2374 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:805 +#: panels/power/cc-power-panel.c:2398 msgid "Battery" msgstr "Baterija" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:619 msgctxt "Battery power" msgid "Charging" msgstr "Punjenje" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:626 msgctxt "Battery power" msgid "Caution" msgstr "Upozorenje" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:631 msgctxt "Battery power" msgid "Low" msgstr "Niska" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:636 msgctxt "Battery power" msgid "Good" msgstr "Dobra" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:641 msgctxt "Battery power" msgid "Fully charged" msgstr "Potpuno napunjeno" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:645 msgctxt "Battery power" msgid "Empty" msgstr "Prazna" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:803 msgid "Batteries" msgstr "Baterije" -#: panels/power/cc-power-panel.c:1236 +#: panels/power/cc-power-panel.c:1243 msgid "When _idle" msgstr "Pri _mirovanju" -#: panels/power/cc-power-panel.c:1690 +#: panels/power/cc-power-panel.c:1708 msgid "Power Saving" msgstr "Štednja energije" -#: panels/power/cc-power-panel.c:1721 +#: panels/power/cc-power-panel.c:1739 msgid "_Screen brightness" msgstr "_Svjetlina zaslona" -#: panels/power/cc-power-panel.c:1740 +#: panels/power/cc-power-panel.c:1758 msgid "Automatic brightness" msgstr "Automatska svjetlina" -#: panels/power/cc-power-panel.c:1760 +#: panels/power/cc-power-panel.c:1778 msgid "_Keyboard brightness" msgstr "_Svjetlina tipkovnice" -#: panels/power/cc-power-panel.c:1770 +#: panels/power/cc-power-panel.c:1788 msgid "_Dim screen when inactive" msgstr "_Zatamni zaslon kada je neaktivan" -#: panels/power/cc-power-panel.c:1795 +#: panels/power/cc-power-panel.c:1813 msgid "_Blank screen" msgstr "_Zatamni zaslon" -#: panels/power/cc-power-panel.c:1832 +#: panels/power/cc-power-panel.c:1850 msgid "_Wi-Fi" msgstr "_Bežična mreža" -#: panels/power/cc-power-panel.c:1837 +#: panels/power/cc-power-panel.c:1855 msgid "Turn off Wi-Fi to save power." msgstr "Isključi bežičnu mrežu u svrhu štednje energije." -#: panels/power/cc-power-panel.c:1862 +#: panels/power/cc-power-panel.c:1880 msgid "_Mobile broadband" msgstr "_Mobilni širokopojasni internet" -#: panels/power/cc-power-panel.c:1867 +#: panels/power/cc-power-panel.c:1885 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "" "Isključi mobilni širokopojasni internet (3G, 4G, LTE, itd.) u svrhu štednje " "energije." -#: panels/power/cc-power-panel.c:1920 +#: panels/power/cc-power-panel.c:1944 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1925 +#: panels/power/cc-power-panel.c:1949 msgid "Turn off Bluetooth to save power." msgstr "Isključi Bluetooth u svrhu štednje energije." -#: panels/power/cc-power-panel.c:1984 +#: panels/power/cc-power-panel.c:2008 msgid "When on battery power" msgstr "Na bateriji" -#: panels/power/cc-power-panel.c:1986 +#: panels/power/cc-power-panel.c:2010 msgid "When plugged in" msgstr "Na napajanju" -#: panels/power/cc-power-panel.c:2081 +#: panels/power/cc-power-panel.c:2105 msgid "Suspend" msgstr "Suspendiraj" -#: panels/power/cc-power-panel.c:2082 +#: panels/power/cc-power-panel.c:2106 msgid "Power Off" msgstr "Isključi" -#: panels/power/cc-power-panel.c:2083 +#: panels/power/cc-power-panel.c:2107 msgid "Hibernate" msgstr "Hiberniraj" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2108 msgid "Nothing" msgstr "Ništa" #. Frame header -#: panels/power/cc-power-panel.c:2198 +#: panels/power/cc-power-panel.c:2222 msgid "Suspend & Power Button" msgstr "Suspenzija i tipka isključivanja" -#: panels/power/cc-power-panel.c:2237 +#: panels/power/cc-power-panel.c:2261 msgid "_Automatic suspend" msgstr "_Automatska suspenzija" -#: panels/power/cc-power-panel.c:2238 +#: panels/power/cc-power-panel.c:2262 msgid "Automatic suspend" msgstr "Automatska suspenzija" -#: panels/power/cc-power-panel.c:2305 +#: panels/power/cc-power-panel.c:2329 msgid "_When the Power Button is pressed" msgstr "_Kada je tipka isključivanja pritisnuta" -#: panels/power/cc-power-panel.c:2424 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2448 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Uređaji" @@ -4100,12 +4127,13 @@ msgid "View your battery status and change power saving settings" msgstr "" "Pogledajte svoje stanje baterije i promijenite postavke štednje energije" -#: panels/power/gnome-power-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/power/gnome-power-panel.desktop.in.in:7 msgid "gnome-power-manager" msgstr "gnome-upravitelj-energijom" -#. Translators: those are keywords for the power control-center panel -#: panels/power/gnome-power-panel.desktop.in.in:18 +#. Translators: Search terms to find the Power panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/power/gnome-power-panel.desktop.in.in:19 msgid "" "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" msgstr "" @@ -4221,18 +4249,18 @@ msgid "Authentication Required" msgstr "Potrebna je ovjera" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "Pisač “%s” je obrisan" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Neuspjelo dodavanje novoga pisača." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "Nemoguće učitati kor. sučelje: %s" @@ -4272,12 +4300,13 @@ msgid "Add printers, view printer jobs and decide how you want to print" msgstr "" "Dodajte pisače, pogledajte zadatke ispisivanja i odredite kakav ispis želite" -#: panels/printers/gnome-printers-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/printers/gnome-printers-panel.desktop.in.in:7 msgid "printer" msgstr "pisač" -#. Translators: those are keywords for the printing control-center panel -#: panels/printers/gnome-printers-panel.desktop.in.in:15 +#. Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/printers/gnome-printers-panel.desktop.in.in:16 msgid "Printer;Queue;Print;Paper;Ink;Toner;" msgstr "Pisač;Red;Ispis;Papir;Tinta;Toner;" @@ -4370,7 +4399,7 @@ msgid "Select Printer Driver" msgstr "Odaberi upravljački program za pisač" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Odaberi" @@ -4427,55 +4456,55 @@ msgid "Reverse portrait" msgstr "Obrnuto uspravno" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Na čekanju" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Pauzirano" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Potrebna je ovjera" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "Obrada" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Zaustavljen" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Otkazan" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Prekinut" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Završen" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" @@ -4484,14 +4513,14 @@ msgstr[1] "%u zadatka zahtijevaju ovjeru" msgstr[2] "%u zadataka zahtijeva ovjeru" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s — aktivnih zadataka" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "Upišite korisničko ime i lozinku za ispis sa %s." @@ -4859,25 +4888,25 @@ msgstr "" "Nažalost! Usluga ispisa\n" "sustava nije dostupna." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Zaključavanje zaslona" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "Koristi se" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Uključeno" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Isključeno" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Usluge lokacije" @@ -4946,12 +4975,13 @@ msgstr "" "vidjeti" #. FIXME -#: panels/privacy/gnome-privacy-panel.desktop.in.in:7 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:8 msgid "preferences-system-privacy" msgstr "osobitosti-privatnosti-sustava" -#. Translators: those are keywords for the privacy control-center panel -#: panels/privacy/gnome-privacy-panel.desktop.in.in:19 +#. Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:20 msgid "" "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" "network;identity;" @@ -5137,11 +5167,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Ostalo" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Nema odabranih načina unosa" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "Zaslon _prijave" @@ -5187,12 +5217,13 @@ msgid "" msgstr "" "Odaberite vaš jezik prikaza, formate, rasporede tipkovnice i ulazne izvore" -#: panels/region/gnome-region-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/region/gnome-region-panel.desktop.in.in:7 msgid "preferences-desktop-locale" msgstr "osobitosti-lokalizacije-radne površine" -#. Translators: those are keywords for the region control-center panel -#: panels/region/gnome-region-panel.desktop.in.in:18 +#. Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/region/gnome-region-panel.desktop.in.in:19 msgid "Language;Layout;Keyboard;Input;" msgstr "Jezik;Raspored;Tipkovnica;ulaz;" @@ -5324,12 +5355,13 @@ msgstr "" "Upravljajte koje će aplikacije prikazati rezultate pretrage u pregledu " "aktivnosti" -#: panels/search/gnome-search-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/search/gnome-search-panel.desktop.in.in:7 msgid "preferences-system-search" msgstr "osobitosti-pretrage-sustava" -#. Translators: those are keywords for the search control-center panel -#: panels/search/gnome-search-panel.desktop.in.in:18 +#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/search/gnome-search-panel.desktop.in.in:19 msgid "Search;Find;Index;Hide;Privacy;Results;" msgstr "Pretraga;Pretraži;Sadržaj;Sakrij;Privatnost;Rezultati;" @@ -5432,12 +5464,13 @@ msgstr "Dijeljenje" msgid "Control what you want to share with others" msgstr "Postavite što želite dijeliti s ostalim korisnicima" -#: panels/sharing/gnome-sharing-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:7 msgid "preferences-system-sharing" msgstr "osobitosti-dijeljenja-sustava" -#. Translators: those are keywords for the sharing control-center panel -#: panels/sharing/gnome-sharing-panel.desktop.in.in:15 +#. Translators: Search terms to find the Sharing panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:16 msgid "" "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" "movies;server;renderer;" @@ -5541,12 +5574,13 @@ msgstr "Zvuk" msgid "Change sound levels, inputs, outputs, and alert sounds" msgstr "Promijenite glasnoću zvuka, ulaze, izlaze i zvukove upozorenja" -#: panels/sound/data/gnome-sound-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:7 msgid "multimedia-volume-control" msgstr "upravljanje-glasnoćom zvuka-multimedije" -#. Translators: those are keywords for the sound control-center panel -#: panels/sound/data/gnome-sound-panel.desktop.in.in:19 +#. Translators: Search terms to find the Sound panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:20 msgid "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;" msgstr "" "Kartica;Mikrofon;Glasnoća zvuka;Isčezni;Uravnoteženje;Bluetooth;Slušalice s " @@ -5739,34 +5773,200 @@ msgstr "Dubokotonac" msgid "Custom" msgstr "Prilagođeno" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Odspojeno" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Povezivanje" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Povezano" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Greška ovjere" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Odobravanje" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Smanjena funkcionalnost" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Povezano i odobreno" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Nepoznato" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Odobreno na:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Povezano na:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Upisano:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "Neuspjelo odobravanje uređaja: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "Neuspjelo zaboravljanje uređaja: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Naziv:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Stanje:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Odobri i poveži" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Zaboravi uređaj" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Greška" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Odobreno" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "Thunderbolt podsustav (boltd) nije instaliran ili podešen ispravno." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"Thunderbolt se ne može otkriti.\n" +"Ili sustav nema podršku za Thunderbolt, jer je onemogućena u BIOSU ili je " +"postavljena nepodržana razina sigurnosti u BIOSU." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "Thunderbolt podrška je onemogućena u BIOSU." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Greška prebacivanja izravnog načina :%s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Nema Thunderbolt podrške" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Izravan pristup" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "Dopusti izravan pristup uređajima poput dokova i vanjskih GPU-ova." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Samo USB i Display Port uređaji se mogu spojiti." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Uređaji na čekanju" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Nema spojenih uređaja" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Upravljaj Thunderbolt uređajima" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Uobičajena" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Srednja" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Velika" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Veća" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "Najveća" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5778,12 +5978,13 @@ msgstr[2] "%d piksela" msgid "Make it easier to see, hear, type, point and click" msgstr "Make it easier to see, hear, type, point and click" -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:7 msgid "preferences-desktop-accessibility" msgstr "osobitosti-pristupačnosti-radne površine" -#. Translators: those are keywords for the universal access control-center panel -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:18 +#. Translators: Search terms to find the Universal Access panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 msgid "" "Keyboard;Mouse;a11y;Accessibility;Contrast;Zoom;Screen;Reader;text;font;size;" "AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;click;Delay;Assist;Repeat;Blink;" @@ -5813,7 +6014,7 @@ msgid "C_ursor Size" msgstr "V_eličina pokazivača" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Uvećanje" @@ -6107,27 +6308,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Velika" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Kratko" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ zaslona" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ zaslona" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ zaslona" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Dugo" @@ -6152,134 +6353,134 @@ msgstr "Lijeva polovina" msgid "Right Half" msgstr "Desna polovina" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Mogućnosti približenja/udaljenja" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "_Uvećavanje:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Prati pokazivač miša" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "_Dio zaslona:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "_Povećalo se proteže van zaslona" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "_Drži pokazivač povećala u središtu" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "Pokazivač povećala _gura sadržaj okolo" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "Pokazivač povećala se pomiče sa _sadržajem" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Položaj povećala:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Povećalo" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Debljina:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Tanko" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Debelo" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "_Duljina:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "Bo_ja:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "_Nišan:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "_Preklapa pokazivač miša" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Nišan" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "_Bijelo na crno:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Svjetlina:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Kontrast:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "Bo_ja" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Nepoznata" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Potpuna" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Niska" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Visoka" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Niska" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Visoka" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Efekti boje:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Efekti boje" @@ -6420,12 +6621,13 @@ msgstr "Korisnici" msgid "Add or remove users and change your password" msgstr "Dodajte ili uklonite korisnike i promijenite svoju lozinku" -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:7 msgid "system-users" msgstr "korisnici-sustava" -#. Translators: those are keywords for the user accounts control-center panel -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:19 +#. Translators: Search terms to find the Users panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:20 msgid "Login;Name;Fingerprint;Avatar;Logo;Face;Password;" msgstr "Prijava;Ime;Otisak prsta;Avatar;Logo;Lice;Lozinka;" @@ -6868,7 +7070,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6876,7 +7078,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6913,7 +7115,7 @@ msgstr "Lozinka ne može biti promijenjena" msgid "The passwords do not match." msgstr "Lozinka se ne podudara." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Potraži još slika" @@ -6941,30 +7143,30 @@ msgstr "Neispravna lozinka, pokušajte ponovno" msgid "Couldn’t connect to the %s domain: %s" msgstr "Nemoguće povezivanje s %s domenom: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Vaš račun" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Neuspjelo brisanje korisnika" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Nemoguće je opozvati udaljeno upravljanog korisnika" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Ne možete obrisati vlastiti račun." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s je još prijavljen" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -6972,12 +7174,12 @@ msgstr "" "Brisanje korisnika dok su prijavljeni može ostaviti sustav u neupotrebljivom " "stanju." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "Želite li zadržati %s's datoteke?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -6985,47 +7187,47 @@ msgstr "" "Moguće je očuvati osobnu mapu, e-poštu i privremene datoteke kada se briše " "korisnički račun." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "_Obriši datoteke" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "_Zadrži datoteke" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "Sigurno želite opozvati udaljeno upravljani %s's račun?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Obriši" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Račun onemogućen" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Biti će postavljen kod sljedeće prijave" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Nepoznata" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Prijavljeni" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Neuspjelo kontaktiranje usluge računa" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Pobrinite se da je AccountService instaliran i omogućen." @@ -7033,7 +7235,7 @@ msgstr "Pobrinite se da je AccountService instaliran i omogućen." #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7041,12 +7243,12 @@ msgstr "" "Kako bi napravili promjene\n" "prvo kliknite * ikonu" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Napravite korisnički račun" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7054,12 +7256,12 @@ msgstr "" "Kako biste napravili korisnički račun,\n" "najprije kliknite na ikonu *" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Obrišite odabrani korisnički račun" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7193,12 +7395,13 @@ msgid "Set button mappings and adjust stylus sensitivity for graphics tablets" msgstr "" "Postavi tipke mapiranja i prilagodi osjetljivost pisaljke grafičkih tableta" -#: panels/wacom/gnome-wacom-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:7 msgid "input-tablet" msgstr "način unosa-tableta" -#. Translators: those are keywords for the wacom tablet control-center panel -#: panels/wacom/gnome-wacom-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wacom Tablet panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:19 msgid "Tablet;Wacom;Stylus;Eraser;Mouse;" msgstr "Tablet;Wacom;Pisaljka;Gumica;Miš;" @@ -7334,35 +7537,35 @@ msgstr "" "Središte upravljanja je GNOME glavno sučelje za podešavanje vaše radne " "površine." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Prikaži broj inačice" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Omogući opširni opisni način rada" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Prikaži pregled" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Pretraživanje niza" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Prikaži moguće nazive panela i izađi" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Panel za prikaz" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGUMENT…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Dostupni paneli:" @@ -7374,11 +7577,13 @@ msgstr "Pomoć" msgid "Quit" msgstr "Zatvori" -#: shell/gnome-control-center.desktop.in.in:4 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: shell/gnome-control-center.desktop.in.in:5 msgid "gnome-control-center" msgstr "gnome-središte-upravljanja" -#: shell/gnome-control-center.desktop.in.in:15 +#. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: shell/gnome-control-center.desktop.in.in:17 msgid "Preferences;Settings;" msgstr "Osobitosti;Postavke;" @@ -7634,12 +7839,6 @@ msgstr "Zvukovi sustava" #~ msgid "_Method" #~ msgstr "_Način" -#~ msgid "Add Device" -#~ msgstr "Dodaj uređaj" - -#~ msgid "Remove Device" -#~ msgstr "Ukloni uređaj" - #~ msgid "VPN Type" #~ msgstr "VPN vrsta" @@ -8,7 +8,7 @@ # Andras Timar <timar at gnome dot hu>, 2001, 2002, 2003. # Gabor Sari <saga at gnome dot hu>, 2003. # Laszlo Dvornik <dvornik at gnome dot hu>, 2004. -# Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017. +# Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018. # Mate ORY <orymate at gmail d0t com>, 2006. # Richard Somloi <ricsipontaz at gmail dot com>, 2011, 2012. # Peter Trombitas <trombipeti at gmail dot com>, 2012. @@ -16,18 +16,18 @@ msgid "" msgstr "" "Project-Id-Version: gnome-control-center master\n" -"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" -"issues\n" -"POT-Creation-Date: 2018-02-23 19:10+0000\n" -"PO-Revision-Date: 2018-02-25 20:45+0100\n" -"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +"es\n" +"POT-Creation-Date: 2018-05-03 08:07+0000\n" +"PO-Revision-Date: 2018-05-05 17:37+0100\n" +"Last-Translator: Gabor Kelemen <kelemeng at ubuntu dot com>\n" "Language-Team: Hungarian <openscope at googlegroups dot com>\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 1.2\n" +"X-Generator: Lokalize 2.0\n" #: panels/background/background.ui:49 msgid "_Background" @@ -111,16 +111,16 @@ msgid "You can add images to your %s folder and they will show up here" msgstr "A %s mappába felvett képek itt megjelennek" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 #: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 #: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -129,10 +129,10 @@ msgstr "A %s mappába felvett képek itt megjelennek" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "Mé_gse" @@ -177,39 +177,39 @@ msgstr "preferences-desktop-wallpaper" msgid "Wallpaper;Screen;Desktop;" msgstr "Háttérkép;Képernyő;Asztal;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Repülőgép üzemmód kikapcsolása" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Nem található Bluetooth" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Csatlakoztasson egy kulcsot a Bluetooth használatához." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth kikapcsolva" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Kapcsolja be eszközök csatlakoztatásához és fájlátvitelek fogadásához." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Repülőgép üzemmód be" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "A Bluetooth ki van kapcsolva repülőgép üzemmódban." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Hardver repülőgép üzemmódja be" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "" "Kapcsolja ki a Repülőgép üzemmód kapcsolót a Bluetooth bekapcsolásához." @@ -235,7 +235,7 @@ msgid "share;sharing;bluetooth;obex;" msgstr "share;megosztás;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "" "Helyezze a kalibrációs eszköz a négyzetre, és nyomja meg a „Kezdés” gombot" @@ -243,7 +243,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -253,7 +253,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -262,54 +262,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Zárja le a laptop fedelét" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Belső hiba történt, a folytatás nem lehetséges." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "A kalibráláshoz szükséges eszközök nincsenek telepítve." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "A profil nem állítható elő." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "A cél fehér pont nem szerezhető be." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Kész!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "A kalibrálás sikertelen!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Eltávolíthatja a kalibrálóeszközt." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "Ne zavarja a kalibrálóeszközt a folyamat során" @@ -371,48 +371,48 @@ msgstr "Nem kalibrált" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Alapértelmezett: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Színtér: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Tesztprofil: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Válasszon ICC profilfájlt" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Importálás" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Támogatott ICC profilok" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Minden fájl" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Képernyő" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "A fájl feltöltése meghiúsult: %s" @@ -420,42 +420,42 @@ msgstr "A fájl feltöltése meghiúsult: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "A profil feltöltve ide:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Írja le ezt az URL-címet." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "" "Indítsa újra a számítógépet, és indítsa el az általában használt operációs " "rendszerét." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "" "Írja be az URL-címet a böngészőjébe a profil letöltéséhez és telepítéséhez." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Profil mentése" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "M_entés" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Színprofil létrehozása a kiválasztott eszközhöz" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -464,12 +464,12 @@ msgstr "" "megfelelően van-e csatlakoztatva." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "A mérőkészülék nem támogatja a nyomtatóprofilozást." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Az eszköztípus jelenleg nem támogatott." @@ -915,6 +915,12 @@ msgstr "%b. %e." msgid "%b %e, %Y" msgstr "%Y. %b. %e." +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Hotspot" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Nyelv" @@ -1111,58 +1117,58 @@ msgstr "Rendszer dátum- és időbeállításainak módosítása" msgid "To change time or date settings, you need to authenticate." msgstr "Hitelesítés szükséges a dátum- és időbeállítások módosításához." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Fekvő" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Álló (jobbra)" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Álló (balra)" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Fekvő (fordított)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Tájolás" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Felbontás" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Frissítés gyakorisága" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Méretezés" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "TV-hez igazítás" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Elsődleges kijelző" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Elrendezés megjelenítése" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1170,59 +1176,67 @@ msgstr "" "Húzza a kijelzőket az elrendezésnek megfelelően. A felső sáv csak az " "elsődleges kijelzőre kerül." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Megjelenítés módja" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Kijelzők egyesítése" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Tükrözés" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Másodlagos kijelző" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Módosítások alkalmazása?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Alkalmaz" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Módosítások alkalmazása?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "A módosítások nem alkalmazhatóak" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Ez hardveres korlátozások miatt is lehet." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1991 panels/power/cc-power-panel.c:1998 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Be" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1985 panels/power/cc-power-panel.c:1996 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1230,11 +1244,11 @@ msgstr "Be" msgid "Off" msgstr "Ki" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "Éjszakai _fény" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "A képernyő-információk nem kérhetők le" @@ -1274,7 +1288,7 @@ msgstr "Napnyugtától napkeltéig" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Kézi" @@ -1323,8 +1337,8 @@ msgstr "" "redshift;szín;napkelte;napnyugta;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Ismeretlen" @@ -1332,24 +1346,24 @@ msgstr "Ismeretlen" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; Összeállítás-azonosító: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64 bites" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32 bites" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "%s verzió" @@ -1682,8 +1696,8 @@ msgstr "Parancsikonok" msgid "Launch help browser" msgstr "Súgóböngésző indítása" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Beállítások" @@ -1792,7 +1806,7 @@ msgstr "Nagy kontraszt be- vagy kikapcsolása" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Egyéni gyorsbillentyűk" @@ -1803,7 +1817,7 @@ msgstr "Egyéni gyorsbillentyűk" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -2101,7 +2115,7 @@ msgid "Single click, secondary button" msgstr "Egy kattintás, másodlagos gomb" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:583 msgid "Network proxy" msgstr "Hálózati proxy" @@ -2109,23 +2123,23 @@ msgstr "Hálózati proxy" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:719 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "%s VPN" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:783 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "Hoppá, valami elromlott. Lépjen kapcsolatba a szoftver szállítójával." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:789 msgid "NetworkManager needs to be running." msgstr "A Hálózatkezelőnek futnia kell." -#: panels/network/cc-wifi-panel.c:213 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Wi-Fi" @@ -2269,7 +2283,7 @@ msgid "Remove VPN" msgstr "VPN eltávolítása" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Részletek" @@ -2406,7 +2420,7 @@ msgstr "" #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automatikus" @@ -2604,9 +2618,9 @@ msgid "Select file to import" msgstr "Válassza ki az importálandó fájlt" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Megnyitás" @@ -3027,19 +3041,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Jelszó" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Wi-Fi kikapcsolása" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "Kapcsolódás _rejtett hálózathoz…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "Wi-Fi hotspot be_kapcsolása…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "_Ismert Wi-Fi hálózatok" @@ -3349,23 +3363,23 @@ msgstr "Hiányzó firmware" msgid "Cable unplugged" msgstr "Kábel kihúzva" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "meghatározatlan hiba a 802.1X biztonságban (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "nincs fájl kiválasztva" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "meghatározatlan hiba az eap-method fájl ellenőrzése közben" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM vagy PKCS#12 személyes kulcsok (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "DER vagy PEM tanúsítványok (*.der, *.pem, *.crt, *.cer)" @@ -3782,19 +3796,19 @@ msgstr "Egyéb" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "%s fiók" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Hiba a fiók eltávolításakor" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> eltávolítva" @@ -3845,18 +3859,18 @@ msgstr "Fiók hozzáadása" msgid "Remove Account" msgstr "Fiók eltávolítása" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Ismeretlen idő" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i perc" msgstr[1] "%i perc" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3865,258 +3879,299 @@ msgstr[1] "%i óra" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s, %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "óra" msgstr[1] "óra" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "perc" msgstr[1] "perc" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s a teljes feltöltésig" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Figyelem: %s van hátra" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "%s van hátra" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Teljesen feltöltve" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Lemerült" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Töltés" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Kisülés" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Elsődleges" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Extra" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Vezeték nélküli egér" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Vezeték nélküli billentyűzet" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Szünetmentes tápegység (UPS)" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Személyes digitális asszisztens" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Mobiltelefon" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Médialejátszó" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Táblagép" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Számítógép" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Bemeneti eszköz játékokhoz" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2377 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Akkumulátor" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "Töltés" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Figyelem" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Alacsony" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "Jó" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Teljesen feltöltve" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Üres" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Akkumulátorok" -#: panels/power/cc-power-panel.c:1239 +#: panels/power/cc-power-panel.c:1206 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d óra" +msgstr[1] "%d óra" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d perc" +msgstr[1] "%d perc" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d másodperc" +msgstr[1] "%d másodperc" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +msgctxt "time" +msgid "%s %s" +msgstr "%s %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +msgid "0 seconds" +msgstr "0 másodperc" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Ü_resjáratban" -#: panels/power/cc-power-panel.c:1693 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Energiatakarékosság" -#: panels/power/cc-power-panel.c:1724 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "_Képernyő fényereje" -#: panels/power/cc-power-panel.c:1743 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Automatikus fényerő" -#: panels/power/cc-power-panel.c:1763 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "Billentyűzet _fényereje" -#: panels/power/cc-power-panel.c:1773 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "Képer_nyő elhalványítása, ha inaktív" -#: panels/power/cc-power-panel.c:1798 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" msgstr "Képernyő _elsötétítése" -#: panels/power/cc-power-panel.c:1835 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1840 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Wi-Fi kikapcsolása az energiatakarékosság érdekében." -#: panels/power/cc-power-panel.c:1865 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "_Mobil széles sáv" -#: panels/power/cc-power-panel.c:1870 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "" "Mobil széles sáv (3G, 4G, LTE stb.) kikapcsolása az energiatakarékosság " "érdekében." -#: panels/power/cc-power-panel.c:1923 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "Bl_uetooth" -#: panels/power/cc-power-panel.c:1928 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Bluetooth kikapcsolása az energiatakarékosság érdekében." -#: panels/power/cc-power-panel.c:1987 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "Akkumulátoron" -#: panels/power/cc-power-panel.c:1989 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Ha csatlakoztatva van" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Felfüggesztés" -#: panels/power/cc-power-panel.c:2085 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Kikapcsolás" -#: panels/power/cc-power-panel.c:2086 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Hibernálás" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Ne tegyen semmit" #. Frame header -#: panels/power/cc-power-panel.c:2201 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Felfüggesztés és kikapcsolás gombok" -#: panels/power/cc-power-panel.c:2240 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "_Automatikus felfüggesztés" -#: panels/power/cc-power-panel.c:2241 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Automatikus felfüggesztés" -#: panels/power/cc-power-panel.c:2308 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "A _bekapcsológomb megnyomásakor" -#: panels/power/cc-power-panel.c:2427 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Eszközök" @@ -4253,18 +4308,18 @@ msgid "Authentication Required" msgstr "Hitelesítés szükséges" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "A(z) „%s” nyomtató törölve lett" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Az új nyomtató hozzáadása meghiúsult." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "A felület nem tölthető be: %s" @@ -4377,21 +4432,21 @@ msgid "Test Page" msgstr "Tesztoldal" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "%s adatai" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "Nem található megfelelő illesztőprogram" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "Válasszon PPD fájlt" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4403,7 +4458,7 @@ msgid "Select Printer Driver" msgstr "Válassza ki a nyomtató-illesztőprogramot" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Kijelölés" @@ -4460,55 +4515,55 @@ msgid "Reverse portrait" msgstr "Fordított álló" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Függőben" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Szüneteltetve" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Hitelesítés szükséges" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "Feldolgozás" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Leállítva" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Megszakítva" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Félbeszakítva" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Befejezve" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" @@ -4516,14 +4571,14 @@ msgstr[0] "%u feladat hitelesítést igényel" msgstr[1] "%u feladat hitelesítést igényel" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s – Aktív feladatok" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "Hitelesítési adatok megadása a következőről történő nyomtatáshoz: %s." @@ -4890,25 +4945,25 @@ msgstr "" "Elnézést, a rendszer nyomtatószolgáltatása\n" "nem tűnik elérhetőnek." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Képernyőzár" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "Használatban" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Be" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Ki" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Helymeghatározó szolgáltatások" @@ -5136,9 +5191,8 @@ msgid "" "Uses Mozilla Location Service: <a href='https://location.services.mozilla." "com/privacy'>Privacy Policy</a>" msgstr "" -"A Mozilla helymeghatározási szolgáltatást használja: <a " -"href='https://location.services.mozilla.com/privacy'>adatvédelmi irányelvek<" -"/a>" +"A Mozilla helymeghatározási szolgáltatást használja: <a href='https://" +"location.services.mozilla.com/privacy'>adatvédelmi irányelvek</a>" #: panels/privacy/privacy.ui:828 msgid "_Location Services" @@ -5171,11 +5225,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Egyéb" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Nincs kiválasztva bemeneti forrás" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "Bejelentkezési _képernyő" @@ -5401,7 +5455,7 @@ msgid "Preferences" msgstr "Beállítások" #. Label -#: panels/sharing/cc-sharing-networks.c:305 +#: panels/sharing/cc-sharing-networks.c:307 msgid "No networks selected for sharing" msgstr "Nincs kiválasztott hálózat a megosztáshoz" @@ -5780,34 +5834,203 @@ msgstr "Mélysugárzó" msgid "Custom" msgstr "Egyéni" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Bontva" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Kapcsolódás" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Kapcsolódva" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Engedélyezési hiba" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Engedélyezés" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Csökkentett funkcionalitás" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Kapcsolódva és engedélyezve" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Ismeretlen" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Engedélyezve ekkor:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Kapcsolódva ekkor:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Bejegyezve ekkor:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "Az eszköz engedélyezése meghiúsult: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "Az eszköz elfelejtése meghiúsult: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Név:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Állapot:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Engedélyezés és kapcsolódás" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Eszköz elfelejtése" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Hiba" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Engedélyezve" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"A Thunderbolt alrendszer (boltd) nincs telepítve vagy rosszul van beállítva." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"A Thunderbolt nem észlelhető.\n" +"Vagy hiányzik a rendszerből a Thunderbolt támogatás, vagy le lett tiltva a " +"BIOS-ban, vagy nem támogatott biztonsági szintre van állítva a BIOS-ban." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "A Thunderbolt támogatás le lett tiltva a BIOS-ban." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Hiba a közvetlen módra váltáskor: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Nincs Thunderbolt támogatás" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Közvetlen hozzáférés" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "" +"Közvetlen hozzáférés engedélyezése az olyan eszközökhöz, mint a dokkolók és " +"külső GPU-k." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Csak USB és Display Port eszközök csatlakoztathatóak." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Függőben lévő eszközök" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Nincs eszköz csatlakoztatva" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Thunderbolt eszközök kezelése" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Alapértelmezett" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Közepes" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Nagy" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Nagyobb" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "Legnagyobb" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5854,7 +6077,7 @@ msgid "C_ursor Size" msgstr "K_urzorméret" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Nagyítás" @@ -6147,27 +6370,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Magas" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Rövid" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ képernyő" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ képernyő" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ képernyő" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Hosszú" @@ -6192,134 +6415,134 @@ msgstr "Bal fél" msgid "Right Half" msgstr "Jobb fél" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Nagyító beállításai" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "_Nagyítás:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "Egérkurzor _követése" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "Képernyő_részlet:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "A nagyító _kiterjed a képernyőn kívülre is" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "A nagyítókurzor középen _tartása" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "A nagyítókurzor _eltolja a tartalmakat" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "A nagyítókurzor a tartalmakkal együtt _mozog" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Nagyító pozíciója:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Nagyító" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Vastagság:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Vékony" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Vastag" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "_Hossz:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "_Szín:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "Szál_keresztek:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "Át_fedi az egérkurzort" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Szálkeresztek" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "F_ehér a feketén:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Fényerő:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Kontraszt:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "_Szín" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Nincs" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Teljes" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Alacsony" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Magas" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Alacsony" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Nagy" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Színeffektusok:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Színeffektusok" @@ -6735,29 +6958,29 @@ msgstr "Ismeretlen hiba" msgid "Should match the web address of your login provider." msgstr "Egyeznie kell a bejelentkezés szolgáltatójának webcímével." -#: panels/user-accounts/um-account-dialog.c:229 +#: panels/user-accounts/um-account-dialog.c:228 msgid "Failed to add account" msgstr "A fiók hozzáadása sikertelen" -#: panels/user-accounts/um-account-dialog.c:462 +#: panels/user-accounts/um-account-dialog.c:461 msgid "Passwords do not match." msgstr "Nem egyeznek a megadott jelszavak." -#: panels/user-accounts/um-account-dialog.c:717 -#: panels/user-accounts/um-account-dialog.c:763 -#: panels/user-accounts/um-account-dialog.c:784 +#: panels/user-accounts/um-account-dialog.c:716 +#: panels/user-accounts/um-account-dialog.c:762 +#: panels/user-accounts/um-account-dialog.c:783 msgid "Failed to register account" msgstr "A fiók regisztrálása sikertelen" -#: panels/user-accounts/um-account-dialog.c:907 +#: panels/user-accounts/um-account-dialog.c:906 msgid "No supported way to authenticate with this domain" msgstr "Nincs támogatott módszer a tartományban való hitelesítésre" -#: panels/user-accounts/um-account-dialog.c:980 +#: panels/user-accounts/um-account-dialog.c:979 msgid "Failed to join domain" msgstr "Nem sikerült a tartományhoz csatlakozni" -#: panels/user-accounts/um-account-dialog.c:1041 +#: panels/user-accounts/um-account-dialog.c:1040 msgid "" "That login name didn’t work.\n" "Please try again." @@ -6765,7 +6988,7 @@ msgstr "" "A bejelentkezési név nem működik.\n" "Próbálja újra." -#: panels/user-accounts/um-account-dialog.c:1048 +#: panels/user-accounts/um-account-dialog.c:1047 msgid "" "That login password didn’t work.\n" "Please try again." @@ -6773,11 +6996,11 @@ msgstr "" "A bejelentkezési jelszó nem működik.\n" "Próbálja újra." -#: panels/user-accounts/um-account-dialog.c:1056 +#: panels/user-accounts/um-account-dialog.c:1055 msgid "Failed to log into domain" msgstr "Nem sikerült bejelentkezni a tartományba" -#: panels/user-accounts/um-account-dialog.c:1114 +#: panels/user-accounts/um-account-dialog.c:1113 msgid "Unable to find the domain. Maybe you misspelled it?" msgstr "A tartomány nem található. Lehet, hogy elgépelte?" @@ -6911,7 +7134,7 @@ msgstr "%s – %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k.%M" @@ -6919,7 +7142,7 @@ msgstr "%k.%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6956,58 +7179,57 @@ msgstr "A jelszót nem sikerült megváltoztatni" msgid "The passwords do not match." msgstr "A jelszavak nem egyeznek." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "További képek tallózása" -#: panels/user-accounts/um-realm-manager.c:350 +#: panels/user-accounts/um-realm-manager.c:310 msgid "Cannot automatically join this type of domain" msgstr "Ilyen típusú tartományhoz nem lehet automatikusan csatlakozni" -#: panels/user-accounts/um-realm-manager.c:413 -#, c-format +#: panels/user-accounts/um-realm-manager.c:313 msgid "No such domain or realm found" msgstr "Nem található ilyen tartomány vagy zóna" -#: panels/user-accounts/um-realm-manager.c:815 -#: panels/user-accounts/um-realm-manager.c:829 +#: panels/user-accounts/um-realm-manager.c:735 +#: panels/user-accounts/um-realm-manager.c:749 #, c-format msgid "Cannot log in as %s at the %s domain" msgstr "Nem lehet bejelentkezni %s néven a(z) %s tartományba" -#: panels/user-accounts/um-realm-manager.c:821 +#: panels/user-accounts/um-realm-manager.c:741 msgid "Invalid password, please try again" msgstr "Érvénytelen jelszó, próbálja újra" -#: panels/user-accounts/um-realm-manager.c:834 +#: panels/user-accounts/um-realm-manager.c:754 #, c-format msgid "Couldn’t connect to the %s domain: %s" msgstr "Nem lehet csatlakozni a(z) %s tartományhoz: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Az Ön fiókja" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "A felhasználó törlése meghiúsult" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "A távmenedzselt felhasználó visszavonása meghiúsult" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Nem törölheti saját fiókját." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s még be van jelentkezve" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -7015,12 +7237,12 @@ msgstr "" "A bejelentkezett felhasználók törlése a rendszert inkonzisztens állapotban " "hagyhatja." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "Meg szeretné tartani %s fájljait?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7028,47 +7250,47 @@ msgstr "" "Felhasználói fiók törlésekor lehetősége van a saját könyvtár, a levelezési " "várólista és az ideiglenes fájlok megtartására." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "Fájlok _törlése" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "Fájlok _megtartása" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "Biztosan vissza szeretné vonni a távmenedzselt %s fiókját?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Törlés" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Fiók letiltva" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Következő belépéskor állítandó be" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Nincs" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Bejelentkezve" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "A fiókszolgáltatás nem érhető el" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Győződjön meg róla, hogy az AccountService telepítve van és fut." @@ -7076,7 +7298,7 @@ msgstr "Győződjön meg róla, hogy az AccountService telepítve van és fut." #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7084,12 +7306,12 @@ msgstr "" "A módosítások végrehajtásához\n" "előbb kattintson a * ikonra" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Felhasználói fiók létrehozása" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7097,12 +7319,12 @@ msgstr "" "Felhasználói fiók létrehozásához\n" "először kattintson a * ikonra" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Kijelölt felhasználói fiók törlése" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7377,35 +7599,35 @@ msgstr "" "A vezérlőközpont a GNOME elsődleges felülete az asztali környezet különböző " "jellemzőinek beállításához." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Verziószám kiírása" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Részletes mód engedélyezése" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Áttekintés megjelenítése" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Karakterlánc keresése" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Lehetséges panelnevek felsorolása és kilépés" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Megjelenítendő panel" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGUMENTUM…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Elérhető panelek:" @@ -7457,12 +7679,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Keresés megszakítása" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Hotspot" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "Az azonosító a megnyitandó legutolsó Beállítások panelhez" @@ -7472,8 +7688,9 @@ msgid "" "The identifier for the last Settings panel to be opened. Unrecognised values " "will be ignored and the first panel in the list selected." msgstr "" -"Az azonosító a megnyitandó legutolsó Beállítások panelhez. A felismerhetetlen " -"értékek mellőzve lesznek, és a listában lévő első panel kerül kiválasztásra." +"Az azonosító a megnyitandó legutolsó Beállítások panelhez. A " +"felismerhetetlen értékek mellőzve lesznek, és a listában lévő első panel " +"kerül kiválasztásra." #: shell/panel-list.ui:195 msgid "No results found" @@ -29,8 +29,8 @@ msgstr "" "Project-Id-Version: gnome-control-center\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-20 09:14+0000\n" -"PO-Revision-Date: 2018-02-22 16:34+0900\n" +"POT-Creation-Date: 2018-03-26 22:21+0000\n" +"PO-Revision-Date: 2018-04-06 17:53+0900\n" "Last-Translator: Changwoo Ryu <cwryu@debian.org>\n" "Language-Team: GNOME Korea <gnome-kr@googlegroups.com>\n" "Language: ko\n" @@ -124,12 +124,12 @@ msgstr "이미지 파일을 %s 폴더에 놓으면 여기 나타납니다" #: panels/background/cc-background-chooser-dialog.c:560 #: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2597 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 -#: panels/network/net-device-wifi.c:1371 panels/network/net-device-wifi.c:1451 -#: panels/network/net-device-wifi.c:1690 panels/network/network-wifi.ui:24 +#: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 +#: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 #: panels/printers/pp-details-dialog.c:331 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 @@ -140,10 +140,10 @@ msgstr "이미지 파일을 %s 폴더에 놓으면 여기 나타납니다" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "취소(_C)" @@ -178,12 +178,13 @@ msgstr "배경" msgid "Change your background image to a wallpaper or photo" msgstr "배경을 이미지나 사진으로 바꿉니다" -#: panels/background/gnome-background-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/background/gnome-background-panel.desktop.in.in:7 msgid "preferences-desktop-wallpaper" msgstr "preferences-desktop-wallpaper" -#. Translators: those are keywords for the background control-center panel -#: panels/background/gnome-background-panel.desktop.in.in:14 +#. Translators: Search terms to find the Background panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/background/gnome-background-panel.desktop.in.in:15 msgid "Wallpaper;Screen;Desktop;" msgstr "Wallpaper;배경;Screen;화면;Desktop;바탕 화면;" @@ -233,12 +234,13 @@ msgstr "블루투스" msgid "Turn Bluetooth on and off and connect your devices" msgstr "블루투스를 켜거나 끄고 블루투스 장치에 연결합니다" -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:5 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:6 msgid "bluetooth" -msgstr "블루투스" +msgstr "bluetooth" -#. Translators: those are keywords for the bluetooth control-center panel -#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:18 +#. Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/bluetooth/gnome-bluetooth-panel.desktop.in.in:19 msgid "share;sharing;bluetooth;obex;" msgstr "share;sharing;공유;bluetooth;블루투스;obex;" @@ -873,12 +875,13 @@ msgid "" "Calibrate the color of your devices, such as displays, cameras or printers" msgstr "디스플레이, 카메라, 프린터같은 장치의 색을 보정합니다" -#: panels/color/gnome-color-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/color/gnome-color-panel.desktop.in.in:7 msgid "preferences-color" msgstr "preferences-color" -#. Translators: those are keywords for the color control-center panel -#: panels/color/gnome-color-panel.desktop.in.in:18 +#. Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/color/gnome-color-panel.desktop.in.in:19 msgid "Color;ICC;Profile;Calibrate;Printer;Display;" msgstr "" "Color;색;ICC;Profile;프로파일;Calibrate;보정;Printer;프린터;Display;디스플레" @@ -1096,12 +1099,13 @@ msgstr "오전 / 오후" msgid "Change the date and time, including time zone" msgstr "날짜와 시각(표준 시간대 포함)을 바꿉니다" -#: panels/datetime/gnome-datetime-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:7 msgid "preferences-system-time" msgstr "preferences-system-time" -#. Translators: those are keywords for the date and time control-center panel -#: panels/datetime/gnome-datetime-panel.desktop.in.in:14 +#. Translators: Search terms to find the Date and Time panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/datetime/gnome-datetime-panel.desktop.in.in:15 msgid "Clock;Timezone;Location;" msgstr "Clock;시계;Timezone;시간대;Location;위치;" @@ -1113,58 +1117,58 @@ msgstr "시스템의 날짜와 시간 설정을 바꿉니다" msgid "To change time or date settings, you need to authenticate." msgstr "시간 또는 날짜 설정을 바꾸려면 인증이 필요합니다." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:732 msgctxt "Display rotation" msgid "Landscape" msgstr "가로" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:735 msgctxt "Display rotation" msgid "Portrait Right" msgstr "세로 오른쪽" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:738 msgctxt "Display rotation" msgid "Portrait Left" msgstr "세로 왼쪽" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:741 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "가로 (뒤집힘)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:808 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "방향" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:873 panels/display/cc-display-panel.c:1676 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "해상도" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:961 msgid "Refresh Rate" msgstr "주사율" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1098 msgid "Scale" msgstr "크기 조정" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1151 msgid "Adjust for TV" msgstr "TV에 맞게 조정" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1413 msgid "Primary Display" msgstr "주요 디스플레이" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1442 msgid "Display Arrangement" msgstr "디스플레이 배치" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1443 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1172,41 +1176,41 @@ msgstr "" "설정에 맞는 디스플레이를 끌어 놓으십시오. 화면 위 표시 막대는 주요 디스플레이" "에서 표시됩니다." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1866 msgid "Display Mode" msgstr "디스플레이 모드" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1882 msgid "Join Displays" msgstr "디스플레이 연결" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1885 msgid "Mirror" msgstr "동일 화면" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1888 msgid "Single Display" msgstr "단일 디스플레이" -#: panels/display/cc-display-panel.c:2590 +#: panels/display/cc-display-panel.c:2593 msgid "Apply Changes?" msgstr "변경 사항을 적용하시겠습니까?" -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2607 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "적용(_A)" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2982 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3198 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1995 +#: panels/power/cc-power-panel.c:1994 panels/power/cc-power-panel.c:2001 #: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 #: panels/universal-access/cc-ua-panel.c:333 #: panels/universal-access/cc-ua-panel.c:714 @@ -1216,9 +1220,9 @@ msgstr "%.2lf Hz" msgid "On" msgstr "켬" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3198 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1982 panels/power/cc-power-panel.c:1993 +#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1999 #: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 #: panels/universal-access/cc-ua-panel.c:333 #: panels/universal-access/cc-ua-panel.c:714 @@ -1232,11 +1236,11 @@ msgstr "켬" msgid "Off" msgstr "끔" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3219 msgid "_Night Light" msgstr "야간 모드(_N)" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3284 msgid "Could not get screen information" msgstr "화면 정보를 읽어 올 수 없습니다" @@ -1310,12 +1314,13 @@ msgstr "디스플레이" msgid "Choose how to use connected monitors and projectors" msgstr "연결한 모니터와 프로젝터 사용법을 정합니다" -#: panels/display/gnome-display-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/display/gnome-display-panel.desktop.in.in:7 msgid "preferences-desktop-display" msgstr "preferences-desktop-display" -#. Translators: those are keywords for the display control-center panel -#: panels/display/gnome-display-panel.desktop.in.in:18 +#. Translators: Search terms to find the Displays panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/display/gnome-display-panel.desktop.in.in:19 msgid "" "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" "redshift;color;sunset;sunrise;" @@ -1453,12 +1458,13 @@ msgstr "기본 프로그램" msgid "Configure Default Applications" msgstr "기본 프로그램 설정" -#: panels/info/gnome-default-apps-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-default-apps-panel.desktop.in.in:7 msgid "starred" msgstr "starred" -#. Translators: those are keywords for the Default Applications panel -#: panels/info/gnome-default-apps-panel.desktop.in.in:18 +#. Translators: Search terms to find the Default Applications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-default-apps-panel.desktop.in.in:19 msgid "default;application;preferred;media;" msgstr "" "default;기본;기본값;application;프로그램;앱;애플리케이션;preferred;media;미디" @@ -1472,14 +1478,17 @@ msgstr "정보" msgid "View information about your system" msgstr "시스템의 정보를 봅니다" -#: panels/info/gnome-info-overview-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-info-overview-panel.desktop.in.in:7 msgid "help-about" msgstr "help-about" -#. Translators: those are keywords for the System Information panel +#. Translators: Search terms to find the About panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. "Preferred Applications" is the old name for the preference, so make #. sure that you use the same "translation" for those keywords -#: panels/info/gnome-info-overview-panel.desktop.in.in:20 +#: panels/info/gnome-info-overview-panel.desktop.in.in:23 msgid "" "device;system;information;memory;processor;version;default;application;" "preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" @@ -1497,12 +1506,13 @@ msgstr "이동식 미디어" msgid "Configure Removable Media settings" msgstr "이동식 미디어 설정" -#: panels/info/gnome-removable-media-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/info/gnome-removable-media-panel.desktop.in.in:7 msgid "media-removable" msgstr "media-removable" -#. Translators: those are keywords for the Removable Media panel -#: panels/info/gnome-removable-media-panel.desktop.in.in:18 +#. Translators: Search terms to find the Removable Media panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/info/gnome-removable-media-panel.desktop.in.in:19 msgid "" "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" "removable;media;autorun;" @@ -1681,8 +1691,8 @@ msgstr "실행 아이콘" msgid "Launch help browser" msgstr "도움말 보기 실행" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:222 +#: shell/cc-window.c:760 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "설정" @@ -1891,12 +1901,13 @@ msgstr "키보드" msgid "View and change keyboard shortcuts and set your typing preferences" msgstr "키보드 바로 가기를 보거나 바꾸고 키보드 타이핑을 설정합니다" -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:7 msgid "input-keyboard" msgstr "input-keyboard" -#. Translators: those are keywords for the keyboard control-center panel -#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:18 +#. Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 msgid "" "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" msgstr "" @@ -1927,9 +1938,7 @@ msgstr "다르게 검색해 보십시오" #: panels/keyboard/shortcut-editor.ui:68 panels/keyboard/shortcut-editor.ui:318 msgid "Press Esc to cancel or Backspace to reset the keyboard shortcut." -msgstr "" -"키보드 바로가기 입력에서 Esc를 누르면 취소하고, 백스페이스를 누르면 초기화합" -"니다." +msgstr "키보드 바로 가기 입력에서 Esc를 누르면 취소하고, 백스페이스를 누르면 초기화합니다." #: panels/keyboard/shortcut-editor.ui:156 panels/printers/details-dialog.ui:38 #: panels/sound/gvc-mixer-dialog.c:1480 @@ -1987,12 +1996,13 @@ msgid "" msgstr "" "마우스 및 터치패드 민감도를 바꾸고 오른손잡이용인지 왼손잡이용인지 설정합니다" -#: panels/mouse/gnome-mouse-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:7 msgid "input-mouse" msgstr "input-mouse" -#. Translators: those are keywords for the mouse and touchpad control-center panel -#: panels/mouse/gnome-mouse-panel.desktop.in.in:18 +#. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/mouse/gnome-mouse-panel.desktop.in.in:19 msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" msgstr "" "Trackpad;트랙패드;Pointer;포인터;Click;클릭;누르기;Tap;두드리기;Double;더블;" @@ -2105,8 +2115,8 @@ msgstr "네트워크 프록시" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "%s VPN(가상사설망)" @@ -2119,9 +2129,9 @@ msgstr "앗, 뭔가 잘못됐습니다. 소프트웨어 공급자에게 연락 msgid "NetworkManager needs to be running." msgstr "NetworkManager가 동작해야 합니다." -#: panels/network/cc-wifi-panel.c:212 +#: panels/network/cc-wifi-panel.c:213 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "와이파이" @@ -2172,31 +2182,31 @@ msgstr "프로파일 %d" #. TRANSLATORS: this WEP WiFi security #: panels/network/connection-editor/ce-page-details.c:56 -#: panels/network/net-device-wifi.c:231 panels/network/net-device-wifi.c:453 +#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:468 msgid "WEP" msgstr "WEP" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:60 -#: panels/network/net-device-wifi.c:235 panels/network/net-device-wifi.c:458 +#: panels/network/net-device-wifi.c:239 panels/network/net-device-wifi.c:473 #: panels/network/network-wifi.ui:593 msgid "WPA" msgstr "WPA" #. TRANSLATORS: this WPA WiFi security #: panels/network/connection-editor/ce-page-details.c:64 -#: panels/network/net-device-wifi.c:239 +#: panels/network/net-device-wifi.c:243 msgid "WPA2" msgstr "WPA2" #. TRANSLATORS: this Enterprise WiFi security #: panels/network/connection-editor/ce-page-details.c:69 -#: panels/network/net-device-wifi.c:244 +#: panels/network/net-device-wifi.c:248 msgid "Enterprise" msgstr "기업용" #: panels/network/connection-editor/ce-page-details.c:74 -#: panels/network/net-device-wifi.c:249 panels/network/net-device-wifi.c:443 +#: panels/network/net-device-wifi.c:253 panels/network/net-device-wifi.c:458 msgctxt "Wifi security" msgid "None" msgstr "없음" @@ -2208,7 +2218,7 @@ msgstr "안 함" #: panels/network/connection-editor/ce-page-details.c:110 #: panels/network/net-device-ethernet.c:121 -#: panels/network/net-device-wifi.c:552 +#: panels/network/net-device-wifi.c:567 #, c-format msgid "%i day ago" msgid_plural "%i days ago" @@ -2216,37 +2226,37 @@ msgstr[0] " %i일 전" #. Translators: network device speed #: panels/network/connection-editor/ce-page-details.c:225 -#: panels/network/net-device-ethernet.c:50 panels/network/net-device-wifi.c:608 +#: panels/network/net-device-ethernet.c:50 panels/network/net-device-wifi.c:646 #, c-format msgid "%d Mb/s" msgstr "%d Mb/s" #: panels/network/connection-editor/ce-page-details.c:251 -#: panels/network/net-device-wifi.c:637 +#: panels/network/net-device-wifi.c:675 msgctxt "Signal strength" msgid "None" msgstr "없음" #: panels/network/connection-editor/ce-page-details.c:253 -#: panels/network/net-device-wifi.c:639 +#: panels/network/net-device-wifi.c:677 msgctxt "Signal strength" msgid "Weak" msgstr "약함" #: panels/network/connection-editor/ce-page-details.c:255 -#: panels/network/net-device-wifi.c:641 +#: panels/network/net-device-wifi.c:679 msgctxt "Signal strength" msgid "Ok" msgstr "좋음" #: panels/network/connection-editor/ce-page-details.c:257 -#: panels/network/net-device-wifi.c:643 +#: panels/network/net-device-wifi.c:681 msgctxt "Signal strength" msgid "Good" msgstr "좋음" #: panels/network/connection-editor/ce-page-details.c:259 -#: panels/network/net-device-wifi.c:645 +#: panels/network/net-device-wifi.c:683 msgctxt "Signal strength" msgid "Excellent" msgstr "최상" @@ -2264,7 +2274,7 @@ msgid "Remove VPN" msgstr "VPN(가상사설망) 제거" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:214 #: shell/panel-list.ui:103 msgid "Details" msgstr "자세히 보기" @@ -2601,7 +2611,7 @@ msgstr "가져올 파일을 선택하십시오" #: panels/network/connection-editor/vpn-helpers.c:182 #: panels/printers/pp-details-dialog.c:332 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "열기(_O)" @@ -2666,12 +2676,13 @@ msgstr "네트워크" msgid "Control how you connect to the Internet" msgstr "어떻게 인터넷에 연결할지 정합니다" -#: panels/network/gnome-network-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-network-panel.desktop.in.in:7 msgid "network-workgroup" msgstr "network-workgroup" -#. Translators: those are keywords for the network control-center panel -#: panels/network/gnome-network-panel.desktop.in.in:18 +#. Translators: Search terms to find the Network panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-network-panel.desktop.in.in:19 msgid "" "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;" "DNS;" @@ -2684,12 +2695,13 @@ msgstr "" msgid "Control how you connect to Wi-Fi networks" msgstr "어떻게 와이파이 네트워크에 연결할지 정합니다" -#: panels/network/gnome-wifi-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/network/gnome-wifi-panel.desktop.in.in:7 msgid "network-wireless" msgstr "network-wireless" -#. Translators: those are keywords for the wi-fi control-center panel -#: panels/network/gnome-wifi-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wi-Fi panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/network/gnome-wifi-panel.desktop.in.in:19 msgid "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;" msgstr "" "Network;네트워크;Wireless;무선;Wi-Fi;Wifi;와이파이;IP;LAN;랜;Proxy;프록시;" @@ -2697,17 +2709,17 @@ msgstr "" "망;;DNS;네임서버;" #: panels/network/net-device-ethernet.c:107 -#: panels/network/net-device-wifi.c:538 +#: panels/network/net-device-wifi.c:553 msgid "never" msgstr "안 함" #: panels/network/net-device-ethernet.c:117 -#: panels/network/net-device-wifi.c:548 +#: panels/network/net-device-wifi.c:563 msgid "today" msgstr "오늘" #: panels/network/net-device-ethernet.c:119 -#: panels/network/net-device-wifi.c:550 +#: panels/network/net-device-wifi.c:565 msgid "yesterday" msgstr "어제" @@ -2732,7 +2744,7 @@ msgid "Wired" msgstr "유선" #: panels/network/net-device-ethernet.c:344 -#: panels/network/net-device-wifi.c:1849 panels/network/network-ethernet.ui:120 +#: panels/network/net-device-wifi.c:1895 panels/network/network-ethernet.ui:120 #: panels/network/network-mobile.ui:394 panels/network/network-simple.ui:75 #: panels/network/network-vpn.ui:79 msgid "Options…" @@ -2742,64 +2754,64 @@ msgstr "옵션…" msgid "Add new connection" msgstr "새 연결 추가" -#: panels/network/net-device-wifi.c:1328 +#: panels/network/net-device-wifi.c:1368 #, c-format msgid "Switching on the wireless hotspot will disconnect you from <b>%s</b>." msgstr "무선 핫스팟을 전환하면 <b>%s</b>의 연결이 끊어집니다." -#: panels/network/net-device-wifi.c:1332 +#: panels/network/net-device-wifi.c:1372 msgid "" "It is not possible to access the Internet through your wireless while the " "hotspot is active." msgstr "핫스팟이 동작할 때는 무선으로 인터넷에 연결할 수 없습니다." -#: panels/network/net-device-wifi.c:1339 +#: panels/network/net-device-wifi.c:1379 msgid "Turn On Wi-Fi Hotspot?" msgstr "와이파이 핫스팟을 켜시겠습니까?" -#: panels/network/net-device-wifi.c:1361 +#: panels/network/net-device-wifi.c:1401 msgid "" "Wi-Fi hotspots are usually used to share an additional Internet connection " "over Wi-Fi." msgstr "와이파이 핫스팟은 인터넷 연결을 와이파이를 통해 공유할 때 사용됩니다." -#: panels/network/net-device-wifi.c:1372 +#: panels/network/net-device-wifi.c:1412 msgid "_Turn On" msgstr "켜기(_T)" -#: panels/network/net-device-wifi.c:1449 +#: panels/network/net-device-wifi.c:1489 msgid "Stop hotspot and disconnect any users?" msgstr "핫스팟을 중지하고 연결 중인 사용자를 끊으시겠습니까?" -#: panels/network/net-device-wifi.c:1452 +#: panels/network/net-device-wifi.c:1492 msgid "_Stop Hotspot" msgstr "핫스팟 중지(_S)" -#: panels/network/net-device-wifi.c:1552 +#: panels/network/net-device-wifi.c:1592 msgid "System policy prohibits use as a Hotspot" msgstr "시스템 정책이 핫스팟 사용을 막습니다" -#: panels/network/net-device-wifi.c:1555 +#: panels/network/net-device-wifi.c:1595 msgid "Wireless device does not support Hotspot mode" msgstr "무선 장치에서 핫스팟 모드를 지원하지 않습니다" -#: panels/network/net-device-wifi.c:1687 +#: panels/network/net-device-wifi.c:1733 msgid "" "Network details for the selected networks, including passwords and any " "custom configuration will be lost." msgstr "" "선택한 네트워크의 상세 정보(암호 및 기타 사용자 설정 정보 포함)가 지워집니다." -#: panels/network/net-device-wifi.c:1691 panels/network/network-wifi.ui:1362 +#: panels/network/net-device-wifi.c:1737 panels/network/network-wifi.ui:1362 msgid "_Forget" msgstr "저장 지우기(_F)" -#: panels/network/net-device-wifi.c:2000 panels/network/net-device-wifi.c:2007 +#: panels/network/net-device-wifi.c:2046 panels/network/net-device-wifi.c:2053 msgid "Known Wi-Fi Networks" msgstr "알려진 와이파이 네트워크" #. translators: This is the label for the "Forget wireless network" functionality -#: panels/network/net-device-wifi.c:2040 +#: panels/network/net-device-wifi.c:2086 msgctxt "Wi-Fi Network" msgid "_Forget" msgstr "지우기(_F)" @@ -3015,19 +3027,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "암호" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "와이파이 끄기" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "숨겨진 네트워크에 연결(_C)…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "와이파이 핫스팟 켜기(_T)…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "알려진 와이파이 네트워크(_K)" @@ -3336,23 +3348,23 @@ msgstr "펌웨어 없음" msgid "Cable unplugged" msgstr "케이블 분리됨" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "802.1X 보안에 (WPA-EAP) 정의하지 않은 오류" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "파일을 선택하지 않았습니다" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "EAP-METHOD 파일을 검증하는 중 지정하지 않은 오류" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM 또는 PKCS#12 형식 개인 키(*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "DER 또는 PEM 형식 인증서(*.der, *.pem, *.crt, *.cer)" @@ -3731,12 +3743,13 @@ msgstr "알림" msgid "Control which notifications are displayed and what they show" msgstr "어떤 알림을 표시할지 및 무엇을 표시할지 설정합니다" -#: panels/notifications/gnome-notifications-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:7 msgid "preferences-system-notifications" msgstr "preferences-system-notifications" -#. Translators: those are keywords for the notifications control-center panel -#: panels/notifications/gnome-notifications-panel.desktop.in.in:19 +#. Translators: Search terms to find the Notifications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/notifications/gnome-notifications-panel.desktop.in.in:20 msgid "Notifications;Banner;Message;Tray;Popup;" msgstr "" "Notifications;알림;Banner;안내판;Message;메시지;Tray;트레이;Popup;팝업;" @@ -3762,19 +3775,19 @@ msgstr "기타" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:596 #, c-format msgid "%s Account" msgstr "%s 계정" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:888 msgid "Error removing account" msgstr "계정 제거 오류" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:953 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> 제거함" @@ -3787,13 +3800,16 @@ msgstr "온라인 계정" msgid "Connect to your online accounts and decide what to use them for" msgstr "온라인 계정에 연결하고 그 계정을 어디에 이용할지 설정합니다" -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:7 msgid "goa-panel" msgstr "goa-panel" -#. Translators: those are keywords for the online-accounts control-center panel +#. Translators: Search terms to find the Online Accounts panel. +#. Do NOT translate or localize the semicolons! +#. The list MUST also end with a semicolon! #. For ReadItLater and Pocket, see http://en.wikipedia.org/wiki/Pocket_(application) -#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:19 +#: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:22 msgid "" "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" @@ -3952,7 +3968,7 @@ msgstr "게임 입력 장치" #. TRANSLATORS: secondary battery, misc #: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2374 +#: panels/power/cc-power-panel.c:2380 msgid "Battery" msgstr "배터리" @@ -3996,100 +4012,100 @@ msgstr "방전됨" msgid "Batteries" msgstr "배터리" -#: panels/power/cc-power-panel.c:1236 +#: panels/power/cc-power-panel.c:1242 msgid "When _idle" msgstr "입력이 없을 때(_I)" -#: panels/power/cc-power-panel.c:1690 +#: panels/power/cc-power-panel.c:1696 msgid "Power Saving" msgstr "절전" -#: panels/power/cc-power-panel.c:1721 +#: panels/power/cc-power-panel.c:1727 msgid "_Screen brightness" msgstr "화면 밝기(_S)" -#: panels/power/cc-power-panel.c:1740 +#: panels/power/cc-power-panel.c:1746 msgid "Automatic brightness" msgstr "자동 밝기 조절" -#: panels/power/cc-power-panel.c:1760 +#: panels/power/cc-power-panel.c:1766 msgid "_Keyboard brightness" msgstr "키보드 밝기 조절(_K)" -#: panels/power/cc-power-panel.c:1770 +#: panels/power/cc-power-panel.c:1776 msgid "_Dim screen when inactive" msgstr "입력이 없으면 화면 어둡게(_D)" -#: panels/power/cc-power-panel.c:1795 +#: panels/power/cc-power-panel.c:1801 msgid "_Blank screen" msgstr "빈 화면(_B)" -#: panels/power/cc-power-panel.c:1832 +#: panels/power/cc-power-panel.c:1838 msgid "_Wi-Fi" msgstr "와이파이(_W)" -#: panels/power/cc-power-panel.c:1837 +#: panels/power/cc-power-panel.c:1843 msgid "Turn off Wi-Fi to save power." msgstr "전기 사용을 줄이려면 와이파이를 끄십시오." -#: panels/power/cc-power-panel.c:1862 +#: panels/power/cc-power-panel.c:1868 msgid "_Mobile broadband" msgstr "휴대전화 네트워크(_M)" -#: panels/power/cc-power-panel.c:1867 +#: panels/power/cc-power-panel.c:1873 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "전기 사용을 줄이려면 휴대전화 네트워크를(3G, 4G, LTE 등) 끄십시오." -#: panels/power/cc-power-panel.c:1920 +#: panels/power/cc-power-panel.c:1926 msgid "_Bluetooth" msgstr "블루투스(_B)" -#: panels/power/cc-power-panel.c:1925 +#: panels/power/cc-power-panel.c:1931 msgid "Turn off Bluetooth to save power." msgstr "전기 사용을 줄이려면 블루투스를 끄십시오." -#: panels/power/cc-power-panel.c:1984 +#: panels/power/cc-power-panel.c:1990 msgid "When on battery power" msgstr "배터리 전원 사용할 때" -#: panels/power/cc-power-panel.c:1986 +#: panels/power/cc-power-panel.c:1992 msgid "When plugged in" msgstr "전원이 연결되었을 때" -#: panels/power/cc-power-panel.c:2081 +#: panels/power/cc-power-panel.c:2087 msgid "Suspend" msgstr "대기 모드" -#: panels/power/cc-power-panel.c:2082 +#: panels/power/cc-power-panel.c:2088 msgid "Power Off" msgstr "전원 끄기" -#: panels/power/cc-power-panel.c:2083 +#: panels/power/cc-power-panel.c:2089 msgid "Hibernate" msgstr "최대 절전" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2090 msgid "Nothing" msgstr "아무것도 하지 않기" #. Frame header -#: panels/power/cc-power-panel.c:2198 +#: panels/power/cc-power-panel.c:2204 msgid "Suspend & Power Button" msgstr "대기 모드 및 전원 단추" -#: panels/power/cc-power-panel.c:2237 +#: panels/power/cc-power-panel.c:2243 msgid "_Automatic suspend" msgstr "자동 대기 모드(_A)" -#: panels/power/cc-power-panel.c:2238 +#: panels/power/cc-power-panel.c:2244 msgid "Automatic suspend" msgstr "자동 대기 모드" -#: panels/power/cc-power-panel.c:2305 +#: panels/power/cc-power-panel.c:2311 msgid "_When the Power Button is pressed" msgstr "전원 단추를 눌렀을 때(_W)" -#: panels/power/cc-power-panel.c:2424 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2430 shell/cc-window.c:218 #: shell/panel-list.ui:45 msgid "Devices" msgstr "장치" @@ -4102,12 +4118,13 @@ msgstr "전원" msgid "View your battery status and change power saving settings" msgstr "배터리 상태를 보고 절전 설정을 바꿉니다" -#: panels/power/gnome-power-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/power/gnome-power-panel.desktop.in.in:7 msgid "gnome-power-manager" msgstr "gnome-power-manager" -#. Translators: those are keywords for the power control-center panel -#: panels/power/gnome-power-panel.desktop.in.in:18 +#. Translators: Search terms to find the Power panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/power/gnome-power-panel.desktop.in.in:19 msgid "" "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" msgstr "" @@ -4223,18 +4240,18 @@ msgid "Authentication Required" msgstr "인증 필요" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:808 #, c-format msgid "Printer “%s” has been deleted" msgstr "“%s” 프린터를 삭제했습니다" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1053 msgid "Failed to add new printer." msgstr "새 프린터 추가에 실패했습니다." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1388 #, c-format msgid "Could not load ui: %s" msgstr "UI를 읽어들일 수 없습니다: %s" @@ -4273,12 +4290,13 @@ msgstr "프린터" msgid "Add printers, view printer jobs and decide how you want to print" msgstr "프린터 추가, 인쇄 작업 보기, 어떻게 인쇄할지 설정" -#: panels/printers/gnome-printers-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/printers/gnome-printers-panel.desktop.in.in:7 msgid "printer" -msgstr "프린터" +msgstr "printer" -#. Translators: those are keywords for the printing control-center panel -#: panels/printers/gnome-printers-panel.desktop.in.in:15 +#. Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/printers/gnome-printers-panel.desktop.in.in:16 msgid "Printer;Queue;Print;Paper;Ink;Toner;" msgstr "" "Printer;프린터;Queue;대기열;Print;인쇄;Paper;용지;종이;Ink;잉크;Toner;토너;" @@ -4369,7 +4387,7 @@ msgid "Select Printer Driver" msgstr "프린터 드라이버 선택" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "선택" @@ -4426,69 +4444,69 @@ msgid "Reverse portrait" msgstr "가로 방향 뒤집기" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "대기" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "일시 중지 상태" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "인증 필요" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "처리 중" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "중지" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "취소" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "중지됨" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "완료" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" msgstr[0] "작업 %u개에 인증이 필요합니다" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s — 활성 작업" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "%s에서 인쇄하려면 인증 정보가 필요합니다." @@ -4938,12 +4956,13 @@ msgid "Protect your personal information and control what others might see" msgstr "개인 정보를 보호하고, 다른 사람이 볼 수 있는 사항을 설정합니다" #. FIXME -#: panels/privacy/gnome-privacy-panel.desktop.in.in:7 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:8 msgid "preferences-system-privacy" msgstr "preferences-system-privacy" -#. Translators: those are keywords for the privacy control-center panel -#: panels/privacy/gnome-privacy-panel.desktop.in.in:19 +#. Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/privacy/gnome-privacy-panel.desktop.in.in:20 msgid "" "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" "network;identity;" @@ -5178,12 +5197,13 @@ msgid "" "Select your display language, formats, keyboard layouts and input sources" msgstr "표시할 언어, 여러가지 형식, 키보드 배치, 입력 소스를 선택합니다." -#: panels/region/gnome-region-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/region/gnome-region-panel.desktop.in.in:7 msgid "preferences-desktop-locale" msgstr "preferences-desktop-locale" -#. Translators: those are keywords for the region control-center panel -#: panels/region/gnome-region-panel.desktop.in.in:18 +#. Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/region/gnome-region-panel.desktop.in.in:19 msgid "Language;Layout;Keyboard;Input;" msgstr "Language;언어;Layout;배치;Keyboard;키보드;Input;입력;" @@ -5314,12 +5334,13 @@ msgid "" "Control which applications show search results in the Activities Overview" msgstr "어떤 프로그램에서 활동 내역에 검색 결과를 표시할지 설정합니다." -#: panels/search/gnome-search-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/search/gnome-search-panel.desktop.in.in:7 msgid "preferences-system-search" msgstr "preferences-system-search" -#. Translators: those are keywords for the search control-center panel -#: panels/search/gnome-search-panel.desktop.in.in:18 +#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/search/gnome-search-panel.desktop.in.in:19 msgid "Search;Find;Index;Hide;Privacy;Results;" msgstr "" "Search;검색;Find;찾기;Index;인덱스;색인;Hide;숨기기;Privacy;개인;정보;사생활;" @@ -5424,12 +5445,13 @@ msgstr "공유" msgid "Control what you want to share with others" msgstr "다른 사람과 공유할 사항을 정합니다" -#: panels/sharing/gnome-sharing-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:7 msgid "preferences-system-sharing" msgstr "preferences-system-sharing" -#. Translators: those are keywords for the sharing control-center panel -#: panels/sharing/gnome-sharing-panel.desktop.in.in:15 +#. Translators: Search terms to find the Sharing panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sharing/gnome-sharing-panel.desktop.in.in:16 msgid "" "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" "movies;server;renderer;" @@ -5534,12 +5556,13 @@ msgstr "소리" msgid "Change sound levels, inputs, outputs, and alert sounds" msgstr "사운드 음량과, 입력, 출력, 경고음을 바꿉니다" -#: panels/sound/data/gnome-sound-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:7 msgid "multimedia-volume-control" msgstr "multimedia-volume-control" -#. Translators: those are keywords for the sound control-center panel -#: panels/sound/data/gnome-sound-panel.desktop.in.in:19 +#. Translators: Search terms to find the Sound panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/sound/data/gnome-sound-panel.desktop.in.in:20 msgid "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;" msgstr "" "Card;카드;Microphone;마이크;Volume;볼륨;음량;Fade;페이드;Balance;균형;밸런스;" @@ -5769,13 +5792,14 @@ msgstr[0] "%d픽셀" msgid "Make it easier to see, hear, type, point and click" msgstr "보기, 듣기, 타이핑, 누르기 편의 사항" -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:7 msgid "preferences-desktop-accessibility" msgstr "preferences-desktop-accessibility" # 원문이 'Mouse' 키워드 중복 -#. Translators: those are keywords for the universal access control-center panel -#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:18 +#. Translators: Search terms to find the Universal Access panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 msgid "" "Keyboard;Mouse;a11y;Accessibility;Contrast;Zoom;Screen;Reader;text;font;size;" "AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;click;Delay;Assist;Repeat;Blink;" @@ -6406,12 +6430,13 @@ msgstr "사용자" msgid "Add or remove users and change your password" msgstr "사용자 추가/제거 및 암호 바꾸기" -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:7 msgid "system-users" msgstr "system-users" -#. Translators: those are keywords for the user accounts control-center panel -#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:19 +#. Translators: Search terms to find the Users panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:20 msgid "Login;Name;Fingerprint;Avatar;Logo;Face;Password;" msgstr "" "Login;로그인;Name;이름;Fingerprint;지문;Avatar;아바타;Logo;로고;Face;얼굴;" @@ -6850,7 +6875,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6858,7 +6883,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6895,7 +6920,7 @@ msgstr "암호를 바꿀 수 없습니다" msgid "The passwords do not match." msgstr "암호가 다릅니다." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "다른 사진 찾아보기" @@ -6923,41 +6948,41 @@ msgstr "암호가 잘못되었으니 다시 시도해주십시오" msgid "Couldn’t connect to the %s domain: %s" msgstr "%s 도메인에 연결할 수 없습니다: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "내 계정" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "사용자 삭제에 실패했습니다" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "원격에서 관리하는 사용자를 철회하는데 실패했습니다" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "자기 계정은 삭제할 수 없습니다." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s 사용자가 아직 로그인 중입니다" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." msgstr "로그인 중인 사용자를 삭제하면 시스템이 불안정한 상태가 될 수 있습니다." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "%s 사용자의 파일을 유지하시겠습니까?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -6965,47 +6990,47 @@ msgstr "" "사용자 계정을 삭제할 때 홈 디렉터리, 메일 스풀, 임시 파일을 유지할 수 있습니" "다." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "파일 삭제(_D)" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "파일 유지(_K)" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "정말로 원격에서 관리하는 %s의 계정을 철회하시겠습니까?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "삭제(_D)" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "계정 사용 중지됨" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "다음 로그인에 설정 예정" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "없음" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "로그인함" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "계정 서비스 연결에 실패했습니다" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "AccountService를 설치하고 사용 표시했는지 확인하십시오." @@ -7013,7 +7038,7 @@ msgstr "AccountService를 설치하고 사용 표시했는지 확인하십시오 #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7021,12 +7046,12 @@ msgstr "" "바꾸려면,\n" "먼저 * 아이콘을 누르십시오" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "새 사용자 계정 만들기" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7034,12 +7059,12 @@ msgstr "" "사용자 계정을 만드려면,\n" "먼저 * 아이콘을 누르십시오" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "선택한 사용자 계정 삭제" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7170,12 +7195,13 @@ msgid "Set button mappings and adjust stylus sensitivity for graphics tablets" msgstr "" "그래픽 디지타이저의 단추 매핑을 설정하고 스타일러스의 민감도를 조정합니다" -#: panels/wacom/gnome-wacom-panel.desktop.in.in:6 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:7 msgid "input-tablet" msgstr "input-tablet" -#. Translators: those are keywords for the wacom tablet control-center panel -#: panels/wacom/gnome-wacom-panel.desktop.in.in:18 +#. Translators: Search terms to find the Wacom Tablet panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/wacom/gnome-wacom-panel.desktop.in.in:19 msgid "Tablet;Wacom;Stylus;Eraser;Mouse;" msgstr "" "Tablet;태블릿;디지타이저;Wacom;와콤;Stylus;스타일러스;Eraser;지우개;Mouse;마" @@ -7357,11 +7383,13 @@ msgstr "도움말" msgid "Quit" msgstr "끝내기" -#: shell/gnome-control-center.desktop.in.in:4 +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: shell/gnome-control-center.desktop.in.in:5 msgid "gnome-control-center" msgstr "gnome-control-center" -#: shell/gnome-control-center.desktop.in.in:15 +#. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: shell/gnome-control-center.desktop.in.in:17 msgid "Preferences;Settings;" msgstr "Preferences;기본 설정;Settings;설정;" @@ -17,17 +17,18 @@ msgstr "" "Project-Id-Version: gnome-control-center\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-03-08 11:52+0000\n" -"PO-Revision-Date: 2018-03-03 14:01+0200\n" -"Last-Translator: Daniel Șerbănescu <daniel [at] serbanescu [dot] dk>\n" +"POT-Creation-Date: 2018-04-26 16:26+0000\n" +"PO-Revision-Date: 2018-04-27 00:50+0300\n" +"Last-Translator: Florentina Mușat <florentina.musat.28 [at] gmail [dot] " +"com>\n" "Language-Team: Gnome Romanian Translation Team\n" "Language: ro\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==0 || (n%100 > 0 && n%100 < " -"20)) ? 1 : 2);;\n" -"X-Generator: Virtaal 0.7.1\n" +"20)) ? 1 : 2);\n" +"X-Generator: Poedit 2.0.7\n" "X-Launchpad-Export-Date: 2014-07-13 17:08+0000\n" "X-Project-Style: gnome\n" @@ -113,16 +114,16 @@ msgid "You can add images to your %s folder and they will show up here" msgstr "Puteți adăuga imagini în directorul %s și acestea vor fi afișate aici" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 #: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 #: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -131,8 +132,8 @@ msgstr "Puteți adăuga imagini în directorul %s și acestea vor fi afișate ai #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 #: panels/user-accounts/um-user-panel.c:634 #: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" @@ -179,39 +180,39 @@ msgstr "preferences-desktop-wallpaper" msgid "Wallpaper;Screen;Desktop;" msgstr "Wallpaper;Screen;Desktop;Tapet;Ecran;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Închide modul Avion" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Nu a fost găsit adaptor Bluetooth" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Introduceți un dispozitiv pentru a folosi Bluetooth." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth este oprit" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Deschideți pentru a putea conecta dispozitive și transfera fișiere." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Mod avion este pornit" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "Bluetooth este dezactivat când modul avion este pornit." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Mod hardware avion este pornit" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Opriți modul avion pentru a putea activa Bluetooth." @@ -236,7 +237,7 @@ msgid "share;sharing;bluetooth;obex;" msgstr "share;sharing;bluetooth;obex;partajează;partajare;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "" "Plasați dispozitivul de calibrare deasupra pătratului și apăsați „Start”" @@ -244,7 +245,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "" @@ -254,7 +255,7 @@ msgstr "" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "" @@ -264,54 +265,54 @@ msgstr "" #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Închideți capacul laptopului" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "A apărut o eroare internă nerecuperabilă." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "Uneltele pentru calibrare nu sunt instalate." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "Nu s-a putut genera profilul." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "Nu s-a putut găsi punctul de țintă alb." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Gata!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Calibrare eșuată!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Puteți deconecta dispozitivul de calibrare." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:554 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "Nu deranjați dispozitivul în timpul calibrării" @@ -373,48 +374,48 @@ msgstr "Necalibrat" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " msgstr "Implicit: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Spațiu culoare: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Profil de test: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "Selectați un fișier profil ICC" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_Importă" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Profile ICC recunoscute" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Toate fișierele" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Ecran" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Eșec la încărcarea fișierului: %s" @@ -422,39 +423,39 @@ msgstr "Eșec la încărcarea fișierului: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "Profilul a fost încărcat în:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Scrieți acest URL." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "Reporniți calculatorul și intrați în sistemul de operare obișnuit." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "Scrieți URL-ul în navigator pentru a descărca și instala profilul." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Salvare profil" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Salvare" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Creează un profil de culoare pentru dispozitivul ales" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -463,12 +464,12 @@ msgstr "" "conectat." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "Instrumentul de măsură nu suportă profilarea pentru imprimante." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Tipul de dispozitiv nu este recunoscut." @@ -924,6 +925,12 @@ msgstr "%b %e" msgid "%b %e, %Y" msgstr "%b %e, %Y" +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Hotspot" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Limba" @@ -1120,58 +1127,58 @@ msgstr "Modifică data și ora sistemului" msgid "To change time or date settings, you need to authenticate." msgstr "Pentru a schimba data sau ora, trebuie să vă autentificați." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Peisaj" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Portret dreapta" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Portret stânga" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Peisaj (inversat)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Orientare" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Rezoluție" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Rata de reîmprospătare" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Scalează" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "Reglează pentru TV" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Afișaj primar" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Aranjamentul afișajelor" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1179,59 +1186,67 @@ msgstr "" "Trageți afișaje potrivit situației dumneavoastră. Bara de sus este plasată " "pe afișajul primar." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Modul de afișaj" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Unește afișaje" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Oglindire" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Afișaj singular" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Aplicați modificările?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Aplică" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Aplicați modificările?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "Nu se pot aplica modificările" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Aceasta poate fi din cauza limitărilor de hardware." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1994 panels/power/cc-power-panel.c:2001 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Pornit" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1999 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1239,11 +1254,11 @@ msgstr "Pornit" msgid "Off" msgstr "Oprit" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "Lumină _nocturnă" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "Nu s-au putut obține informații despre ecran" @@ -1283,7 +1298,7 @@ msgstr "Apus la răsărit" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Manual" @@ -1333,8 +1348,8 @@ msgstr "" "Albastru;culoare;apus;răsărit;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Necunoscut" @@ -1342,24 +1357,24 @@ msgstr "Necunoscut" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; ID-ul compilării: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64-biți" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32-biți" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Versiunea %s" @@ -1427,7 +1442,7 @@ msgstr "disc HD DVD gol" #: panels/info/cc-info-removable-media-panel.c:445 msgid "Blu-ray video disc" -msgstr "disc video Blu-ray" +msgstr "Disc video Blu-ray" #: panels/info/cc-info-removable-media-panel.c:446 msgid "e-book reader" @@ -1435,7 +1450,7 @@ msgstr "cititor de cărți electronice" #: panels/info/cc-info-removable-media-panel.c:447 msgid "HD DVD video disc" -msgstr "disc video HD DVD" +msgstr "Disc video HD DVD" #: panels/info/cc-info-removable-media-panel.c:448 msgid "Picture CD" @@ -1694,8 +1709,8 @@ msgstr "Lansatori" msgid "Launch help browser" msgstr "Lansează navigatorul de ajutor" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:762 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Configurări" @@ -1804,7 +1819,7 @@ msgstr "Activează sau dezactivează contrastul puternic" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Scurtături personalizate" @@ -1815,7 +1830,7 @@ msgstr "Scurtături personalizate" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -1920,7 +1935,7 @@ msgstr "" "Scurtătură;Scurtături;Fereastră;Redimensionează;Sursă;Blochează;Volum;" #: panels/keyboard/gnome-keyboard-panel.ui:67 panels/region/input-options.ui:68 -#: shell/cc-application.c:252 +#: shell/cc-application.c:255 msgid "Keyboard Shortcuts" msgstr "Scurtături tastatură" @@ -2113,7 +2128,7 @@ msgid "Single click, secondary button" msgstr "Un clic, buton secundar" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:581 msgid "Network proxy" msgstr "Proxy rețea" @@ -2121,23 +2136,23 @@ msgstr "Proxy rețea" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:717 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "%s VPN" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:781 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "" "Ups, ceva nu a funcționat corect. Vă rugăm să contactați distribuitorul de " "software." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:787 msgid "NetworkManager needs to be running." msgstr "NetworkManager trebuie să funcționeze." -#: panels/network/cc-wifi-panel.c:213 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 #: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" @@ -2284,7 +2299,7 @@ msgid "Remove VPN" msgstr "Elimină VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Detalii" @@ -2419,7 +2434,7 @@ msgstr "Adecvat pentru conexiuni care au limite sau taxe pentru date." #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Automat" @@ -2617,9 +2632,9 @@ msgid "Select file to import" msgstr "Selectează fișierul de importat" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Deschide" @@ -3358,23 +3373,23 @@ msgstr "Lipsă firmware" msgid "Cable unplugged" msgstr "Cablu neconectat" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "eroare nespecificată în securitatea 802.1X (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "niciun fișier selectat" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "eroare nespecificată la validarea fișierului metodă eap" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM, sau chei private PKCS#12 (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "Certificate DER sau PEM (*.der, *.pem, *.crt, *.cer)" @@ -3792,19 +3807,19 @@ msgstr "Altele" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:596 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "Cont %s" -#: panels/online-accounts/cc-online-accounts-panel.c:888 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Eroare la eliminarea contului" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:953 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> eliminat" @@ -3858,41 +3873,41 @@ msgstr "Adaugă un cont" msgid "Remove Account" msgstr "Ștergere cont" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Timp necunoscut" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" -msgstr[0] "un minut" +msgstr[0] "%i minut" msgstr[1] "%i minute" msgstr[2] "%i de minute" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" -msgstr[0] "o oră" +msgstr[0] "%i oră" msgstr[1] "%i ore" msgstr[2] "%i de ore" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "oră" msgstr[1] "ore" msgstr[2] "de ore" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "minut" @@ -3900,239 +3915,283 @@ msgstr[1] "minute" msgstr[2] "de minute" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "%s până e încărcată complet" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Atenție: au mai rămas %s" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "au mai rămas %s" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Complet încărcat" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Descărcată complet" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Se încarcă" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Se descarcă" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Principal" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Extra" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Mouse fără fir" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Tastatură fără fir" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Sursă de curent neîntreruptibilă" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Asistent personal digital" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Telefon celular" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Player media" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tabletă" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Calculator" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Dispozitiv de intrare pentru jocuri" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2380 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Baterie" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "Se încarcă" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Atenție" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Scăzută" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "Bună" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Complet încărcat" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Descărcată complet" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Baterii" -#: panels/power/cc-power-panel.c:1242 +#: panels/power/cc-power-panel.c:1206 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d oră" +msgstr[1] "%d ore" +msgstr[2] "%d de ore" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minut" +msgstr[1] "%d minute" +msgstr[2] "%d de minute" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d secundă" +msgstr[1] "%d secunde" +msgstr[2] "%d de secunde" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +msgctxt "time" +msgid "%s %s" +msgstr "%s %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +msgid "0 seconds" +msgstr "0 secunde" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Când e _inactiv" -#: panels/power/cc-power-panel.c:1696 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Economisire de energie" -#: panels/power/cc-power-panel.c:1727 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "Luminozitate ec_ran" -#: panels/power/cc-power-panel.c:1746 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Luminozitate automată" -#: panels/power/cc-power-panel.c:1766 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "Luminozitate _tastatură" -#: panels/power/cc-power-panel.c:1776 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "_Diminuează luminozitatea la inactivitate" -#: panels/power/cc-power-panel.c:1801 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" msgstr "Ecran _gol" -#: panels/power/cc-power-panel.c:1838 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1843 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Închide Wi-Fi pentru a economisi energia." -#: panels/power/cc-power-panel.c:1868 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "Internet _mobil de bandă largă" -#: panels/power/cc-power-panel.c:1873 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "" "Închide internetul mobil (3G, 4G, LTE, etc.) pentru a economisi energie." -#: panels/power/cc-power-panel.c:1926 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1931 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Închide Bluetooth pentru a economisi energia." -#: panels/power/cc-power-panel.c:1990 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "Când funcționează pe baterie" -#: panels/power/cc-power-panel.c:1992 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Alimentat de la rețea" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Suspendă" -#: panels/power/cc-power-panel.c:2088 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Oprește" -#: panels/power/cc-power-panel.c:2089 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Hibernează" -#: panels/power/cc-power-panel.c:2090 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Nimic" #. Frame header -#: panels/power/cc-power-panel.c:2204 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Buton de suspendare și oprire" -#: panels/power/cc-power-panel.c:2243 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "Suspendare _automată" -#: panels/power/cc-power-panel.c:2244 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Suspendare automată" -#: panels/power/cc-power-panel.c:2311 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "_Când butonul de oprire este apăsat" -#: panels/power/cc-power-panel.c:2430 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Dispozitive" @@ -4163,11 +4222,11 @@ msgstr "20 de minute" #: panels/power/power.ui:21 msgid "25 minutes" -msgstr "25 minute" +msgstr "25 de minute" #: panels/power/power.ui:29 msgid "45 minutes" -msgstr "45 minute" +msgstr "45 de minute" #: panels/power/power.ui:33 panels/privacy/privacy.ui:42 #: panels/privacy/privacy.ui:56 @@ -4266,18 +4325,18 @@ msgid "Authentication Required" msgstr "Necesită autentificare" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:808 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "Imprimanta „%s” a fost ștearsă" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1053 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Nu s-a putut adăuga imprimanta nouă." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1388 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "Nu s-a putut încărca interfața cu utilizatorul: %s" @@ -4390,21 +4449,21 @@ msgid "Test Page" msgstr "Pagină de test" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "Detalii %s" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "Nu s-a găsit un driver potrivit" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "Specificați fișierul PPD" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4417,7 +4476,7 @@ msgid "Select Printer Driver" msgstr "Selectați driverul imprimantei" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Selectează" @@ -4907,25 +4966,25 @@ msgstr "" "Ne pare rău! Se pare că serviciul\n" "de tipărire al sistemului nu este disponibil." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Blocare ecran" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "În uz" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Pornit" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Oprit" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Servicii de locație" @@ -4955,11 +5014,11 @@ msgstr "Toate fișierele temporare vor fi șterse permanent." #: panels/privacy/cc-privacy-panel.c:1102 msgid "_Purge Temporary Files" -msgstr "_Purjează fișierele temporare" +msgstr "Șterge fișierele tem_porare" #: panels/privacy/cc-privacy-panel.c:1124 panels/privacy/privacy.ui:432 msgid "Purge Trash & Temporary Files" -msgstr "Purjare gunoi și fișiere temporare" +msgstr "Golește gunoiul și șterge fișierele temporare" #: panels/privacy/cc-privacy-panel.c:1164 panels/privacy/privacy.ui:637 msgid "Software Usage" @@ -5118,7 +5177,7 @@ msgstr "Gol_ește gunoiul…" #: panels/privacy/privacy.ui:606 msgid "_Purge Temporary Files…" -msgstr "_Purjează fișierele temporare…" +msgstr "Șterge fișierele tem_porare…" #: panels/privacy/privacy.ui:654 msgid "" @@ -5129,12 +5188,11 @@ msgid "" "All the information we collect is made anonymous, and we will never share " "your data with third parties." msgstr "" -"Dacă ne trimiteți informații despre cum folosiți software-ul, aceasta ne " -"ajută să vă facem niște recomandări mai precise. Ne ajută și la " -"îmbunătățirea software-ului.\n" +"Trimiterea de informații despre ce software utilizați ne ajută să furnizăm " +"recomandări mai precise. Ne ajută și la îmbunătățirea software-ului.\n" "\n" -"Toată informația colectată este anonomizată și nu o vom împărtăși niciodată " -"cu terți." +"Toate informațiile colectate sunt anonime, și nu le vom partaja niciodată cu " +"părți terțe." #: panels/privacy/privacy.ui:681 msgid "_Send software usage statistics" @@ -5187,11 +5245,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Altele" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Nicio sursă de intrare selectată" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "_Ecran de autentificare" @@ -5538,7 +5596,7 @@ msgstr "Autentifica_re la distanță" #: panels/sharing/sharing.ui:272 msgid "Some services are disabled because of no network access." -msgstr "Unele servicii sunt dezactivate din lipsa accesului la rețea" +msgstr "Unele servicii sunt dezactivate din lipsa accesului la rețea." #: panels/sharing/sharing.ui:286 panels/sharing/sharing.ui:413 msgid "File Sharing" @@ -5798,34 +5856,202 @@ msgstr "Subwoofer" msgid "Custom" msgstr "Personalizat" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Deconectat" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Se conectează" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Conectat" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Eroare de autorizare" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Autorizare" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Funcționalitate redusă" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Conectat și autorizat" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Necunoscut" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Autorizat la:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Conectat la:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Înscris la:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "Nu s-a putut autoriza dispozitivul: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "Nu s-a putut uita dispozitivul: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Nume:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Stare:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Autorizează și conectează" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Uită dispozitivul" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Eroare" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Autorizat" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"Subsistemul Thunderbolt (boltd) nu este instalat sau configurat corect." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"Nu s-a putut detecta Thunderbolt.\n" +"Fie sistemul nu are suport pentru Thunderbolt, a fost dezactivat în BIOS sau " +"este stabilit la un nivel de securitate nesuportat în BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "Suportul pentru Thunderbolt a fost dezactivat în BIOS." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Eroare la comutarea modului direct: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Nu este suport pentru Thunderbolt" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Acces direct" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "" +"Permite accesul direct la dispozitive precum docurile și GPU-urile externe." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Doar dispozitivele USB sau port de afișaj pot atașa." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Dispozitive în așteptare" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Nu sunt dispozitive atașate" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Administrează dispozitive Thunderbolt" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Implicită" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Medie" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Mare" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Mai mare" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "Cel mai mare" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5836,7 +6062,7 @@ msgstr[2] "%d de pixeli" #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:4 msgid "Make it easier to see, hear, type, point and click" msgstr "" -"Interfața mai ușor de văzut, auzit și de utilizat cu tastatura și mausul." +"Facilitează vederea, auzul, tastatul, mutatul mausului și apăsarea clicului" #. Translators: Do NOT translate or transliterate this text (this is an icon file name)! #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:7 @@ -5856,7 +6082,7 @@ msgstr "" #: panels/universal-access/uap.ui:89 msgid "_Always Show Universal Access Menu" -msgstr "_Arată întotdeauna meniul „Acces Universal”" +msgstr "_Arată întotdeauna meniul de acces universal" #: panels/universal-access/uap.ui:131 msgid "Seeing" @@ -5875,7 +6101,7 @@ msgid "C_ursor Size" msgstr "Dimenisunea c_ursorului" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Zoom" @@ -5939,7 +6165,7 @@ msgstr "Dimensiunea cursorului" msgid "" "Cursor size can be combined with zoom to make it easier to see the cursor." msgstr "" -"Dimenisunea cursorului poate fi combinată cu zoom pentru a face ecranul mai " +"Dimensiunea cursorului poate fi combinată cu zoom pentru a face ecranul mai " "lizibil." #: panels/universal-access/uap.ui:1105 @@ -5948,7 +6174,8 @@ msgstr "Cititor de ecran" #: panels/universal-access/uap.ui:1122 msgid "The screen reader reads displayed text as you move the focus." -msgstr "Cititorul de ecran afișează textul afișat în fereastra activă" +msgstr "" +"Cititorul de ecran citește textul afișat în timp ce mutați focalizarea." #: panels/universal-access/uap.ui:1155 msgid "_Screen Reader" @@ -6043,7 +6270,7 @@ msgstr "Taste _lente" msgid "Puts a delay between when a key is pressed and when it is accepted" msgstr "" "Introduce o întârziere între momentul în care o tastă este apăsată și cel în " -"care este acceptată." +"care este acceptată" #: panels/universal-access/uap.ui:1988 panels/universal-access/uap.ui:2201 #: panels/universal-access/uap.ui:2538 @@ -6170,27 +6397,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Mare" -#: panels/universal-access/zoom-options.c:339 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Scurtă" -#: panels/universal-access/zoom-options.c:340 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ de ecran" -#: panels/universal-access/zoom-options.c:341 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ de ecran" -#: panels/universal-access/zoom-options.c:342 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ de ecran" -#: panels/universal-access/zoom-options.c:343 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Lungă" @@ -6215,134 +6442,134 @@ msgstr "Jumătatea stângă" msgid "Right Half" msgstr "Jumătatea dreaptă" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Opțiuni zoom" -#: panels/universal-access/zoom-options.ui:187 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "_Mărire:" -#: panels/universal-access/zoom-options.ui:251 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Urmărește cursorul mausului" -#: panels/universal-access/zoom-options.ui:271 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "Parte _ecran:" -#: panels/universal-access/zoom-options.ui:333 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "Lupa se _extinde peste marginile ecranului" -#: panels/universal-access/zoom-options.ui:352 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "_Păstrează centrat cursorul lupei" -#: panels/universal-access/zoom-options.ui:371 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "Cursorul lupei îm_pinge conținutul" -#: panels/universal-access/zoom-options.ui:390 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "Cursorul lupei se mișcă odată cu _conținutul" -#: panels/universal-access/zoom-options.ui:424 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Poziție lupă:" -#: panels/universal-access/zoom-options.ui:445 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Lupă" -#: panels/universal-access/zoom-options.ui:492 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Grosime:" -#: panels/universal-access/zoom-options.ui:518 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "Subțire" -#: panels/universal-access/zoom-options.ui:550 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Gros" -#: panels/universal-access/zoom-options.ui:576 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "_Lungime:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:628 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "Cu_loare:" -#: panels/universal-access/zoom-options.ui:692 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "Țin_tă:" -#: panels/universal-access/zoom-options.ui:743 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "Suprapune peste curs_orul mausului" -#: panels/universal-access/zoom-options.ui:781 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Țintă" -#: panels/universal-access/zoom-options.ui:830 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "_Alb pe negru:" -#: panels/universal-access/zoom-options.ui:853 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Luminozitate:" -#: panels/universal-access/zoom-options.ui:877 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Contrast:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:900 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "Cu_loare" -#: panels/universal-access/zoom-options.ui:928 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Niciuna" -#: panels/universal-access/zoom-options.ui:960 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Completă" -#: panels/universal-access/zoom-options.ui:1026 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Scăzută" -#: panels/universal-access/zoom-options.ui:1059 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Ridicată" -#: panels/universal-access/zoom-options.ui:1090 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Scăzut" -#: panels/universal-access/zoom-options.ui:1123 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Ridicat" -#: panels/universal-access/zoom-options.ui:1159 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Efecte de culoare:" -#: panels/universal-access/zoom-options.ui:1184 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Efecte de culoare" @@ -6603,7 +6830,7 @@ msgstr "Pentru modificarea datelor utilizatorilor trebuie să vă autentificați #: panels/user-accounts/pw-utils.c:81 msgctxt "Password hint" msgid "The new password needs to be different from the old one." -msgstr "Noua parolă nu conține suficiente caractere diferite" +msgstr "Noua parolă trebuie să fie diferită de parola veche." #: panels/user-accounts/pw-utils.c:83 msgctxt "Password hint" @@ -6759,29 +6986,29 @@ msgstr "Eroare necunoscută" msgid "Should match the web address of your login provider." msgstr "Trebuie să potriviți adresele web a furnizorului de logare." -#: panels/user-accounts/um-account-dialog.c:229 +#: panels/user-accounts/um-account-dialog.c:228 msgid "Failed to add account" msgstr "Eșec la adăugarea contului" -#: panels/user-accounts/um-account-dialog.c:462 +#: panels/user-accounts/um-account-dialog.c:461 msgid "Passwords do not match." msgstr "Parolele nu se potrivesc." -#: panels/user-accounts/um-account-dialog.c:717 -#: panels/user-accounts/um-account-dialog.c:763 -#: panels/user-accounts/um-account-dialog.c:784 +#: panels/user-accounts/um-account-dialog.c:716 +#: panels/user-accounts/um-account-dialog.c:762 +#: panels/user-accounts/um-account-dialog.c:783 msgid "Failed to register account" msgstr "Eșec la înregistrarea contului" -#: panels/user-accounts/um-account-dialog.c:907 +#: panels/user-accounts/um-account-dialog.c:906 msgid "No supported way to authenticate with this domain" msgstr "Nici o metodă suportată pentru autentificarea cu acest domeniu" -#: panels/user-accounts/um-account-dialog.c:980 +#: panels/user-accounts/um-account-dialog.c:979 msgid "Failed to join domain" msgstr "Eșec la înregistrarea domeniului" -#: panels/user-accounts/um-account-dialog.c:1041 +#: panels/user-accounts/um-account-dialog.c:1040 msgid "" "That login name didn’t work.\n" "Please try again." @@ -6789,7 +7016,7 @@ msgstr "" "Numele de autentificare nu a funcționat.\n" "Încercați din nou." -#: panels/user-accounts/um-account-dialog.c:1048 +#: panels/user-accounts/um-account-dialog.c:1047 msgid "" "That login password didn’t work.\n" "Please try again." @@ -6797,11 +7024,11 @@ msgstr "" "Parola de autentificare nu a funcționat.\n" "Încercați din nou." -#: panels/user-accounts/um-account-dialog.c:1056 +#: panels/user-accounts/um-account-dialog.c:1055 msgid "Failed to log into domain" msgstr "Eșec la conectarea în domeniu" -#: panels/user-accounts/um-account-dialog.c:1114 +#: panels/user-accounts/um-account-dialog.c:1113 msgid "Unable to find the domain. Maybe you misspelled it?" msgstr "Nu se poate găsi domeniul. Poate l-ați scris greșit?" @@ -6982,30 +7209,29 @@ msgstr "Parola nu a putut fi schimbată" msgid "The passwords do not match." msgstr "Parolele nu se potrivesc." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Răsfoiește pentru mai multe imagini" -#: panels/user-accounts/um-realm-manager.c:350 +#: panels/user-accounts/um-realm-manager.c:310 msgid "Cannot automatically join this type of domain" msgstr "Nu se poate conecta automat la acest tip de domeniu" -#: panels/user-accounts/um-realm-manager.c:413 -#, c-format +#: panels/user-accounts/um-realm-manager.c:313 msgid "No such domain or realm found" msgstr "Nu este găsit niciun domeniu și nicio valoare reală" -#: panels/user-accounts/um-realm-manager.c:815 -#: panels/user-accounts/um-realm-manager.c:829 +#: panels/user-accounts/um-realm-manager.c:735 +#: panels/user-accounts/um-realm-manager.c:749 #, c-format msgid "Cannot log in as %s at the %s domain" msgstr "Nu se poate realiza conectarea ca %s în domeniul %s" -#: panels/user-accounts/um-realm-manager.c:821 +#: panels/user-accounts/um-realm-manager.c:741 msgid "Invalid password, please try again" msgstr "Parola nu este validă, încercați din nou" -#: panels/user-accounts/um-realm-manager.c:834 +#: panels/user-accounts/um-realm-manager.c:754 #, c-format msgid "Couldn’t connect to the %s domain: %s" msgstr "Nu se poate realiza conectarea la domeniul %s: %s" @@ -7156,7 +7382,7 @@ msgid "" "digits and the following characters: . - _" msgstr "" "Numele de utilizator poate conține numai litere mari și mici de la a la z, " -"cifre și oricare din caracterele: „.”, „-” și „_”" +"cifre și următoarele caractere: . - _" #: panels/user-accounts/um-utils.c:509 msgid "This will be used to name your home folder and can’t be changed." @@ -7406,43 +7632,43 @@ msgstr "" "Centrul de control este interfața principală GNOME pentru configurări ale " "calculatorului dumneavoastră." -#: shell/cc-application.c:59 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Afișează număr versiune" -#: shell/cc-application.c:60 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Activează modul volubil" -#: shell/cc-application.c:61 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Afișează prezentarea generală" -#: shell/cc-application.c:62 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Caută un șir" -#: shell/cc-application.c:63 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Listează nume posibile pentru panouri și apoi închide fereastra" -#: shell/cc-application.c:64 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Panou de afișat" -#: shell/cc-application.c:64 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [ARGUMENT…]" -#: shell/cc-application.c:135 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Panouri disponibile:" -#: shell/cc-application.c:253 +#: shell/cc-application.c:256 msgid "Help" msgstr "Ajutor" -#: shell/cc-application.c:254 +#: shell/cc-application.c:257 msgid "Quit" msgstr "Ieșire" @@ -7486,12 +7712,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Anulează căutarea" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Hotspot" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "Identificatorul ultimului panou de configurări de deschis" @@ -7714,12 +7934,6 @@ msgstr "Sunete de sistem" #~ msgid "_Method" #~ msgstr "_Metodă" -#~ msgid "Add Device" -#~ msgstr "Adaugă dispozitiv" - -#~ msgid "Remove Device" -#~ msgstr "Șterge dispozitiv" - #~ msgid "VPN Type" #~ msgstr "Tip de VPN" @@ -7741,9 +7955,6 @@ msgstr "Sunete de sistem" #~ msgid "Shortcut;Repeat;Blink;" #~ msgstr "Shortcut;Repeat;Blink;Scurtatură;" -#~ msgid "_Name:" -#~ msgstr "_Nume:" - #~ msgid "Add Shortcut" #~ msgstr "Adaugă scurtătură" @@ -8393,8 +8604,8 @@ msgstr "Sunete de sistem" #~ "Select a monitor to change its properties; drag it to rearrange its " #~ "placement." #~ msgstr "" -#~ "Selectați un monitor pentru a-i schimba proprietățile; trageți-l pentru a-l " -#~ "rearanja." +#~ "Selectați un monitor pentru a-i schimba proprietățile; trageți-l pentru a-" +#~ "l rearanja." #~ msgid "%a %R" #~ msgstr "%a %R" @@ -8742,9 +8953,6 @@ msgstr "Sunete de sistem" #~ msgid "Mesh" #~ msgstr "Mesh" -#~ msgid "Disconnected" -#~ msgstr "Deconectat" - #~ msgid "Power management settings" #~ msgstr "Configurări administrare consum" @@ -24,8 +24,8 @@ msgstr "" "Project-Id-Version: ru\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-23 19:10+0000\n" -"PO-Revision-Date: 2018-03-05 16:11+0300\n" +"POT-Creation-Date: 2018-03-26 22:21+0000\n" +"PO-Revision-Date: 2018-04-12 14:35+0300\n" "Last-Translator: Stas Solovey <whats_up@tut.by>\n" "Language-Team: Русский <gnome-cyr@gnome.org>\n" "Language: ru\n" @@ -120,7 +120,7 @@ msgstr "Можно добавить изображения в папку %s и #: panels/background/cc-background-chooser-dialog.c:560 #: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2597 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 @@ -136,10 +136,10 @@ msgstr "Можно добавить изображения в папку %s и #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_Отменить" @@ -918,12 +918,12 @@ msgstr "Вчера" #. Translators: This is a date format string in the style of "Feb 24". #: panels/common/cc-util.c:138 msgid "%b %e" -msgstr "%e %b." +msgstr "%-d %b" #. Translators: This is a date format string in the style of "Feb 24, 2013". #: panels/common/cc-util.c:143 msgid "%b %e, %Y" -msgstr "%e %b. %Y" +msgstr "%-d %b %Y" #: panels/common/language-chooser.ui:5 msgid "Language" @@ -944,17 +944,15 @@ msgstr "Месяц" msgid "Year" msgstr "Год" -# fix даты #. Translators: This is the full date and time format used in 12-hour mode. #: panels/datetime/cc-datetime-panel.c:333 msgid "%e %B %Y, %l:%M %p" -msgstr "%e %b. %Y, %l:%M %p" +msgstr "%-d %B %Y, %-l∶%M %p" -# fix даты #. Translators: This is the full date and time format used in 24-hour mode. #: panels/datetime/cc-datetime-panel.c:338 msgid "%e %B %Y, %R" -msgstr "%e %b. %Y, %R" +msgstr "%-d %B %Y, %R" #. Translators: "city, country" #: panels/datetime/cc-datetime-panel.c:503 @@ -980,7 +978,7 @@ msgstr "UTC%:::z" #. Translators: This is the time format used in 12-hour mode. #: panels/datetime/cc-datetime-panel.c:542 msgid "%l:%M %p" -msgstr "%l:%M %p" +msgstr "%-l∶%M %p" #. Translators: This is the time format used in 24-hour mode. #: panels/datetime/cc-datetime-panel.c:547 @@ -1123,58 +1121,58 @@ msgstr "Изменить системное время и дату" msgid "To change time or date settings, you need to authenticate." msgstr "Для изменения времени или даты требуется аутентификация." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:732 msgctxt "Display rotation" msgid "Landscape" msgstr "Ландшафтная" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:735 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Портретная справа" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:738 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Портретная слева" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:741 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Ландшафтная (перевернутая)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:808 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Ориентация" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:873 panels/display/cc-display-panel.c:1676 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Разрешение" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:961 msgid "Refresh Rate" msgstr "Частота обновления" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1098 msgid "Scale" msgstr "Масштаб" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1151 msgid "Adjust for TV" msgstr "Отрегулировать для ТВ" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1413 msgid "Primary Display" msgstr "Основной дисплей" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1442 msgid "Display Arrangement" msgstr "Расположение дисплея" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1443 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1182,41 +1180,41 @@ msgstr "" "Перетащите дисплеи в соответствии с нужной конфигурацией. Верхняя панель " "помещается на основной дисплей." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1866 msgid "Display Mode" msgstr "Режим дисплея" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1882 msgid "Join Displays" msgstr "Объединить дисплеи" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1885 msgid "Mirror" msgstr "Зеркальное отображение" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1888 msgid "Single Display" msgstr "Один дисплей" -#: panels/display/cc-display-panel.c:2590 +#: panels/display/cc-display-panel.c:2593 msgid "Apply Changes?" msgstr "Применить изменения?" -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2607 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "_Применить" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2982 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Гц" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3198 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1991 panels/power/cc-power-panel.c:1998 +#: panels/power/cc-power-panel.c:1994 panels/power/cc-power-panel.c:2001 #: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 #: panels/universal-access/cc-ua-panel.c:333 #: panels/universal-access/cc-ua-panel.c:714 @@ -1226,9 +1224,9 @@ msgstr "%.2lf Гц" msgid "On" msgstr "Включено" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3198 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1985 panels/power/cc-power-panel.c:1996 +#: panels/power/cc-power-panel.c:1988 panels/power/cc-power-panel.c:1999 #: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 #: panels/universal-access/cc-ua-panel.c:333 #: panels/universal-access/cc-ua-panel.c:714 @@ -1242,11 +1240,11 @@ msgstr "Включено" msgid "Off" msgstr "Выключено" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3219 msgid "_Night Light" msgstr "_Ночная подсветка" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3284 msgid "Could not get screen information" msgstr "Не удалось получить информацию об экране" @@ -1693,8 +1691,8 @@ msgstr "Запуск приложений" msgid "Launch help browser" msgstr "Запустить справочный браузер" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:222 +#: shell/cc-window.c:760 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Параметры" @@ -2118,8 +2116,8 @@ msgstr "Прокси" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "VPN %s" @@ -2136,7 +2134,7 @@ msgstr "NetworkManager должен быть запущен." #: panels/network/cc-wifi-panel.c:213 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Wi-Fi" @@ -2281,7 +2279,7 @@ msgid "Remove VPN" msgstr "Удалить VPN" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:214 #: shell/panel-list.ui:103 msgid "Details" msgstr "Подробности" @@ -2618,7 +2616,7 @@ msgstr "Выберите файл для импортирования" #: panels/network/connection-editor/vpn-helpers.c:182 #: panels/printers/pp-details-dialog.c:332 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Открыть" @@ -3040,19 +3038,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Пароль" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Выключить Wi-Fi" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "_Подключиться к скрытой сети…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "_Включить точку доступа Wi-Fi…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "_Известные сети Wi-Fi" @@ -3361,23 +3359,23 @@ msgstr "Отсутствует прошивка" msgid "Cable unplugged" msgstr "Кабель не подключён" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "неизвестная ошибка в безопасности 802.1X (wpa-eap)" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "файлы не выбраны" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "неизвестная ошибка проверки файла ЕАР-методом" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM, или приватные ключи PKCS#12 (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "Сертификаты DER или PEM (*.der, *.pem, *.crt, *.cer)" @@ -3796,19 +3794,19 @@ msgstr "Другое" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:596 #, c-format msgid "%s Account" msgstr "Учётная запись %s" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:888 msgid "Error removing account" msgstr "Ошибка при удалении учётной записи" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:953 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> удалён" @@ -3998,7 +3996,7 @@ msgstr "Игровое устройство ввода" #. TRANSLATORS: secondary battery, misc #: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2377 +#: panels/power/cc-power-panel.c:2380 msgid "Battery" msgstr "Батарея" @@ -4042,102 +4040,102 @@ msgstr "Полностью разряжена" msgid "Batteries" msgstr "Батареи" -#: panels/power/cc-power-panel.c:1239 +#: panels/power/cc-power-panel.c:1242 msgid "When _idle" msgstr "При п_ростое" -#: panels/power/cc-power-panel.c:1693 +#: panels/power/cc-power-panel.c:1696 msgid "Power Saving" msgstr "Энергосбережение" -#: panels/power/cc-power-panel.c:1724 +#: panels/power/cc-power-panel.c:1727 msgid "_Screen brightness" msgstr "Яркость _экрана" -#: panels/power/cc-power-panel.c:1743 +#: panels/power/cc-power-panel.c:1746 msgid "Automatic brightness" msgstr "Автоматическая регулировка яркости" -#: panels/power/cc-power-panel.c:1763 +#: panels/power/cc-power-panel.c:1766 msgid "_Keyboard brightness" msgstr "Яркость подсветки _клавиатуры" -#: panels/power/cc-power-panel.c:1773 +#: panels/power/cc-power-panel.c:1776 msgid "_Dim screen when inactive" msgstr "У_меньшать яркость экрана при простое" -#: panels/power/cc-power-panel.c:1798 +#: panels/power/cc-power-panel.c:1801 msgid "_Blank screen" msgstr "_Выключение экрана" -#: panels/power/cc-power-panel.c:1835 +#: panels/power/cc-power-panel.c:1838 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1840 +#: panels/power/cc-power-panel.c:1843 msgid "Turn off Wi-Fi to save power." msgstr "Выключите Wi-Fi для уменьшения энергопотребления." -#: panels/power/cc-power-panel.c:1865 +#: panels/power/cc-power-panel.c:1868 msgid "_Mobile broadband" msgstr "_Мобильный Интернет" -#: panels/power/cc-power-panel.c:1870 +#: panels/power/cc-power-panel.c:1873 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "" "Выключите адаптер мобильного широкополосного доступа (3G, 4G, WiMax и т.д.) " "для уменьшения энергопотребления." -#: panels/power/cc-power-panel.c:1923 +#: panels/power/cc-power-panel.c:1926 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1928 +#: panels/power/cc-power-panel.c:1931 msgid "Turn off Bluetooth to save power." msgstr "Выключите Bluetooth для уменьшения энергопотребления." -#: panels/power/cc-power-panel.c:1987 +#: panels/power/cc-power-panel.c:1990 msgid "When on battery power" msgstr "При работе от батареи" -#: panels/power/cc-power-panel.c:1989 +#: panels/power/cc-power-panel.c:1992 msgid "When plugged in" msgstr "При подключении" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2087 msgid "Suspend" msgstr "Перевести в режим ожидания" -#: panels/power/cc-power-panel.c:2085 +#: panels/power/cc-power-panel.c:2088 msgid "Power Off" msgstr "Выключить" -#: panels/power/cc-power-panel.c:2086 +#: panels/power/cc-power-panel.c:2089 msgid "Hibernate" msgstr "Перевести в режим гибернации" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2090 msgid "Nothing" msgstr "Ничего не делать" #. Frame header -#: panels/power/cc-power-panel.c:2201 +#: panels/power/cc-power-panel.c:2204 msgid "Suspend & Power Button" msgstr "Режим ожидания и кнопка выключения" -#: panels/power/cc-power-panel.c:2240 +#: panels/power/cc-power-panel.c:2243 msgid "_Automatic suspend" msgstr "_Автоматический режим ожидания" -#: panels/power/cc-power-panel.c:2241 +#: panels/power/cc-power-panel.c:2244 msgid "Automatic suspend" msgstr "Автоматический режим ожидания" -#: panels/power/cc-power-panel.c:2308 +#: panels/power/cc-power-panel.c:2311 msgid "_When the Power Button is pressed" msgstr "_При нажатии кнопки выключения" -#: panels/power/cc-power-panel.c:2427 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2430 shell/cc-window.c:218 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Устройства" @@ -4288,18 +4286,18 @@ msgid "Authentication Required" msgstr "Требуется аутентификация" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:808 #, c-format msgid "Printer “%s” has been deleted" msgstr "Принтер «%s» удалён" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1053 msgid "Failed to add new printer." msgstr "Не удалось добавить новый принтер." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1388 #, c-format msgid "Could not load ui: %s" msgstr "Не удалось загрузить интерфейс пользователя: %s" @@ -4436,7 +4434,7 @@ msgid "Select Printer Driver" msgstr "Выберите драйвер принтера" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Выбрать" @@ -4493,55 +4491,55 @@ msgid "Reverse portrait" msgstr "Перевёрнутая портретная" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Ожидание" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Приостановлено" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Требуется аутентификация" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "Выполняется" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Остановлено" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "Отменено" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Прервано" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Выполнено" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" @@ -4550,14 +4548,14 @@ msgstr[1] "%u задания требуют аутентификацию" msgstr[2] "%u заданий требуют аутентификацию" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "Текущие задания — %s" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format msgid "Enter credentials to print from %s." msgstr "Введите учётные данные для печати из %s." @@ -6930,14 +6928,14 @@ msgstr "На прошлой неделе" #: panels/user-accounts/um-history-dialog.c:83 msgctxt "login history week label" msgid "%b %e" -msgstr "%e %b." +msgstr "%-d %b" #. Translators: This is a date format string in the style of "Feb 24, 2013", #. shown as the last day of a week on login history dialog. #: panels/user-accounts/um-history-dialog.c:88 msgctxt "login history week label" msgid "%b %e, %Y" -msgstr "%e %b. %Y" +msgstr "%-d %b %Y" #. Translators: This indicates a week label on a login history. #. The first %s is the first day of a week, and the second %s the last day. @@ -6950,7 +6948,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6958,7 +6956,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6995,7 +6993,7 @@ msgstr "Не удалось изменить пароль" msgid "The passwords do not match." msgstr "Пароли не совпадают." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Найти дополнительные изображения" @@ -7023,30 +7021,30 @@ msgstr "Неправильный пароль, попробуйте ещё ра msgid "Couldn’t connect to the %s domain: %s" msgstr "Не удалось подключиться к домену %s: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Ваша учётная запись" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Не удалось удалить пользователя" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Не удалось аннулировать удалённого пользователя" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Нельзя удалить собственную учётную запись." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s всё ещё находится в системе" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." @@ -7054,12 +7052,12 @@ msgstr "" "Удаление пользователя, с незавершённым сеансом, может привести систему в " "противоречивое состояние." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "Хотите сохранить файлы пользователя %s?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7067,47 +7065,47 @@ msgstr "" "Можно сохранить домашнюю папку, почтовый ящик и временные файлы при удалении " "учётной записи пользователя." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "_Удалить файлы" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "_Сохранить файлы" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "Действительно аннулировать удалённую учётную запись %s?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Удалить" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Учётная запись отключена" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Установить при следующем входе в систему" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Нет" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Авторизованный" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Не удалось связаться со службой учётных записей" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Убедитесь, что AccountService установлен и включён." @@ -7115,7 +7113,7 @@ msgstr "Убедитесь, что AccountService установлен и вкл #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7123,12 +7121,12 @@ msgstr "" "Чтобы изменить,\n" "сначала нажмите на значок *" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Создать учётную запись пользователя" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7136,12 +7134,12 @@ msgstr "" "Чтобы создать учётную запись пользователя,\n" "сначала нажмите на значок *" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Удалить выбранную учётную запись пользователя" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -11,22 +11,23 @@ # Muhammet Kara <muhammetk@gmail.com>, 2011, 2012, 2013, 2014, 2015, 2016, 2017. # Emin Tufan Çetin <etcetin@gmail.com>, 2013, 2016, 2017, 2018. # Furkan Ahmet Kara <furkanahmetkara.fk@gmail.com>, 2018. +# Çağatay Yiğit Şahin <cyigitsahin@outlook.com>, 2018. # msgid "" msgstr "" "Project-Id-Version: gnome-control-center\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" "issues\n" -"POT-Creation-Date: 2018-02-23 19:10+0000\n" -"PO-Revision-Date: 2018-02-24 17:06+0200\n" -"Last-Translator: Furkan Ahmet Kara <furkanahmetkara.fk@gmail.com>\n" +"POT-Creation-Date: 2018-05-03 08:05+0000\n" +"PO-Revision-Date: 2018-05-06 15:04+0300\n" +"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n" "Language-Team: Türkçe <gnome-turk@gnome.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: Gtranslator 2.91.7\n" +"X-Generator: Poedit 2.0.7\n" #: panels/background/background.ui:49 msgid "_Background" @@ -112,16 +113,16 @@ msgstr "" "gözükecektir" #: panels/background/cc-background-chooser-dialog.c:560 -#: panels/color/cc-color-panel.c:225 panels/color/cc-color-panel.c:963 +#: panels/color/cc-color-panel.c:224 panels/color/cc-color-panel.c:962 #: panels/color/color-calibrate.ui:25 panels/color/color.ui:657 -#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2594 +#: panels/common/language-chooser.ui:23 panels/display/cc-display-panel.c:2610 #: panels/network/connection-editor/connection-editor.ui:15 #: panels/network/connection-editor/vpn-helpers.c:181 #: panels/network/connection-editor/vpn-helpers.c:310 #: panels/network/net-device-wifi.c:1411 panels/network/net-device-wifi.c:1491 #: panels/network/net-device-wifi.c:1736 panels/network/network-wifi.ui:24 #: panels/printers/new-printer-dialog.ui:45 -#: panels/printers/pp-details-dialog.c:331 +#: panels/printers/pp-details-dialog.c:330 #: panels/privacy/cc-privacy-panel.c:1053 panels/region/format-chooser.ui:25 #: panels/region/input-chooser.ui:13 #: panels/search/cc-search-locations-dialog.c:642 @@ -130,10 +131,10 @@ msgstr "" #: panels/user-accounts/data/join-dialog.ui:20 #: panels/user-accounts/data/password-dialog.ui:21 #: panels/user-accounts/um-fingerprint-dialog.c:261 -#: panels/user-accounts/um-photo-dialog.c:102 -#: panels/user-accounts/um-photo-dialog.c:229 -#: panels/user-accounts/um-user-panel.c:635 -#: panels/user-accounts/um-user-panel.c:653 +#: panels/user-accounts/um-photo-dialog.c:103 +#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:652 msgid "_Cancel" msgstr "_İptal" @@ -178,39 +179,39 @@ msgstr "preferences-desktop-wallpaper" msgid "Wallpaper;Screen;Desktop;" msgstr "Duvar kağıdı;Ekran;Masaüstü;" -#: panels/bluetooth/cc-bluetooth-panel.c:265 +#: panels/bluetooth/cc-bluetooth-panel.c:266 msgid "Turn Off Airplane Mode" msgstr "Uçak Kipini Kapat" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "No Bluetooth Found" msgstr "Bluetooth Bulunamadı" -#: panels/bluetooth/cc-bluetooth-panel.c:330 +#: panels/bluetooth/cc-bluetooth-panel.c:329 msgid "Plug in a dongle to use Bluetooth." msgstr "Bluetooth özelliğini kullanmak için aygıt takmalısınız." -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Bluetooth Turned Off" msgstr "Bluetooth Kapatıldı" -#: panels/bluetooth/cc-bluetooth-panel.c:331 +#: panels/bluetooth/cc-bluetooth-panel.c:330 msgid "Turn on to connect devices and receive file transfers." msgstr "Aygıtlara bağlanmak ve dosya aktarımı yapmak için açın." -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Airplane Mode is on" msgstr "Uçak Kipi açık" -#: panels/bluetooth/cc-bluetooth-panel.c:332 +#: panels/bluetooth/cc-bluetooth-panel.c:331 msgid "Bluetooth is disabled when airplane mode is on." msgstr "Uçak kipi açıldığında Bluetooth devre dışı kalır." -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Hardware Airplane Mode is on" msgstr "Donanımsal Uçak Kipi açık" -#: panels/bluetooth/cc-bluetooth-panel.c:333 +#: panels/bluetooth/cc-bluetooth-panel.c:332 msgid "Turn off the Airplane mode switch to enable Bluetooth." msgstr "Bluetooth’u etkinleştirmek için Uçak kipini kapat." @@ -235,14 +236,14 @@ msgid "share;sharing;bluetooth;obex;" msgstr "paylaş;paylaşım;bluetooth;obex;" #. TRANSLATORS: The user has to attach the sensor to the screen -#: panels/color/cc-color-calibrate.c:361 +#: panels/color/cc-color-calibrate.c:363 msgid "Place your calibration device over the square and press “Start”" msgstr "Kalibrasyon aygıtınızı karenin üzerine yerleştirin ve “Başlat”a basın" #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:367 +#: panels/color/cc-color-calibrate.c:369 msgid "" "Move your calibration device to the calibrate position and press “Continue”" msgstr "Kalibrasyon aygıtınızı kalibrasyon konumuna getirip “Devam Et”e basın" @@ -250,7 +251,7 @@ msgstr "Kalibrasyon aygıtınızı kalibrasyon konumuna getirip “Devam Et”e #. TRANSLATORS: Some calibration devices need the user to move a #. * dial or switch manually. We also show a picture showing them #. * what to do... -#: panels/color/cc-color-calibrate.c:373 +#: panels/color/cc-color-calibrate.c:375 msgid "" "Move your calibration device to the surface position and press “Continue”" msgstr "Kalibrasyon aygıtınızı yüzey konumuna getirip “Devam Et”e basın" @@ -258,54 +259,54 @@ msgstr "Kalibrasyon aygıtınızı yüzey konumuna getirip “Devam Et”e bası #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor #. * is built into the palmrest and we need to fullscreen the #. * sample widget and shut the lid. -#: panels/color/cc-color-calibrate.c:379 +#: panels/color/cc-color-calibrate.c:381 msgid "Shut the laptop lid" msgstr "Dizüstü bilgisayarın kapağını kapat" #. TRANSLATORS: We suck, the calibation failed and we have no #. * good idea why or any suggestions -#: panels/color/cc-color-calibrate.c:410 +#: panels/color/cc-color-calibrate.c:412 msgid "An internal error occurred that could not be recovered." msgstr "Telafi edilemeyecek bir iç hata oluştu." #. TRANSLATORS: Some required-at-runtime tools were not #. * installed, which should only affect insane distros -#: panels/color/cc-color-calibrate.c:415 +#: panels/color/cc-color-calibrate.c:417 msgid "Tools required for calibration are not installed." msgstr "Kalibrasyon için gerekli araçlar kurulu değil." #. TRANSLATORS: The profile failed for some reason -#: panels/color/cc-color-calibrate.c:421 +#: panels/color/cc-color-calibrate.c:423 msgid "The profile could not be generated." msgstr "Profil oluşturulamadı." #. TRANSLATORS: The user specified a whitepoint that was #. * unobtainable with the hardware they've got -- see #. * https://en.wikipedia.org/wiki/White_point for details -#: panels/color/cc-color-calibrate.c:427 +#: panels/color/cc-color-calibrate.c:429 msgid "The target whitepoint was not obtainable." msgstr "Hedef beyaznokta bulunabilir değildi." #. TRANSLATORS: the display calibration process is finished -#: panels/color/cc-color-calibrate.c:467 +#: panels/color/cc-color-calibrate.c:469 msgid "Complete!" msgstr "Tamamlandı!" #. TRANSLATORS: the display calibration failed, and we also show #. * the translated (or untranslated) error string after this -#: panels/color/cc-color-calibrate.c:475 +#: panels/color/cc-color-calibrate.c:477 msgid "Calibration failed!" msgstr "Kalibrasyon başarısız!" #. TRANSLATORS: The user can now remove the sensor from the screen -#: panels/color/cc-color-calibrate.c:482 +#: panels/color/cc-color-calibrate.c:484 msgid "You can remove the calibration device." msgstr "Kalibrasyon aygıtını çıkartabilirsiniz." #. TRANSLATORS: The user has to be careful not to knock the #. * display off the screen (although we do cope if this is #. * detected early enough) -#: panels/color/cc-color-calibrate.c:553 +#: panels/color/cc-color-calibrate.c:556 msgid "Do not disturb the calibration device while in progress" msgstr "Kalibrasyon esnasında kalibrasyon aygıtıyla oynamayın" @@ -367,48 +368,48 @@ msgstr "Kalibrasyon yok" #. TRANSLATORS: this is a profile prefix to signify the #. * profile has been auto-generated for this hardware -#: panels/color/cc-color-panel.c:141 +#: panels/color/cc-color-panel.c:140 msgid "Default: " -msgstr "Öntanımlı:" +msgstr "Öntanımlı: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile his a standard space like AdobeRGB -#: panels/color/cc-color-panel.c:149 +#: panels/color/cc-color-panel.c:148 msgid "Colorspace: " msgstr "Colorspace: " #. TRANSLATORS: this is a profile prefix to signify the #. * profile is a test profile -#: panels/color/cc-color-panel.c:156 +#: panels/color/cc-color-panel.c:155 msgid "Test profile: " msgstr "Sınama profili: " #. TRANSLATORS: an ICC profile is a file containing colorspace data -#: panels/color/cc-color-panel.c:223 +#: panels/color/cc-color-panel.c:222 msgid "Select ICC Profile File" msgstr "ICC Profil Dosyasını Seç" -#: panels/color/cc-color-panel.c:226 +#: panels/color/cc-color-panel.c:225 msgid "_Import" msgstr "_İçe Aktar" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:237 +#: panels/color/cc-color-panel.c:236 msgid "Supported ICC profiles" msgstr "Desteklenen ICC profilleri" #. TRANSLATORS: filter name on the file->open dialog -#: panels/color/cc-color-panel.c:244 +#: panels/color/cc-color-panel.c:243 #: panels/network/wireless-security/eap-method-fast.c:417 msgid "All files" msgstr "Tüm dosyalar" -#: panels/color/cc-color-panel.c:583 +#: panels/color/cc-color-panel.c:582 msgid "Screen" msgstr "Ekran" #. TRANSLATORS: this is when the upload of the profile failed -#: panels/color/cc-color-panel.c:908 +#: panels/color/cc-color-panel.c:907 #, c-format msgid "Failed to upload file: %s" msgstr "Dosya yüklenmesi başarısız: %s" @@ -416,40 +417,40 @@ msgstr "Dosya yüklenmesi başarısız: %s" #. TRANSLATORS: these are instructions on how to recover #. * the ICC profile on the native operating system and are #. * only shown when the user uses a LiveCD to calibrate -#: panels/color/cc-color-panel.c:922 +#: panels/color/cc-color-panel.c:921 msgid "The profile has been uploaded to:" msgstr "Profil şuraya yüklendi:" -#: panels/color/cc-color-panel.c:924 +#: panels/color/cc-color-panel.c:923 msgid "Write down this URL." msgstr "Bu URL’yi not edin." -#: panels/color/cc-color-panel.c:925 +#: panels/color/cc-color-panel.c:924 msgid "Restart this computer and boot your normal operating system." msgstr "" "Bu bilgisayarı yeniden başlatın ve olağan işletim sisteminizi başlatın." -#: panels/color/cc-color-panel.c:926 +#: panels/color/cc-color-panel.c:925 msgid "Type the URL into your browser to download and install the profile." msgstr "Profili indirmek ve yüklemek için adresi tarayıcınıza yazın." #. TRANSLATORS: this is the dialog to save the ICC profile -#: panels/color/cc-color-panel.c:960 +#: panels/color/cc-color-panel.c:959 msgid "Save Profile" msgstr "Profili Kaydet" -#: panels/color/cc-color-panel.c:964 +#: panels/color/cc-color-panel.c:963 #: panels/network/connection-editor/vpn-helpers.c:311 msgid "_Save" msgstr "_Kaydet" #. TRANSLATORS: this is when the button is sensitive -#: panels/color/cc-color-panel.c:1325 +#: panels/color/cc-color-panel.c:1324 msgid "Create a color profile for the selected device" msgstr "Seçilen aygıt için bir renk profili oluştur" #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1340 panels/color/cc-color-panel.c:1364 +#: panels/color/cc-color-panel.c:1339 panels/color/cc-color-panel.c:1363 msgid "" "The measuring instrument is not detected. Please check it is turned on and " "correctly connected." @@ -458,12 +459,12 @@ msgstr "" "bağlandığından emin olunuz." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1374 +#: panels/color/cc-color-panel.c:1373 msgid "The measuring instrument does not support printer profiling." msgstr "Ölçüm aygıtı yazıcı profillemeyi desteklemiyor." #. TRANSLATORS: this is when the button is insensitive -#: panels/color/cc-color-panel.c:1385 +#: panels/color/cc-color-panel.c:1384 msgid "The device type is not currently supported." msgstr "Aygıt türü şu anda desteklenmiyor." @@ -867,7 +868,7 @@ msgstr "Renk" msgid "" "Calibrate the color of your devices, such as displays, cameras or printers" msgstr "" -"Ekran, kamera veya yazıcı gibi aygıtlarınızın renk kalibrasyonunu yapın." +"Ekran, kamera veya yazıcı gibi aygıtlarınızın renk kalibrasyonunu yapın" #. Translators: Do NOT translate or transliterate this text (this is an icon file name)! #: panels/color/gnome-color-panel.desktop.in.in:7 @@ -912,6 +913,12 @@ msgstr "%e %b" msgid "%b %e, %Y" msgstr "%e %b, %Y" +#. translators: This is the default hotspot name, need to be less than 32-bytes +#: panels/common/hostname-helper.c:189 +msgctxt "hotspot" +msgid "Hotspot" +msgstr "Erişim Noktası" + #: panels/common/language-chooser.ui:5 msgid "Language" msgstr "Dil" @@ -1040,7 +1047,7 @@ msgstr "Saat" #. Translator: this is the separator between hours and minutes, like in HH∶MM #: panels/datetime/datetime.ui:121 msgid "∶" -msgstr ":" +msgstr "∶" #: panels/datetime/datetime.ui:143 msgid "Minute" @@ -1110,58 +1117,58 @@ msgstr "" "Saat ya da tarih ayarlarını değiştirmek için kimliğinizi doğrulamanız " "gerekiyor." -#: panels/display/cc-display-panel.c:729 +#: panels/display/cc-display-panel.c:739 msgctxt "Display rotation" msgid "Landscape" msgstr "Yatay" -#: panels/display/cc-display-panel.c:732 +#: panels/display/cc-display-panel.c:742 msgctxt "Display rotation" msgid "Portrait Right" msgstr "Dikey Sağ" -#: panels/display/cc-display-panel.c:735 +#: panels/display/cc-display-panel.c:745 msgctxt "Display rotation" msgid "Portrait Left" msgstr "Dikey Sol" -#: panels/display/cc-display-panel.c:738 +#: panels/display/cc-display-panel.c:748 msgctxt "Display rotation" msgid "Landscape (flipped)" msgstr "Yatay (ters yüz)" #. Translators: This option sets orientation of print (portrait, landscape...) -#: panels/display/cc-display-panel.c:805 +#: panels/display/cc-display-panel.c:816 #: panels/printers/pp-options-dialog.c:558 msgid "Orientation" msgstr "Yönelim" -#: panels/display/cc-display-panel.c:870 panels/display/cc-display-panel.c:1673 +#: panels/display/cc-display-panel.c:885 panels/display/cc-display-panel.c:1691 #: panels/printers/pp-options-dialog.c:87 msgid "Resolution" msgstr "Çözünürlük" -#: panels/display/cc-display-panel.c:958 +#: panels/display/cc-display-panel.c:974 msgid "Refresh Rate" msgstr "Tazeleme Hızı" -#: panels/display/cc-display-panel.c:1095 +#: panels/display/cc-display-panel.c:1111 msgid "Scale" msgstr "Ölçekle" -#: panels/display/cc-display-panel.c:1148 +#: panels/display/cc-display-panel.c:1164 msgid "Adjust for TV" msgstr "TV için Ayarla" -#: panels/display/cc-display-panel.c:1410 +#: panels/display/cc-display-panel.c:1427 msgid "Primary Display" msgstr "Birincil Ekran" -#: panels/display/cc-display-panel.c:1439 +#: panels/display/cc-display-panel.c:1456 msgid "Display Arrangement" msgstr "Ekran Düzeni" -#: panels/display/cc-display-panel.c:1440 +#: panels/display/cc-display-panel.c:1457 msgid "" "Drag displays to match your setup. The top bar is placed on the primary " "display." @@ -1169,59 +1176,67 @@ msgstr "" "Ekranları, düzeninizle eşleşecek şekilde sürükleyin. Üst çubuk, birincil " "ekranda gösterilir." -#: panels/display/cc-display-panel.c:1863 +#: panels/display/cc-display-panel.c:1881 msgid "Display Mode" msgstr "Ekran Kipi" -#: panels/display/cc-display-panel.c:1879 +#: panels/display/cc-display-panel.c:1897 msgid "Join Displays" msgstr "Ekranları Birleştir" -#: panels/display/cc-display-panel.c:1882 +#: panels/display/cc-display-panel.c:1900 msgid "Mirror" msgstr "Aynala" -#: panels/display/cc-display-panel.c:1885 +#: panels/display/cc-display-panel.c:1903 msgid "Single Display" msgstr "Tek Ekran" -#: panels/display/cc-display-panel.c:2590 -msgid "Apply Changes?" -msgstr "Değişiklikler Uygulansın Mı?" - -#: panels/display/cc-display-panel.c:2604 +#: panels/display/cc-display-panel.c:2620 #: panels/network/connection-editor/connection-editor.ui:24 #: panels/network/network-wifi.ui:38 msgid "_Apply" msgstr "Uygul_a" -#: panels/display/cc-display-panel.c:2979 +#: panels/display/cc-display-panel.c:2642 +msgid "Apply Changes?" +msgstr "Değişiklikler Uygulansın Mı?" + +#: panels/display/cc-display-panel.c:2647 +msgid "Changes Cannot be Applied" +msgstr "Değişiklikler Uygulanamadı" + +#: panels/display/cc-display-panel.c:2648 +msgid "This could be due to hardware limitations." +msgstr "Bu donanım kısıtlamalarından kaynaklanabilir." + +#: panels/display/cc-display-panel.c:3003 #, c-format msgid "%.2lf Hz" msgstr "%.2lf Hz" #. TRANSLATORS: the state of the night light setting -#: panels/display/cc-display-panel.c:3195 +#: panels/display/cc-display-panel.c:3219 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1991 panels/power/cc-power-panel.c:1998 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 +#: panels/power/cc-power-panel.c:2097 panels/power/cc-power-panel.c:2104 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 msgid "On" msgstr "Açık" -#: panels/display/cc-display-panel.c:3195 panels/network/net-proxy.c:54 +#: panels/display/cc-display-panel.c:3219 panels/network/net-proxy.c:54 #: panels/notifications/cc-notifications-panel.c:292 -#: panels/power/cc-power-panel.c:1985 panels/power/cc-power-panel.c:1996 -#: panels/privacy/cc-privacy-panel.c:190 panels/privacy/cc-privacy-panel.c:257 -#: panels/universal-access/cc-ua-panel.c:333 -#: panels/universal-access/cc-ua-panel.c:714 -#: panels/universal-access/cc-ua-panel.c:727 -#: panels/universal-access/cc-ua-panel.c:739 -#: panels/universal-access/cc-ua-panel.c:910 panels/universal-access/uap.ui:334 +#: panels/power/cc-power-panel.c:2091 panels/power/cc-power-panel.c:2102 +#: panels/privacy/cc-privacy-panel.c:191 panels/privacy/cc-privacy-panel.c:258 +#: panels/universal-access/cc-ua-panel.c:334 +#: panels/universal-access/cc-ua-panel.c:715 +#: panels/universal-access/cc-ua-panel.c:728 +#: panels/universal-access/cc-ua-panel.c:740 +#: panels/universal-access/cc-ua-panel.c:911 panels/universal-access/uap.ui:334 #: panels/universal-access/uap.ui:380 panels/universal-access/uap.ui:426 #: panels/universal-access/uap.ui:532 panels/universal-access/uap.ui:685 #: panels/universal-access/uap.ui:731 panels/universal-access/uap.ui:777 @@ -1229,11 +1244,11 @@ msgstr "Açık" msgid "Off" msgstr "Kapalı" -#: panels/display/cc-display-panel.c:3216 +#: panels/display/cc-display-panel.c:3240 msgid "_Night Light" msgstr "_Gece Işığı" -#: panels/display/cc-display-panel.c:3281 +#: panels/display/cc-display-panel.c:3305 msgid "Could not get screen information" msgstr "Ekran bilgisi alınamadı" @@ -1273,7 +1288,7 @@ msgstr "Gün Batımından Gün Doğumuna" #: panels/network/connection-editor/ip6-page.ui:83 #: panels/network/net-proxy.c:56 panels/network/network-proxy.ui:113 #: panels/network/network-wifi.ui:777 panels/network/network-wifi.ui:1054 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Manual" msgstr "Elle" @@ -1318,12 +1333,12 @@ msgid "" "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" "redshift;color;sunset;sunrise;" msgstr "" -"xrandr;Projektör;Ekran;Çözünürlük;Tazele;Yenile;Monitör;Gece;Işık;Mavi;" -"redshift;renk;gün doğumu;gün batımı;" +"Panel;Projektör;Gösterici;xrandr;Ekran;Çözünürlük;Tazele;Yenile;Monitör;Gece;" +"Işık;Mavi;redshift;renk;gün doğumu;gün batımı;" #. TRANSLATORS: AP type -#: panels/info/cc-info-overview-panel.c:374 -#: panels/info/cc-info-overview-panel.c:457 panels/network/panel-common.c:123 +#: panels/info/cc-info-overview-panel.c:373 +#: panels/info/cc-info-overview-panel.c:456 panels/network/panel-common.c:123 msgid "Unknown" msgstr "Bilinmeyen" @@ -1331,24 +1346,24 @@ msgstr "Bilinmeyen" #. * example: #. * "Fedora 25 (Workstation Edition); Build ID: xyz" or #. * "Ubuntu 16.04 LTS; Build ID: jki" -#: panels/info/cc-info-overview-panel.c:465 +#: panels/info/cc-info-overview-panel.c:464 #, c-format msgid "%s; Build ID: %s" msgstr "%s; İnşa Kimliği: %s" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:482 +#: panels/info/cc-info-overview-panel.c:481 #, c-format msgid "64-bit" msgstr "64-bit" #. translators: This is the type of architecture for the OS -#: panels/info/cc-info-overview-panel.c:485 +#: panels/info/cc-info-overview-panel.c:484 #, c-format msgid "32-bit" msgstr "32-bit" -#: panels/info/cc-info-overview-panel.c:775 +#: panels/info/cc-info-overview-panel.c:773 #, c-format msgid "Version %s" msgstr "Sürüm %s" @@ -1679,8 +1694,8 @@ msgstr "Başlatıcılar" msgid "Launch help browser" msgstr "Yardım tarayıcısını çalıştır" -#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:223 -#: shell/cc-window.c:761 shell/gnome-control-center.desktop.in.in:3 +#: panels/keyboard/01-launchers.xml.in:6 shell/cc-window.c:237 +#: shell/cc-window.c:773 shell/gnome-control-center.desktop.in.in:3 #: shell/window.ui:125 msgid "Settings" msgstr "Ayarlar" @@ -1789,7 +1804,7 @@ msgstr "Yüksek karşıtlık açık ya da kapalı" #: panels/keyboard/cc-keyboard-manager.c:506 #: panels/keyboard/cc-keyboard-manager.c:514 -#: panels/keyboard/cc-keyboard-manager.c:822 +#: panels/keyboard/cc-keyboard-manager.c:821 msgid "Custom Shortcuts" msgstr "Özel Kısayollar" @@ -1800,7 +1815,7 @@ msgstr "Özel Kısayollar" #. * The device has been disabled #: panels/keyboard/cc-keyboard-option.c:263 #: panels/keyboard/cc-keyboard-option.c:382 -#: panels/keyboard/keyboard-shortcuts.c:435 +#: panels/keyboard/keyboard-shortcuts.c:434 #: panels/keyboard/shortcut-editor.ui:96 panels/network/network-proxy.ui:123 #: panels/network/network-wifi.ui:782 panels/network/network-wifi.ui:1059 #: panels/user-accounts/um-fingerprint-dialog.c:211 @@ -2099,7 +2114,7 @@ msgid "Single click, secondary button" msgstr "Tek tıklama, ikincil düğme" #. add proxy to device list -#: panels/network/cc-network-panel.c:579 +#: panels/network/cc-network-panel.c:583 msgid "Network proxy" msgstr "Ağ Vekili" @@ -2107,23 +2122,23 @@ msgstr "Ağ Vekili" #. * window for vpn connections, it is also used to display #. * vpn connections in the device list. #. -#: panels/network/cc-network-panel.c:715 panels/network/net-vpn.c:192 -#: panels/network/net-vpn.c:321 +#: panels/network/cc-network-panel.c:719 panels/network/net-vpn.c:167 +#: panels/network/net-vpn.c:296 #, c-format msgid "%s VPN" msgstr "%s VPN" -#: panels/network/cc-network-panel.c:779 panels/network/wifi.ui:282 +#: panels/network/cc-network-panel.c:783 panels/network/wifi.ui:282 msgid "Oops, something has gone wrong. Please contact your software vendor." msgstr "Aahh, birşeyler ters gitti. Lütfen yazılım sağlayıcınıza başvurun." -#: panels/network/cc-network-panel.c:785 +#: panels/network/cc-network-panel.c:789 msgid "NetworkManager needs to be running." msgstr "NetworkManager’in çalışıyor olması gerekir." -#: panels/network/cc-wifi-panel.c:213 +#: panels/network/cc-wifi-panel.c:214 #: panels/network/gnome-wifi-panel.desktop.in.in:3 -#: panels/network/network-wifi.ui:1766 +#: panels/network/network-wifi.ui:1769 msgid "Wi-Fi" msgstr "Kablosuz" @@ -2266,7 +2281,7 @@ msgid "Remove VPN" msgstr "VPN’yi Kaldır" #: panels/network/connection-editor/ce-page-details.c:334 -#: panels/network/network-wifi.ui:1456 shell/cc-window.c:215 +#: panels/network/network-wifi.ui:1456 shell/cc-window.c:229 #: shell/panel-list.ui:103 msgid "Details" msgstr "Ayrıntılar" @@ -2401,7 +2416,7 @@ msgstr "Veri ücreti veya sınırı olan bağlantılar için uygundur." #: panels/network/connection-editor/ip6-page.ui:291 #: panels/network/net-proxy.c:58 panels/network/network-proxy.ui:103 #: panels/network/wireless-security/eap-method-peap.ui:22 -#: panels/privacy/cc-privacy-panel.c:217 +#: panels/privacy/cc-privacy-panel.c:218 msgid "Automatic" msgstr "Kendiliğinden" @@ -2598,9 +2613,9 @@ msgid "Select file to import" msgstr "İçe aktarılacak dosyayı seçin" #: panels/network/connection-editor/vpn-helpers.c:182 -#: panels/printers/pp-details-dialog.c:332 +#: panels/printers/pp-details-dialog.c:331 #: panels/sharing/cc-sharing-panel.c:385 -#: panels/user-accounts/um-photo-dialog.c:230 +#: panels/user-accounts/um-photo-dialog.c:231 msgid "_Open" msgstr "_Aç" @@ -3022,19 +3037,19 @@ msgctxt "Wi-Fi passkey" msgid "Password" msgstr "Parola" -#: panels/network/network-wifi.ui:1796 +#: panels/network/network-wifi.ui:1799 msgid "Turn Wi-Fi off" msgstr "Kablosuzu Kapat" -#: panels/network/network-wifi.ui:1828 +#: panels/network/network-wifi.ui:1831 msgid "_Connect to Hidden Network…" msgstr "Gizli Ağa _Bağlan…" -#: panels/network/network-wifi.ui:1838 +#: panels/network/network-wifi.ui:1841 msgid "_Turn On Wi-Fi Hotspot…" msgstr "Kablosuz Erişim Nok_tasını Aç…" -#: panels/network/network-wifi.ui:1848 +#: panels/network/network-wifi.ui:1851 msgid "_Known Wi-Fi Networks" msgstr "_Bilinen Wi-Fi Ağları" @@ -3343,23 +3358,23 @@ msgstr "Firmware eksik" msgid "Cable unplugged" msgstr "Kablo takılı değil" -#: panels/network/wireless-security/eap-method.c:57 +#: panels/network/wireless-security/eap-method.c:69 msgid "undefined error in 802.1X security (wpa-eap)" msgstr "802.1X güvenliğinde (wpa-eap) tanımlanmamış hata" -#: panels/network/wireless-security/eap-method.c:233 +#: panels/network/wireless-security/eap-method.c:245 msgid "no file selected" msgstr "hiçbir dosya seçilmedi" -#: panels/network/wireless-security/eap-method.c:264 +#: panels/network/wireless-security/eap-method.c:276 msgid "unspecified error validating eap-method file" msgstr "eap-method dosyası doğrulamada belirtilmemiş hata" -#: panels/network/wireless-security/eap-method.c:439 +#: panels/network/wireless-security/eap-method.c:451 msgid "DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12, *.key)" msgstr "DER, PEM, veya PKCS#12 özel anahtarları (*.der, *.pem, *.p12, *.key)" -#: panels/network/wireless-security/eap-method.c:442 +#: panels/network/wireless-security/eap-method.c:454 msgid "DER or PEM certificates (*.der, *.pem, *.crt, *.cer)" msgstr "DER veya PEM sertifikaları (*.der, *.pem, *.crt, *.cer)" @@ -3774,19 +3789,19 @@ msgstr "Diğer" #. translators: This is the title of the "Show Account" dialog. The #. * %s is the name of the provider. e.g., 'Google'. -#: panels/online-accounts/cc-online-accounts-panel.c:551 +#: panels/online-accounts/cc-online-accounts-panel.c:612 #, c-format msgid "%s Account" msgstr "%s Hesabı" -#: panels/online-accounts/cc-online-accounts-panel.c:843 +#: panels/online-accounts/cc-online-accounts-panel.c:904 msgid "Error removing account" msgstr "Hesap silinirken hata oluştu" #. Translators: The %s is the username (eg., debarshi.ray@gmail.com #. * or rishi). #. -#: panels/online-accounts/cc-online-accounts-panel.c:908 +#: panels/online-accounts/cc-online-accounts-panel.c:969 #, c-format msgid "<b>%s</b> removed" msgstr "<b>%s</b> kaldırıldı" @@ -3839,17 +3854,17 @@ msgstr "Hesap ekle" msgid "Remove Account" msgstr "Hesabı Kaldır" -#: panels/power/cc-power-panel.c:253 +#: panels/power/cc-power-panel.c:254 msgid "Unknown time" msgstr "Bilinmeyen süre" -#: panels/power/cc-power-panel.c:259 +#: panels/power/cc-power-panel.c:260 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i dakika" -#: panels/power/cc-power-panel.c:271 +#: panels/power/cc-power-panel.c:272 #, c-format msgid "%i hour" msgid_plural "%i hours" @@ -3857,254 +3872,292 @@ msgstr[0] "%i saat" #. TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" #. * Swap order with "%2$s %2$i %1$s %1$i if needed -#: panels/power/cc-power-panel.c:279 +#: panels/power/cc-power-panel.c:280 #, c-format msgid "%i %s %i %s" msgstr "%i %s %i %s" -#: panels/power/cc-power-panel.c:280 +#: panels/power/cc-power-panel.c:281 msgid "hour" msgid_plural "hours" msgstr[0] "saat" -#: panels/power/cc-power-panel.c:281 +#: panels/power/cc-power-panel.c:282 msgid "minute" msgid_plural "minutes" msgstr[0] "dakika" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:300 +#: panels/power/cc-power-panel.c:301 #, c-format msgid "%s until fully charged" msgstr "Tam dolana kadar %s" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:307 +#: panels/power/cc-power-panel.c:308 #, c-format msgid "Caution: %s remaining" msgstr "Dikkat: %s kaldı" #. TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" -#: panels/power/cc-power-panel.c:312 +#: panels/power/cc-power-panel.c:313 #, c-format msgid "%s remaining" msgstr "%s kaldı" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:317 panels/power/cc-power-panel.c:345 +#: panels/power/cc-power-panel.c:318 panels/power/cc-power-panel.c:346 msgid "Fully charged" msgstr "Tamamen dolu" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:321 panels/power/cc-power-panel.c:349 +#: panels/power/cc-power-panel.c:322 panels/power/cc-power-panel.c:350 msgid "Empty" msgstr "Boş" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:336 +#: panels/power/cc-power-panel.c:337 msgid "Charging" msgstr "Şarj oluyor" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:341 +#: panels/power/cc-power-panel.c:342 msgid "Discharging" msgstr "Boşalıyor" -#: panels/power/cc-power-panel.c:464 +#: panels/power/cc-power-panel.c:465 msgctxt "Battery name" msgid "Main" msgstr "Birincil" -#: panels/power/cc-power-panel.c:466 +#: panels/power/cc-power-panel.c:467 msgctxt "Battery name" msgid "Extra" msgstr "Ek" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:537 +#: panels/power/cc-power-panel.c:538 msgid "Wireless mouse" msgstr "Kablosuz fare" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:540 +#: panels/power/cc-power-panel.c:541 msgid "Wireless keyboard" msgstr "Kablosuz klavye" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:543 +#: panels/power/cc-power-panel.c:544 msgid "Uninterruptible power supply" msgstr "Kesintisiz güç kaynağı" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:546 +#: panels/power/cc-power-panel.c:547 msgid "Personal digital assistant" msgstr "Kişisel sayısal yardımcı (PDA)" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:549 +#: panels/power/cc-power-panel.c:550 msgid "Cellphone" msgstr "Cep telefonu" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:552 +#: panels/power/cc-power-panel.c:553 msgid "Media player" msgstr "Ortam oynatıcısı" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:555 panels/wacom/cc-wacom-panel.c:793 +#: panels/power/cc-power-panel.c:556 panels/wacom/cc-wacom-panel.c:793 msgid "Tablet" msgstr "Tablet" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:558 +#: panels/power/cc-power-panel.c:559 msgid "Computer" msgstr "Bilgisayar" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:561 +#: panels/power/cc-power-panel.c:562 msgid "Gaming input device" msgstr "Oyun girdi aygıtı" #. TRANSLATORS: secondary battery, misc -#: panels/power/cc-power-panel.c:564 panels/power/cc-power-panel.c:804 -#: panels/power/cc-power-panel.c:2377 +#: panels/power/cc-power-panel.c:565 panels/power/cc-power-panel.c:829 +#: panels/power/cc-power-panel.c:2483 msgid "Battery" msgstr "Pil" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:618 +#: panels/power/cc-power-panel.c:632 msgctxt "Battery power" msgid "Charging" msgstr "Doluyor" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:625 +#: panels/power/cc-power-panel.c:639 msgctxt "Battery power" msgid "Caution" msgstr "Dikkat" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:630 +#: panels/power/cc-power-panel.c:644 msgctxt "Battery power" msgid "Low" msgstr "Düşük" #. TRANSLATORS: secondary battery -#: panels/power/cc-power-panel.c:635 +#: panels/power/cc-power-panel.c:649 msgctxt "Battery power" msgid "Good" msgstr "İyi" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:640 +#: panels/power/cc-power-panel.c:654 msgctxt "Battery power" msgid "Fully charged" msgstr "Tamamen dolu" #. TRANSLATORS: primary battery -#: panels/power/cc-power-panel.c:644 +#: panels/power/cc-power-panel.c:658 msgctxt "Battery power" msgid "Empty" msgstr "Boş" -#: panels/power/cc-power-panel.c:802 +#: panels/power/cc-power-panel.c:827 msgid "Batteries" msgstr "Piller" -#: panels/power/cc-power-panel.c:1239 +#: panels/power/cc-power-panel.c:1206 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d saat" + +#: panels/power/cc-power-panel.c:1208 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d dakika" + +#: panels/power/cc-power-panel.c:1211 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "%d saniye" + +#. 5 hours 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1217 +#, c-format +msgctxt "time" +msgid "%s %s %s" +msgstr "%s %s %s" + +#. 2 minutes 12 seconds +#: panels/power/cc-power-panel.c:1220 +#, c-format +msgctxt "time" +msgid "%s %s" +msgstr "%s %s" + +#. 0 seconds +#: panels/power/cc-power-panel.c:1226 +msgid "0 seconds" +msgstr "0 saniye" + +#: panels/power/cc-power-panel.c:1328 msgid "When _idle" msgstr "Bo_şta olduğunda" -#: panels/power/cc-power-panel.c:1693 +#: panels/power/cc-power-panel.c:1793 msgid "Power Saving" msgstr "Güç Tasarrufu" -#: panels/power/cc-power-panel.c:1724 +#: panels/power/cc-power-panel.c:1824 msgid "_Screen brightness" msgstr "_Ekran parlaklığı" -#: panels/power/cc-power-panel.c:1743 +#: panels/power/cc-power-panel.c:1843 msgid "Automatic brightness" msgstr "Kendiliğinden parlaklık" -#: panels/power/cc-power-panel.c:1763 +#: panels/power/cc-power-panel.c:1863 msgid "_Keyboard brightness" msgstr "_Klavye parlaklığı" -#: panels/power/cc-power-panel.c:1773 +#: panels/power/cc-power-panel.c:1873 msgid "_Dim screen when inactive" msgstr "Etkin olunma_dığında ekranı karart" -#: panels/power/cc-power-panel.c:1798 +#: panels/power/cc-power-panel.c:1898 msgid "_Blank screen" msgstr "_Boş Ekran" -#: panels/power/cc-power-panel.c:1835 +#: panels/power/cc-power-panel.c:1935 msgid "_Wi-Fi" msgstr "_Wi-Fi" -#: panels/power/cc-power-panel.c:1840 +#: panels/power/cc-power-panel.c:1940 msgid "Turn off Wi-Fi to save power." msgstr "Enerji tasarrufu için Kablosuz Ağı kapatın." -#: panels/power/cc-power-panel.c:1865 +#: panels/power/cc-power-panel.c:1965 msgid "_Mobile broadband" msgstr "_Mobil Genişbant" -#: panels/power/cc-power-panel.c:1870 +#: panels/power/cc-power-panel.c:1970 msgid "Turn off mobile broadband (3G, 4G, LTE, etc.) to save power." msgstr "Enerji tasarrufu için mobil genişbantı (3G, 4G, LTE, vb.) kapat." -#: panels/power/cc-power-panel.c:1923 +#: panels/power/cc-power-panel.c:2029 msgid "_Bluetooth" msgstr "_Bluetooth" -#: panels/power/cc-power-panel.c:1928 +#: panels/power/cc-power-panel.c:2034 msgid "Turn off Bluetooth to save power." msgstr "Enerji tasarrufu için Bluetoothʼu kapatın." -#: panels/power/cc-power-panel.c:1987 +#: panels/power/cc-power-panel.c:2093 msgid "When on battery power" msgstr "Pille çalışırken" -#: panels/power/cc-power-panel.c:1989 +#: panels/power/cc-power-panel.c:2095 msgid "When plugged in" msgstr "Fişe takıldığında" -#: panels/power/cc-power-panel.c:2084 +#: panels/power/cc-power-panel.c:2190 msgid "Suspend" msgstr "Askıya al" -#: panels/power/cc-power-panel.c:2085 +#: panels/power/cc-power-panel.c:2191 msgid "Power Off" msgstr "Kapat" -#: panels/power/cc-power-panel.c:2086 +#: panels/power/cc-power-panel.c:2192 msgid "Hibernate" msgstr "Derin uyku" -#: panels/power/cc-power-panel.c:2087 +#: panels/power/cc-power-panel.c:2193 msgid "Nothing" msgstr "Hiçbir şey" #. Frame header -#: panels/power/cc-power-panel.c:2201 +#: panels/power/cc-power-panel.c:2307 msgid "Suspend & Power Button" msgstr "Askıya Alma ve Güç Düğmesi" -#: panels/power/cc-power-panel.c:2240 +#: panels/power/cc-power-panel.c:2346 msgid "_Automatic suspend" msgstr "Kendiliğinden _askıya al" -#: panels/power/cc-power-panel.c:2241 +#: panels/power/cc-power-panel.c:2347 msgid "Automatic suspend" msgstr "Kendiliğinden askıya al" -#: panels/power/cc-power-panel.c:2308 +#: panels/power/cc-power-panel.c:2414 msgid "_When the Power Button is pressed" msgstr "Gü_ç düğmesine basıldığında" -#: panels/power/cc-power-panel.c:2427 shell/cc-window.c:219 +#: panels/power/cc-power-panel.c:2533 panels/thunderbolt/cc-bolt-panel.ui:466 +#: panels/thunderbolt/cc-bolt-panel.ui:525 shell/cc-window.c:233 #: shell/panel-list.ui:45 msgid "Devices" msgstr "Aygıtlar" @@ -4237,18 +4290,18 @@ msgid "Authentication Required" msgstr "Kimlik doğrulaması gerekli" #. Translators: %s is the printer name -#: panels/printers/cc-printers-panel.c:791 +#: panels/printers/cc-printers-panel.c:809 #, c-format msgid "Printer “%s” has been deleted" msgstr "“%s” yazıcısı silindi" #. Translators: Addition of the new printer failed. -#: panels/printers/cc-printers-panel.c:1036 +#: panels/printers/cc-printers-panel.c:1054 msgid "Failed to add new printer." msgstr "Yeni yazıcı eklenemedi." #. Translators: The XML file containing user interface can not be loaded -#: panels/printers/cc-printers-panel.c:1371 +#: panels/printers/cc-printers-panel.c:1391 #, c-format msgid "Could not load ui: %s" msgstr "Arayüz yüklenemedi: %s" @@ -4301,7 +4354,6 @@ msgstr "Yazıcı;Kuyruk;Yazdır;Kâğıt;Mürekkep;Toner;" #. Translators: This is a windows domain used with SMB protocol. #: panels/printers/jobs-dialog.ui:44 -#| msgid "_Domain" msgid "Domain" msgstr "Etki Alanı" @@ -4317,7 +4369,6 @@ msgstr "Tümünü Temizle" #. Translators: This button pop up authentication dialog for print jobs which need credentials. #: panels/printers/jobs-dialog.ui:225 -#| msgid "Authenticate" msgid "_Authenticate" msgstr "Kimlik doğrul_ama" @@ -4363,21 +4414,21 @@ msgid "Test Page" msgstr "Deneme Sayfası" #. Translators: This is the title of the dialog. %s is the printer name. -#: panels/printers/pp-details-dialog.c:135 -#: panels/printers/pp-details-dialog.c:435 +#: panels/printers/pp-details-dialog.c:134 +#: panels/printers/pp-details-dialog.c:434 #, c-format msgid "%s Details" msgstr "%s Ayrıntıları" -#: panels/printers/pp-details-dialog.c:184 +#: panels/printers/pp-details-dialog.c:183 msgid "No suitable driver found" msgstr "Uygun sürücü bulunamadı" -#: panels/printers/pp-details-dialog.c:328 +#: panels/printers/pp-details-dialog.c:327 msgid "Select PPD File" msgstr "PPD Dosyası Seç" -#: panels/printers/pp-details-dialog.c:337 +#: panels/printers/pp-details-dialog.c:336 msgid "" "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." "PPD.GZ)" @@ -4390,7 +4441,7 @@ msgid "Select Printer Driver" msgstr "Yazıcı Sürücüsü Seçin" #: panels/printers/ppd-selection-dialog.ui:40 -#: panels/user-accounts/um-photo-dialog.c:104 +#: panels/user-accounts/um-photo-dialog.c:105 msgid "Select" msgstr "Seç" @@ -4447,73 +4498,70 @@ msgid "Reverse portrait" msgstr "Ters dikey" #. Translators: Job's state (job is waiting to be printed) -#: panels/printers/pp-jobs-dialog.c:243 +#: panels/printers/pp-jobs-dialog.c:234 msgctxt "print job" msgid "Pending" msgstr "Beklemede" #. Translators: Job's state (job is held for printing) -#: panels/printers/pp-jobs-dialog.c:249 +#: panels/printers/pp-jobs-dialog.c:240 msgctxt "print job" msgid "Paused" msgstr "Duraklatıldı" #. Translators: Job's state (job needs authentication to proceed further) -#: panels/printers/pp-jobs-dialog.c:254 -#| msgid "Authentication required" +#: panels/printers/pp-jobs-dialog.c:245 msgctxt "print job" msgid "Authentication required" msgstr "Kimlik doğrulaması gerekli" #. Translators: Job's state (job is currently printing) -#: panels/printers/pp-jobs-dialog.c:259 +#: panels/printers/pp-jobs-dialog.c:250 msgctxt "print job" msgid "Processing" msgstr "İşleniyor" #. Translators: Job's state (job has been stopped) -#: panels/printers/pp-jobs-dialog.c:263 +#: panels/printers/pp-jobs-dialog.c:254 msgctxt "print job" msgid "Stopped" msgstr "Durduruldu" #. Translators: Job's state (job has been canceled) -#: panels/printers/pp-jobs-dialog.c:267 +#: panels/printers/pp-jobs-dialog.c:258 msgctxt "print job" msgid "Canceled" msgstr "İptal edildi" #. Translators: Job's state (job has aborted due to error) -#: panels/printers/pp-jobs-dialog.c:271 +#: panels/printers/pp-jobs-dialog.c:262 msgctxt "print job" msgid "Aborted" msgstr "Hata nedeniyle iptal edildi" #. Translators: Job's state (job has completed successfully) -#: panels/printers/pp-jobs-dialog.c:275 +#: panels/printers/pp-jobs-dialog.c:266 msgctxt "print job" msgid "Completed" msgstr "Tamamlandı" #. Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. -#: panels/printers/pp-jobs-dialog.c:399 +#: panels/printers/pp-jobs-dialog.c:390 #, c-format -#| msgid "Server requires authentication" msgid "%u Job Requires Authentication" msgid_plural "%u Jobs Require Authentication" msgstr[0] "%u Görev Kimlik Doğrulaması Gerektiriyor" #. Translators: This is the printer name for which we are showing the active jobs -#: panels/printers/pp-jobs-dialog.c:617 +#: panels/printers/pp-jobs-dialog.c:620 #, c-format msgctxt "Printer jobs dialog title" msgid "%s — Active Jobs" msgstr "%s — Etkin Görevler" #. Translators: The printer needs authentication info to print. -#: panels/printers/pp-jobs-dialog.c:622 +#: panels/printers/pp-jobs-dialog.c:625 #, c-format -#| msgid "Enter username and password to view printers on %s." msgid "Enter credentials to print from %s." msgstr "%s üzerinden yazdırmak için kimlik bilgilerini girin." @@ -4877,25 +4925,25 @@ msgstr "" "Üzgünüm! Sistem yazdırma hizmeti\n" "kullanılamıyor." -#: panels/privacy/cc-privacy-panel.c:387 panels/privacy/privacy.ui:280 +#: panels/privacy/cc-privacy-panel.c:388 panels/privacy/privacy.ui:280 msgid "Screen Lock" msgstr "Ekran Kilidi" -#: panels/privacy/cc-privacy-panel.c:438 +#: panels/privacy/cc-privacy-panel.c:439 msgid "In use" msgstr "Kullanımda" -#: panels/privacy/cc-privacy-panel.c:443 +#: panels/privacy/cc-privacy-panel.c:444 msgctxt "Location services status" msgid "On" msgstr "Açık" -#: panels/privacy/cc-privacy-panel.c:444 +#: panels/privacy/cc-privacy-panel.c:445 msgctxt "Location services status" msgid "Off" msgstr "Kapalı" -#: panels/privacy/cc-privacy-panel.c:823 panels/privacy/privacy.ui:745 +#: panels/privacy/cc-privacy-panel.c:825 panels/privacy/privacy.ui:745 msgid "Location Services" msgstr "Konum Hizmetleri" @@ -5157,11 +5205,11 @@ msgctxt "Input Source" msgid "Other" msgstr "Diğer" -#: panels/region/cc-region-panel.c:881 +#: panels/region/cc-region-panel.c:882 msgid "No input source selected" msgstr "Girdi kaynağı seçilmedi" -#: panels/region/cc-region-panel.c:1773 +#: panels/region/cc-region-panel.c:1774 msgid "Login _Screen" msgstr "Oturum A_çma Ekranı" @@ -5386,7 +5434,7 @@ msgid "Preferences" msgstr "Tercihler" #. Label -#: panels/sharing/cc-sharing-networks.c:305 +#: panels/sharing/cc-sharing-networks.c:307 msgid "No networks selected for sharing" msgstr "Paylaşımı için ağ seçilmedi" @@ -5713,7 +5761,7 @@ msgstr "Ses Etkileri" #: panels/sound/gvc-mixer-dialog.c:1754 msgid "_Alert volume:" -msgstr "Uy_arı ses düzeyi: " +msgstr "Uy_arı ses düzeyi:" #: panels/sound/gvc-mixer-dialog.c:1775 msgid "No application is currently playing or recording audio." @@ -5764,34 +5812,203 @@ msgstr "Subwoofer" msgid "Custom" msgstr "Özel" +#: panels/thunderbolt/cc-bolt-device-dialog.c:86 +#: panels/thunderbolt/cc-bolt-device-entry.c:119 +msgctxt "Thunderbolt Device Status" +msgid "Disconnected" +msgstr "Bağlantısı Kesilmiş" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:89 +#: panels/thunderbolt/cc-bolt-device-entry.c:122 +msgctxt "Thunderbolt Device Status" +msgid "Connecting" +msgstr "Bağlanıyor" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:92 +#: panels/thunderbolt/cc-bolt-device-entry.c:126 +#: panels/thunderbolt/cc-bolt-device-entry.c:138 +msgctxt "Thunderbolt Device Status" +msgid "Connected" +msgstr "Bağlı" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:95 +msgctxt "Thunderbolt Device Status" +msgid "Authorization Error" +msgstr "Yetkilendirme Hatası" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:98 +#: panels/thunderbolt/cc-bolt-device-entry.c:132 +msgctxt "Thunderbolt Device Status" +msgid "Authorizing" +msgstr "Yetkilendiriliyor" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:105 +msgctxt "Thunderbolt Device Status" +msgid "Reduced Functionality" +msgstr "Azaltılmış İşlev" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:107 +msgctxt "Thunderbolt Device Status" +msgid "Connected & Authorized" +msgstr "Bağlı ve Yetkilendirilmiş" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:113 +#: panels/thunderbolt/cc-bolt-device-entry.c:146 +msgctxt "Thunderbolt Device Status" +msgid "Unknown" +msgstr "Bilinmeyen" + +#. Translators: The time point the device was authorized. +#: panels/thunderbolt/cc-bolt-device-dialog.c:169 +msgid "Authorized at:" +msgstr "Yetkilendirilmiş:" + +#. Translators: The time point the device was connected. +#: panels/thunderbolt/cc-bolt-device-dialog.c:175 +msgid "Connected at:" +msgstr "Bağlı:" + +#. Translators: The time point the device was enrolled, +#. * i.e. authorized and stored in the device database. +#: panels/thunderbolt/cc-bolt-device-dialog.c:182 +msgid "Enrolled at:" +msgstr "Kaydedilmiş:" + +#: panels/thunderbolt/cc-bolt-device-dialog.c:250 +msgid "Failed to authorize device: " +msgstr "Aygıt yetkilendirilemedi: " + +#: panels/thunderbolt/cc-bolt-device-dialog.c:327 +msgid "Failed to forget device: " +msgstr "Aygıt unutulamadı: " + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:109 +msgid "Name:" +msgstr "Ad:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:141 +msgid "Status:" +msgstr "Durum:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:174 +msgid "UUID:" +msgstr "UUID:" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:280 +msgid "Authorize and Connect" +msgstr "Yetkilendir ve Bağla" + +#: panels/thunderbolt/cc-bolt-device-dialog.ui:303 +msgid "Forget Device" +msgstr "Aygıtı Unut" + +#: panels/thunderbolt/cc-bolt-device-entry.c:129 +msgctxt "Thunderbolt Device Status" +msgid "Error" +msgstr "Hata" + +#: panels/thunderbolt/cc-bolt-device-entry.c:140 +msgctxt "Thunderbolt Device Status" +msgid "Authorized" +msgstr "Yetkilendirilmiş" + +#: panels/thunderbolt/cc-bolt-panel.c:175 +msgid "" +"The Thunderbolt subsystem (boltd) is not installed or not set up properly." +msgstr "" +"Thunderbolt altsistemi (boltd) yüklenmemiş veya doğru şekilde ayarlanmamış." + +#: panels/thunderbolt/cc-bolt-panel.c:460 +msgid "" +"Thunderbolt could not be detected.\n" +"Either the system lacks Thunderbolt support, it has been disabled in the " +"BIOS or is set to an unsupported security level in the BIOS." +msgstr "" +"Thunderbolt algılanamadı.\n" +"Sistemin Thunderbolt desteği yok, BIOS’ta devre dışı bırakılmış veya BIOS’ta " +"desteklenmeyen bir güvenlik düzeyine ayarlanmış." + +#: panels/thunderbolt/cc-bolt-panel.c:504 +msgid "Thunderbolt support has been disabled in the BIOS." +msgstr "Thunderbolt desteği BIOS’ta devre dışı bırakılmış." + +#: panels/thunderbolt/cc-bolt-panel.c:613 +#, c-format +msgid "Error switching direct mode: %s" +msgstr "Doğrudan kipe geçilirken hata: %s" + +#: panels/thunderbolt/cc-bolt-panel.ui:143 +msgid "No Thunderbolt support" +msgstr "Thunderbolt desteği yok" + +#: panels/thunderbolt/cc-bolt-panel.ui:246 +msgid "Direct Access" +msgstr "Doğrudan Erişim" + +#: panels/thunderbolt/cc-bolt-panel.ui:269 +msgid "Allow direct access to devices such as docks and external GPUs." +msgstr "" +"Bağlantı istasyonları ve haricî grafik işlemciler gibi aygıtlara doğrudan " +"erişim tanı." + +#: panels/thunderbolt/cc-bolt-panel.ui:289 +msgid "Only USB and Display Port devices can attach." +msgstr "Yalnızca USB ve Display Port aygıtları bağlanabilir." + +#: panels/thunderbolt/cc-bolt-panel.ui:397 +msgid "Pending Devices" +msgstr "Bekleyen Aygıtlar" + +#: panels/thunderbolt/cc-bolt-panel.ui:535 +msgid "No devices attached" +msgstr "Aygıt bağlanmamış" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:3 +msgid "Thunderbolt" +msgstr "Thunderbolt" + +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:4 +msgid "Manage Thunderbolt devices" +msgstr "Thunderbolt aygıtlarını yönet" + +#. Translators: Do NOT translate or transliterate this text (this is an icon file name)! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:7 +msgid "thunderbolt" +msgstr "thunderbolt" + +#. Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in:19 +msgid "Thunderbolt;" +msgstr "Thunderbolt;" + #. translators: the labels will read: #. * Cursor Size: Default -#: panels/universal-access/cc-ua-panel.c:353 +#: panels/universal-access/cc-ua-panel.c:354 msgctxt "cursor size" msgid "Default" msgstr "Öntanımlı" -#: panels/universal-access/cc-ua-panel.c:356 +#: panels/universal-access/cc-ua-panel.c:357 msgctxt "cursor size" msgid "Medium" msgstr "Orta" -#: panels/universal-access/cc-ua-panel.c:359 +#: panels/universal-access/cc-ua-panel.c:360 msgctxt "cursor size" msgid "Large" msgstr "Büyük" -#: panels/universal-access/cc-ua-panel.c:362 +#: panels/universal-access/cc-ua-panel.c:363 msgctxt "cursor size" msgid "Larger" msgstr "Çok Büyük" -#: panels/universal-access/cc-ua-panel.c:365 +#: panels/universal-access/cc-ua-panel.c:366 msgctxt "cursor size" msgid "Largest" msgstr "En Büyük" -#: panels/universal-access/cc-ua-panel.c:369 +#: panels/universal-access/cc-ua-panel.c:370 #, c-format msgid "%d pixel" msgid_plural "%d pixels" @@ -5799,7 +6016,7 @@ msgstr[0] "%d piksel" #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:4 msgid "Make it easier to see, hear, type, point and click" -msgstr "Görme, duyma, yazma, işaretleme ve tıklamayı kolaylaştır." +msgstr "Görme, duyma, yazma, işaretleme ve tıklamayı kolaylaştır" #. Translators: Do NOT translate or transliterate this text (this is an icon file name)! #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:7 @@ -5837,7 +6054,7 @@ msgid "C_ursor Size" msgstr "İ_mleç Boyutu" #: panels/universal-access/uap.ui:316 -#: panels/universal-access/zoom-options.ui:98 +#: panels/universal-access/zoom-options.ui:99 msgid "_Zoom" msgstr "_Yaklaştır" @@ -5902,7 +6119,7 @@ msgid "" "Cursor size can be combined with zoom to make it easier to see the cursor." msgstr "" "İmleç boyutu, imleci görmeyi kolaylaştırması için yakınlaştırma ile " -"birleştirilebilir. " +"birleştirilebilir." #: panels/universal-access/uap.ui:1105 msgid "Screen Reader" @@ -6097,7 +6314,7 @@ msgstr "_Üzerindeyken Tıklama" #: panels/universal-access/uap.ui:2668 msgid "Trigger a click when the pointer hovers" -msgstr "Belirteç nesne üstüne geldiğinde tıklama yap" +msgstr "Belirteç nesne üstüne geldiğinde tıkla" #: panels/universal-access/uap.ui:2701 msgid "D_elay:" @@ -6127,27 +6344,27 @@ msgctxt "dwell click threshold" msgid "Large" msgstr "Büyük" -#: panels/universal-access/zoom-options.c:333 +#: panels/universal-access/zoom-options.c:338 msgctxt "Distance" msgid "Short" msgstr "Kısa" -#: panels/universal-access/zoom-options.c:334 +#: panels/universal-access/zoom-options.c:339 msgctxt "Distance" msgid "¼ Screen" msgstr "¼ Ekran" -#: panels/universal-access/zoom-options.c:335 +#: panels/universal-access/zoom-options.c:340 msgctxt "Distance" msgid "½ Screen" msgstr "½ Ekran" -#: panels/universal-access/zoom-options.c:336 +#: panels/universal-access/zoom-options.c:341 msgctxt "Distance" msgid "¾ Screen" msgstr "¾ Ekran" -#: panels/universal-access/zoom-options.c:337 +#: panels/universal-access/zoom-options.c:342 msgctxt "Distance" msgid "Long" msgstr "Uzun" @@ -6172,134 +6389,134 @@ msgstr "Sol Yarı" msgid "Right Half" msgstr "Sağ Yarı" -#: panels/universal-access/zoom-options.ui:77 +#: panels/universal-access/zoom-options.ui:78 msgid "Zoom Options" msgstr "Yakınlaştırma Seçenekleri" -#: panels/universal-access/zoom-options.ui:186 +#: panels/universal-access/zoom-options.ui:188 msgid "_Magnification:" msgstr "Büyüt_me:" -#: panels/universal-access/zoom-options.ui:250 +#: panels/universal-access/zoom-options.ui:252 msgid "_Follow mouse cursor" msgstr "_Fare imlecini takip et" -#: panels/universal-access/zoom-options.ui:270 +#: panels/universal-access/zoom-options.ui:272 msgid "_Screen part:" msgstr "_Ekrandan bölüm:" -#: panels/universal-access/zoom-options.ui:332 +#: panels/universal-access/zoom-options.ui:334 msgid "Magnifier _extends outside of screen" msgstr "Büyüt_eç ekranın dışına taşar" -#: panels/universal-access/zoom-options.ui:351 +#: panels/universal-access/zoom-options.ui:353 msgid "_Keep magnifier cursor centered" msgstr "B_üyüteç imlecini ortalı tut" -#: panels/universal-access/zoom-options.ui:370 +#: panels/universal-access/zoom-options.ui:372 msgid "Magnifier cursor _pushes contents around" msgstr "Büyüteç imleci çevresindeki içeriği _iter" -#: panels/universal-access/zoom-options.ui:389 +#: panels/universal-access/zoom-options.ui:391 msgid "Magnifier cursor moves with _contents" msgstr "Büyüteç imleci i_çerik ile birlikte hareket eder" -#: panels/universal-access/zoom-options.ui:423 +#: panels/universal-access/zoom-options.ui:425 msgid "Magnifier Position:" msgstr "Büyüteç Konumu:" -#: panels/universal-access/zoom-options.ui:444 +#: panels/universal-access/zoom-options.ui:446 msgid "Magnifier" msgstr "Büyüteç" -#: panels/universal-access/zoom-options.ui:490 +#: panels/universal-access/zoom-options.ui:493 msgid "_Thickness:" msgstr "_Kalınlık:" -#: panels/universal-access/zoom-options.ui:516 +#: panels/universal-access/zoom-options.ui:519 msgctxt "universal access, thickness" msgid "Thin" msgstr "İnce" -#: panels/universal-access/zoom-options.ui:548 +#: panels/universal-access/zoom-options.ui:551 msgctxt "universal access, thickness" msgid "Thick" msgstr "Kalın" -#: panels/universal-access/zoom-options.ui:574 +#: panels/universal-access/zoom-options.ui:577 msgid "_Length:" msgstr "Uzun_luk:" #. The color of the accessibility crosshair -#: panels/universal-access/zoom-options.ui:626 +#: panels/universal-access/zoom-options.ui:629 msgid "Co_lor:" msgstr "Re_nk:" -#: panels/universal-access/zoom-options.ui:690 +#: panels/universal-access/zoom-options.ui:693 msgid "_Crosshairs:" msgstr "_Referans Noktaları:" -#: panels/universal-access/zoom-options.ui:741 +#: panels/universal-access/zoom-options.ui:744 msgid "_Overlaps mouse cursor" msgstr "Fare imleci ile _örtüşür" -#: panels/universal-access/zoom-options.ui:779 +#: panels/universal-access/zoom-options.ui:782 msgid "Crosshairs" msgstr "Çarpılar" -#: panels/universal-access/zoom-options.ui:827 +#: panels/universal-access/zoom-options.ui:831 msgid "_White on black:" msgstr "_Siyah üzerine beyaz:" -#: panels/universal-access/zoom-options.ui:850 +#: panels/universal-access/zoom-options.ui:854 msgid "_Brightness:" msgstr "_Parlaklık:" -#: panels/universal-access/zoom-options.ui:874 +#: panels/universal-access/zoom-options.ui:878 msgid "_Contrast:" msgstr "_Karşıtlık:" #. The contrast scale goes from Color to None (grayscale) -#: panels/universal-access/zoom-options.ui:897 +#: panels/universal-access/zoom-options.ui:901 msgctxt "universal access, contrast" msgid "Co_lor" msgstr "R_enk" -#: panels/universal-access/zoom-options.ui:925 +#: panels/universal-access/zoom-options.ui:929 msgctxt "universal access, color" msgid "None" msgstr "Hiçbiri" -#: panels/universal-access/zoom-options.ui:957 +#: panels/universal-access/zoom-options.ui:961 msgctxt "universal access, color" msgid "Full" msgstr "Tam" -#: panels/universal-access/zoom-options.ui:1023 +#: panels/universal-access/zoom-options.ui:1027 msgctxt "universal access, brightness" msgid "Low" msgstr "Düşük" -#: panels/universal-access/zoom-options.ui:1056 +#: panels/universal-access/zoom-options.ui:1060 msgctxt "universal access, brightness" msgid "High" msgstr "Yüksek" -#: panels/universal-access/zoom-options.ui:1087 +#: panels/universal-access/zoom-options.ui:1091 msgctxt "universal access, contrast" msgid "Low" msgstr "Düşük" -#: panels/universal-access/zoom-options.ui:1120 +#: panels/universal-access/zoom-options.ui:1124 msgctxt "universal access, contrast" msgid "High" msgstr "Yüksek" -#: panels/universal-access/zoom-options.ui:1156 +#: panels/universal-access/zoom-options.ui:1160 msgid "Color Effects:" msgstr "Renk Etkileri:" -#: panels/universal-access/zoom-options.ui:1181 +#: panels/universal-access/zoom-options.ui:1185 msgid "Color Effects" msgstr "Renk Etkileri" @@ -6715,29 +6932,29 @@ msgstr "Bilinmeyen hata" msgid "Should match the web address of your login provider." msgstr "Hesap sağlayıcınızın web adresi ile aynı olmalıdır." -#: panels/user-accounts/um-account-dialog.c:229 +#: panels/user-accounts/um-account-dialog.c:228 msgid "Failed to add account" msgstr "Hesap eklenemedi" -#: panels/user-accounts/um-account-dialog.c:462 +#: panels/user-accounts/um-account-dialog.c:461 msgid "Passwords do not match." -msgstr "Parolalar uyuşmuyor" +msgstr "Parolalar uyuşmuyor." -#: panels/user-accounts/um-account-dialog.c:717 -#: panels/user-accounts/um-account-dialog.c:763 -#: panels/user-accounts/um-account-dialog.c:784 +#: panels/user-accounts/um-account-dialog.c:716 +#: panels/user-accounts/um-account-dialog.c:762 +#: panels/user-accounts/um-account-dialog.c:783 msgid "Failed to register account" msgstr "Hesap kaydedilemedi" -#: panels/user-accounts/um-account-dialog.c:907 +#: panels/user-accounts/um-account-dialog.c:906 msgid "No supported way to authenticate with this domain" msgstr "Bu alan adıyla kimlik doğrulama yapılamaz" -#: panels/user-accounts/um-account-dialog.c:980 +#: panels/user-accounts/um-account-dialog.c:979 msgid "Failed to join domain" msgstr "Etki alanına katılma başarısız" -#: panels/user-accounts/um-account-dialog.c:1041 +#: panels/user-accounts/um-account-dialog.c:1040 msgid "" "That login name didn’t work.\n" "Please try again." @@ -6745,7 +6962,7 @@ msgstr "" "Oturum açma adı işe yaramadı.\n" "Lütfen yeniden deneyin." -#: panels/user-accounts/um-account-dialog.c:1048 +#: panels/user-accounts/um-account-dialog.c:1047 msgid "" "That login password didn’t work.\n" "Please try again." @@ -6753,11 +6970,11 @@ msgstr "" "Oturum açma parolası işe yaramadı.\n" "Lütfen yeniden deneyin." -#: panels/user-accounts/um-account-dialog.c:1056 +#: panels/user-accounts/um-account-dialog.c:1055 msgid "Failed to log into domain" msgstr "Etki alanına girilemedi" -#: panels/user-accounts/um-account-dialog.c:1114 +#: panels/user-accounts/um-account-dialog.c:1113 msgid "Unable to find the domain. Maybe you misspelled it?" msgstr "Etki alanı bulunamadı. Belki yanlış yazmışsınızdır?" @@ -6891,7 +7108,7 @@ msgstr "%s — %s" #. Translators: This is a time format string in the style of "22:58". #. It indicates a login time which follows a date. #: panels/user-accounts/um-history-dialog.c:177 -#: panels/user-accounts/um-user-panel.c:767 +#: panels/user-accounts/um-user-panel.c:766 msgctxt "login date-time" msgid "%k:%M" msgstr "%k:%M" @@ -6899,7 +7116,7 @@ msgstr "%k:%M" #. Translators: This indicates a login date-time. #. The first %s is a date, and the second %s a time. #: panels/user-accounts/um-history-dialog.c:180 -#: panels/user-accounts/um-user-panel.c:771 +#: panels/user-accounts/um-user-panel.c:770 #, c-format msgctxt "login date-time" msgid "%s, %s" @@ -6922,7 +7139,7 @@ msgstr "%s — Hesap Etkinliği" #: panels/user-accounts/um-password-dialog.c:144 msgid "Please choose another password." -msgstr "Lütfen farklı bir parola seçin" +msgstr "Lütfen başka bir parola seçin." #: panels/user-accounts/um-password-dialog.c:153 msgid "Please type your current password again." @@ -6936,70 +7153,69 @@ msgstr "Parolanız değiştirilemedi" msgid "The passwords do not match." msgstr "Parolalar eşleşmiyor." -#: panels/user-accounts/um-photo-dialog.c:226 +#: panels/user-accounts/um-photo-dialog.c:227 msgid "Browse for more pictures" msgstr "Daha çok resim için göz at" -#: panels/user-accounts/um-realm-manager.c:350 +#: panels/user-accounts/um-realm-manager.c:310 msgid "Cannot automatically join this type of domain" msgstr "Bu tür bir etki alanına kendiliğinden girilemiyor" -#: panels/user-accounts/um-realm-manager.c:413 -#, c-format +#: panels/user-accounts/um-realm-manager.c:313 msgid "No such domain or realm found" msgstr "Böyle bir etki alanı veya alan (realm) yok" -#: panels/user-accounts/um-realm-manager.c:815 -#: panels/user-accounts/um-realm-manager.c:829 +#: panels/user-accounts/um-realm-manager.c:735 +#: panels/user-accounts/um-realm-manager.c:749 #, c-format msgid "Cannot log in as %s at the %s domain" msgstr "%2$s etki alanına %1$s olarak giriş yapılamıyor" -#: panels/user-accounts/um-realm-manager.c:821 +#: panels/user-accounts/um-realm-manager.c:741 msgid "Invalid password, please try again" msgstr "Yanlış parola, lütfen yeniden deneyin" -#: panels/user-accounts/um-realm-manager.c:834 +#: panels/user-accounts/um-realm-manager.c:754 #, c-format msgid "Couldn’t connect to the %s domain: %s" msgstr "%s etki alanına bağlanılamadı: %s" -#: panels/user-accounts/um-user-panel.c:201 +#: panels/user-accounts/um-user-panel.c:200 msgid "Your account" msgstr "Hesabınız" -#: panels/user-accounts/um-user-panel.c:381 +#: panels/user-accounts/um-user-panel.c:380 msgid "Failed to delete user" msgstr "Kullanıcı silinemedi" -#: panels/user-accounts/um-user-panel.c:439 -#: panels/user-accounts/um-user-panel.c:498 -#: panels/user-accounts/um-user-panel.c:550 +#: panels/user-accounts/um-user-panel.c:438 +#: panels/user-accounts/um-user-panel.c:497 +#: panels/user-accounts/um-user-panel.c:549 msgid "Failed to revoke remotely managed user" msgstr "Uzaktan yönetilen kullanıcı iptal edilemedi" -#: panels/user-accounts/um-user-panel.c:604 +#: panels/user-accounts/um-user-panel.c:603 msgid "You cannot delete your own account." msgstr "Kendi hesabınızı silemezsiniz." -#: panels/user-accounts/um-user-panel.c:613 +#: panels/user-accounts/um-user-panel.c:612 #, c-format msgid "%s is still logged in" msgstr "%s halen sisteme giriş yapmış durumda" -#: panels/user-accounts/um-user-panel.c:617 +#: panels/user-accounts/um-user-panel.c:616 msgid "" "Deleting a user while they are logged in can leave the system in an " "inconsistent state." msgstr "" "Giriş yapmış bir kullanıcıyı silmek sistemi tutarsız bir duruma sokabilir." -#: panels/user-accounts/um-user-panel.c:626 +#: panels/user-accounts/um-user-panel.c:625 #, c-format msgid "Do you want to keep %s’s files?" msgstr "%s’in dosyalarını saklamak ister misiniz?" -#: panels/user-accounts/um-user-panel.c:630 +#: panels/user-accounts/um-user-panel.c:629 msgid "" "It is possible to keep the home directory, mail spool and temporary files " "around when deleting a user account." @@ -7007,49 +7223,49 @@ msgstr "" "Kullanıcı silerken ev klasörünü, postalarını ve geçici dosyalarını bırakmak " "mümkün." -#: panels/user-accounts/um-user-panel.c:633 +#: panels/user-accounts/um-user-panel.c:632 msgid "_Delete Files" msgstr "_Dosyaları Sil" -#: panels/user-accounts/um-user-panel.c:634 +#: panels/user-accounts/um-user-panel.c:633 msgid "_Keep Files" msgstr "Dosyaları _Tut" -#: panels/user-accounts/um-user-panel.c:648 +#: panels/user-accounts/um-user-panel.c:647 #, c-format msgid "Are you sure you want to revoke remotely managed %s’s account?" msgstr "" "Uzaktan yönetilen %s kullanıcısının hesabını iptal etmek istediğinizden emin " "misiniz?" -#: panels/user-accounts/um-user-panel.c:652 +#: panels/user-accounts/um-user-panel.c:651 msgid "_Delete" msgstr "_Sil" -#: panels/user-accounts/um-user-panel.c:702 +#: panels/user-accounts/um-user-panel.c:701 msgctxt "Password mode" msgid "Account disabled" msgstr "Hesap devre dışı" -#: panels/user-accounts/um-user-panel.c:710 +#: panels/user-accounts/um-user-panel.c:709 msgctxt "Password mode" msgid "To be set at next login" msgstr "Bir sonraki girişte ayarlanacak" -#: panels/user-accounts/um-user-panel.c:713 +#: panels/user-accounts/um-user-panel.c:712 msgctxt "Password mode" msgid "None" msgstr "Hiçbiri" -#: panels/user-accounts/um-user-panel.c:760 +#: panels/user-accounts/um-user-panel.c:759 msgid "Logged in" msgstr "Oturum açık" -#: panels/user-accounts/um-user-panel.c:1107 +#: panels/user-accounts/um-user-panel.c:1106 msgid "Failed to contact the accounts service" msgstr "Hesap hizmetiyle bağlantı kurulamadı" -#: panels/user-accounts/um-user-panel.c:1109 +#: panels/user-accounts/um-user-panel.c:1108 msgid "Please make sure that the AccountService is installed and enabled." msgstr "Lütfen AccountService’in kurulu ve etkin olduğundan emin olun." @@ -7057,7 +7273,7 @@ msgstr "Lütfen AccountService’in kurulu ve etkin olduğundan emin olun." #. * We split the line in 2 here to "make it look good", as there's #. * no good way to do this in GTK+ for tooltips. See: #. * https://bugzilla.gnome.org/show_bug.cgi?id=657168 -#: panels/user-accounts/um-user-panel.c:1141 +#: panels/user-accounts/um-user-panel.c:1140 msgid "" "To make changes,\n" "click the * icon first" @@ -7065,12 +7281,12 @@ msgstr "" "Değişiklik yapmak için,\n" "önce * simgesine tıklayın" -#: panels/user-accounts/um-user-panel.c:1181 +#: panels/user-accounts/um-user-panel.c:1180 msgid "Create a user account" msgstr "Kullanıcı hesabı oluştur" -#: panels/user-accounts/um-user-panel.c:1192 -#: panels/user-accounts/um-user-panel.c:1371 +#: panels/user-accounts/um-user-panel.c:1191 +#: panels/user-accounts/um-user-panel.c:1370 msgid "" "To create a user account,\n" "click the * icon first" @@ -7078,12 +7294,12 @@ msgstr "" "Kullanıcı hesabı oluşturmak için,\n" "önce * simgesine tıklayın" -#: panels/user-accounts/um-user-panel.c:1202 +#: panels/user-accounts/um-user-panel.c:1201 msgid "Delete the selected user account" msgstr "Seçilen kullanıcı hesabını sil" -#: panels/user-accounts/um-user-panel.c:1214 -#: panels/user-accounts/um-user-panel.c:1376 +#: panels/user-accounts/um-user-panel.c:1213 +#: panels/user-accounts/um-user-panel.c:1375 msgid "" "To delete the selected user account,\n" "click the * icon first" @@ -7361,35 +7577,35 @@ msgstr "" "Denetim merkezi, masaüstünüzün çeşitli yönlerini yapılandırmak için GNOME’un " "temel arabirimidir." -#: shell/cc-application.c:47 +#: shell/cc-application.c:60 msgid "Display version number" msgstr "Sürüm numarasını göster" -#: shell/cc-application.c:48 +#: shell/cc-application.c:61 msgid "Enable verbose mode" msgstr "Ayrıntılı kipi etkinleştir" -#: shell/cc-application.c:49 +#: shell/cc-application.c:62 msgid "Show the overview" msgstr "Genel görünümü göster" -#: shell/cc-application.c:50 +#: shell/cc-application.c:63 msgid "Search for the string" msgstr "Dizgeyi ara" -#: shell/cc-application.c:51 +#: shell/cc-application.c:64 msgid "List possible panel names and exit" msgstr "Olası panel adlarını listele ve çık" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "Panel to display" msgstr "Gösterilecek panel" -#: shell/cc-application.c:52 +#: shell/cc-application.c:65 msgid "[PANEL] [ARGUMENT…]" msgstr "[PANEL] [BAĞIMSIZ DEĞİŞKEN…]" -#: shell/cc-application.c:117 +#: shell/cc-application.c:136 msgid "Available panels:" msgstr "Kullanılabilir Paneller:" @@ -7441,12 +7657,6 @@ msgctxt "shortcut window" msgid "Cancel search" msgstr "Aramayı iptal et" -#. translators: This is the default hotspot name, need to be less than 32-bytes -#: shell/hostname-helper.c:189 -msgctxt "hotspot" -msgid "Hotspot" -msgstr "Erişim Noktası" - #: shell/org.gnome.ControlCenter.gschema.xml:5 msgid "The identifier for the last Settings panel to be opened" msgstr "En son açılan Ayarlar paneli için tanımlayıcı" @@ -7660,12 +7870,6 @@ msgstr "Sistem Sesleri" #~ msgid "_Method" #~ msgstr "Yönte_m" -#~ msgid "Add Device" -#~ msgstr "Aygıt Ekle" - -#~ msgid "Remove Device" -#~ msgstr "Aygıtı Kaldır" - #~ msgid "VPN Type" #~ msgstr "VPN Türü" @@ -7971,9 +8175,6 @@ msgstr "Sistem Sesleri" #~ "Bir kısayolu düzenlemek için, ilgili satıra tıklayın ve tuşlara ya da " #~ "temizlemek için Backspace tuşuna basın." -#~ msgid "_Name:" -#~ msgstr "_İsim:" - #~ msgid "Add Shortcut" #~ msgstr "Kısayol Ekle" diff --git a/search-provider/meson.build b/search-provider/meson.build index ef24b2f01..294464c5d 100644 --- a/search-provider/meson.build +++ b/search-provider/meson.build @@ -4,11 +4,11 @@ service_conf.set('libexecdir', control_center_libexecdir) service = 'org.gnome.ControlCenter.SearchProvider.service' configure_file( - input: service + '.in', - output: service, - install: true, - install_dir: join_paths(control_center_datadir, 'dbus-1', 'services'), - configuration: service_conf + input : service + '.in', + output : service, + install : true, + install_dir : join_paths(control_center_datadir, 'dbus-1', 'services'), + configuration : service_conf ) install_data( @@ -26,8 +26,8 @@ sources = files( sources += gnome.gdbus_codegen( 'cc-shell-search-provider-generated', 'org.gnome.ShellSearchProvider2.xml', - interface_prefix: 'org.gnome.', - namespace: 'Cc' + interface_prefix : 'org.gnome.', + namespace : 'Cc' ) cflags = '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) @@ -38,12 +38,12 @@ libs = [ ] executable( - meson.project_name() + '-search-provider', - sources, - include_directories: top_inc, - dependencies: shell_deps, - c_args: cflags, - link_with: libs, - install: true, - install_dir: control_center_libexecdir + 'gnome-control-center-search-provider', + sources, + include_directories : top_inc, + dependencies : shell_deps, + c_args : cflags, + link_with : libs, + install : true, + install_dir : control_center_libexecdir ) diff --git a/shell/cc-application.c b/shell/cc-application.c index 8beb61714..3f828f3a6 100644 --- a/shell/cc-application.c +++ b/shell/cc-application.c @@ -26,8 +26,9 @@ #include <gio/gio.h> #include "cc-application.h" +#include "cc-log.h" +#include "cc-object-storage.h" #include "cc-panel-loader.h" -#include "cc-shell-log.h" #include "cc-window.h" #if defined(HAVE_WACOM) || defined(HAVE_CHEESE) @@ -157,7 +158,9 @@ cc_application_command_line (GApplication *application, options = g_application_command_line_get_options_dict (command_line); debug = g_variant_dict_contains (options, "verbose"); - cc_shell_log_set_debug (debug); + + if (debug) + cc_log_init (); gtk_window_present (GTK_WINDOW (self->window)); @@ -264,6 +267,15 @@ cc_application_startup (GApplication *application) self->window = cc_window_new (GTK_APPLICATION (application)); } +static void +cc_application_finalize (GObject *object) +{ + /* Destroy the object storage cache when finalizing */ + cc_object_storage_destroy (); + + G_OBJECT_CLASS (cc_application_parent_class)->finalize (object); +} + static GObject * cc_application_constructor (GType type, guint n_construct_params, @@ -289,6 +301,7 @@ cc_application_class_init (CcApplicationClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GApplicationClass *application_class = G_APPLICATION_CLASS (klass); + object_class->finalize = cc_application_finalize; object_class->constructor = cc_application_constructor; application_class->activate = cc_application_activate; application_class->startup = cc_application_startup; @@ -299,6 +312,8 @@ cc_application_class_init (CcApplicationClass *klass) static void cc_application_init (CcApplication *self) { + cc_object_storage_initialize (); + g_application_add_main_option_entries (G_APPLICATION (self), all_options); } diff --git a/shell/cc-debug.h.in b/shell/cc-debug.h.in new file mode 100644 index 000000000..226f82e03 --- /dev/null +++ b/shell/cc-debug.h.in @@ -0,0 +1,229 @@ +/* cc-debug.h.in + * + * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib.h> + +/** + * SECTION:cc-debug + * @short_description: Debugging macros + * @title:Debugging + * @stability:stable + * + * Macros used for tracing and debugging code. These + * are only valid when Settings is compiled with tracing + * suppoer (pass `--enable-tracing` to the configure + * script to do that). + */ + +G_BEGIN_DECLS + +#ifndef CC_ENABLE_TRACE +# define CC_ENABLE_TRACE @ENABLE_TRACING@ +#endif +#if CC_ENABLE_TRACE != 1 +# undef CC_ENABLE_TRACE +#endif + +/** + * CC_LOG_LEVEL_TRACE: (skip) + */ +#ifndef CC_LOG_LEVEL_TRACE +# define CC_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT)) +#endif + +#ifdef CC_ENABLE_TRACE + +/** + * CC_TRACE_MSG: + * @fmt: printf-like format of the message + * @...: arguments for @fmt + * + * Prints a trace message. + */ +# define CC_TRACE_MSG(fmt, ...) \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " MSG: %s():%d: " fmt, \ + G_STRFUNC, __LINE__, ##__VA_ARGS__) + +/** + * CC_PROBE: + * + * Prints a probing message. Put this macro in the code when + * you want to check the program reaches a certain section + * of code. + */ +# define CC_PROBE \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "PROBE: %s():%d", \ + G_STRFUNC, __LINE__) + +/** + * CC_TODO: + * @_msg: the message to print + * + * Prints a TODO message. + */ +# define CC_TODO(_msg) \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \ + G_STRFUNC, __LINE__, _msg) + +/** + * CC_ENTRY: + * + * Prints an entry message. This shouldn't be used in + * critical functions. Place this at the beggining of + * the function, before any assertion. + */ +# define CC_ENTRY \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \ + G_STRFUNC, __LINE__) + +/** + * CC_EXIT: + * + * Prints an exit message. This shouldn't be used in + * critical functions. Place this at the end of + * the function, after any relevant code. If the + * function returns something, use CC_RETURN() + * instead. + */ +# define CC_EXIT \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d", \ + G_STRFUNC, __LINE__); \ + return; \ + } G_STMT_END + +/** + * CC_GOTO: + * @_l: goto tag + * + * Logs a goto jump. + */ +# define CC_GOTO(_l) \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")",\ + G_STRFUNC, __LINE__); \ + goto _l; \ + } G_STMT_END + +/** + * CC_RETURN: + * @_r: the return value. + * + * Prints an exit message, and returns @_r. See #CC_EXIT. + */ +# define CC_RETURN(_r) \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \ + G_STRFUNC, __LINE__); \ + return _r; \ + } G_STMT_END + +#else + +/** + * CC_TODO: + * @_msg: the message to print + * + * Prints a TODO message. + */ +# define CC_TODO(_msg) + +/** + * CC_PROBE: + * + * Prints a probing message. + */ +# define CC_PROBE + +/** + * CC_TRACE_MSG: + * @fmt: printf-like format of the message + * @...: arguments for @fmt + * + * Prints a trace message. + */ +# define CC_TRACE_MSG(fmt, ...) + +/** + * CC_ENTRY: + * + * Prints a probing message. This shouldn't be used in + * critical functions. Place this at the beggining of + * the function, before any assertion. + */ +# define CC_ENTRY + +/** + * CC_GOTO: + * @_l: goto tag + * + * Logs a goto jump. + */ +# define CC_GOTO(_l) goto _l + +/** + * CC_EXIT: + * + * Prints an exit message. This shouldn't be used in + * critical functions. Place this at the end of + * the function, after any relevant code. If the + * function returns somethin, use CC_RETURN() + * instead. + */ +# define CC_EXIT return + +/** + * CC_RETURN: + * @_r: the return value. + * + * Prints an exit message, and returns @_r. See #CC_EXIT. + */ +# define CC_RETURN(_r) return _r +#endif + +/** + * _CC_BUG: (skip) + */ +#define _CC_BUG(Component, Description, File, Line, Func, ...) \ + G_STMT_START { \ + g_printerr ("-----------------------------------------------------------------\n"); \ + g_printerr ("You've found a bug in Settings or one of its dependent libraries.\n"); \ + g_printerr ("Please help us help you by filing a bug report at:\n"); \ + g_printerr ("\n"); \ + g_printerr ("@BUGREPORT_URL@&component=%s\n", Component); \ + g_printerr ("\n"); \ + g_printerr ("%s:%d in function %s()\n", File, Line, Func); \ + g_printerr ("\n"); \ + g_printerr (Description"\n", ##__VA_ARGS__); \ + g_printerr ("-----------------------------------------------------------------\n"); \ + } G_STMT_END + +/** + * CC_BUG: + * @Component: the component + * @Description: the description + * @...: extra arguments + * + * Logs a bug-friendly message. + */ +#define CC_BUG(Component, Description, ...) \ + _CC_BUG(Component, Description, __FILE__, __LINE__, G_STRFUNC, ##__VA_ARGS__) + +G_END_DECLS diff --git a/shell/cc-editable-entry.c b/shell/cc-editable-entry.c deleted file mode 100644 index 8c81fc112..000000000 --- a/shell/cc-editable-entry.c +++ /dev/null @@ -1,644 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright 2009-2010 Red Hat, Inc, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Written by: Matthias Clasen <mclasen@redhat.com> - */ - -#include <gdk/gdkkeysyms.h> -#include "cc-editable-entry.h" - -#define EMPTY_TEXT "\xe2\x80\x94" - -struct _CcEditableEntryPrivate { - GtkStack *stack; - GtkLabel *label; - GtkButton *button; - GtkEntry *entry; - - gchar *text; - gboolean editable; - gboolean selectable; - gint weight; - gboolean weight_set; - gdouble scale; - gboolean scale_set; - gint width_chars; - gint max_width_chars; - PangoEllipsizeMode ellipsize; - - gboolean in_stop_editing; -}; - -#define CC_EDITABLE_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryPrivate)) - -enum { - PROP_0, - PROP_TEXT, - PROP_EDITABLE, - PROP_SELECTABLE, - PROP_SCALE, - PROP_SCALE_SET, - PROP_WEIGHT, - PROP_WEIGHT_SET, - PROP_WIDTH_CHARS, - PROP_MAX_WIDTH_CHARS, - PROP_ELLIPSIZE -}; - -enum { - EDITING_DONE, - LAST_SIGNAL -}; - -#define PAGE_LABEL "_label" -#define PAGE_BUTTON "_button" -#define PAGE_ENTRY "_entry" - -static guint signals [LAST_SIGNAL] = { 0, }; - -G_DEFINE_TYPE (CcEditableEntry, cc_editable_entry, GTK_TYPE_BIN); - -void -cc_editable_entry_set_text (CcEditableEntry *e, - const gchar *text) -{ - CcEditableEntryPrivate *priv; - gchar *tmp; - GtkWidget *label; - - priv = e->priv; - - tmp = g_strdup (text); - g_free (priv->text); - priv->text = tmp; - - gtk_entry_set_text (priv->entry, tmp); - - if (tmp == NULL || tmp[0] == '\0') - tmp = EMPTY_TEXT; - - gtk_label_set_text (priv->label, tmp); - label = gtk_bin_get_child (GTK_BIN (priv->button)); - gtk_label_set_text (GTK_LABEL (label), tmp); - - g_object_notify (G_OBJECT (e), "text"); -} - -const gchar * -cc_editable_entry_get_text (CcEditableEntry *e) -{ - return e->priv->text; -} - -void -cc_editable_entry_set_editable (CcEditableEntry *e, - gboolean editable) -{ - CcEditableEntryPrivate *priv; - - priv = e->priv; - - if (priv->editable != editable) { - priv->editable = editable; - - gtk_stack_set_visible_child_name (e->priv->stack, editable ? PAGE_BUTTON : PAGE_LABEL); - - g_object_notify (G_OBJECT (e), "editable"); - } -} - -gboolean -cc_editable_entry_get_editable (CcEditableEntry *e) -{ - return e->priv->editable; -} - -void -cc_editable_entry_set_selectable (CcEditableEntry *e, - gboolean selectable) -{ - CcEditableEntryPrivate *priv; - - priv = e->priv; - - if (priv->selectable != selectable) { - priv->selectable = selectable; - - gtk_label_set_selectable (priv->label, selectable); - - g_object_notify (G_OBJECT (e), "selectable"); - } -} - -gboolean -cc_editable_entry_get_selectable (CcEditableEntry *e) -{ - return e->priv->selectable; -} - - -static void -update_fonts (CcEditableEntry *e) -{ - PangoAttrList *attrs; - PangoAttribute *attr; - GtkWidget *label; - - CcEditableEntryPrivate *priv = e->priv; - - attrs = pango_attr_list_new (); - if (priv->scale_set) { - attr = pango_attr_scale_new (priv->scale); - pango_attr_list_insert (attrs, attr); - } - if (priv->weight_set) { - attr = pango_attr_weight_new (priv->weight); - pango_attr_list_insert (attrs, attr); - } - - gtk_label_set_attributes (priv->label, attrs); - - label = gtk_bin_get_child (GTK_BIN (priv->button)); - gtk_label_set_attributes (GTK_LABEL (label), attrs); - gtk_entry_set_attributes (priv->entry, attrs); - - pango_attr_list_unref (attrs); -} - -void -cc_editable_entry_set_weight (CcEditableEntry *e, - gint weight) -{ - CcEditableEntryPrivate *priv = e->priv; - - if (priv->weight == weight && priv->weight_set) - return; - - priv->weight = weight; - priv->weight_set = TRUE; - - update_fonts (e); - - g_object_notify (G_OBJECT (e), "weight"); - g_object_notify (G_OBJECT (e), "weight-set"); -} - -gint -cc_editable_entry_get_weight (CcEditableEntry *e) -{ - return e->priv->weight; -} - -void -cc_editable_entry_set_scale (CcEditableEntry *e, - gdouble scale) -{ - CcEditableEntryPrivate *priv = e->priv; - - if (priv->scale == scale && priv->scale_set) - return; - - priv->scale = scale; - priv->scale_set = TRUE; - - update_fonts (e); - - g_object_notify (G_OBJECT (e), "scale"); - g_object_notify (G_OBJECT (e), "scale-set"); -} - -gdouble -cc_editable_entry_get_scale (CcEditableEntry *e) -{ - return e->priv->scale; -} - -void -cc_editable_entry_set_width_chars (CcEditableEntry *e, - gint n_chars) -{ - CcEditableEntryPrivate *priv = e->priv; - GtkWidget *label; - - if (priv->width_chars != n_chars) { - label = gtk_bin_get_child (GTK_BIN (priv->button)); - - gtk_entry_set_width_chars (priv->entry, n_chars); - gtk_label_set_width_chars (priv->label, n_chars); - gtk_label_set_width_chars (GTK_LABEL (label), n_chars); - - priv->width_chars = n_chars; - g_object_notify (G_OBJECT (e), "width-chars"); - gtk_widget_queue_resize (GTK_WIDGET (priv->entry)); - gtk_widget_queue_resize (GTK_WIDGET (priv->label)); - gtk_widget_queue_resize (GTK_WIDGET (label)); - } -} - -gint -cc_editable_entry_get_width_chars (CcEditableEntry *e) -{ - return e->priv->width_chars; -} - -void -cc_editable_entry_set_max_width_chars (CcEditableEntry *e, - gint n_chars) -{ - CcEditableEntryPrivate *priv = e->priv; - GtkWidget *label; - - if (priv->max_width_chars != n_chars) { - label = gtk_bin_get_child (GTK_BIN (priv->button)); - gtk_label_set_max_width_chars (priv->label, n_chars); - gtk_label_set_max_width_chars (GTK_LABEL (label), n_chars); - - priv->max_width_chars = n_chars; - g_object_notify (G_OBJECT (e), "max-width-chars"); - gtk_widget_queue_resize (GTK_WIDGET (priv->entry)); - gtk_widget_queue_resize (GTK_WIDGET (priv->label)); - gtk_widget_queue_resize (GTK_WIDGET (label)); - } -} - -gint -cc_editable_entry_get_max_width_chars (CcEditableEntry *e) -{ - return e->priv->max_width_chars; -} - -void -cc_editable_entry_set_ellipsize (CcEditableEntry *e, - PangoEllipsizeMode mode) -{ - CcEditableEntryPrivate *priv = e->priv; - GtkWidget *label; - - if ((PangoEllipsizeMode) priv->ellipsize != mode) { - label = gtk_bin_get_child (GTK_BIN (priv->button)); - gtk_label_set_ellipsize (priv->label, mode); - gtk_label_set_ellipsize (GTK_LABEL (label), mode); - - priv->ellipsize = mode; - g_object_notify (G_OBJECT (e), "ellipsize"); - gtk_widget_queue_resize (GTK_WIDGET (priv->label)); - gtk_widget_queue_resize (GTK_WIDGET (label)); - } -} - -PangoEllipsizeMode -cc_editable_entry_get_ellipsize (CcEditableEntry *e) -{ - return e->priv->ellipsize; -} - -static void -cc_editable_entry_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - CcEditableEntry *e = CC_EDITABLE_ENTRY (object); - - switch (prop_id) { - case PROP_TEXT: - cc_editable_entry_set_text (e, g_value_get_string (value)); - break; - case PROP_EDITABLE: - cc_editable_entry_set_editable (e, g_value_get_boolean (value)); - break; - case PROP_SELECTABLE: - cc_editable_entry_set_selectable (e, g_value_get_boolean (value)); - break; - case PROP_WEIGHT: - cc_editable_entry_set_weight (e, g_value_get_int (value)); - break; - case PROP_WEIGHT_SET: - e->priv->weight_set = g_value_get_boolean (value); - break; - case PROP_SCALE: - cc_editable_entry_set_scale (e, g_value_get_double (value)); - break; - case PROP_SCALE_SET: - e->priv->scale_set = g_value_get_boolean (value); - break; - case PROP_WIDTH_CHARS: - cc_editable_entry_set_width_chars (e, g_value_get_int (value)); - break; - case PROP_MAX_WIDTH_CHARS: - cc_editable_entry_set_max_width_chars (e, g_value_get_int (value)); - break; - case PROP_ELLIPSIZE: - cc_editable_entry_set_ellipsize (e, g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -cc_editable_entry_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - CcEditableEntry *e = CC_EDITABLE_ENTRY (object); - - switch (prop_id) { - case PROP_TEXT: - g_value_set_string (value, - cc_editable_entry_get_text (e)); - break; - case PROP_EDITABLE: - g_value_set_boolean (value, - cc_editable_entry_get_editable (e)); - break; - case PROP_SELECTABLE: - g_value_set_boolean (value, - cc_editable_entry_get_selectable (e)); - break; - case PROP_WEIGHT: - g_value_set_int (value, - cc_editable_entry_get_weight (e)); - break; - case PROP_WEIGHT_SET: - g_value_set_boolean (value, e->priv->weight_set); - break; - case PROP_SCALE: - g_value_set_double (value, - cc_editable_entry_get_scale (e)); - break; - case PROP_SCALE_SET: - g_value_set_boolean (value, e->priv->scale_set); - break; - case PROP_WIDTH_CHARS: - g_value_set_int (value, - cc_editable_entry_get_width_chars (e)); - break; - case PROP_MAX_WIDTH_CHARS: - g_value_set_int (value, - cc_editable_entry_get_max_width_chars (e)); - break; - case PROP_ELLIPSIZE: - g_value_set_enum (value, - cc_editable_entry_get_ellipsize (e)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -cc_editable_entry_finalize (GObject *object) -{ - CcEditableEntry *e = (CcEditableEntry*)object; - - g_free (e->priv->text); - - G_OBJECT_CLASS (cc_editable_entry_parent_class)->finalize (object); -} - -static void -cc_editable_entry_class_init (CcEditableEntryClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - - object_class->set_property = cc_editable_entry_set_property; - object_class->get_property = cc_editable_entry_get_property; - object_class->finalize = cc_editable_entry_finalize; - - signals[EDITING_DONE] = - g_signal_new ("editing-done", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (CcEditableEntryClass, editing_done), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_object_class_install_property (object_class, PROP_TEXT, - g_param_spec_string ("text", - "Text", "The text of the button", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EDITABLE, - g_param_spec_boolean ("editable", - "Editable", "Whether the text can be edited", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_SELECTABLE, - g_param_spec_boolean ("selectable", - "Selectable", "Whether the text can be selected by mouse", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_WEIGHT, - g_param_spec_int ("weight", - "Font Weight", "The font weight to use", - 0, G_MAXINT, PANGO_WEIGHT_NORMAL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_WEIGHT_SET, - g_param_spec_boolean ("weight-set", - "Font Weight Set", "Whether a font weight is set", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_SCALE, - g_param_spec_double ("scale", - "Font Scale", "The font scale to use", - 0.0, G_MAXDOUBLE, 1.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_SCALE_SET, - g_param_spec_boolean ("scale-set", - "Font Scale Set", "Whether a font scale is set", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_WIDTH_CHARS, - g_param_spec_int ("width-chars", - "Width In Characters", "The desired width of the editable entry, in characters", - -1, G_MAXINT, -1, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_MAX_WIDTH_CHARS, - g_param_spec_int ("max-width-chars", - "Maximum Width In Characters","The desired maximum width of the editable entry, in characters", - -1, G_MAXINT, -1, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_ELLIPSIZE, - g_param_spec_enum ("ellipsize", - "Ellipsize", "The preferred place to ellipsize the string, if the editable entry does not have enough room to display the entire string", - PANGO_TYPE_ELLIPSIZE_MODE, PANGO_ELLIPSIZE_NONE, - G_PARAM_READWRITE)); - - g_type_class_add_private (class, sizeof (CcEditableEntryPrivate)); -} - -static void -start_editing (CcEditableEntry *e) -{ - gtk_stack_set_visible_child_name (e->priv->stack, PAGE_ENTRY); - gtk_widget_grab_focus (GTK_WIDGET (e->priv->entry)); -} - -static void -stop_editing (CcEditableEntry *e) -{ - gboolean has_focus; - - /* Avoid launching another "editing-done" signal - * caused by the notebook page change */ - if (e->priv->in_stop_editing) - return; - - e->priv->in_stop_editing = TRUE; - has_focus = gtk_widget_has_focus (GTK_WIDGET (e->priv->entry)); - gtk_stack_set_visible_child_name (e->priv->stack, PAGE_BUTTON); - if (has_focus) - gtk_widget_grab_focus (GTK_WIDGET (e->priv->button)); - - cc_editable_entry_set_text (e, gtk_entry_get_text (e->priv->entry)); - g_signal_emit (e, signals[EDITING_DONE], 0); - e->priv->in_stop_editing = FALSE; -} - -static void -cancel_editing (CcEditableEntry *e) -{ - gtk_entry_set_text (e->priv->entry, cc_editable_entry_get_text (e)); - gtk_stack_set_visible_child_name (e->priv->stack, PAGE_BUTTON); - gtk_widget_grab_focus (GTK_WIDGET (e->priv->button)); -} - -static void -button_clicked (GtkWidget *widget, - CcEditableEntry *e) -{ - start_editing (e); -} - -static void -entry_activated (GtkWidget *widget, - CcEditableEntry *e) -{ - stop_editing (e); -} - -static gboolean -entry_focus_out (GtkWidget *widget, - GdkEventFocus *event, - CcEditableEntry *e) -{ - stop_editing (e); - return FALSE; -} - -static gboolean -entry_key_press (GtkWidget *widget, - GdkEventKey *event, - CcEditableEntry *e) -{ - if (event->keyval == GDK_KEY_Escape) { - cancel_editing (e); - } - return FALSE; -} - -static void -update_button_padding (CcEditableEntry *e, gpointer user_data) -{ - CcEditableEntryPrivate *priv = e->priv; - GtkStyleContext *context; - GtkStateFlags state; - GtkBorder padding, border; - gint margin; - - context = gtk_widget_get_style_context (GTK_WIDGET (priv->button)); - state = gtk_style_context_get_state (context); - - gtk_style_context_get_padding (context, state, &padding); - gtk_style_context_get_border (context, state, &border); - - margin = padding.left + border.left; - gtk_widget_set_margin_start (GTK_WIDGET (priv->label), margin); - gtk_widget_set_margin_end (GTK_WIDGET (priv->label), margin); -} - -static void -cc_editable_entry_init (CcEditableEntry *e) -{ - CcEditableEntryPrivate *priv; - - priv = e->priv = CC_EDITABLE_ENTRY_GET_PRIVATE (e); - - priv->weight = PANGO_WEIGHT_NORMAL; - priv->weight_set = FALSE; - priv->scale = 1.0; - priv->scale_set = FALSE; - priv->width_chars = -1; - priv->max_width_chars = -1; - priv->ellipsize = PANGO_ELLIPSIZE_NONE; - priv->stack = GTK_STACK (gtk_stack_new ()); - - /* Label */ - priv->label = (GtkLabel*)gtk_label_new (EMPTY_TEXT); - g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL); - gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->label), PAGE_LABEL); - - /* Button */ - priv->button = (GtkButton*)gtk_button_new_with_label (EMPTY_TEXT); - gtk_widget_set_receives_default ((GtkWidget*)priv->button, TRUE); - gtk_button_set_relief (priv->button, GTK_RELIEF_NONE); - g_object_set (G_OBJECT (gtk_bin_get_child (GTK_BIN (priv->button))), "xalign", 0.0, NULL); - - gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->button), PAGE_BUTTON); - g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked), e); - - /* Entry */ - priv->entry = (GtkEntry*)gtk_entry_new (); - gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->entry), PAGE_ENTRY); - - g_signal_connect (priv->entry, "activate", G_CALLBACK (entry_activated), e); - g_signal_connect (priv->entry, "focus-out-event", G_CALLBACK (entry_focus_out), e); - g_signal_connect (priv->entry, "key-press-event", G_CALLBACK (entry_key_press), e); - - g_signal_connect (e, "style-updated", G_CALLBACK (update_button_padding), NULL); - - gtk_container_add (GTK_CONTAINER (e), (GtkWidget*)priv->stack); - - gtk_widget_show ((GtkWidget*)priv->stack); - gtk_widget_show ((GtkWidget*)priv->label); - gtk_widget_show ((GtkWidget*)priv->button); - gtk_widget_show ((GtkWidget*)priv->entry); - - gtk_stack_set_visible_child_name (e->priv->stack, PAGE_LABEL); -} - -GtkWidget * -cc_editable_entry_new (void) -{ - return (GtkWidget *) g_object_new (CC_TYPE_EDITABLE_ENTRY, NULL); -} diff --git a/shell/cc-editable-entry.h b/shell/cc-editable-entry.h deleted file mode 100644 index 9d61c5480..000000000 --- a/shell/cc-editable-entry.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright 2009-2010 Red Hat, Inc, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Written by: Matthias Clasen <mclasen@redhat.com> - */ - -#ifndef _CC_EDITABLE_ENTRY_H_ -#define _CC_EDITABLE_ENTRY_H_ - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define CC_TYPE_EDITABLE_ENTRY cc_editable_entry_get_type() - -#define CC_EDITABLE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntry)) -#define CC_EDITABLE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryClass)) -#define CC_IS_EDITABLE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_EDITABLE_ENTRY)) -#define CC_IS_EDITABLE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_EDITABLE_ENTRY)) -#define CC_EDITABLE_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryClass)) - -typedef struct _CcEditableEntry CcEditableEntry; -typedef struct _CcEditableEntryClass CcEditableEntryClass; -typedef struct _CcEditableEntryPrivate CcEditableEntryPrivate; - -struct _CcEditableEntry -{ - GtkAlignment parent; - - CcEditableEntryPrivate *priv; -}; - -struct _CcEditableEntryClass -{ - GtkAlignmentClass parent_class; - - void (* editing_done) (CcEditableEntry *entry); -}; - -GType cc_editable_entry_get_type (void) G_GNUC_CONST; -GtkWidget *cc_editable_entry_new (void); -void cc_editable_entry_set_text (CcEditableEntry *entry, - const gchar *text); -const gchar *cc_editable_entry_get_text (CcEditableEntry *entry); -void cc_editable_entry_set_editable (CcEditableEntry *entry, - gboolean editable); -gboolean cc_editable_entry_get_editable (CcEditableEntry *entry); -void cc_editable_entry_set_selectable (CcEditableEntry *entry, - gboolean selectable); -gboolean cc_editable_entry_get_selectable (CcEditableEntry *entry); -void cc_editable_entry_set_weight (CcEditableEntry *entry, - gint weight); -gint cc_editable_entry_get_weight (CcEditableEntry *entry); -void cc_editable_entry_set_scale (CcEditableEntry *entry, - gdouble scale); -gdouble cc_editable_entry_get_scale (CcEditableEntry *entry); -void cc_editable_entry_set_width_chars (CcEditableEntry *entry, - gint n_chars); -gint cc_editable_entry_get_width_chars (CcEditableEntry *entry); -void cc_editable_entry_set_max_width_chars (CcEditableEntry *entry, - gint n_chars); -gint cc_editable_entry_get_max_width_chars (CcEditableEntry *entry); -void cc_editable_entry_set_ellipsize (CcEditableEntry *entry, - PangoEllipsizeMode mode); -PangoEllipsizeMode cc_editable_entry_get_ellipsize (CcEditableEntry *entry); - -G_END_DECLS - -#endif /* _CC_EDITABLE_ENTRY_H_ */ diff --git a/shell/cc-log.c b/shell/cc-log.c new file mode 100644 index 000000000..5f6645cbe --- /dev/null +++ b/shell/cc-log.c @@ -0,0 +1,107 @@ +/* cc-shell-log.c + * + * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "cc-debug.h" +#include "cc-log.h" + +#include <unistd.h> +#include <glib.h> + +G_LOCK_DEFINE_STATIC (channel_lock); + +GIOChannel *standard_channel = NULL; + +static const gchar* ignored_domains[] = +{ + "GdkPixbuf", + NULL +}; + +static const gchar * +log_level_str (GLogLevelFlags log_level) +{ + switch (((gulong)log_level & G_LOG_LEVEL_MASK)) + { + case G_LOG_LEVEL_ERROR: return " \033[1;31mERROR\033[0m"; + case G_LOG_LEVEL_CRITICAL: return "\033[1;35mCRITICAL\033[0m"; + case G_LOG_LEVEL_WARNING: return " \033[1;33mWARNING\033[0m"; + case G_LOG_LEVEL_MESSAGE: return " \033[1;34mMESSAGE\033[0m"; + case G_LOG_LEVEL_INFO: return " \033[1;32mINFO\033[0m"; + case G_LOG_LEVEL_DEBUG: return " \033[1;32mDEBUG\033[0m"; + case CC_LOG_LEVEL_TRACE: return " \033[1;36mTRACE\033[0m"; + default: return " UNKNOWN"; + } +} + +static void +log_handler (const gchar *domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + GTimeVal tv; + struct tm tt; + time_t t; + const gchar *level; + gchar ftime[32]; + gchar *buffer; + + /* Skip ignored log domains */ + if (domain && g_strv_contains (ignored_domains, domain)) + return; + + level = log_level_str (log_level); + g_get_current_time (&tv); + t = (time_t) tv.tv_sec; + tt = *localtime (&t); + strftime (ftime, sizeof (ftime), "%H:%M:%S", &tt); + buffer = g_strdup_printf ("%s.%04ld %24s: %s: %s\n", + ftime, + tv.tv_usec / 1000, + domain, + level, + message); + + /* Safely write to the channel */ + G_LOCK (channel_lock); + + g_io_channel_write_chars (standard_channel, buffer, -1, NULL, NULL); + g_io_channel_flush (standard_channel, NULL); + + G_UNLOCK (channel_lock); + + g_free (buffer); +} + +void +cc_log_init (void) +{ + static gsize initialized = FALSE; + + if (g_once_init_enter (&initialized)) + { + standard_channel = g_io_channel_unix_new (STDOUT_FILENO); + + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + + g_log_set_default_handler (log_handler, NULL); + + g_once_init_leave (&initialized, TRUE); + } +} + diff --git a/shell/cc-log.h b/shell/cc-log.h new file mode 100644 index 000000000..2d04c0ba7 --- /dev/null +++ b/shell/cc-log.h @@ -0,0 +1,25 @@ +/* cc-log.h + * + * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +G_BEGIN_DECLS + +void cc_log_init (void); + +G_END_DECLS diff --git a/shell/cc-object-storage.c b/shell/cc-object-storage.c new file mode 100644 index 000000000..46038cc34 --- /dev/null +++ b/shell/cc-object-storage.c @@ -0,0 +1,438 @@ +/* cc-object-storage.h + * + * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define G_LOG_DOMAIN "cc-object-storage" + +#include "cc-object-storage.h" + +struct _CcObjectStorage +{ + GObject parent_instance; + + GHashTable *id_to_object; +}; + +G_DEFINE_TYPE (CcObjectStorage, cc_object_storage, G_TYPE_OBJECT) + +/* Singleton instance */ +CcObjectStorage *_instance = NULL; + +/* GTask API to create a new D-Bus proxy */ +typedef struct +{ + GBusType bus_type; + GDBusProxyFlags flags; + gchar *name; + gchar *path; + gchar *interface; + gboolean cached; +} TaskData; + +static TaskData* +task_data_new (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface) +{ + TaskData *data = g_slice_new (TaskData); + data->bus_type = bus_type; + data->flags =flags; + data->name = g_strdup (name); + data->path = g_strdup (path); + data->interface = g_strdup (interface); + data->cached = FALSE; + + return data; +} + +static void +task_data_free (TaskData *data) +{ + g_free (data->name); + g_free (data->path); + g_free (data->interface); + g_slice_free (TaskData, data); +} + +static void +create_dbus_proxy_in_thread_cb (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + TaskData *data = task_data; + + proxy = g_dbus_proxy_new_for_bus_sync (data->bus_type, + data->flags, + NULL, + data->name, + data->path, + data->interface, + cancellable, + &local_error); + + if (local_error) + { + g_task_return_error (task, local_error); + return; + } + + g_task_return_pointer (task, g_object_ref (g_steal_pointer (&proxy)), g_object_unref); +} + +static void +cc_object_storage_finalize (GObject *object) +{ + CcObjectStorage *self = (CcObjectStorage *)object; + + g_debug ("Destroying cached objects"); + + g_clear_pointer (&self->id_to_object, g_hash_table_destroy); + + G_OBJECT_CLASS (cc_object_storage_parent_class)->finalize (object); +} + +static void +cc_object_storage_class_init (CcObjectStorageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = cc_object_storage_finalize; +} + +static void +cc_object_storage_init (CcObjectStorage *self) +{ + self->id_to_object = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} + +/** + * cc_object_storage_has_object: + * @key: the unique string identifier of the object + * + * Checks whether there is an object associated with @key. + * + * Returns: %TRUE if the object is stored, %FALSE otherwise. + */ +gboolean +cc_object_storage_has_object (const gchar *key) +{ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + + return g_hash_table_contains (_instance->id_to_object, key); +} + +/** + * cc_object_storage_add_object: + * @key: the unique string identifier of the object + * @object: (type GObject): the object to be stored + * + * Adds @object to the object storage. It is a programming error to try to + * add an object that was already added. + * + * @object must be a GObject. + * + * Always check if the object is stored with cc_object_storage_has_object() + * before calling this function. + */ +void +cc_object_storage_add_object (const gchar *key, + gpointer object) +{ + /* Trying to add an object that was already added is a hard error. Each + * object must be added once, and only once, over the entire lifetime + * of the application. + */ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + g_assert (G_IS_OBJECT (object)); + g_assert (!g_hash_table_contains (_instance->id_to_object, key)); + + g_debug ("Adding object %s (%s → %p) to the storage", + g_type_name (G_OBJECT_TYPE (object)), + key, + object); + + g_hash_table_insert (_instance->id_to_object, g_strdup (key), g_object_ref (object)); +} + +/** + * cc_object_storage_get_object: + * @key: the unique string identifier of the object + * + * Retrieves the object associated with @key. It is a programming error to + * try to retrieve an object before adding it. + * + * Always check if the object is stored with cc_object_storage_has_object() + * before calling this function. + * + * Returns: (transfer full): the GObject associated with @key. + */ +gpointer +cc_object_storage_get_object (const gchar *key) +{ + /* Trying to peek an object that was not yet added is a hard error. Users + * of this API need to first check if the object is available with + * cc_object_storage_has_object(). + */ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + g_assert (g_hash_table_contains (_instance->id_to_object, key)); + + return g_object_ref (g_hash_table_lookup (_instance->id_to_object, key)); +} + +/** + * cc_object_storage_create_dbus_proxy_sync: + * @name: the D-Bus name + * @flags: the D-Bus proxy flags + * @path: the D-Bus object path + * @interface: the D-Bus interface name + * @cancellable: (nullable): #GCancellable to cancel the operation + * @error: (nullable): return location for a #GError + * + * Synchronously create a #GDBusProxy with @name, @path and @interface, + * stores it in the cache, and returns the newly created proxy. + * + * If a proxy with that signature is already created, it will be used + * instead of creating a new one. + * + * Returns: (transfer full)(nullable): the new #GDBusProxy. + */ +gpointer +cc_object_storage_create_dbus_proxy_sync (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree gchar *key = NULL; + + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (name && *name); + g_assert (path && *path); + g_assert (interface && *interface); + g_assert (!error || !*error); + + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface); + + /* Check if a DBus proxy with that signature is already available; if it is, + * return that instead of a new one. + */ + if (g_hash_table_contains (_instance->id_to_object, key)) + return cc_object_storage_get_object (key); + + proxy = g_dbus_proxy_new_for_bus_sync (bus_type, + flags, + NULL, + name, + path, + interface, + cancellable, + &local_error); + + if (local_error) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return NULL; + } + + /* Store the newly created D-Bus proxy */ + cc_object_storage_add_object (key, proxy); + + return g_steal_pointer (&proxy); +} + + +/** + * cc_object_storage_create_dbus_proxy: + * @name: the D-Bus name + * @flags: the D-Bus proxy flags + * @path: the D-Bus object path + * @interface: the D-Bus interface name + * @cancellable: (nullable): #GCancellable to cancel the operation + * @callback: callback for when the async operation is finished + * @user_data: user data for @callback + * + * Asynchronously create a #GDBusProxy with @name, @path and @interface. + * + * If a proxy with that signature is already created, it will be used instead of + * creating a new one. + * + * It is a programming error to create the an identical proxy while asynchronously + * creating one. Not cancelling this operation will result in an assertion failure + * when calling cc_object_storage_create_dbus_proxy_finish(). + */ +void +cc_object_storage_create_dbus_proxy (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + g_autofree gchar *key = NULL; + TaskData *data = NULL; + + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (name && *name); + g_assert (path && *path); + g_assert (interface && *interface); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + data = task_data_new (bus_type, flags, name, path, interface); + + task = g_task_new (_instance, cancellable, callback, user_data); + g_task_set_source_tag (task, cc_object_storage_create_dbus_proxy); + g_task_set_task_data (task, data, (GDestroyNotify) task_data_free); + + /* Check if the D-Bus proxy is already created */ + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface); + + if (g_hash_table_contains (_instance->id_to_object, key)) + { + /* Mark this GTask as already cached, so we can call the right assertions + * on the callback + * */ + data->cached = TRUE; + + g_debug ("Found in cache the D-Bus proxy %s", key); + + g_task_return_pointer (task, cc_object_storage_get_object (key), g_object_unref); + return; + } + + g_task_run_in_thread (task, create_dbus_proxy_in_thread_cb); +} + +/** + * cc_object_storage_create_dbus_proxy_finish: + * @result: + * @error: (nullable): return location for a #GError + * + * Finishes a D-Bus proxy creation started by cc_object_storage_create_dbus_proxy(). + * + * Synchronously create a #GDBusProxy with @name, @path and @interface, + * stores it in the cache, and returns the newly created proxy. + * + * If a proxy with that signature is already created, it will be used + * instead of creating a new one. + * + * Returns: (transfer full)(nullable): the new #GDBusProxy. + */ +gpointer +cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result, + GError **error) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree gchar *key = NULL; + TaskData *task_data; + GTask *task; + + task = G_TASK (result); + + g_assert (task && G_TASK (result)); + g_assert (!error || !*error); + + task_data = g_task_get_task_data (task); + + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", + task_data->name, + task_data->path, + task_data->interface); + + /* Either we have the object stored right when trying to create it - in which case, + * task_data->cached == TRUE and cc_object_storage_has_object (key) == TRUE - or we + * didn't have a cached proxy before, and we shouldn't have it now. + * + * This is to force consumers of this code to *never* try to create the same D-Bus + * proxy asynchronously multiple times. Trying to do so is considered a programming + * error. + */ + g_assert (task_data != NULL); + g_assert (task_data->cached == cc_object_storage_has_object (key)); + + /* Retrieve the newly created proxy */ + proxy = g_task_propagate_pointer (task, &local_error); + + /* If the proxy is not cached, do the normal caching routine */ + if (local_error) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return NULL; + } + + /* If the proxy is already cached, destroy the newly created and used the cached proxy + * instead. + */ + if (cc_object_storage_has_object (key)) + return cc_object_storage_get_object (key); + + /* Store the newly created D-Bus proxy */ + cc_object_storage_add_object (key, proxy); + + return g_steal_pointer (&proxy); +} + +/** + * cc_object_storage_init: + * + * Initializes the single CcObjectStorage. This must be called only once, + * and before every other method of this object. + */ +void +cc_object_storage_initialize (void) +{ + g_assert (_instance == NULL); + + if (g_once_init_enter (&_instance)) + { + CcObjectStorage *instance = g_object_new (CC_TYPE_OBJECT_STORAGE, NULL); + + g_debug ("Initializing object storage"); + + g_once_init_leave (&_instance, instance); + } +} + +/** + * cc_object_storage_destroy: + * + * Destroys the instance of #CcObjectStorage. This must be called only + * once during the application lifetime. It is a programming error to + * call this function multiple times + */ +void +cc_object_storage_destroy (void) +{ + g_assert (_instance != NULL); + + g_clear_object (&_instance); +} diff --git a/shell/cc-object-storage.h b/shell/cc-object-storage.h new file mode 100644 index 000000000..efea0e294 --- /dev/null +++ b/shell/cc-object-storage.h @@ -0,0 +1,65 @@ +/* cc-object-storage.h + * + * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +/* Default storage keys */ +#define CC_OBJECT_NMCLIENT "CcObjectStorage::nm-client" + + +#define CC_TYPE_OBJECT_STORAGE (cc_object_storage_get_type()) + +G_DECLARE_FINAL_TYPE (CcObjectStorage, cc_object_storage, CC, OBJECT_STORAGE, GObject) + +gboolean cc_object_storage_has_object (const gchar *key); + +void cc_object_storage_add_object (const gchar *key, + gpointer object); + +gpointer cc_object_storage_get_object (const gchar *key); + +gpointer cc_object_storage_create_dbus_proxy_sync (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GError **error); + +void cc_object_storage_create_dbus_proxy (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gpointer cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result, + GError **error); + +void cc_object_storage_initialize (void); + +void cc_object_storage_destroy (void); + +G_END_DECLS diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c index 0fd093cf9..f5b83509d 100644 --- a/shell/cc-panel-list.c +++ b/shell/cc-panel-list.c @@ -294,6 +294,7 @@ static const gchar * const panel_order[] = { "mouse", "printers", "removable-media", + "thunderbolt", "wacom", "color", diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c index df3a8020c..55492ef98 100644 --- a/shell/cc-panel-loader.c +++ b/shell/cc-panel-loader.c @@ -54,6 +54,9 @@ extern GType cc_region_panel_get_type (void); extern GType cc_search_panel_get_type (void); extern GType cc_sharing_panel_get_type (void); extern GType cc_sound_panel_get_type (void); +#ifdef BUILD_THUNDERBOLT +extern GType cc_bolt_panel_get_type (void); +#endif /* BUILD_THUNDERBOLT */ extern GType cc_ua_panel_get_type (void); extern GType cc_user_panel_get_type (void); #ifdef BUILD_WACOM @@ -99,6 +102,9 @@ static struct { PANEL_TYPE("search", cc_search_panel_get_type ), PANEL_TYPE("sharing", cc_sharing_panel_get_type ), PANEL_TYPE("sound", cc_sound_panel_get_type ), +#ifdef BUILD_THUNDERBOLT + PANEL_TYPE("thunderbolt", cc_bolt_panel_get_type ), +#endif PANEL_TYPE("universal-access", cc_ua_panel_get_type ), PANEL_TYPE("user-accounts", cc_user_panel_get_type ), #ifdef BUILD_WACOM diff --git a/shell/cc-shell-log.c b/shell/cc-shell-log.c deleted file mode 100644 index 14a122722..000000000 --- a/shell/cc-shell-log.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2009 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include "config.h" - -#include <glib.h> -#include <glib/gstdio.h> - -#include "cc-shell-log.h" - -static int log_levels = G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_ERROR | - G_LOG_LEVEL_WARNING | - G_LOG_LEVEL_MESSAGE | - G_LOG_LEVEL_INFO | - G_LOG_LEVEL_DEBUG; - -static void -cc_shell_log_default_handler (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer unused_data) -{ - if ((log_level & log_levels) == 0) - return; - - g_log_default_handler (log_domain, log_level, message, unused_data); -} - -void -cc_shell_log_init (void) -{ - g_log_set_default_handler (cc_shell_log_default_handler, NULL); -} - -void -cc_shell_log_set_debug (gboolean debug) -{ - - if (debug) { - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); - log_levels |= (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO); - g_debug ("Enabling debugging"); - } -} diff --git a/shell/cc-shell-model.c b/shell/cc-shell-model.c index 55f3e3c82..4dcddba45 100644 --- a/shell/cc-shell-model.c +++ b/shell/cc-shell-model.c @@ -19,23 +19,25 @@ * Author: Thomas Wood <thos@gnome.org> */ +#include "cc-shell-model.h" +#include "cc-util.h" + #include <string.h> #include <gio/gdesktopappinfo.h> -#include "cc-shell-model.h" -#include "cc-util.h" - #define GNOME_SETTINGS_PANEL_ID_KEY "X-GNOME-Settings-Panel" #define GNOME_SETTINGS_PANEL_CATEGORY GNOME_SETTINGS_PANEL_ID_KEY #define GNOME_SETTINGS_PANEL_ID_KEYWORDS "Keywords" -struct _CcShellModelPrivate +struct _CcShellModel { - gchar **sort_terms; + GtkListStore parent; + + GStrv sort_terms; }; -G_DEFINE_TYPE_WITH_PRIVATE (CcShellModel, cc_shell_model, GTK_TYPE_LIST_STORE) +G_DEFINE_TYPE (CcShellModel, cc_shell_model, GTK_TYPE_LIST_STORE) static gint sort_by_name (GtkTreeModel *model, @@ -224,20 +226,19 @@ cc_shell_model_sort_func (GtkTreeModel *model, gpointer data) { CcShellModel *self = data; - CcShellModelPrivate *priv = self->priv; - if (!priv->sort_terms || !priv->sort_terms[0]) + if (!self->sort_terms || !self->sort_terms[0]) return sort_by_name (model, a, b); else - return sort_with_terms (model, a, b, priv->sort_terms); + return sort_with_terms (model, a, b, self->sort_terms); } static void cc_shell_model_finalize (GObject *object) { - CcShellModelPrivate *priv = CC_SHELL_MODEL (object)->priv;; + CcShellModel *self = CC_SHELL_MODEL (object); - g_strfreev (priv->sort_terms); + g_clear_pointer (&self->sort_terms, g_strfreev); G_OBJECT_CLASS (cc_shell_model_parent_class)->finalize (object); } @@ -245,9 +246,8 @@ cc_shell_model_finalize (GObject *object) static void cc_shell_model_class_init (CcShellModelClass *klass) { - GObjectClass *gobject_class; + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = cc_shell_model_finalize; } @@ -257,8 +257,6 @@ cc_shell_model_init (CcShellModel *self) GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_APP_INFO, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV}; - self->priv = cc_shell_model_get_instance_private (self); - gtk_list_store_set_column_types (GTK_LIST_STORE (self), N_COLS, types); @@ -328,6 +326,30 @@ cc_shell_model_add_item (CcShellModel *model, } gboolean +cc_shell_model_has_panel (CcShellModel *model, + const char *id) +{ + GtkTreeIter iter; + gboolean valid; + + g_assert (id); + + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter); + while (valid) + { + g_autofree gchar *panel_id = NULL; + + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, COL_ID, &panel_id, -1); + if (g_str_equal (id, panel_id)) + return TRUE; + + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter); + } + + return FALSE; +} + +gboolean cc_shell_model_iter_matches_search (CcShellModel *model, GtkTreeIter *iter, const char *term) @@ -366,13 +388,14 @@ void cc_shell_model_set_sort_terms (CcShellModel *self, gchar **terms) { - CcShellModelPrivate *priv = self->priv; + g_return_if_fail (CC_IS_SHELL_MODEL (self)); - g_strfreev (priv->sort_terms); - priv->sort_terms = g_strdupv (terms); + g_clear_pointer (&self->sort_terms, g_strfreev); + self->sort_terms = g_strdupv (terms); /* trigger a re-sort */ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (self), cc_shell_model_sort_func, - self, NULL); + self, + NULL); } diff --git a/shell/cc-shell-model.h b/shell/cc-shell-model.h index 259407109..b0fe50ff6 100644 --- a/shell/cc-shell-model.h +++ b/shell/cc-shell-model.h @@ -18,9 +18,7 @@ * Author: Thomas Wood <thos@gnome.org> */ - -#ifndef _CC_SHELL_MODEL_H -#define _CC_SHELL_MODEL_H +#pragma once #include <gtk/gtk.h> @@ -28,31 +26,10 @@ G_BEGIN_DECLS #define CC_TYPE_SHELL_MODEL cc_shell_model_get_type() -#define CC_SHELL_MODEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - CC_TYPE_SHELL_MODEL, CcShellModel)) - -#define CC_SHELL_MODEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - CC_TYPE_SHELL_MODEL, CcShellModelClass)) - -#define CC_IS_SHELL_MODEL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - CC_TYPE_SHELL_MODEL)) - -#define CC_IS_SHELL_MODEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - CC_TYPE_SHELL_MODEL)) +G_DECLARE_FINAL_TYPE (CcShellModel, cc_shell_model, CC, SHELL_MODEL, GtkListStore) -#define CC_SHELL_MODEL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - CC_TYPE_SHELL_MODEL, CcShellModelClass)) - -typedef struct _CcShellModel CcShellModel; -typedef struct _CcShellModelClass CcShellModelClass; -typedef struct _CcShellModelPrivate CcShellModelPrivate; - -typedef enum { +typedef enum +{ CC_CATEGORY_CONNECTIVITY, CC_CATEGORY_PERSONALIZATION, CC_CATEGORY_ACCOUNT, @@ -77,34 +54,22 @@ enum N_COLS }; -struct _CcShellModel -{ - GtkListStore parent; - CcShellModelPrivate *priv; -}; +CcShellModel* cc_shell_model_new (void); -struct _CcShellModelClass -{ - GtkListStoreClass parent_class; -}; +void cc_shell_model_add_item (CcShellModel *model, + CcPanelCategory category, + GAppInfo *appinfo, + const char *id); -GType cc_shell_model_get_type (void) G_GNUC_CONST; +gboolean cc_shell_model_has_panel (CcShellModel *model, + const char *id); -CcShellModel *cc_shell_model_new (void); +gboolean cc_shell_model_iter_matches_search (CcShellModel *model, + GtkTreeIter *iter, + const char *term); -void cc_shell_model_add_item (CcShellModel *model, - CcPanelCategory category, - GAppInfo *appinfo, - const char *id); - -gboolean cc_shell_model_iter_matches_search (CcShellModel *model, - GtkTreeIter *iter, - const char *term); - -void cc_shell_model_set_sort_terms (CcShellModel *model, - gchar **terms); +void cc_shell_model_set_sort_terms (CcShellModel *model, + GStrv terms); G_END_DECLS - -#endif /* _CC_SHELL_MODEL_H */ diff --git a/shell/cc-window.c b/shell/cc-window.c index f7593dc55..50d3995d7 100644 --- a/shell/cc-window.c +++ b/shell/cc-window.c @@ -20,6 +20,8 @@ * Author: Thomas Wood <thos@gnome.org> */ +#define G_LOG_DOMAIN "cc-window" + #include <config.h> #include "cc-window.h" @@ -31,6 +33,7 @@ #include <gdk/gdkkeysyms.h> #include <gdk/gdkx.h> #include <string.h> +#include <time.h> #include "cc-panel.h" #include "cc-shell.h" @@ -62,6 +65,7 @@ struct _CcWindow GtkWidget *search_entry; GtkWidget *lock_button; GtkWidget *current_panel_box; + GtkWidget *development_warning_dialog; GtkWidget *current_panel; char *current_panel_id; GQueue *previous_panels; @@ -88,8 +92,49 @@ enum }; /* Auxiliary methods */ -static const gchar * -get_icon_name_from_g_icon (GIcon *gicon) +static gboolean +in_flatpak_sandbox (void) +{ + return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS); +} + +static void +add_development_build_css (CcWindow *self) +{ + g_autoptr(GtkCssProvider) provider = NULL; + g_autoptr(GError) error = NULL; + + /* This CSS snipped is added on development builds of GNOME Settings. It is + * not meant to be beautiful (althout it is) and is only supposed to integrate + * with Adwaita light (although it integrates well with dark too). + */ + + const gchar *development_build_css = + "window.development-version headerbar {\n" + " background: @theme_bg_color linear-gradient(to top,\n" + " alpha(@theme_selected_bg_color, 0.34),\n" + " alpha(@theme_selected_bg_color, 0.27) 2px,\n" + " alpha(@theme_selected_bg_color, 0.20) 3px);\n" + "}"; + + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "development-version"); + + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, development_build_css, -1, &error); + + if (error) + { + g_error ("Failed to load CSS: %s", error->message); + return; + } + + gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (GTK_WIDGET (self)), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); +} + +static gchar * +get_symbolic_icon_name_from_g_icon (GIcon *gicon) { const gchar * const *names; GtkIconTheme *icon_theme; @@ -103,8 +148,11 @@ get_icon_name_from_g_icon (GIcon *gicon) for (i = 0; names[i] != NULL; i++) { - if (gtk_icon_theme_has_icon (icon_theme, names[i])) - return names[i]; + g_autofree gchar *name = NULL; + name = g_strdup_printf ("%s-symbolic", names[i]); + + if (gtk_icon_theme_has_icon (icon_theme, name)) + return g_steal_pointer (&name); } return NULL; @@ -117,14 +165,20 @@ activate_panel (CcWindow *self, const gchar *name, GIcon *gicon) { + g_autoptr (GTimer) timer = NULL; GtkWidget *box, *title_widget; - const gchar *icon_name; + gdouble ellapsed_time; if (!id) return FALSE; + timer = g_timer_new (); + g_settings_set_string (self->settings, "last-panel", id); + /* Begin the profile */ + g_timer_start (timer); + self->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, parameters)); cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (self->current_panel)); gtk_widget_show (self->current_panel); @@ -144,18 +198,21 @@ activate_panel (CcWindow *self, gtk_stack_set_visible_child_name (GTK_STACK (self->stack), id); /* set the title of the window */ - icon_name = get_icon_name_from_g_icon (gicon); - gtk_window_set_role (GTK_WINDOW (self), id); gtk_header_bar_set_title (GTK_HEADER_BAR (self->panel_headerbar), name); - gtk_window_set_default_icon_name (icon_name); - gtk_window_set_icon_name (GTK_WINDOW (self), icon_name); title_widget = cc_panel_get_title_widget (CC_PANEL (self->current_panel)); gtk_header_bar_set_custom_title (GTK_HEADER_BAR (self->panel_headerbar), title_widget); self->current_panel_box = box; + /* Finish profiling */ + g_timer_stop (timer); + + ellapsed_time = g_timer_elapsed (timer, NULL); + + g_debug ("Time to open panel '%s': %lfs", name, ellapsed_time); + return TRUE; } @@ -253,9 +310,8 @@ setup_model (CcWindow *shell) g_autofree gchar *name = NULL; g_autofree gchar *description = NULL; g_autofree gchar *id = NULL; - g_autofree gchar *symbolic_icon = NULL; + g_autofree gchar *icon_name = NULL; g_autofree GStrv keywords = NULL; - const gchar *icon_name; gtk_tree_model_get (model, &iter, COL_CATEGORY, &category, @@ -266,8 +322,7 @@ setup_model (CcWindow *shell) COL_KEYWORDS, &keywords, -1); - icon_name = get_icon_name_from_g_icon (icon); - symbolic_icon = g_strdup_printf ("%s-symbolic", icon_name); + icon_name = get_symbolic_icon_name_from_g_icon (icon); cc_panel_list_add_panel (CC_PANEL_LIST (shell->panel_list), category, @@ -275,7 +330,7 @@ setup_model (CcWindow *shell) name, description, keywords, - symbolic_icon); + icon_name); valid = gtk_tree_model_iter_next (model, &iter); } @@ -288,12 +343,15 @@ set_active_panel_from_id (CcShell *shell, GVariant *parameters, GError **error) { + g_autoptr(GIcon) gicon = NULL; + g_autofree gchar *name = NULL; GtkTreeIter iter; - gboolean iter_valid; - gchar *name = NULL; - GIcon *gicon = NULL; - CcWindow *self = CC_WINDOW (shell); GtkWidget *old_panel; + CcWindow *self; + gboolean iter_valid; + gboolean activated; + + self = CC_WINDOW (shell); /* When loading the same panel again, just set its parameters */ if (g_strcmp0 (self->current_panel_id, start_id) == 0) @@ -332,26 +390,25 @@ set_active_panel_from_id (CcShell *shell, if (!name) { g_warning ("Could not find settings panel \"%s\"", start_id); + return TRUE; } - else if (!activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon)) - { - /* Failed to activate the panel for some reason, - * let's keep the old panel around instead */ - } - else - { - /* Successful activation */ - g_free (self->current_panel_id); - self->current_panel_id = g_strdup (start_id); - if (old_panel) - gtk_container_remove (GTK_CONTAINER (self->stack), old_panel); + /* Activate the panel */ + activated = activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon); - cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id); - } + /* Failed to activate the panel for some reason, let's keep the old + * panel around instead */ + if (!activated) + return TRUE; - g_clear_pointer (&name, g_free); - g_clear_object (&gicon); + /* Successful activation */ + g_free (self->current_panel_id); + self->current_panel_id = g_strdup (start_id); + + if (old_panel) + gtk_container_remove (GTK_CONTAINER (self->stack), old_panel); + + cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id); return TRUE; } @@ -370,13 +427,10 @@ set_active_panel (CcWindow *shell, /* set the new panel */ if (panel) - { - shell->active_panel = g_object_ref (panel); - } + shell->active_panel = g_object_ref (panel); else - { - shell_show_overview_page (shell); - } + shell_show_overview_page (shell); + g_object_notify (G_OBJECT (shell), "active-panel"); } } @@ -568,6 +622,17 @@ split_decorations_cb (GtkSettings *settings, gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (self->panel_headerbar), layout_end); } +static void +on_development_warning_dialog_responded_cb (GtkWidget *dialog, + gint response, + CcWindow *self) +{ + g_debug ("Disabling development build warning dialog"); + g_settings_set_boolean (self->settings, "show-development-warning", FALSE); + + gtk_widget_hide (dialog); +} + /* CcShell implementation */ static gboolean cc_window_set_active_panel_from_id (CcShell *shell, @@ -606,6 +671,19 @@ cc_shell_iface_init (CcShellInterface *iface) iface->get_toplevel = cc_window_get_toplevel; } +/* GtkWidget overrides */ +static void +cc_window_map (GtkWidget *widget) +{ + CcWindow *self = (CcWindow *) widget; + + GTK_WIDGET_CLASS (cc_window_parent_class)->map (widget); + + /* Show a warning for Flatpak builds */ + if (in_flatpak_sandbox () && g_settings_get_boolean (self->settings, "show-development-warning")) + gtk_window_present (GTK_WINDOW (self->development_warning_dialog)); +} + /* GObject Implementation */ static void cc_window_get_property (GObject *object, @@ -683,10 +761,13 @@ cc_window_class_init (CcWindowClass *klass) object_class->dispose = cc_window_dispose; object_class->finalize = cc_window_finalize; + widget_class->map = cc_window_map; + g_object_class_override_property (object_class, PROP_ACTIVE_PANEL, "active-panel"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/ControlCenter/gtk/window.ui"); + gtk_widget_class_bind_template_child (widget_class, CcWindow, development_warning_dialog); gtk_widget_class_bind_template_child (widget_class, CcWindow, header); gtk_widget_class_bind_template_child (widget_class, CcWindow, header_box); gtk_widget_class_bind_template_child (widget_class, CcWindow, header_sizegroup); @@ -702,6 +783,7 @@ cc_window_class_init (CcWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, CcWindow, top_right_box); gtk_widget_class_bind_template_callback (widget_class, gdk_window_set_cb); + gtk_widget_class_bind_template_callback (widget_class, on_development_warning_dialog_responded_cb); gtk_widget_class_bind_template_callback (widget_class, panel_list_view_changed_cb); gtk_widget_class_bind_template_callback (widget_class, previous_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, search_entry_activate_cb); @@ -744,10 +826,14 @@ cc_window_init (CcWindow *self) /* After everything is loaded, select the last used panel, if any, * or the first visible panel */ id = g_settings_get_string (self->settings, "last-panel"); - if (id != NULL && *id != '\0') + if (id != NULL && cc_shell_model_has_panel (CC_SHELL_MODEL (self->store), id)) cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), id); else cc_panel_list_activate (CC_PANEL_LIST (self->panel_list)); + + /* Add a custom CSS class on development builds */ + if (in_flatpak_sandbox ()) + add_development_build_css (self); } CcWindow * @@ -779,4 +865,4 @@ cc_window_set_search_item (CcWindow *center, gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (center->search_bar), TRUE); gtk_entry_set_text (GTK_ENTRY (center->search_entry), search); gtk_editable_set_position (GTK_EDITABLE (center->search_entry), -1); -}
\ No newline at end of file +} diff --git a/shell/meson.build b/shell/meson.build index d9364521b..73b18f84e 100644 --- a/shell/meson.build +++ b/shell/meson.build @@ -7,53 +7,50 @@ service_conf.set('bindir', control_center_bindir) service = 'org.gnome.ControlCenter.service' configure_file( - input: service + '.in', - output: service, - install: true, - install_dir: join_paths(control_center_datadir, 'dbus-1', 'services'), - configuration: service_conf + input : service + '.in', + output : service, + install : true, + install_dir : join_paths(control_center_datadir, 'dbus-1', 'services'), + configuration : service_conf ) desktop = 'gnome-control-center.desktop' desktop_in = configure_file( - input: desktop + '.in.in', - output: desktop + '.in', - configuration: desktop_conf + input : desktop + '.in.in', + output : desktop + '.in', + configuration : desktop_conf ) i18n.merge_file( - desktop, - type: 'desktop', - input: desktop_in, - output: desktop, - po_dir: po_dir, - install: true, - install_dir: control_center_desktopdir + desktop, + type : 'desktop', + input : desktop_in, + output : desktop, + po_dir : po_dir, + install : true, + install_dir : control_center_desktopdir ) cflags = ['-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)] libshell = static_library( - 'shell', - sources: 'cc-shell-model.c', - include_directories: [top_inc, common_inc], - dependencies: common_deps, - c_args: cflags + 'shell', + sources : 'cc-shell-model.c', + include_directories : [top_inc, common_inc], + dependencies : common_deps, + c_args : cflags ) -common_sources = files( +sources = files( 'cc-application.c', - 'cc-editable-entry.c', - 'cc-hostname-entry.c', + 'cc-log.c', + 'cc-object-storage.c', 'cc-panel-loader.c', 'cc-panel.c', 'cc-shell-category-view.c', 'cc-shell-item-view.c', - 'cc-shell-log.c', 'cc-shell.c', - 'hostname-helper.c', - 'list-box-helper.c', 'main.c' ) @@ -63,14 +60,14 @@ resource_data = files( 'window.ui' ) -common_sources += gnome.compile_resources( +sources += gnome.compile_resources( 'resources', meson.project_name() + '.gresource.xml', dependencies: resource_data, export: true ) -sources = common_sources + files( +sources += files( 'cc-panel-list.c', 'cc-window.c' ) @@ -78,7 +75,7 @@ sources = common_sources + files( shell_deps = common_deps + [ libdevice_dep, liblanguage_dep, - polkit_gobject_dep, + libwidgets_dep, x11_dep ] @@ -90,48 +87,61 @@ if host_is_linux_not_s390 shell_deps += wacom_deps endif +# Debug +debug_conf = configuration_data() +debug_conf.set('BUGREPORT_URL', 'http://bugzilla.gnome.org/enter_bug.cgi?product=' + meson.project_name()) +debug_conf.set10('ENABLE_TRACING', enable_tracing) + +sources += configure_file( + input : 'cc-debug.h.in', + output : 'cc-debug.h', + configuration : debug_conf +) + executable( meson.project_name(), - sources, - include_directories: top_inc, - dependencies: shell_deps, - c_args: cflags, - link_with: panels_libs + [libshell], - install: true + sources, + include_directories : top_inc, + dependencies : shell_deps, + c_args : cflags, + link_with : panels_libs + [libshell], + install : true ) # Because it is confusing and somewhat problematic to directly add and compile # cc-panel-loader.o by another directory (i.e. the shell search provider), we # have to create a library and link it there, just like libshell.la. libpanel_loader = static_library( - 'panel_loader', - sources: 'cc-panel-loader.c', - include_directories: top_inc, - dependencies: common_deps, - c_args: cflags + ['-DCC_PANEL_LOADER_NO_GTYPES'] + 'panel_loader', + sources : 'cc-panel-loader.c', + include_directories : top_inc, + dependencies : common_deps, + c_args : cflags + ['-DCC_PANEL_LOADER_NO_GTYPES'] ) -test_unit = 'test-hostname' - +# libshell_test sources = files( - 'hostname-helper.c', - test_unit + '.c' + 'cc-panel.c', + 'cc-shell.c', + 'cc-log.c', + 'cc-object-storage.c', ) - -cflags += [ - '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()), - '-DTEST_TOPSRCDIR="@0@"'.format(meson.source_root()) -] - -exe = executable( - test_unit, - sources, - include_directories: top_inc, - dependencies: common_deps, - c_args: cflags +libtestshell = static_library( + 'testshell', + sources, + include_directories : top_inc, + dependencies : common_deps + [ libwidgets_dep ], + c_args : cflags, + link_with : panels_libs +) +libtestshell_dep = declare_dependency( + include_directories : top_inc, + link_with : libtestshell ) +libtestshell_deps = common_deps + [ libwidgets_dep, libtestshell_dep ] -test(test_unit, exe) -install_data ('org.gnome.ControlCenter.gschema.xml', - install_dir: control_center_schemadir) +install_data ( + 'org.gnome.ControlCenter.gschema.xml', + install_dir : control_center_schemadir +) diff --git a/shell/org.gnome.ControlCenter.gschema.xml b/shell/org.gnome.ControlCenter.gschema.xml index a40b9b08c..40350bca4 100644 --- a/shell/org.gnome.ControlCenter.gschema.xml +++ b/shell/org.gnome.ControlCenter.gschema.xml @@ -8,5 +8,12 @@ will be ignored and the first panel in the list selected. </description> </key> + <key name="show-development-warning" type="b"> + <default>true</default> + <summary>Show warning when running a development build of Settings</summary> + <description> + Whether Settings should show a warning when running a development build. + </description> + </key> </schema> </schemalist> diff --git a/shell/window.ui b/shell/window.ui index 92ff197ce..c34ce60bc 100644 --- a/shell/window.ui +++ b/shell/window.ui @@ -224,4 +224,17 @@ <widget name="sidebar_box"/> </widgets> </object> + + <!-- Warning dialog for development builds --> + <object class="GtkMessageDialog" id="development_warning_dialog"> + <property name="message-type">warning</property> + <property name="transient-for">CcWindow</property> + <property name="resizable">false</property> + <property name="modal">true</property> + <property name="buttons">ok</property> + <property name="text" translatable="yes">Warning: Development Version</property> + <property name="secondary-text" translatable="yes">This version of Settings should only be used for development purposes. You may experience incorrect system behavior, data loss, and other unexpected issues. </property> + <signal name="response" handler="on_development_warning_dialog_responded_cb" object="CcWindow" swapped="no" /> + </object> + </interface> diff --git a/tests/ci-helper.sh b/tests/ci-helper.sh new file mode 100755 index 000000000..f8409dd21 --- /dev/null +++ b/tests/ci-helper.sh @@ -0,0 +1,61 @@ +#!/bin/bash -e + +function do_print_labels(){ + + if [[ -n "${1}" ]]; then + label_len=${#1} + span=$(((54 - $label_len) / 2)) + + echo + echo "= ======================================================== =" + printf "%s %${span}s %s %${span}s %s\n" "=" "" "$1" "" "=" + echo "= ======================================================== =" + else + echo "= ========================= Done ========================= =" + echo + fi +} + +function do_show_info(){ + + local compiler=gcc + + echo -n "Processors: "; grep -c ^processor /proc/cpuinfo + grep ^MemTotal /proc/meminfo + id; uname -a + printenv + echo '-----------------------------------------' + cat /etc/*-release + echo '-----------------------------------------' + + if [[ ! -z $CC ]]; then + compiler=$CC + fi + echo 'Compiler version' + $compiler --version + echo '-----------------------------------------' + $compiler -dM -E -x c /dev/null + echo '-----------------------------------------' +} + +function do_check_warnings(){ + + cat compilation.log | grep "warning:" | awk '{total+=1}END{print "Total number of warnings: "total}' +} + +# ----------- ----------- +if [[ $1 == "INFO" ]]; then + do_print_labels 'Build environment ' + do_show_info + do_print_labels + +elif [[ $1 == "GIT_INFO" ]]; then + do_print_labels 'The Commit' + git log --pretty=format:"%h %cd %s" -1; echo + do_print_labels + +elif [[ $1 == "WARNINGS" ]]; then + do_print_labels 'Warnings Report ' + do_check_warnings + do_print_labels +fi diff --git a/shell/hostnames-test.txt b/tests/common/hostnames-test.txt index 5a31ce28b..5a31ce28b 100644 --- a/shell/hostnames-test.txt +++ b/tests/common/hostnames-test.txt diff --git a/tests/common/meson.build b/tests/common/meson.build new file mode 100644 index 000000000..4d982f029 --- /dev/null +++ b/tests/common/meson.build @@ -0,0 +1,23 @@ + + +test_unit = 'test-hostname' + +sources = files( + test_unit + '.c' +) + +cflags = [ + '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()), + '-DTEST_TOPSRCDIR="@0@"'.format(meson.source_root()) +] + +exe = executable( + test_unit, + sources, + include_directories : [ top_inc, common_inc ], + dependencies : common_deps + [libwidgets_dep], + c_args : cflags, +) + +test(test_unit, exe) + diff --git a/shell/ssids-test.txt b/tests/common/ssids-test.txt index 0545437cf..0545437cf 100644 --- a/shell/ssids-test.txt +++ b/tests/common/ssids-test.txt diff --git a/shell/test-hostname.c b/tests/common/test-hostname.c index 3df293051..4e14f715a 100644 --- a/shell/test-hostname.c +++ b/tests/common/test-hostname.c @@ -129,8 +129,8 @@ int main (int argc, char **argv) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); g_test_init (&argc, &argv, NULL); - g_test_add_func ("/shell/hostname", test_hostname); - g_test_add_func ("/shell/ssid", test_ssid); + g_test_add_func ("/common/hostname", test_hostname); + g_test_add_func ("/common/ssid", test_ssid); return g_test_run (); } diff --git a/tests/datetime/meson.build b/tests/datetime/meson.build new file mode 100644 index 000000000..fd0896400 --- /dev/null +++ b/tests/datetime/meson.build @@ -0,0 +1,35 @@ + +test_units = [ + 'test-timezone', + 'test-timezone-gfx', + 'test-endianess', +] + +includes = [top_inc, include_directories('../../panels/datetime')] +env = [ + 'G_MESSAGES_DEBUG=all', + 'BUILDDIR=' + meson.current_build_dir(), + 'TOP_BUILDDIR=' + meson.build_root() +] +cflags = [ + '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()), + '-DSRCDIR="@0@"'.format(meson.source_root() + '/panels/datetime') +] + +foreach unit: test_units + exe = executable( + unit, + [unit + '.c'], + include_directories : includes, + dependencies : common_deps + [m_dep], + link_with : [datetime_panel_lib], + c_args : cflags + ) +endforeach + +test( + 'test-datetime', + find_program('test-datetime.py'), + env : env, + timeout : 10 +)
\ No newline at end of file diff --git a/tests/datetime/test-datetime.py b/tests/datetime/test-datetime.py new file mode 100644 index 000000000..c478374a8 --- /dev/null +++ b/tests/datetime/test-datetime.py @@ -0,0 +1,54 @@ +#!/usr/bin/python3 +# Copyright © 2018 Red Hat, Inc +# 2018 Endless Mobile, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Authors: Benjamin Berg <bberg@redhat.com> +# Georges Basile Stavracas Neto <georges@endlessm.com> + +import os +import sys +import unittest + +try: + import dbusmock +except ImportError: + sys.stderr.write('You need python-dbusmock (http://pypi.python.org/pypi/python-dbusmock) for this test suite.\n') + sys.exit(1) + +# Add the shared directory to the search path +sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'shared')) + +from gtest import GTest +from x11session import X11SessionTestCase + +BUILDDIR = os.environ.get('BUILDDIR', os.path.join(os.path.dirname(__file__))) + + +class EndianessTestCase(X11SessionTestCase, GTest): + g_test_exe = os.path.join(BUILDDIR, 'test-endianess') + + +class TimezoneTestCase(X11SessionTestCase, GTest): + g_test_exe = os.path.join(BUILDDIR, 'test-timezone') + + +class TimezoneGfxTestCase(X11SessionTestCase, GTest): + g_test_exe = os.path.join(BUILDDIR, 'test-timezone-gfx') + + +if __name__ == '__main__': + _test = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) + unittest.main(testRunner=_test)
\ No newline at end of file diff --git a/panels/datetime/test-endianess.c b/tests/datetime/test-endianess.c index 06b26131b..06b26131b 100644 --- a/panels/datetime/test-endianess.c +++ b/tests/datetime/test-endianess.c diff --git a/tests/datetime/test-timezone-gfx.c b/tests/datetime/test-timezone-gfx.c new file mode 100644 index 000000000..22619c30c --- /dev/null +++ b/tests/datetime/test-timezone-gfx.c @@ -0,0 +1,74 @@ +#include <config.h> +#include <locale.h> +#include <gtk/gtk.h> + +#include "cc-datetime-resources.h" +#include "tz.h" + +static void +test_timezone_gfx (gconstpointer data) +{ + g_autoptr(TzDB) db = NULL; + GPtrArray *locs; + const char *pixmap_dir; + guint i; + + pixmap_dir = data; + db = tz_load_db (); + locs = tz_get_locations (db); + + for (i = 0; i < locs->len ; i++) + { + g_autofree gchar *filename = NULL; + g_autofree gchar *path = NULL; + TzLocation *location; + TzInfo *info; + gdouble selected_offset; + gchar buf[16]; + + location = locs->pdata[i]; + info = tz_info_from_location (location); + selected_offset = tz_location_get_utc_offset (location) / (60.0 * 60.0) + (info->daylight ? -1.0 : 0.0); + + filename = g_strdup_printf ("timezone_%s.png", g_ascii_formatd (buf, sizeof (buf), "%g", selected_offset)); + path = g_build_filename (pixmap_dir, filename, NULL); + + if (!g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + g_message ("File '%s' missing for zone '%s'", filename, location->zone); + g_test_fail (); + } + } +} + +gint +main (gint argc, + gchar **argv) +{ + gchar *pixmap_dir; + + setlocale (LC_ALL, ""); + g_test_init (&argc, &argv, NULL); + + g_setenv ("G_DEBUG", "fatal_warnings", FALSE); + + g_resources_register (cc_datetime_get_resource ()); + + if (argc == 2) + { + pixmap_dir = g_strdup (argv[1]); + } + else if (argc == 1) + { + pixmap_dir = g_strdup (SRCDIR "/data/"); + } + else + { + g_message ("Usage: %s [PIXMAP DIRECTORY]", argv[0]); + return 1; + } + + g_test_add_data_func ("/datetime/timezone-gfx", pixmap_dir, test_timezone_gfx); + + return g_test_run (); +} diff --git a/tests/datetime/test-timezone.c b/tests/datetime/test-timezone.c new file mode 100644 index 000000000..5962fc45e --- /dev/null +++ b/tests/datetime/test-timezone.c @@ -0,0 +1,65 @@ +#include <locale.h> +#include <gtk/gtk.h> +#include "cc-datetime-resources.h" +#include "cc-timezone-map.h" + +static void +test_timezone (void) +{ + g_autoptr(GHashTable) ht = NULL; + CcTimezoneMap *map; + TzDB *tz_db; + guint i; + + ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + map = cc_timezone_map_new (); + tz_db = tz_load_db (); + + g_assert_nonnull (tz_db); + g_assert_nonnull (tz_db->locations); + + for (i = 0; tz_db->locations && i < tz_db->locations->len; i++) + { + g_autofree gchar *clean_tz = NULL; + TzLocation *location = NULL; + + location = g_ptr_array_index (tz_db->locations, i); + clean_tz = tz_info_get_clean_name (tz_db, location->zone); + + if (!cc_timezone_map_set_timezone (map, location->zone)) + { + if (!g_hash_table_contains (ht, clean_tz)) + { + if (g_strcmp0 (clean_tz, location->zone) == 0) + g_printerr ("Failed to locate timezone '%s'\n", location->zone); + else + g_printerr ("Failed to locate timezone '%s' (original name: '%s')\n", clean_tz, location->zone); + g_hash_table_insert (ht, g_strdup (clean_tz), GINT_TO_POINTER (TRUE)); + } + + /* We don't warn for those, we'll just fallback + * in the panel code */ + if (!g_str_equal (clean_tz, "posixrules") && !g_str_equal (clean_tz, "Factory")) + g_test_fail (); + } + } + + tz_db_free (tz_db); +} + +gint +main (gint argc, + gchar **argv) +{ + setlocale (LC_ALL, ""); + gtk_init (NULL, NULL); + g_test_init (&argc, &argv, NULL); + + g_resources_register (cc_datetime_get_resource ()); + + g_setenv ("G_DEBUG", "fatal_warnings", FALSE); + + g_test_add_func ("/datetime/timezone", test_timezone); + + return g_test_run (); +} diff --git a/panels/info/info-cleanup-test.txt b/tests/info/info-cleanup-test.txt index 29f4e79fc..29f4e79fc 100644 --- a/panels/info/info-cleanup-test.txt +++ b/tests/info/info-cleanup-test.txt diff --git a/tests/info/meson.build b/tests/info/meson.build new file mode 100644 index 000000000..202e9e34e --- /dev/null +++ b/tests/info/meson.build @@ -0,0 +1,21 @@ + +test_units = [ + 'test-info-cleanup' +] + +includes = [top_inc, include_directories('../../panels/info')] +cflags = '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()) + +foreach unit: test_units + exe = executable( + unit, + [unit + '.c'], + include_directories : includes, + dependencies : common_deps, + link_with : [info_panel_lib], + c_args : cflags + ) + + test(unit, exe) +endforeach + diff --git a/panels/info/test-info-cleanup.c b/tests/info/test-info-cleanup.c index 3e6bebd2e..3e6bebd2e 100644 --- a/panels/info/test-info-cleanup.c +++ b/tests/info/test-info-cleanup.c diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 000000000..33b460148 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,7 @@ +subdir('common') +subdir('datetime') +if host_is_linux + subdir('network') +endif +subdir('printers') +subdir('info') diff --git a/tests/network/cc-test-window.c b/tests/network/cc-test-window.c new file mode 100644 index 000000000..dcda579b3 --- /dev/null +++ b/tests/network/cc-test-window.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2009, 2010 Intel, Inc. + * Copyright (c) 2010, 2018 Red Hat, Inc. + * Copyright (c) 2016 Endless, Inc. + * + * The Control Center 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. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Benjamin Berg <bberg@redhat.com> + */ + +#define G_LOG_DOMAIN "cc-test-window" + +#include <config.h> + +#include "cc-test-window.h" + +#include <gio/gio.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> +#include <string.h> + +#include "shell/cc-panel.h" +#include "shell/cc-shell.h" +#include "cc-util.h" + + +struct _CcTestWindow +{ + GtkWindow parent; + + GtkWidget *main_box; + + GtkWidget *header; + CcPanel *active_panel; +}; + +static void cc_shell_iface_init (CcShellInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (CcTestWindow, cc_test_window, GTK_TYPE_WINDOW, + G_IMPLEMENT_INTERFACE (CC_TYPE_SHELL, cc_shell_iface_init)) + +enum +{ + PROP_0, + PROP_ACTIVE_PANEL +}; + + + +static void +set_active_panel (CcTestWindow *shell, + CcPanel *panel) +{ + g_assert (CC_IS_SHELL (shell)); + g_assert (CC_IS_PANEL (panel)); + + /* Only allow setting to a non NULL value once. */ + g_assert (shell->active_panel == NULL); + + if (panel) + { + shell->active_panel = g_object_ref (panel); + gtk_container_add_with_properties (GTK_CONTAINER (shell->main_box), GTK_WIDGET (panel), + "pack-type", GTK_PACK_END, + "expand", TRUE, + "fill", TRUE, + NULL); + } +} + +/* CcShell implementation */ +static gboolean +cc_test_window_set_active_panel_from_id (CcShell *shell, + const gchar *start_id, + GVariant *parameters, + GError **error) +{ + /* Not implemented */ + g_assert_not_reached (); +} + +static void +cc_test_window_embed_widget_in_header (CcShell *shell, + GtkWidget *widget) +{ + CcTestWindow *self = CC_TEST_WINDOW (shell); + + /* add to main box */ + gtk_container_add_with_properties (GTK_CONTAINER (self->main_box), GTK_WIDGET (widget), + "pack-type", GTK_PACK_START, + "expand", FALSE, + "fill", TRUE, + NULL); + gtk_widget_show (widget); +} + +static GtkWidget * +cc_test_window_get_toplevel (CcShell *shell) +{ + return GTK_WIDGET (shell); +} + +static void +cc_shell_iface_init (CcShellInterface *iface) +{ + iface->set_active_panel_from_id = cc_test_window_set_active_panel_from_id; + iface->embed_widget_in_header = cc_test_window_embed_widget_in_header; + iface->get_toplevel = cc_test_window_get_toplevel; +} + +/* GObject Implementation */ +static void +cc_test_window_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + CcTestWindow *self = CC_TEST_WINDOW (object); + + switch (property_id) + { + case PROP_ACTIVE_PANEL: + g_value_set_object (value, self->active_panel); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_test_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CcTestWindow *shell = CC_TEST_WINDOW (object); + + switch (property_id) + { + case PROP_ACTIVE_PANEL: + set_active_panel (shell, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_test_window_dispose (GObject *object) +{ + CcTestWindow *self = CC_TEST_WINDOW (object); + + g_clear_object (&self->active_panel); + + G_OBJECT_CLASS (cc_test_window_parent_class)->dispose (object); +} + +static void +cc_test_window_class_init (CcTestWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cc_test_window_get_property; + object_class->set_property = cc_test_window_set_property; + object_class->dispose = cc_test_window_dispose; + + g_object_class_override_property (object_class, PROP_ACTIVE_PANEL, "active-panel"); +} + +static void +cc_test_window_init (CcTestWindow *self) +{ + gtk_widget_set_size_request (GTK_WIDGET (self), 500, 800); + + self->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + + gtk_container_add (GTK_CONTAINER (self), self->main_box); +} + +CcTestWindow * +cc_test_window_new (void) +{ + return g_object_new (CC_TYPE_TEST_WINDOW, + "resizable", TRUE, + "title", "Test Settings", + "window-position", GTK_WIN_POS_CENTER, + NULL); +} diff --git a/tests/network/cc-test-window.h b/tests/network/cc-test-window.h new file mode 100644 index 000000000..abbdb61a0 --- /dev/null +++ b/tests/network/cc-test-window.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010 Intel, Inc. + * Copyright (c) 2018 Red Hat, Inc. + * + * The Control Center 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. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Benjamin Berg <bberg@redhat.com> + */ + +#pragma once + +#include <glib-object.h> +#include "shell/cc-shell.h" + +G_BEGIN_DECLS + +#define CC_TYPE_TEST_WINDOW (cc_test_window_get_type ()) + +G_DECLARE_FINAL_TYPE (CcTestWindow, cc_test_window, CC, TEST_WINDOW, GtkWindow) + +CcTestWindow *cc_test_window_new (void); + +G_END_DECLS diff --git a/tests/network/meson.build b/tests/network/meson.build new file mode 100644 index 000000000..5c929232b --- /dev/null +++ b/tests/network/meson.build @@ -0,0 +1,31 @@ + + +includes = [top_inc, include_directories('../../panels/network', 'nm-utils')] +cflags = [ + '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_WITH_GLIB', + '-DNETWORKMANAGER_COMPILATION_TEST', + '-DTEST_NM_SERVICE="@0@"'.format(join_paths(meson.source_root(), 'tests', 'network', 'nm-utils', 'test-networkmanager-service.py')), +] + +exe = executable( + 'test-network-panel', + ['test-network-panel.c', 'cc-test-window.c', 'nm-utils/nm-test-utils-impl.c'], + include_directories : includes + [common_inc], + dependencies : common_deps + network_manager_deps + [libtestshell_dep], + link_with : [network_panel_lib], + c_args : cflags +) + +envs = [ + 'G_MESSAGES_DEBUG=all', + 'BUILDDIR=' + meson.current_build_dir(), + 'TOP_BUILDDIR=' + meson.build_root() +] + +test( + 'test-network-panel', + find_program('test-network-panel.py'), + env : envs, + timeout : 10 +) diff --git a/tests/network/nm-utils/README b/tests/network/nm-utils/README new file mode 100644 index 000000000..2b613ed5e --- /dev/null +++ b/tests/network/nm-utils/README @@ -0,0 +1,17 @@ +These files are either copied from NetworkManager or just empty files. The +files live in the nn-utils subdirectory as that makes the relative +includes that they contain work fine. + +The test-networkmanager-service.py is also from NetworkManager. It is +however extended for our use here. + +gsystem-local-alloc.h: shared/nm-utils/gsystem-local-alloc.h +nm-glib.h: shared/nm-utils/nm-glib.h +nm-macros-internal.h: shared/nm-utils/nm-macros-internal.h +nm-default.h: shared/nm-default.h +nm-dbus-compat.h: shared/nm-dbus-compat.h +nm-default.h: shared/nm-default.h +nm-test-utils-impl.c: shared/nm-test-utils-impl.c +nm-shared-utils.h: empty +nm-test-libnm-utils.h: empty +nm-hash-utils.h: empty diff --git a/tests/network/nm-utils/gsystem-local-alloc.h b/tests/network/nm-utils/gsystem-local-alloc.h new file mode 100644 index 000000000..51b625197 --- /dev/null +++ b/tests/network/nm-utils/gsystem-local-alloc.h @@ -0,0 +1,208 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2012 Colin Walters <walters@verbum.org>. + * + * 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 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GSYSTEM_LOCAL_ALLOC_H__ +#define __GSYSTEM_LOCAL_ALLOC_H__ + +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define GS_DEFINE_CLEANUP_FUNCTION(Type, name, func) \ + static inline void name (void *v) \ + { \ + func (*(Type*)v); \ + } + +#define GS_DEFINE_CLEANUP_FUNCTION0(Type, name, func) \ + static inline void name (void *v) \ + { \ + if (*(Type*)v) \ + func (*(Type*)v); \ + } + +/* These functions shouldn't be invoked directly; + * they are stubs that: + * 1) Take a pointer to the location (typically itself a pointer). + * 2) Provide %NULL-safety where it doesn't exist already (e.g. g_object_unref) + */ + +/** + * gs_free: + * + * Call g_free() on a variable location when it goes out of scope. + */ +#define gs_free __attribute__ ((cleanup(gs_local_free))) +GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free) + +/** + * gs_unref_object: + * + * Call g_object_unref() on a variable location when it goes out of + * scope. Note that unlike g_object_unref(), the variable may be + * %NULL. + */ +#define gs_unref_object __attribute__ ((cleanup(gs_local_obj_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref) + +/** + * gs_unref_variant: + * + * Call g_variant_unref() on a variable location when it goes out of + * scope. Note that unlike g_variant_unref(), the variable may be + * %NULL. + */ +#define gs_unref_variant __attribute__ ((cleanup(gs_local_variant_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GVariant*, gs_local_variant_unref, g_variant_unref) + +/** + * gs_free_variant_iter: + * + * Call g_variant_iter_free() on a variable location when it goes out of + * scope. + */ +#define gs_free_variant_iter __attribute__ ((cleanup(gs_local_variant_iter_free))) +GS_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, gs_local_variant_iter_free, g_variant_iter_free) + +/** + * gs_free_variant_builder: + * + * Call g_variant_builder_unref() on a variable location when it goes out of + * scope. + */ +#define gs_unref_variant_builder __attribute__ ((cleanup(gs_local_variant_builder_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, gs_local_variant_builder_unref, g_variant_builder_unref) + +/** + * gs_unref_array: + * + * Call g_array_unref() on a variable location when it goes out of + * scope. Note that unlike g_array_unref(), the variable may be + * %NULL. + + */ +#define gs_unref_array __attribute__ ((cleanup(gs_local_array_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GArray*, gs_local_array_unref, g_array_unref) + +/** + * gs_unref_ptrarray: + * + * Call g_ptr_array_unref() on a variable location when it goes out of + * scope. Note that unlike g_ptr_array_unref(), the variable may be + * %NULL. + + */ +#define gs_unref_ptrarray __attribute__ ((cleanup(gs_local_ptrarray_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, gs_local_ptrarray_unref, g_ptr_array_unref) + +/** + * gs_unref_hashtable: + * + * Call g_hash_table_unref() on a variable location when it goes out + * of scope. Note that unlike g_hash_table_unref(), the variable may + * be %NULL. + */ +#define gs_unref_hashtable __attribute__ ((cleanup(gs_local_hashtable_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_unref) + +/** + * gs_free_list: + * + * Call g_list_free() on a variable location when it goes out + * of scope. + */ +#define gs_free_list __attribute__ ((cleanup(gs_local_free_list))) +GS_DEFINE_CLEANUP_FUNCTION(GList*, gs_local_free_list, g_list_free) + +/** + * gs_free_slist: + * + * Call g_slist_free() on a variable location when it goes out + * of scope. + */ +#define gs_free_slist __attribute__ ((cleanup(gs_local_free_slist))) +GS_DEFINE_CLEANUP_FUNCTION(GSList*, gs_local_free_slist, g_slist_free) + +/** + * gs_free_checksum: + * + * Call g_checksum_free() on a variable location when it goes out + * of scope. Note that unlike g_checksum_free(), the variable may + * be %NULL. + */ +#define gs_free_checksum __attribute__ ((cleanup(gs_local_checksum_free))) +GS_DEFINE_CLEANUP_FUNCTION0(GChecksum*, gs_local_checksum_free, g_checksum_free) + +/** + * gs_unref_bytes: + * + * Call g_bytes_unref() on a variable location when it goes out + * of scope. Note that unlike g_bytes_unref(), the variable may + * be %NULL. + */ +#define gs_unref_bytes __attribute__ ((cleanup(gs_local_bytes_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GBytes*, gs_local_bytes_unref, g_bytes_unref) + +/** + * gs_strfreev: + * + * Call g_strfreev() on a variable location when it goes out of scope. + */ +#define gs_strfreev __attribute__ ((cleanup(gs_local_strfreev))) +GS_DEFINE_CLEANUP_FUNCTION(char**, gs_local_strfreev, g_strfreev) + +/** + * gs_free_error: + * + * Call g_error_free() on a variable location when it goes out of scope. + */ +#define gs_free_error __attribute__ ((cleanup(gs_local_free_error))) +GS_DEFINE_CLEANUP_FUNCTION0(GError*, gs_local_free_error, g_error_free) + +/** + * gs_unref_keyfile: + * + * Call g_key_file_unref() on a variable location when it goes out of scope. + */ +#define gs_unref_keyfile __attribute__ ((cleanup(gs_local_keyfile_unref))) +GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_keyfile_unref, g_key_file_unref) + +static inline void +gs_cleanup_close_fdp (int *fdp) +{ + int fd; + + g_assert (fdp); + + fd = *fdp; + if (fd != -1) + (void) close (fd); +} + +/** + * gs_fd_close: + * + * Call close() on a variable location when it goes out of scope. + */ +#define gs_fd_close __attribute__((cleanup(gs_cleanup_close_fdp))) + +G_END_DECLS + +#endif diff --git a/tests/network/nm-utils/nm-dbus-compat.h b/tests/network/nm-utils/nm-dbus-compat.h new file mode 100644 index 000000000..dd97b5fd6 --- /dev/null +++ b/tests/network/nm-utils/nm-dbus-compat.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_DBUS_COMPAT_H__ +#define __NM_DBUS_COMPAT_H__ + +/* Copied from <dbus/dbus-shared.h> */ + +/* Bus names */ + +/** The bus name used to talk to the bus itself. */ +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" + +/* Paths */ +/** The object path used to talk to the bus itself. */ +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" +/** The object path used in local/in-process-generated messages. */ +#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local" + +/* Interfaces, these #define don't do much other than + * catch typos at compile time + */ +/** The interface exported by the object with #DBUS_SERVICE_DBUS and #DBUS_PATH_DBUS */ +#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" +/** The interface supported by introspectable objects */ +#define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable" +/** The interface supported by objects with properties */ +#define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" +/** The interface supported by most dbus peers */ +#define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer" + +/** This is a special interface whose methods can only be invoked + * by the local implementation (messages from remote apps aren't + * allowed to specify this interface). + */ +#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local" + +/* Owner flags */ +#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */ +#define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */ +#define DBUS_NAME_FLAG_DO_NOT_QUEUE 0x4 /**< If we can not become the primary owner do not place us in the queue */ + +/* Replies to request for a name */ +#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 /**< Service has become the primary owner of the requested name */ +#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2 /**< Service could not become the primary owner and has been placed in the queue */ +#define DBUS_REQUEST_NAME_REPLY_EXISTS 3 /**< Service is already in the queue */ +#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 /**< Service is already the primary owner */ + +/* Replies to releasing a name */ +#define DBUS_RELEASE_NAME_REPLY_RELEASED 1 /**< Service was released from the given name */ +#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2 /**< The given name does not exist on the bus */ +#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 /**< Service is not an owner of the given name */ + +/* Replies to service starts */ +#define DBUS_START_REPLY_SUCCESS 1 /**< Service was auto started */ +#define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */ + +#endif /* __NM_DBUS_COMPAT_H__ */ diff --git a/tests/network/nm-utils/nm-default.h b/tests/network/nm-utils/nm-default.h new file mode 100644 index 000000000..b9be4768c --- /dev/null +++ b/tests/network/nm-utils/nm-default.h @@ -0,0 +1,316 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 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. + * + * (C) Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEFAULT_H__ +#define __NM_DEFAULT_H__ + +#define NM_NETWORKMANAGER_COMPILATION_WITH_GLIB (1 << 0) +#define NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB (1 << 1) +#define NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG (1 << 2) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM (1 << 3) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE (1 << 4) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE (1 << 5) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL (1 << 6) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE (1 << 7) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_UTIL (1 << 8) +#define NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB (1 << 9) +#define NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON (1 << 10) +#define NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD (1 << 11) + +#define NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_LIBNM ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_LIBNM_UTIL ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_UTIL \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_LIBNM_GLIB ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_LIBNM_UTIL \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_CLIENT ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_DAEMON ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE \ + | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL \ + | NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_SYSTEMD ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_DAEMON \ + | NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD \ + ) + +#define NM_NETWORKMANAGER_COMPILATION_GLIB ( 0 \ + | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB \ + ) + +#ifndef NETWORKMANAGER_COMPILATION +#error Define NETWORKMANAGER_COMPILATION accordingly +#endif + +#ifndef G_LOG_DOMAIN +#if defined(NETWORKMANAGER_COMPILATION_TEST) +#define G_LOG_DOMAIN "test" +#elif NETWORKMANAGER_COMPILATION & NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON +#define G_LOG_DOMAIN "NetworkManager" +#else +#error Need to define G_LOG_DOMAIN +#endif +#elif defined (NETWORKMANAGER_COMPILATION_TEST) || (NETWORKMANAGER_COMPILATION & NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON) +#error Do not define G_LOG_DOMAIN with NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON +#endif + +/*****************************************************************************/ + +/* always include these headers for our internal source files. */ + +#ifndef ___CONFIG_H__ +#define ___CONFIG_H__ +#include <config.h> +#endif + +/* for internal compilation we don't want the deprecation macros + * to be in effect. Define the widest range of versions to effectively + * disable deprecation checks */ +#define NM_VERSION_MIN_REQUIRED NM_VERSION_0_9_8 + +#ifndef NM_MORE_ASSERTS +#define NM_MORE_ASSERTS 0 +#endif + +#if NM_MORE_ASSERTS == 0 +/* The cast macros like NM_TYPE() are implemented via G_TYPE_CHECK_INSTANCE_CAST() + * and _G_TYPE_CIC(). The latter, by default performs runtime checks of the type + * by calling g_type_check_instance_cast(). + * This check has a certain overhead without being helpful. + * + * Example 1: + * static void foo (NMType *obj) + * { + * access_obj_without_check (obj); + * } + * foo ((NMType *) obj); + * // There is no runtime check and passing an invalid pointer + * // leads to a crash. + * + * Example 2: + * static void foo (NMType *obj) + * { + * access_obj_without_check (obj); + * } + * foo (NM_TYPE (obj)); + * // There is a runtime check which prints a g_warning(), but that doesn't + * // avoid the crash as NM_TYPE() cannot do anything then passing on the + * // invalid pointer. + * + * Example 3: + * static void foo (NMType *obj) + * { + * g_return_if_fail (NM_IS_TYPE (obj)); + * access_obj_without_check (obj); + * } + * foo ((NMType *) obj); + * // There is a runtime check which prints a g_critical() which also avoids + * // the crash. That is actually helpful to catch bugs and avoid crashes. + * + * Example 4: + * static void foo (NMType *obj) + * { + * g_return_if_fail (NM_IS_TYPE (obj)); + * access_obj_without_check (obj); + * } + * foo (NM_TYPE (obj)); + * // The runtime check is performed twice, with printing a g_warning() and + * // a g_critical() and avoiding the crash. + * + * Example 3 is how it should be done. Type checks in NM_TYPE() are pointless. + * Disable them for our production builds. + */ +#ifndef G_DISABLE_CAST_CHECKS +#define G_DISABLE_CAST_CHECKS +#endif +#endif + +#if NM_MORE_ASSERTS == 0 +#ifndef G_DISABLE_CAST_CHECKS +/* Unless compiling with G_DISABLE_CAST_CHECKS, glib performs type checking + * during G_VARIANT_TYPE() via g_variant_type_checked_(). This is not necesary + * because commonly this cast is needed during something like + * + * g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}")); + * + * Note that in if the variant type would be invalid, the check still + * wouldn't make the buggy code magically work. Instead of passing a + * bogus type string (bad), it would pass %NULL to g_variant_builder_init() + * (also bad). + * + * Also, a function like g_variant_builder_init() already validates + * the input type via something like + * + * g_return_if_fail (g_variant_type_is_container (type)); + * + * So, by having G_VARIANT_TYPE() also validate the type, we validate + * twice, whereas the first validation is rather pointless because it + * doesn't prevent the function to be called with invalid arguments. + * + * Just patch G_VARIANT_TYPE() to perform no check. + */ +#undef G_VARIANT_TYPE +#define G_VARIANT_TYPE(type_string) ((const GVariantType *) (type_string)) +#endif +#endif + +#include <stdlib.h> + +/*****************************************************************************/ + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_GLIB + +#include <glib.h> + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB +#error Cannot define NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG and NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB +#endif +#include <glib/gi18n.h> +#elif (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB +#include <glib/gi18n-lib.h> +#endif + +/*****************************************************************************/ + +#if NM_MORE_ASSERTS == 0 + +/* glib assertions (g_return_*(), g_assert*()) contain a textual representation + * of the checked statement. This part of the assertion blows up the size of the + * binary. Unless we compile a debug-build with NM_MORE_ASSERTS, drop these + * parts. Note that the failed assertion still prints the file and line where the + * assertion fails. That shall suffice. */ + +static inline void +_nm_g_return_if_fail_warning (const char *log_domain, + const char *file, + int line) +{ + char file_buf[256 + 15]; + + g_snprintf (file_buf, sizeof (file_buf), "((%s:%d))", file, line); + g_return_if_fail_warning (log_domain, file_buf, "<dropped>"); +} + +#define g_return_if_fail_warning(log_domain, pretty_function, expression) \ + _nm_g_return_if_fail_warning (log_domain, __FILE__, __LINE__) + +#define g_assertion_message_expr(domain, file, line, func, expr) \ + g_assertion_message_expr(domain, file, line, "<unknown-fcn>", (expr) ? "<dropped>" : NULL) + +#undef g_return_val_if_reached +#define g_return_val_if_reached(val) \ + G_STMT_START { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + "<dropped>"); \ + return (val); \ + } G_STMT_END + +#undef g_return_if_reached +#define g_return_if_reached() \ + G_STMT_START { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + "<dropped>"); \ + return; \ + } G_STMT_END + +#define NM_ASSERT_G_RETURN_EXPR(expr) "<dropped>" +#define NM_ASSERT_NO_MSG 1 + +#else + +#define NM_ASSERT_G_RETURN_EXPR(expr) ""expr"" +#define NM_ASSERT_NO_MSG 0 + +#endif + +/*****************************************************************************/ + +#include "nm-utils/nm-macros-internal.h" +#include "nm-utils/nm-shared-utils.h" + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_UTIL +/* no hash-utils in legacy code. */ +#else +#include "nm-utils/nm-hash-utils.h" +#endif + +/*****************************************************************************/ + +#if (NETWORKMANAGER_COMPILATION) & (NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_UTIL) +#include "nm-version.h" +#endif + +/*****************************************************************************/ + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON +#include "nm-types.h" +#include "nm-logging.h" +#endif + +#if ((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM) && !((NETWORKMANAGER_COMPILATION) & (NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL)) +#include "NetworkManager.h" +#endif + +#endif /* NM_NETWORKMANAGER_COMPILATION_WITH_GLIB */ + +/*****************************************************************************/ + +#endif /* __NM_DEFAULT_H__ */ diff --git a/tests/network/nm-utils/nm-glib.h b/tests/network/nm-utils/nm-glib.h new file mode 100644 index 000000000..f1498dc4e --- /dev/null +++ b/tests/network/nm-utils/nm-glib.h @@ -0,0 +1,125 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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. + * + * Copyright 2008 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_GLIB_H__ +#define __NM_GLIB_H__ + + +#include <gio/gio.h> +#include <string.h> + +#include "gsystem-local-alloc.h" + +#ifdef __clang__ + +#undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#undef G_GNUC_END_IGNORE_DEPRECATIONS + +#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") + +#define G_GNUC_END_IGNORE_DEPRECATIONS \ + _Pragma("clang diagnostic pop") + +#endif + +/* g_assert_cmpmem() is only available since glib 2.46. */ +#if !GLIB_CHECK_VERSION (2, 45, 7) +#define g_assert_cmpmem(m1, l1, m2, l2) G_STMT_START {\ + gconstpointer __m1 = m1, __m2 = m2; \ + int __l1 = l1, __l2 = l2; \ + if (__l1 != __l2) \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #l1 " (len(" #m1 ")) == " #l2 " (len(" #m2 "))", __l1, "==", __l2, 'i'); \ + else if (memcmp (__m1, __m2, __l1) != 0) \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + "assertion failed (" #m1 " == " #m2 ")"); \ + } G_STMT_END +#endif + +/* Rumtime check for glib version. First do a compile time check which + * (if satisfied) shortcuts the runtime check. */ +static inline gboolean +nm_glib_check_version (guint major, guint minor, guint micro) +{ + return GLIB_CHECK_VERSION (major, minor, micro) + || ( ( glib_major_version > major) + || ( glib_major_version == major + && glib_minor_version > minor) + || ( glib_major_version == major + && glib_minor_version == minor + && glib_micro_version < micro)); +} + +#if !GLIB_CHECK_VERSION(2, 44, 0) +static inline gpointer +g_steal_pointer (gpointer pp) +{ + gpointer *ptr = (gpointer *) pp; + gpointer ref; + + ref = *ptr; + *ptr = NULL; + + return ref; +} + +/* type safety */ +#define g_steal_pointer(pp) \ + (0 ? (*(pp)) : (g_steal_pointer) (pp)) +#endif + + +static inline gboolean +_nm_g_strv_contains (const gchar * const *strv, + const gchar *str) +{ +#if !GLIB_CHECK_VERSION(2, 44, 0) + g_return_val_if_fail (strv != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + for (; *strv != NULL; strv++) { + if (g_str_equal (str, *strv)) + return TRUE; + } + + return FALSE; +#else + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + return g_strv_contains (strv, str); + G_GNUC_END_IGNORE_DEPRECATIONS +#endif +} +#define g_strv_contains _nm_g_strv_contains + +#if !GLIB_CHECK_VERSION (2, 56, 0) +#define g_object_ref(Obj) ((typeof(Obj)) g_object_ref (Obj)) +#define g_object_ref_sink(Obj) ((typeof(Obj)) g_object_ref_sink (Obj)) +#endif + +#ifndef g_autofree +/* we still don't rely on recent glib to provide g_autofree. Hence, we continue + * to use our gs_* free macros that we took from libgsystem. + * + * To ease migration towards g_auto*, add a compat define for g_autofree. */ +#define g_autofree gs_free +#endif + +#endif /* __NM_GLIB_H__ */ diff --git a/tests/network/nm-utils/nm-hash-utils.h b/tests/network/nm-utils/nm-hash-utils.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/network/nm-utils/nm-hash-utils.h diff --git a/tests/network/nm-utils/nm-macros-internal.h b/tests/network/nm-utils/nm-macros-internal.h new file mode 100644 index 000000000..2e3940fd7 --- /dev/null +++ b/tests/network/nm-utils/nm-macros-internal.h @@ -0,0 +1,1384 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 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. + * + * (C) Copyright 2014 Red Hat, Inc. + */ + +#ifndef __NM_MACROS_INTERNAL_H__ +#define __NM_MACROS_INTERNAL_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#define _nm_packed __attribute__ ((packed)) +#define _nm_unused __attribute__ ((unused)) +#define _nm_pure __attribute__ ((pure)) +#define _nm_const __attribute__ ((const)) +#define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b))) +#define _nm_align(s) __attribute__ ((aligned (s))) +#define _nm_alignof(type) __alignof (type) +#define _nm_alignas(type) _nm_align (_nm_alignof (type)) + +#if __GNUC__ >= 7 +#define _nm_fallthrough __attribute__ ((fallthrough)) +#else +#define _nm_fallthrough +#endif + +/*****************************************************************************/ + +#ifdef thread_local +#define _nm_thread_local thread_local +/* + * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 + */ +#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) +#define _nm_thread_local _Thread_local +#else +#define _nm_thread_local __thread +#endif + +/*****************************************************************************/ + +#include "nm-glib.h" + +/*****************************************************************************/ + +#define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m)) + +#define nm_auto(fcn) __attribute__ ((cleanup(fcn))) + +static inline int nm_close (int fd); + +/** + * nm_auto_free: + * + * Call free() on a variable location when it goes out of scope. + */ +#define nm_auto_free nm_auto(_nm_auto_free_impl) +GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free) + +static inline void +nm_free_secret (char *secret) +{ + if (secret) { + memset (secret, 0, strlen (secret)); + g_free (secret); + } +} + +static inline void +_nm_auto_free_secret_impl (char **v) +{ + nm_free_secret (*v); +} + +/** + * nm_auto_free_secret: + * + * Call g_free() on a variable location when it goes out of scope. + * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out + * the secret. + */ +#define nm_auto_free_secret nm_auto(_nm_auto_free_secret_impl) + +static inline void +_nm_auto_unset_gvalue_impl (GValue *v) +{ + g_value_unset (v); +} +#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl) + +static inline void +_nm_auto_unref_gtypeclass (gpointer v) +{ + if (v && *((gpointer *) v)) + g_type_class_unref (*((gpointer *) v)); +} +#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass) + +static inline void +_nm_auto_free_gstring_impl (GString **str) +{ + if (*str) + g_string_free (*str, TRUE); +} +#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring_impl) + +static inline void +_nm_auto_close_impl (int *pfd) +{ + if (*pfd >= 0) { + int errsv = errno; + + (void) nm_close (*pfd); + errno = errsv; + } +} +#define nm_auto_close nm_auto(_nm_auto_close_impl) + +static inline void +_nm_auto_fclose_impl (FILE **pfd) +{ + if (*pfd) { + int errsv = errno; + + (void) fclose (*pfd); + errno = errsv; + } +} +#define nm_auto_fclose nm_auto(_nm_auto_fclose_impl) + +static inline void +_nm_auto_protect_errno (int *p_saved_errno) +{ + errno = *p_saved_errno; +} +#define NM_AUTO_PROTECT_ERRNO(errsv_saved) nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno) + +/*****************************************************************************/ + +/* http://stackoverflow.com/a/11172679 */ +#define _NM_UTILS_MACRO_FIRST(...) __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway) +#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...) first + +#define _NM_UTILS_MACRO_REST(...) __NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__) +#define __NM_UTILS_MACRO_REST_HELPER(qty, ...) __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__) +#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...) __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__) +#define __NM_UTILS_MACRO_REST_HELPER_ONE(first) +#define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ +#define __NM_UTILS_MACRO_REST_NUM(...) \ + __NM_UTILS_MACRO_REST_SELECT_30TH(__VA_ARGS__, \ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) +#define __NM_UTILS_MACRO_REST_SELECT_30TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, ...) a30 + +/*****************************************************************************/ + +/* http://stackoverflow.com/a/2124385/354393 */ + +#define NM_NARG(...) \ + _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N()) +#define _NM_NARG(...) \ + _NM_NARG_ARG_N(__VA_ARGS__) +#define _NM_NARG_ARG_N( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define _NM_NARG_RSEQ_N() \ + 63,62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + +/*****************************************************************************/ + +#if defined (__GNUC__) +#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(GCC diagnostic ignored warning) +#elif defined (__clang__) +#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(clang diagnostic ignored warning) +#endif + +/* you can only suppress a specific warning that the compiler + * understands. Otherwise you will get another compiler warning + * about invalid pragma option. + * It's not that bad however, because gcc and clang often have the + * same name for the same warning. */ + +#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define NM_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("GCC diagnostic push") \ + _Pragma(_NM_PRAGMA_WARNING_DO(warning)) +#elif defined (__clang__) +#define NM_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("clang diagnostic push") \ + _Pragma(_NM_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \ + _Pragma(_NM_PRAGMA_WARNING_DO(warning)) +#else +#define NM_PRAGMA_WARNING_DISABLE(warning) +#endif + +#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define NM_PRAGMA_WARNING_REENABLE \ + _Pragma("GCC diagnostic pop") +#elif defined (__clang__) +#define NM_PRAGMA_WARNING_REENABLE \ + _Pragma("clang diagnostic pop") +#else +#define NM_PRAGMA_WARNING_REENABLE +#endif + +/*****************************************************************************/ + +/** + * NM_G_ERROR_MSG: + * @error: (allow-none): the #GError instance + * + * All functions must follow the convention that when they + * return a failure, they must also set the GError to a valid + * message. For external API however, we want to be extra + * careful before accessing the error instance. Use NM_G_ERROR_MSG() + * which is safe to use on NULL. + * + * Returns: the error message. + **/ +static inline const char * +NM_G_ERROR_MSG (GError *error) +{ + return error ? (error->message ? : "(null)") : "(no-error)"; \ +} + +/*****************************************************************************/ + +/* macro to return strlen() of a compile time string. */ +#define NM_STRLEN(str) ( sizeof ("" str) - 1 ) + +/* returns the length of a NULL terminated array of pointers, + * like g_strv_length() does. The difference is: + * - it operats on arrays of pointers (of any kind, requiring no cast). + * - it accepts NULL to return zero. */ +#define NM_PTRARRAY_LEN(array) \ + ({ \ + typeof (*(array)) *const _array = (array); \ + gsize _n = 0; \ + \ + if (_array) { \ + _nm_unused gconstpointer _type_check_is_pointer = _array[0]; \ + \ + while (_array[_n]) \ + _n++; \ + } \ + _n; \ + }) + +/* Note: @value is only evaluated when *out_val is present. + * Thus, + * NM_SET_OUT (out_str, g_strdup ("hallo")); + * does the right thing. + */ +#define NM_SET_OUT(out_val, value) \ + G_STMT_START { \ + typeof(*(out_val)) *_out_val = (out_val); \ + \ + if (_out_val) { \ + *_out_val = (value); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +#ifndef _NM_CC_SUPPORT_AUTO_TYPE +#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) +#define _NM_CC_SUPPORT_AUTO_TYPE 1 +#else +#define _NM_CC_SUPPORT_AUTO_TYPE 0 +#endif +#endif + +#ifndef _NM_CC_SUPPORT_GENERIC +#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__)) +#define _NM_CC_SUPPORT_GENERIC 1 +#else +#define _NM_CC_SUPPORT_GENERIC 0 +#endif +#endif + +#if _NM_CC_SUPPORT_AUTO_TYPE +#define _nm_auto_type __auto_type +#endif + +#if _NM_CC_SUPPORT_GENERIC +#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \ + (_Generic ((obj_expr), \ + const void *const: ((const type *) (obj)), \ + const void * : ((const type *) (obj)), \ + void *const: (( type *) (obj)), \ + void * : (( type *) (obj)), \ + const type *const: ((const type *) (obj)), \ + const type * : ((const type *) (obj)), \ + type *const: (( type *) (obj)), \ + type * : (( type *) (obj)))) +#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \ + (_Generic ((obj_expr), \ + const void *const: ((const type *) (obj)), \ + const void * : ((const type *) (obj)), \ + void *const: (( type *) (obj)), \ + void * : (( type *) (obj)), \ + const alias_type2 *const: ((const type *) (obj)), \ + const alias_type2 * : ((const type *) (obj)), \ + alias_type2 *const: (( type *) (obj)), \ + alias_type2 * : (( type *) (obj)), \ + const type *const: ((const type *) (obj)), \ + const type * : ((const type *) (obj)), \ + type *const: (( type *) (obj)), \ + type * : (( type *) (obj)))) +#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \ + (_Generic ((obj_expr), \ + const void *const: ((const type *) (obj)), \ + const void * : ((const type *) (obj)), \ + void *const: (( type *) (obj)), \ + void * : (( type *) (obj)), \ + const alias_type2 *const: ((const type *) (obj)), \ + const alias_type2 * : ((const type *) (obj)), \ + alias_type2 *const: (( type *) (obj)), \ + alias_type2 * : (( type *) (obj)), \ + const alias_type3 *const: ((const type *) (obj)), \ + const alias_type3 * : ((const type *) (obj)), \ + alias_type3 *const: (( type *) (obj)), \ + alias_type3 * : (( type *) (obj)), \ + const type *const: ((const type *) (obj)), \ + const type * : ((const type *) (obj)), \ + type *const: (( type *) (obj)), \ + type * : (( type *) (obj)))) +#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \ + (_Generic ((obj_expr), \ + const void *const: ((const type *) (obj)), \ + const void * : ((const type *) (obj)), \ + void *const: (( type *) (obj)), \ + void * : (( type *) (obj)), \ + const alias_type2 *const: ((const type *) (obj)), \ + const alias_type2 * : ((const type *) (obj)), \ + alias_type2 *const: (( type *) (obj)), \ + alias_type2 * : (( type *) (obj)), \ + const alias_type3 *const: ((const type *) (obj)), \ + const alias_type3 * : ((const type *) (obj)), \ + alias_type3 *const: (( type *) (obj)), \ + alias_type3 * : (( type *) (obj)), \ + const alias_type4 *const: ((const type *) (obj)), \ + const alias_type4 * : ((const type *) (obj)), \ + alias_type4 *const: (( type *) (obj)), \ + alias_type4 * : (( type *) (obj)), \ + const type *const: ((const type *) (obj)), \ + const type * : ((const type *) (obj)), \ + type *const: (( type *) (obj)), \ + type * : (( type *) (obj)))) +#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_##n (type, obj_expr, obj, ##__VA_ARGS__)) +#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_x (type, obj_expr, obj, n, ##__VA_ARGS__)) +#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) (_NM_CONSTCAST_FULL_y (type, obj_expr, obj, NM_NARG (dummy, ##__VA_ARGS__), ##__VA_ARGS__)) +#else +#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) ((type *) (obj)) +#endif + +#define NM_CONSTCAST(type, obj, ...) \ + NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__) + +#if _NM_CC_SUPPORT_GENERIC +#define NM_UNCONST_PTR(type, arg) \ + _Generic ((arg), \ + const type *: ((type *) (arg)), \ + type *: ((type *) (arg))) +#else +#define NM_UNCONST_PTR(type, arg) \ + ((type *) (arg)) +#endif + +#if _NM_CC_SUPPORT_GENERIC +#define NM_UNCONST_PPTR(type, arg) \ + _Generic ((arg), \ + const type * *: ((type **) (arg)), \ + type * *: ((type **) (arg)), \ + const type *const*: ((type **) (arg)), \ + type *const*: ((type **) (arg))) +#else +#define NM_UNCONST_PPTR(type, arg) \ + ((type **) (arg)) +#endif + +#define NM_GOBJECT_CAST(type, obj, is_check, ...) \ + ({ \ + const void *_obj = (obj); \ + \ + nm_assert (_obj || (is_check (_obj))); \ + NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \ + }) + +#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \ + ({ \ + const void *_obj = (obj); \ + \ + nm_assert (is_check (_obj)); \ + NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \ + }) + +#if _NM_CC_SUPPORT_GENERIC +/* returns @value, if the type of @value matches @type. + * This requires support for C11 _Generic(). If no support is + * present, this returns @value directly. + * + * It's useful to check the let the compiler ensure that @value is + * of a certain type. */ +#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value))) +#else +#define _NM_ENSURE_TYPE(type, value) (value) +#endif + +#if _NM_CC_SUPPORT_GENERIC +#define NM_PROPAGATE_CONST(test_expr, ptr) \ + (_Generic ((test_expr), \ + const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \ + default: (_Generic ((test_expr), \ + typeof (*(test_expr)) *: (ptr))))) +#else +#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr) +#endif + +/*****************************************************************************/ + +#define _NM_IN_SET_EVAL_1( op, _x, y) (_x == (y)) +#define _NM_IN_SET_EVAL_2( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_1 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_3( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_2 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_4( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_3 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_5( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_4 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_6( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_5 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_7( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_6 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_8( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_7 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_9( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_8 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_10(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_9 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_11(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_10 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_12(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_11 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_13(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_12 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_14(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_13 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_15(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_14 (op, _x, __VA_ARGS__) +#define _NM_IN_SET_EVAL_16(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__) + +#define _NM_IN_SET_EVAL_N2(op, _x, n, ...) (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__)) +#define _NM_IN_SET_EVAL_N(op, type, x, n, ...) \ + ({ \ + type _x = (x); \ + \ + /* trigger a -Wenum-compare warning */ \ + nm_assert (TRUE || _x == (x)); \ + \ + !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__); \ + }) + +#define _NM_IN_SET(op, type, x, ...) _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) + +/* Beware that this does short-circuit evaluation (use "||" instead of "|") + * which has a possibly unexpected non-function-like behavior. + * Use NM_IN_SET_SE if you need all arguments to be evaluted. */ +#define NM_IN_SET(x, ...) _NM_IN_SET(||, typeof (x), x, __VA_ARGS__) + +/* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do + * short-circuit evaluation, which can make a difference if the arguments have + * side-effects. */ +#define NM_IN_SET_SE(x, ...) _NM_IN_SET(|, typeof (x), x, __VA_ARGS__) + +/* the *_TYPED forms allow to explicitly select the type of "x". This is useful + * if "x" doesn't support typeof (bitfields) or you want to gracefully convert + * a type using automatic type conversion rules (but not forcing the conversion + * with a cast). */ +#define NM_IN_SET_TYPED(type, x, ...) _NM_IN_SET(||, type, x, __VA_ARGS__) +#define NM_IN_SET_SE_TYPED(type, x, ...) _NM_IN_SET(|, type, x, __VA_ARGS__) + +/*****************************************************************************/ + +static inline gboolean +_NM_IN_STRSET_streq (const char *x, const char *s) +{ + return s && strcmp (x, s) == 0; +} + +#define _NM_IN_STRSET_EVAL_1( op, _x, y) _NM_IN_STRSET_streq (_x, y) +#define _NM_IN_STRSET_EVAL_2( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_1 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_3( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_2 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_4( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_3 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_5( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_4 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_6( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_5 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_7( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_6 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_8( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_7 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_9( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_8 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_10(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_9 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_11(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_10 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_12(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_11 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_13(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_12 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_14(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_13 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_15(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_14 (op, _x, __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_16(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_15 (op, _x, __VA_ARGS__) + +#define _NM_IN_STRSET_EVAL_N2(op, _x, n, ...) (_NM_IN_STRSET_EVAL_##n(op, _x, __VA_ARGS__)) +#define _NM_IN_STRSET_EVAL_N(op, x, n, ...) \ + ({ \ + const char *_x = (x); \ + ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \ + || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ + ); \ + }) + +/* Beware that this does short-circuit evaluation (use "||" instead of "|") + * which has a possibly unexpected non-function-like behavior. + * Use NM_IN_STRSET_SE if you need all arguments to be evaluted. */ +#define NM_IN_STRSET(x, ...) _NM_IN_STRSET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) + +/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do + * short-circuit evaluation, which can make a difference if the arguments have + * side-effects. */ +#define NM_IN_STRSET_SE(x, ...) _NM_IN_STRSET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) + +#define NM_STRCHAR_ALL(str, ch_iter, predicate) \ + ({ \ + gboolean _val = TRUE; \ + const char *_str = (str); \ + \ + if (_str) { \ + for (;;) { \ + const char ch_iter = _str[0]; \ + \ + if (ch_iter != '\0') { \ + if (predicate) {\ + _str++; \ + continue; \ + } \ + _val = FALSE; \ + } \ + break; \ + } \ + } \ + _val; \ + }) + +#define NM_STRCHAR_ANY(str, ch_iter, predicate) \ + ({ \ + gboolean _val = FALSE; \ + const char *_str = (str); \ + \ + if (_str) { \ + for (;;) { \ + const char ch_iter = _str[0]; \ + \ + if (ch_iter != '\0') { \ + if (predicate) { \ + ; \ + } else { \ + _str++; \ + continue; \ + } \ + _val = TRUE; \ + } \ + break; \ + } \ + } \ + _val; \ + }) + +/*****************************************************************************/ + +/* NM_CACHED_QUARK() returns the GQuark for @string, but caches + * it in a static variable to speed up future lookups. + * + * @string must be a string literal. + */ +#define NM_CACHED_QUARK(string) \ + ({ \ + static GQuark _nm_cached_quark = 0; \ + \ + (G_LIKELY (_nm_cached_quark != 0) \ + ? _nm_cached_quark \ + : (_nm_cached_quark = g_quark_from_static_string (""string""))); \ + }) + +/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK + * with two differences: + * - @string must be a quoted string-literal + * - @fcn must be the full function name, while G_DEFINE_QUARK() appends + * "_quark" to the function name. + * Both properties of G_DEFINE_QUARK() are non favorable, because you can no + * longer grep for string/fcn -- unless you are aware that you are searching + * for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(), + * ctags/cscope can locate the use of @fcn (though it doesn't recognize that + * NM_CACHED_QUARK_FCN() defines it). + */ +#define NM_CACHED_QUARK_FCN(string, fcn) \ +GQuark \ +fcn (void) \ +{ \ + return NM_CACHED_QUARK (string); \ +} + +/*****************************************************************************/ + +#define nm_streq(s1, s2) (strcmp (s1, s2) == 0) +#define nm_streq0(s1, s2) (g_strcmp0 (s1, s2) == 0) + +/*****************************************************************************/ + +static inline GString * +nm_gstring_prepare (GString **l) +{ + if (*l) + g_string_set_size (*l, 0); + else + *l = g_string_sized_new (30); + return *l; +} + +static inline const char * +nm_str_not_empty (const char *str) +{ + return str && str[0] ? str : NULL; +} + +static inline char * +nm_strdup_not_empty (const char *str) +{ + return str && str[0] ? g_strdup (str) : NULL; +} + +static inline char * +nm_str_realloc (char *str) +{ + gs_free char *s = str; + + /* Returns a new clone of @str and frees @str. The point is that @str + * possibly points to a larger chunck of memory. We want to freshly allocate + * a buffer. + * + * We could use realloc(), but that might not do anything or leave + * @str in its memory pool for chunks of a different size (bad for + * fragmentation). + * + * This is only useful when we want to keep the buffer around for a long + * time and want to re-allocate a more optimal buffer. */ + + return g_strdup (s); +} + +/*****************************************************************************/ + +#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \ + (cond) ? (prefix) : "", \ + (cond) ? (str) : (str_else), \ + (cond) ? (suffix) : "" +#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)") + +/*****************************************************************************/ + +/* glib/C provides the following kind of assertions: + * - assert() -- disable with NDEBUG + * - g_return_if_fail() -- disable with G_DISABLE_CHECKS + * - g_assert() -- disable with G_DISABLE_ASSERT + * but they are all enabled by default and usually even production builds have + * these kind of assertions enabled. It also means, that disabling assertions + * is an untested configuration, and might have bugs. + * + * Add our own assertion macro nm_assert(), which is disabled by default and must + * be explicitly enabled. They are useful for more expensive checks or checks that + * depend less on runtime conditions (that is, are generally expected to be true). */ + +#ifndef NM_MORE_ASSERTS +#define NM_MORE_ASSERTS 0 +#endif + +#if NM_MORE_ASSERTS +#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END +#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END +#define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END +#else +#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END +#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END +#define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END +#endif + +/*****************************************************************************/ + +#define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \ +typedef enum { \ + _PROPERTY_ENUMS_0, \ + __VA_ARGS__ \ + _PROPERTY_ENUMS_LAST, \ +} _PropertyEnums; \ +static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, } + +#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \ +NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \ +static inline void \ +_notify (obj_type *obj, _PropertyEnums prop) \ +{ \ + nm_assert (G_IS_OBJECT (obj)); \ + nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \ + g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \ +} + +/*****************************************************************************/ + +#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)) +#if _NM_CC_SUPPORT_AUTO_TYPE +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ + ({ \ + _nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \ + \ + NM_PROPAGATE_CONST (_self, _self->_priv); \ + }) +#else +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv) +#endif + +/*****************************************************************************/ + +static inline gpointer +nm_g_object_ref (gpointer obj) +{ + /* g_object_ref() doesn't accept NULL. */ + if (obj) + g_object_ref (obj); + return obj; +} +#define nm_g_object_ref(obj) ((typeof (obj)) nm_g_object_ref (obj)) + +static inline void +nm_g_object_unref (gpointer obj) +{ + /* g_object_unref() doesn't accept NULL. Usully, we workaround that + * by using g_clear_object(), but sometimes that is not convinient + * (for example as as destroy function for a hash table that can contain + * NULL values). */ + if (obj) + g_object_unref (obj); +} + +/* Assigns GObject @obj to destination @pdst, and takes an additional ref. + * The previous value of @pdst is unrefed. + * + * It makes sure to first increase the ref-count of @obj, and handles %NULL + * @obj correctly. + * */ +#define nm_g_object_ref_set(pp, obj) \ + ({ \ + typeof (*(pp)) *const _pp = (pp); \ + typeof (**_pp) *const _obj = (obj); \ + typeof (**_pp) *_p; \ + gboolean _changed = FALSE; \ + \ + if ( _pp \ + && ((_p = *_pp) != _obj)) { \ + if (_obj) { \ + nm_assert (G_IS_OBJECT (_obj)); \ + g_object_ref (_obj); \ + } \ + if (_p) { \ + nm_assert (G_IS_OBJECT (_p)); \ + *_pp = NULL; \ + g_object_unref (_p); \ + } \ + *_pp = _obj; \ + _changed = TRUE; \ + } \ + _changed; \ + }) + +#define nm_clear_pointer(pp, destroy) \ + ({ \ + typeof (*(pp)) *_pp = (pp); \ + typeof (*_pp) _p; \ + gboolean _changed = FALSE; \ + \ + if ( _pp \ + && (_p = *_pp)) { \ + _nm_unused gconstpointer _p_check_is_pointer = _p; \ + \ + *_pp = NULL; \ + /* g_clear_pointer() assigns @destroy first to a local variable, so that + * you can call "g_clear_pointer (pp, (GDestroyNotify) destroy);" without + * gcc emitting a warning. We don't do that, hence, you cannot cast + * "destroy" first. + * + * On the upside: you are not supposed to cast fcn, because the pointer + * types are preserved. If you really need a cast, you should cast @pp. + * But that is hardly ever necessary. */ \ + (destroy) (_p); \ + \ + _changed = TRUE; \ + } \ + _changed; \ + }) + +/* basically, replaces + * g_clear_pointer (&location, g_free) + * with + * nm_clear_g_free (&location) + * + * Another advantage is that by using a macro and typeof(), it is more + * typesafe and gives you for example a compiler warning when pp is a const + * pointer or points to a const-pointer. + */ +#define nm_clear_g_free(pp) \ + nm_clear_pointer (pp, g_free) + +#define nm_clear_g_object(pp) \ + nm_clear_pointer (pp, g_object_unref) + +static inline gboolean +nm_clear_g_source (guint *id) +{ + guint v; + + if ( id + && (v = *id)) { + *id = 0; + g_source_remove (v); + return TRUE; + } + return FALSE; +} + +static inline gboolean +nm_clear_g_signal_handler (gpointer self, gulong *id) +{ + gulong v; + + if ( id + && (v = *id)) { + *id = 0; + g_signal_handler_disconnect (self, v); + return TRUE; + } + return FALSE; +} + +static inline gboolean +nm_clear_g_variant (GVariant **variant) +{ + GVariant *v; + + if ( variant + && (v = *variant)) { + *variant = NULL; + g_variant_unref (v); + return TRUE; + } + return FALSE; +} + +static inline gboolean +nm_clear_g_cancellable (GCancellable **cancellable) +{ + GCancellable *v; + + if ( cancellable + && (v = *cancellable)) { + *cancellable = NULL; + g_cancellable_cancel (v); + g_object_unref (v); + return TRUE; + } + return FALSE; +} + +/*****************************************************************************/ + +/* Determine whether @x is a power of two (@x being an integer type). + * Basically, this returns TRUE, if @x has exactly one bit set. + * For negative values and zero, this always returns FALSE. */ +#define nm_utils_is_power_of_two(x) ({ \ + typeof(x) __x = (x); \ + \ + ( (__x > ((typeof(__x)) 0)) \ + && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \ + }) + +/*****************************************************************************/ + +#define NM_UTILS_LOOKUP_DEFAULT(v) return (v) +#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v) +#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v) { nm_assert_not_reached (); return (v); } +#define NM_UTILS_LOOKUP_ITEM(v, n) (void) 0; case v: return (n); (void) 0 +#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"") +#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0 +#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() (void) 0; default: break; (void) 0 + +#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \ +scope result_type \ +fcn_name (lookup_type val) \ +{ \ + switch (val) { \ + (void) 0, \ + __VA_ARGS__ \ + (void) 0; \ + }; \ + { unknown_val; } \ +} + +#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \ + _NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__) +#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \ + _NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__) + +/* Call the string-lookup-table function @fcn_name. If the function returns + * %NULL, the numeric index is converted to string using a alloca() buffer. + * Beware: this macro uses alloca(). */ +#define NM_UTILS_LOOKUP_STR(fcn_name, idx) \ + ({ \ + typeof (idx) _idx = (idx); \ + const char *_s; \ + \ + _s = fcn_name (_idx); \ + if (!_s) { \ + _s = g_alloca (30); \ + \ + g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \ + } \ + _s; \ + }) + +/*****************************************************************************/ + +/* check if @flags has exactly one flag (@check) set. You should call this + * only with @check being a compile time constant and a power of two. */ +#define NM_FLAGS_HAS(flags, check) \ + ( G_STATIC_ASSERT_EXPR ((check) > 0 && ((check) & ((check) - 1)) == 0), NM_FLAGS_ANY ((flags), (check)) ) + +#define NM_FLAGS_ANY(flags, check) ( ( ((flags) & (check)) != 0 ) ? TRUE : FALSE ) +#define NM_FLAGS_ALL(flags, check) ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE ) + +#define NM_FLAGS_SET(flags, val) ({ \ + const typeof(flags) _flags = (flags); \ + const typeof(flags) _val = (val); \ + \ + _flags | _val; \ + }) + +#define NM_FLAGS_UNSET(flags, val) ({ \ + const typeof(flags) _flags = (flags); \ + const typeof(flags) _val = (val); \ + \ + _flags & (~_val); \ + }) + +#define NM_FLAGS_ASSIGN(flags, val, assign) ({ \ + const typeof(flags) _flags = (flags); \ + const typeof(flags) _val = (val); \ + \ + (assign) \ + ? _flags | (_val) \ + : _flags & (~_val); \ + }) + +/*****************************************************************************/ + +#define _NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, ORIG_FUNC, VERSIONED_FUNC, ARGS_TYPED, ARGS) \ +RETURN_TYPE VERSIONED_FUNC ARGS_TYPED; \ +RETURN_TYPE VERSIONED_FUNC ARGS_TYPED \ +{ \ + return ORIG_FUNC ARGS; \ +} \ +RETURN_TYPE ORIG_FUNC ARGS_TYPED; \ +__asm__(".symver "G_STRINGIFY(VERSIONED_FUNC)", "G_STRINGIFY(ORIG_FUNC)"@"G_STRINGIFY(VERSION)) + +#define NM_BACKPORT_SYMBOL(VERSION, RETURN_TYPE, FUNC, ARGS_TYPED, ARGS) \ +_NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, FUNC, _##FUNC##_##VERSION, ARGS_TYPED, ARGS) + +/*****************************************************************************/ + +#define nm_str_skip_leading_spaces(str) \ + ({ \ + typeof (*(str)) *_str = (str); \ + _nm_unused const char *_str_type_check = _str; \ + \ + if (_str) { \ + while (g_ascii_isspace (_str[0])) \ + _str++; \ + } \ + _str; \ + }) + +static inline char * +nm_strstrip (char *str) +{ + /* g_strstrip doesn't like NULL. */ + return str ? g_strstrip (str) : NULL; +} + +static inline const char * +nm_strstrip_avoid_copy (const char *str, char **str_free) +{ + gsize l; + char *s; + + nm_assert (str_free && !*str_free); + + if (!str) + return NULL; + + str = nm_str_skip_leading_spaces (str); + l = strlen (str); + if ( l == 0 + || !g_ascii_isspace (str[l - 1])) + return str; + while ( l > 0 + && g_ascii_isspace (str[l - 1])) + l--; + + s = g_new (char, l + 1); + memcpy (s, str, l); + s[l] = '\0'; + *str_free = s; + return s; +} + +/* g_ptr_array_sort()'s compare function takes pointers to the + * value. Thus, you cannot use strcmp directly. You can use + * nm_strcmp_p(). + * + * Like strcmp(), this function is not forgiving to accept %NULL. */ +static inline int +nm_strcmp_p (gconstpointer a, gconstpointer b) +{ + const char *s1 = *((const char **) a); + const char *s2 = *((const char **) b); + + return strcmp (s1, s2); +} + +/* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data(). + * g_ptr_array_sort() just casts nm_strcmp_p() to a function of different + * signature. I guess, in glib there are knowledgeable people that ensure + * that this additional argument doesn't cause problems due to different ABI + * for every architecture that glib supports. + * For NetworkManager, we'd rather avoid such stunts. + **/ +static inline int +nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data) +{ + const char *s1 = *((const char **) a); + const char *s2 = *((const char **) b); + + return strcmp (s1, s2); +} + +static inline int +nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data) +{ + const guint32 a = *((const guint32 *) p_a); + const guint32 b = *((const guint32 *) p_b); + + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +static inline int +nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data) +{ + /* p_a and p_b are two pointers to a pointer, where the pointer is + * interpreted as a integer using GPOINTER_TO_INT(). + * + * That is the case of a hash-table that uses GINT_TO_POINTER() to + * convert integers as pointers, and the resulting keys-as-array + * array. */ + const int a = GPOINTER_TO_INT (*((gconstpointer *) p_a)); + const int b = GPOINTER_TO_INT (*((gconstpointer *) p_b)); + + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +/*****************************************************************************/ + +/* Taken from systemd's UNIQ_T and UNIQ macros. */ + +#define NM_UNIQ_T(x, uniq) G_PASTE(__unique_prefix_, G_PASTE(x, uniq)) +#define NM_UNIQ __COUNTER__ + +/*****************************************************************************/ + +/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate + * the argument possibly twice. + * + * Taken from systemd's MIN()/MAX() macros. */ + +#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b) +#define __NM_MIN(aq, a, bq, b) \ + ({ \ + typeof (a) NM_UNIQ_T(A, aq) = (a); \ + typeof (b) NM_UNIQ_T(B, bq) = (b); \ + ((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ + }) + +#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b) +#define __NM_MAX(aq, a, bq, b) \ + ({ \ + typeof (a) NM_UNIQ_T(A, aq) = (a); \ + typeof (b) NM_UNIQ_T(B, bq) = (b); \ + ((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ + }) + +#define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high) +#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ + ({ \ + typeof(x)NM_UNIQ_T(X,xq) = (x); \ + typeof(low) NM_UNIQ_T(LOW,lowq) = (low); \ + typeof(high) NM_UNIQ_T(HIGH,highq) = (high); \ + \ + ( (NM_UNIQ_T(X,xq) > NM_UNIQ_T(HIGH,highq)) \ + ? NM_UNIQ_T(HIGH,highq) \ + : (NM_UNIQ_T(X,xq) < NM_UNIQ_T(LOW,lowq)) \ + ? NM_UNIQ_T(LOW,lowq) \ + : NM_UNIQ_T(X,xq)); \ + }) + +/*****************************************************************************/ + +static inline guint +nm_encode_version (guint major, guint minor, guint micro) +{ + /* analog to the preprocessor macro NM_ENCODE_VERSION(). */ + return (major << 16) | (minor << 8) | micro; +} + +static inline void +nm_decode_version (guint version, guint *major, guint *minor, guint *micro) +{ + *major = (version & 0xFFFF0000u) >> 16; + *minor = (version & 0x0000FF00u) >> 8; + *micro = (version & 0x000000FFu); +} + +/*****************************************************************************/ + +/* taken from systemd's DECIMAL_STR_MAX() + * + * Returns the number of chars needed to format variables of the + * specified type as a decimal string. Adds in extra space for a + * negative '-' prefix (hence works correctly on signed + * types). Includes space for the trailing NUL. */ +#define NM_DECIMAL_STR_MAX(type) \ + (2+(sizeof(type) <= 1 ? 3 : \ + sizeof(type) <= 2 ? 5 : \ + sizeof(type) <= 4 ? 10 : \ + sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)]))) + +/*****************************************************************************/ + +/* if @str is NULL, return "(null)". Otherwise, allocate a buffer using + * alloca() of and fill it with @str. @str will be quoted with double quote. + * If @str is longer then @trunc_at, the string is truncated and the closing + * quote is instead '^' to indicate truncation. + * + * Thus, the maximum stack allocated buffer will be @trunc_at+3. */ +#define nm_strquote_a(trunc_at, str) \ + ({ \ + const char *const _str = (str); \ + \ + (_str \ + ? ({ \ + const gsize _trunc_at = (trunc_at); \ + const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \ + char *_buf; \ + \ + _buf = g_alloca (_strlen_trunc + 3); \ + _buf[0] = '"'; \ + memcpy (&_buf[1], _str, _strlen_trunc); \ + _buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \ + _buf[_strlen_trunc + 2] = '\0'; \ + _buf; \ + }) \ + : "(null)"); \ + }) + +#define nm_sprintf_buf(buf, format, ...) \ + ({ \ + char * _buf = (buf); \ + int _buf_len; \ + \ + /* some static assert trying to ensure that the buffer is statically allocated. + * It disallows a buffer size of sizeof(gpointer) to catch that. */ \ + G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \ + _buf_len = g_snprintf (_buf, sizeof (buf), \ + ""format"", ##__VA_ARGS__); \ + nm_assert (_buf_len < sizeof (buf)); \ + _buf; \ + }) + +#define nm_sprintf_bufa(n_elements, format, ...) \ + ({ \ + char *_buf; \ + int _buf_len; \ + typeof (n_elements) _n_elements = (n_elements); \ + \ + _buf = g_alloca (_n_elements); \ + _buf_len = g_snprintf (_buf, _n_elements, \ + ""format"", ##__VA_ARGS__); \ + nm_assert (_buf_len < _n_elements); \ + _buf; \ + }) + +/* aims to alloca() a buffer and fill it with printf(format, name). + * Note that format must not contain any format specifier except + * "%s". + * If the resulting string would be too large for stack allocation, + * it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */ +#define nm_construct_name_a(format, name, p_val_to_free) \ + ({ \ + const char *const _name = (name); \ + char **const _p_val_to_free = (p_val_to_free); \ + const gsize _name_len = strlen (_name); \ + char *_buf2; \ + \ + nm_assert (_p_val_to_free && !*_p_val_to_free); \ + if (NM_STRLEN (format) + _name_len < 200) \ + _buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \ + else { \ + _buf2 = g_strdup_printf (format, _name); \ + *_p_val_to_free = _buf2; \ + } \ + (const char *) _buf2; \ + }) + +/*****************************************************************************/ + +/** + * The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too + * convinient to miss and is effectively available in gcc and clang. So, just use it. + * + * Usually, one would include "stdbool.h" to get the "bool" define which aliases + * _Bool. We provide this define here, because we want to make use of it anywhere. + * (also, stdbool.h is again C99). + * + * Using _Bool has advantages over gboolean: + * + * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean + * is a typedef for gint). Especially when having boolean fields in a struct, we can + * thereby easily save some space. + * + * - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing + * will not work: + * gboolean v1 = 1; + * gboolean v2 = 2; + * g_assert_cmpint (v1, ==, v2); // will fail + * For that, we often to use !! to coerce gboolean values to 0 or 1: + * g_assert_cmpint (!!v2, ==, TRUE); + * With _Bool type, this will be handled properly by the compiler. + * + * - For structs, we might want to safe even more space and use bitfields: + * struct s1 { + * gboolean v1:1; + * }; + * But the problem here is that gboolean is signed, so that + * v1 will be either 0 or -1 (not 1, TRUE). Thus, the following + * fails: + * struct s1 s = { .v1 = TRUE, }; + * g_assert_cmpint (s1.v1, ==, TRUE); + * It will however work just fine with bool/_Bool while retaining the + * notion of having a boolean value. + * + * Also, add the defines for "true" and "false". Those are nicely highlighted by the editor + * as special types, contrary to glib's "TRUE"/"FALSE". + */ + +#ifndef bool +#define bool _Bool +#define true 1 +#define false 0 +#endif + + +#ifdef _G_BOOLEAN_EXPR +/* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR(). + * As glib's implementation uses a local variable _g_boolean_var_, + * we cannot do + * g_assert (some_macro ()); + * where some_macro() itself expands to ({g_assert(); ...}). + * In other words, you cannot have a g_assert() inside a g_assert() + * without getting a -Werror=shadow failure. + * + * Workaround that by re-defining _G_BOOLEAN_EXPR() + **/ +#undef _G_BOOLEAN_EXPR +#define __NM_G_BOOLEAN_EXPR_IMPL(v, expr) \ + ({ \ + int NM_UNIQ_T(V, v); \ + \ + if (expr) \ + NM_UNIQ_T(V, v) = 1; \ + else \ + NM_UNIQ_T(V, v) = 0; \ + NM_UNIQ_T(V, v); \ + }) +#define _G_BOOLEAN_EXPR(expr) __NM_G_BOOLEAN_EXPR_IMPL (NM_UNIQ, expr) +#endif + +/*****************************************************************************/ + +/** + * nm_steal_int: + * @p_val: pointer to an int type. + * + * Returns: *p_val and sets *p_val to zero the same time. + * Accepts %NULL, in which case also numeric 0 will be returned. + */ +#define nm_steal_int(p_val) \ + ({ \ + typeof (p_val) const _p_val = (p_val); \ + typeof (*_p_val) _val = 0; \ + \ + if ( _p_val \ + && (_val = *_p_val)) { \ + *_p_val = 0; \ + } \ + _val; \ + }) + +static inline int +nm_steal_fd (int *p_fd) +{ + int fd; + + if ( p_fd + && ((fd = *p_fd) >= 0)) { + *p_fd = -1; + return fd; + } + return -1; +} + +/** + * nm_close: + * + * Like close() but throws an assertion if the input fd is + * invalid. Closing an invalid fd is a programming error, so + * it's better to catch it early. + */ +static inline int +nm_close (int fd) +{ + int r; + + r = close (fd); + nm_assert (r != -1 || fd < 0 || errno != EBADF); + return r; +} + +#endif /* __NM_MACROS_INTERNAL_H__ */ diff --git a/tests/network/nm-utils/nm-shared-utils.h b/tests/network/nm-utils/nm-shared-utils.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/network/nm-utils/nm-shared-utils.h diff --git a/tests/network/nm-utils/nm-test-libnm-utils.h b/tests/network/nm-utils/nm-test-libnm-utils.h new file mode 100644 index 000000000..2ea781b80 --- /dev/null +++ b/tests/network/nm-utils/nm-test-libnm-utils.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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 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. + * + * Copyright 2014 - 2015 Red Hat, Inc. + */ + +#include "NetworkManager.h" + +#include "nm-test-utils.h" + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB +#include "nm-dbus-glib-types.h" +#endif + +/*****************************************************************************/ + +typedef struct { + GDBusConnection *bus; + GDBusProxy *proxy; + GPid pid; + int keepalive_fd; +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + struct { + DBusGConnection *bus; + } libdbus; +#endif +} NMTstcServiceInfo; + +NMTstcServiceInfo *nmtstc_service_init (void); +void nmtstc_service_cleanup (NMTstcServiceInfo *info); + +static inline void _nmtstc_auto_service_cleanup (NMTstcServiceInfo **info) +{ + if (info && *info) { + nmtstc_service_cleanup (*info); + *info = NULL; + } +} + +#define NMTSTC_SERVICE_INFO_SETUP(sinfo) \ + NM_PRAGMA_WARNING_DISABLE ("-Wunused-variable") \ + __attribute__ ((cleanup(_nmtstc_auto_service_cleanup))) NMTstcServiceInfo *sinfo = nmtstc_service_init (); \ + NM_PRAGMA_WARNING_REENABLE + +/*****************************************************************************/ + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + +#include "nm-client.h" +#include "nm-remote-settings.h" + +NMClient *nmtstc_nm_client_new (void); +NMRemoteSettings *nmtstc_nm_remote_settings_new (void); + +#else + +NMDevice *nmtstc_service_add_device (NMTstcServiceInfo *info, + NMClient *client, + const char *method, + const char *ifname); + +NMDevice * nmtstc_service_add_wired_device (NMTstcServiceInfo *sinfo, + NMClient *client, + const char *ifname, + const char *hwaddr, + const char **subchannels); + +#endif + +/*****************************************************************************/ + +void nmtstc_service_add_connection (NMTstcServiceInfo *sinfo, + NMConnection *connection, + gboolean verify_connection, + char **out_path); + +void nmtstc_service_add_connection_variant (NMTstcServiceInfo *sinfo, + GVariant *connection, + gboolean verify_connection, + char **out_path); + +void nmtstc_service_update_connection (NMTstcServiceInfo *sinfo, + const char *path, + NMConnection *connection, + gboolean verify_connection); + +void nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, + const char *path, + GVariant *connection, + gboolean verify_connection); + diff --git a/tests/network/nm-utils/nm-test-utils-impl.c b/tests/network/nm-utils/nm-test-utils-impl.c new file mode 100644 index 000000000..998d792a2 --- /dev/null +++ b/tests/network/nm-utils/nm-test-utils-impl.c @@ -0,0 +1,457 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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. + * + * Copyright 2010 - 2015 Red Hat, Inc. + * + */ + +#include "nm-default.h" + +#include <string.h> + +#include "NetworkManager.h" +#include "nm-dbus-compat.h" + +#include "nm-test-libnm-utils.h" + +/*****************************************************************************/ + +static gboolean +name_exists (GDBusConnection *c, const char *name) +{ + GVariant *reply; + gboolean exists = FALSE; + + reply = g_dbus_connection_call_sync (c, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetNameOwner", + g_variant_new ("(s)", name), + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + NULL, + NULL); + if (reply != NULL) { + exists = TRUE; + g_variant_unref (reply); + } + + return exists; +} + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB +static DBusGProxy * +_libdbus_create_proxy_test (DBusGConnection *bus) +{ + DBusGProxy *proxy; + + proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE, + NM_DBUS_PATH, + "org.freedesktop.NetworkManager.LibnmGlibTest"); + g_assert (proxy); + + dbus_g_proxy_set_default_timeout (proxy, G_MAXINT); + + return proxy; +} +#endif + +NMTstcServiceInfo * +nmtstc_service_init (void) +{ + NMTstcServiceInfo *info; + const char *args[] = { TEST_NM_PYTHON, TEST_NM_SERVICE, NULL }; + GError *error = NULL; + int i; + + info = g_malloc0 (sizeof (*info)); + + info->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + + /* Spawn the test service. info->keepalive_fd will be a pipe to the service's + * stdin; if it closes, the service will exit immediately. We use this to + * make sure the service exits if the test program crashes. + */ + g_spawn_async_with_pipes (NULL, (char **) args, NULL, + G_SPAWN_SEARCH_PATH, + NULL, NULL, + &info->pid, &info->keepalive_fd, NULL, NULL, &error); + g_assert_no_error (error); + + /* Wait until the service is registered on the bus */ + for (i = 1000; i > 0; i--) { + if (name_exists (info->bus, "org.freedesktop.NetworkManager")) + break; + g_usleep (G_USEC_PER_SEC / 50); + } + g_assert (i > 0); + + /* Grab a proxy to our fake NM service to trigger tests */ + info->proxy = g_dbus_proxy_new_sync (info->bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + NM_DBUS_SERVICE, + NM_DBUS_PATH, + "org.freedesktop.NetworkManager.LibnmGlibTest", + NULL, &error); + g_assert_no_error (error); + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + info->libdbus.bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + g_assert_no_error (error); + g_assert (info->libdbus.bus); +#endif + return info; +} + +void +nmtstc_service_cleanup (NMTstcServiceInfo *info) +{ + int i; + + g_object_unref (info->proxy); + kill (info->pid, SIGTERM); + + /* Wait until the bus notices the service is gone */ + for (i = 100; i > 0; i--) { + if (!name_exists (info->bus, "org.freedesktop.NetworkManager")) + break; + g_usleep (G_USEC_PER_SEC / 50); + } + g_assert (i > 0); + + g_object_unref (info->bus); + nm_close (info->keepalive_fd); + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + g_clear_pointer (&info->libdbus.bus, dbus_g_connection_unref); +#endif + + memset (info, 0, sizeof (*info)); + g_free (info); +} + +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB) +typedef struct { + GMainLoop *loop; + const char *ifname; + char *path; + NMDevice *device; +} AddDeviceInfo; + +static void +device_added_cb (NMClient *client, + NMDevice *device, + gpointer user_data) +{ + AddDeviceInfo *info = user_data; + + g_assert (device); + g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, info->path); + g_assert_cmpstr (nm_device_get_iface (device), ==, info->ifname); + + info->device = device; + g_main_loop_quit (info->loop); +} + +static gboolean +timeout (gpointer user_data) +{ + g_assert_not_reached (); + return G_SOURCE_REMOVE; +} + +static GVariant * +call_add_wired_device (GDBusProxy *proxy, const char *ifname, const char *hwaddr, + const char **subchannels, GError **error) +{ + const char *empty[] = { NULL }; + + if (!hwaddr) + hwaddr = "/"; + if (!subchannels) + subchannels = empty; + + return g_dbus_proxy_call_sync (proxy, + "AddWiredDevice", + g_variant_new ("(ss^as)", ifname, hwaddr, subchannels), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + error); +} + +static GVariant * +call_add_device (GDBusProxy *proxy, const char *method, const char *ifname, GError **error) +{ + return g_dbus_proxy_call_sync (proxy, + method, + g_variant_new ("(s)", ifname), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + error); +} + +static NMDevice * +add_device_common (NMTstcServiceInfo *sinfo, NMClient *client, + const char *method, const char *ifname, + const char *hwaddr, const char **subchannels) +{ + AddDeviceInfo info; + GError *error = NULL; + GVariant *ret; + guint timeout_id; + + if (g_strcmp0 (method, "AddWiredDevice") == 0) + ret = call_add_wired_device (sinfo->proxy, ifname, hwaddr, subchannels, &error); + else + ret = call_add_device (sinfo->proxy, method, ifname, &error); + + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); + g_variant_get (ret, "(o)", &info.path); + g_variant_unref (ret); + + /* Wait for libnm to find the device */ + info.ifname = ifname; + info.loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (client, "device-added", + G_CALLBACK (device_added_cb), &info); + timeout_id = g_timeout_add_seconds (5, timeout, NULL); + g_main_loop_run (info.loop); + + g_source_remove (timeout_id); + g_signal_handlers_disconnect_by_func (client, device_added_cb, &info); + g_free (info.path); + g_main_loop_unref (info.loop); + + return info.device; +} + +NMDevice * +nmtstc_service_add_device (NMTstcServiceInfo *sinfo, NMClient *client, + const char *method, const char *ifname) +{ + return add_device_common (sinfo, client, method, ifname, NULL, NULL); +} + +NMDevice * +nmtstc_service_add_wired_device (NMTstcServiceInfo *sinfo, NMClient *client, + const char *ifname, const char *hwaddr, + const char **subchannels) +{ + return add_device_common (sinfo, client, "AddWiredDevice", ifname, hwaddr, subchannels); +} +#endif + +void +nmtstc_service_add_connection (NMTstcServiceInfo *sinfo, + NMConnection *connection, + gboolean verify_connection, + char **out_path) +{ +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + gs_unref_hashtable GHashTable *new_settings = NULL; + gboolean success; + gs_free_error GError *error = NULL; + gs_free char *path = NULL; + gs_unref_object DBusGProxy *proxy = NULL; + + g_assert (sinfo); + g_assert (NM_IS_CONNECTION (connection)); + + new_settings = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL); + + proxy = _libdbus_create_proxy_test (sinfo->libdbus.bus); + + success = dbus_g_proxy_call (proxy, + "AddConnection", + &error, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, new_settings, + G_TYPE_BOOLEAN, verify_connection, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID); + g_assert_no_error (error); + g_assert (success); + + g_assert (path && *path); + + if (out_path) + *out_path = g_strdup (path); +#else + nmtstc_service_add_connection_variant (sinfo, + nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL), + verify_connection, + out_path); +#endif +} + +void +nmtstc_service_add_connection_variant (NMTstcServiceInfo *sinfo, + GVariant *connection, + gboolean verify_connection, + char **out_path) +{ + GVariant *result; + GError *error = NULL; + + g_assert (sinfo); + g_assert (G_IS_DBUS_PROXY (sinfo->proxy)); + g_assert (g_variant_is_of_type (connection, G_VARIANT_TYPE ("a{sa{sv}}"))); + + result = g_dbus_proxy_call_sync (sinfo->proxy, + "AddConnection", + g_variant_new ("(vb)", connection, verify_connection), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)"))); + if (out_path) + g_variant_get (result, "(o)", out_path); + g_variant_unref (result); +} + +void +nmtstc_service_update_connection (NMTstcServiceInfo *sinfo, + const char *path, + NMConnection *connection, + gboolean verify_connection) +{ + if (!path) + path = nm_connection_get_path (connection); + g_assert (path); + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB + { + gs_unref_hashtable GHashTable *new_settings = NULL; + gboolean success; + gs_free_error GError *error = NULL; + gs_unref_object DBusGProxy *proxy = NULL; + + g_assert (sinfo); + g_assert (NM_IS_CONNECTION (connection)); + + new_settings = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL); + + proxy = _libdbus_create_proxy_test (sinfo->libdbus.bus); + + success = dbus_g_proxy_call (proxy, + "UpdateConnection", + &error, + DBUS_TYPE_G_OBJECT_PATH, path, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, new_settings, + G_TYPE_BOOLEAN, verify_connection, + G_TYPE_INVALID, + G_TYPE_INVALID); + g_assert_no_error (error); + g_assert (success); + } +#else + nmtstc_service_update_connection_variant (sinfo, + path, + nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL), + verify_connection); +#endif +} + +void +nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, + const char *path, + GVariant *connection, + gboolean verify_connection) +{ + GVariant *result; + GError *error = NULL; + + g_assert (sinfo); + g_assert (G_IS_DBUS_PROXY (sinfo->proxy)); + g_assert (g_variant_is_of_type (connection, G_VARIANT_TYPE ("a{sa{sv}}"))); + g_assert (path && path[0] == '/'); + + result = g_dbus_proxy_call_sync (sinfo->proxy, + "UpdateConnection", + g_variant_new ("(ovb)", path, connection, verify_connection), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()"))); + g_variant_unref (result); +} + +/*****************************************************************************/ + +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB +NMClient * +nmtstc_nm_client_new (void) +{ + NMClient *client; + DBusGConnection *bus; + GError *error = NULL; + gboolean success; + + bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + g_assert_no_error (error); + g_assert (bus); + + client = g_object_new (NM_TYPE_CLIENT, + NM_OBJECT_DBUS_CONNECTION, bus, + NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, + NULL); + g_assert (client != NULL); + + dbus_g_connection_unref (bus); + + success = g_initable_init (G_INITABLE (client), NULL, &error); + g_assert_no_error (error); + g_assert (success == TRUE); + + return client; +} + +NMRemoteSettings * +nmtstc_nm_remote_settings_new (void) +{ + NMRemoteSettings *settings; + DBusGConnection *bus; + GError *error = NULL; + + bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + g_assert_no_error (error); + g_assert (bus); + + settings = nm_remote_settings_new (bus); + g_assert (settings); + + dbus_g_connection_unref (bus); + + return settings; +} +#endif + +/*****************************************************************************/ diff --git a/tests/network/nm-utils/nm-test-utils.h b/tests/network/nm-utils/nm-test-utils.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/network/nm-utils/nm-test-utils.h diff --git a/tests/network/nm-utils/test-networkmanager-service.py b/tests/network/nm-utils/test-networkmanager-service.py new file mode 100755 index 000000000..9dd95bb77 --- /dev/null +++ b/tests/network/nm-utils/test-networkmanager-service.py @@ -0,0 +1,1445 @@ +#!/usr/bin/env python +# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + +from __future__ import print_function + +from gi.repository import GLib +import sys +import dbus +import dbus.service +import dbus.mainloop.glib +import random +import collections +import uuid + +mainloop = GLib.MainLoop() + +# NM State +NM_STATE_UNKNOWN = 0 +NM_STATE_ASLEEP = 10 +NM_STATE_DISCONNECTED = 20 +NM_STATE_DISCONNECTING = 30 +NM_STATE_CONNECTING = 40 +NM_STATE_CONNECTED_LOCAL = 50 +NM_STATE_CONNECTED_SITE = 60 +NM_STATE_CONNECTED_GLOBAL = 70 + +# Device state +NM_DEVICE_STATE_UNKNOWN = 0 +NM_DEVICE_STATE_UNMANAGED = 10 +NM_DEVICE_STATE_UNAVAILABLE = 20 +NM_DEVICE_STATE_DISCONNECTED = 30 +NM_DEVICE_STATE_PREPARE = 40 +NM_DEVICE_STATE_CONFIG = 50 +NM_DEVICE_STATE_NEED_AUTH = 60 +NM_DEVICE_STATE_IP_CONFIG = 70 +NM_DEVICE_STATE_IP_CHECK = 80 +NM_DEVICE_STATE_SECONDARIES = 90 +NM_DEVICE_STATE_ACTIVATED = 100 +NM_DEVICE_STATE_DEACTIVATING = 110 +NM_DEVICE_STATE_FAILED = 120 + +# Device state reason +NM_DEVICE_STATE_REASON_NONE = 0 +NM_DEVICE_STATE_REASON_UNKNOWN = 1 +NM_DEVICE_STATE_REASON_NOW_MANAGED = 2 +NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3 +NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4 +NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5 +NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6 +NM_DEVICE_STATE_REASON_NO_SECRETS = 7 +NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 +NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9 +NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10 +NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11 +NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12 +NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13 +NM_DEVICE_STATE_REASON_PPP_FAILED = 14 +NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15 +NM_DEVICE_STATE_REASON_DHCP_ERROR = 16 +NM_DEVICE_STATE_REASON_DHCP_FAILED = 17 +NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18 +NM_DEVICE_STATE_REASON_SHARED_FAILED = 19 +NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20 +NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21 +NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22 +NM_DEVICE_STATE_REASON_MODEM_BUSY = 23 +NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24 +NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25 +NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26 +NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27 +NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28 +NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29 +NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30 +NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31 +NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32 +NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33 +NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34 +NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35 +NM_DEVICE_STATE_REASON_REMOVED = 36 +NM_DEVICE_STATE_REASON_SLEEPING = 37 +NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38 +NM_DEVICE_STATE_REASON_USER_REQUESTED = 39 +NM_DEVICE_STATE_REASON_CARRIER = 40 +NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41 +NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42 +NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43 +NM_DEVICE_STATE_REASON_BT_FAILED = 44 +NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED = 45 +NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED = 46 +NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED = 47 +NM_DEVICE_STATE_REASON_GSM_SIM_WRONG = 48 +NM_DEVICE_STATE_REASON_INFINIBAND_MODE = 49 +NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED = 50 +NM_DEVICE_STATE_REASON_BR2684_FAILED = 51 +NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE = 52 +NM_DEVICE_STATE_REASON_SSID_NOT_FOUND = 53 +NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED = 54 +NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED = 55 +NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56 +NM_DEVICE_STATE_REASON_MODEM_FAILED = 57 +NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58 +NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT = 59 +NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60 +NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61 +NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62 + +# Device type +NM_DEVICE_TYPE_UNKNOWN = 0 +NM_DEVICE_TYPE_ETHERNET = 1 +NM_DEVICE_TYPE_WIFI = 2 +NM_DEVICE_TYPE_UNUSED1 = 3 +NM_DEVICE_TYPE_UNUSED2 = 4 +NM_DEVICE_TYPE_BT = 5 +NM_DEVICE_TYPE_OLPC_MESH = 6 +NM_DEVICE_TYPE_WIMAX = 7 +NM_DEVICE_TYPE_MODEM = 8 +NM_DEVICE_TYPE_INFINIBAND = 9 +NM_DEVICE_TYPE_BOND = 10 +NM_DEVICE_TYPE_VLAN = 11 +NM_DEVICE_TYPE_ADSL = 12 +NM_DEVICE_TYPE_BRIDGE = 13 +NM_DEVICE_TYPE_GENERIC = 14 +NM_DEVICE_TYPE_TEAM = 15 + +# AC state +NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0 +NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1 +NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2 +NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3 +NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4 + +######################################################### +IFACE_DBUS = 'org.freedesktop.DBus' + +class UnknownInterfaceException(dbus.DBusException): + _dbus_error_name = IFACE_DBUS + '.UnknownInterface' + +class UnknownPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_DBUS + '.UnknownProperty' + +def to_path_array(src): + array = dbus.Array([], signature=dbus.Signature('o')) + for o in src: + array.append(to_path(o)) + return array + +def to_path(src): + if src: + return dbus.ObjectPath(src.path) + return dbus.ObjectPath("/") + +class ExportedObj(dbus.service.Object): + + DBusInterface = collections.namedtuple('DBusInterface', ['dbus_iface', 'get_props_func', 'prop_changed_func']) + + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self._bus = bus + self.path = object_path + self.__ensure_dbus_ifaces() + object_manager.add_object(self) + + def __ensure_dbus_ifaces(self): + if not hasattr(self, '_ExportedObj__dbus_ifaces'): + self.__dbus_ifaces = {} + + def add_dbus_interface(self, dbus_iface, get_props_func, prop_changed_func): + self.__ensure_dbus_ifaces() + self.__dbus_ifaces[dbus_iface] = ExportedObj.DBusInterface(dbus_iface, get_props_func, prop_changed_func) + + def __dbus_interface_get(self, dbus_iface): + if dbus_iface not in self.__dbus_ifaces: + raise UnknownInterfaceException() + return self.__dbus_ifaces[dbus_iface] + + def _dbus_property_get(self, dbus_iface, propname = None): + props = self.__dbus_interface_get(dbus_iface).get_props_func() + if propname is None: + return props + if propname not in props: + raise UnknownPropertyException() + return props[propname] + + def _dbus_property_notify(self, dbus_iface, propname): + prop = self._dbus_property_get(dbus_iface, propname) + self.__dbus_interface_get(dbus_iface).prop_changed_func(self, { propname: prop }) + ExportedObj.PropertiesChanged(self, dbus_iface, { propname: prop }, []) + + @dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as') + def PropertiesChanged(self, iface, changed, invalidated): + pass + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}') + def GetAll(self, dbus_iface): + return self._dbus_property_get(dbus_iface) + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') + def Get(self, dbus_iface, name): + return self._dbus_property_get(dbus_iface, name) + + def get_managed_ifaces(self): + my_ifaces = {} + for iface in self.__dbus_ifaces: + my_ifaces[iface] = self.__dbus_ifaces[iface].get_props_func() + return self.path, my_ifaces + + def remove_from_connection(self): + object_manager.remove_object(self) + dbus.service.Object.remove_from_connection(self) + +################################################################### +IFACE_DEVICE = 'org.freedesktop.NetworkManager.Device' + +class NotSoftwareException(dbus.DBusException): + _dbus_error_name = IFACE_DEVICE + '.NotSoftware' + +PD_UDI = "Udi" +PD_IFACE = "Interface" +PD_DRIVER = "Driver" +PD_STATE = "State" +PD_STATE_REASON = "StateReason" +PD_ACTIVE_CONNECTION = "ActiveConnection" +PD_IP4_CONFIG = "Ip4Config" +PD_IP6_CONFIG = "Ip6Config" +PD_DHCP4_CONFIG = "Dhcp4Config" +PD_DHCP6_CONFIG = "Dhcp6Config" +PD_MANAGED = "Managed" +PD_AUTOCONNECT = "Autoconnect" +PD_DEVICE_TYPE = "DeviceType" +PD_AVAILABLE_CONNECTIONS = "AvailableConnections" + +class Device(ExportedObj): + counter = 1 + + def __init__(self, bus, iface, devtype): + object_path = "/org/freedesktop/NetworkManager/Devices/%d" % Device.counter + Device.counter = Device.counter + 1 + + self.iface = iface + self.udi = "/sys/devices/virtual/%s" % iface + self.devtype = devtype + self.active_connection = None + self.state = NM_DEVICE_STATE_UNAVAILABLE + self.reason = NM_DEVICE_STATE_REASON_NONE + self.ip4_config = None + self.ip6_config = None + self.dhcp4_config = None + self.dhcp6_config = None + self.available_connections = [] + + self.add_dbus_interface(IFACE_DEVICE, self.__get_props, Device.PropertiesChanged) + ExportedObj.__init__(self, bus, object_path) + + # Properties interface + def __get_props(self): + props = {} + props[PD_UDI] = self.udi + props[PD_IFACE] = self.iface + props[PD_DRIVER] = "virtual" + props[PD_STATE] = dbus.UInt32(self.state) + props[PD_STATE_REASON] = dbus.Struct((dbus.UInt32(self.state), dbus.UInt32(self.reason)), signature='uu') + props[PD_ACTIVE_CONNECTION] = to_path(self.active_connection) + props[PD_IP4_CONFIG] = to_path(self.ip4_config) + props[PD_IP6_CONFIG] = to_path(self.ip6_config) + props[PD_DHCP4_CONFIG] = to_path(self.dhcp4_config) + props[PD_DHCP6_CONFIG] = to_path(self.dhcp6_config) + props[PD_MANAGED] = True + props[PD_AUTOCONNECT] = True + props[PD_DEVICE_TYPE] = dbus.UInt32(self.devtype) + props[PD_AVAILABLE_CONNECTIONS] = to_path_array(self.available_connections) + return props + + # methods + @dbus.service.method(dbus_interface=IFACE_DEVICE, in_signature='', out_signature='') + def Disconnect(self): + pass + + @dbus.service.method(dbus_interface=IFACE_DEVICE, in_signature='', out_signature='') + def Delete(self): + # We don't currently support any software device types, so... + raise NotSoftwareException() + pass + + def __notify(self, propname): + self._dbus_property_notify(IFACE_DEVICE, propname) + + @dbus.service.signal(IFACE_DEVICE, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + def set_active_connection(self, ac): + self.active_connection = ac + self.__notify(PD_ACTIVE_CONNECTION) + + def set_state_reason(self, state, reason): + self.state = state + self.reason = reason + self.__notify(PD_STATE) + self.__notify(PD_STATE_REASON) + + +################################################################### + +def random_mac(): + return '%02X:%02X:%02X:%02X:%02X:%02X' % ( + random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), + random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) + ) + +################################################################### +IFACE_WIRED = 'org.freedesktop.NetworkManager.Device.Wired' + +PE_HW_ADDRESS = "HwAddress" +PE_PERM_HW_ADDRESS = "PermHwAddress" +PE_SPEED = "Speed" +PE_CARRIER = "Carrier" +PE_S390_SUBCHANNELS = "S390Subchannels" + +class WiredDevice(Device): + def __init__(self, bus, iface, mac, subchannels): + + if mac is None: + self.mac = random_mac() + else: + self.mac = mac + self.carrier = False + self.speed = 100 + self.s390_subchannels = subchannels + + self.add_dbus_interface(IFACE_WIRED, self.__get_props, WiredDevice.PropertiesChanged) + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_ETHERNET) + + # Properties interface + def __get_props(self): + props = {} + props[PE_HW_ADDRESS] = self.mac + props[PE_PERM_HW_ADDRESS] = self.mac + props[PE_SPEED] = dbus.UInt32(self.speed) + props[PE_CARRIER] = self.carrier + props[PE_S390_SUBCHANNELS] = self.s390_subchannels + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_WIRED, propname) + + @dbus.service.signal(IFACE_WIRED, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + def set_wired_speed(self, speed): + if speed > 0: + self.speed = speed + self.carrier = True + self.__notify(PE_SPEED) + self.__notify(PE_CARRIER) + else: + self.speed = 100 + self.carrier = False + self.__notify(PE_CARRIER) + self.__notify(PE_SPEED) + +################################################################### +IFACE_VLAN = 'org.freedesktop.NetworkManager.Device.Vlan' + +PV_HW_ADDRESS = "HwAddress" +PV_CARRIER = "Carrier" +PV_VLAN_ID = "VlanId" + +class VlanDevice(Device): + def __init__(self, bus, iface): + self.mac = random_mac() + self.carrier = False + self.vlan_id = 1 + + self.add_dbus_interface(IFACE_VLAN, self.__get_props, VlanDevice.PropertiesChanged) + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_VLAN) + + # Properties interface + def __get_props(self): + props = {} + props[PV_HW_ADDRESS] = self.mac + props[PV_CARRIER] = self.carrier + props[PV_VLAN_ID] = dbus.UInt32(self.vlan_id) + return props + + @dbus.service.signal(IFACE_VLAN, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIFI_AP = 'org.freedesktop.NetworkManager.AccessPoint' + +PP_FLAGS = "Flags" +PP_WPA_FLAGS = "WpaFlags" +PP_RSN_FLAGS = "RsnFlags" +PP_SSID = "Ssid" +PP_FREQUENCY = "Frequency" +PP_HW_ADDRESS = "HwAddress" +PP_MODE = "Mode" +PP_MAX_BITRATE = "MaxBitrate" +PP_STRENGTH = "Strength" + +class WifiAp(ExportedObj): + counter = 0 + + def __init__(self, bus, ssid, mac, flags, wpaf, rsnf, freq): + path = "/org/freedesktop/NetworkManager/AccessPoint/%d" % WifiAp.counter + WifiAp.counter = WifiAp.counter + 1 + + self.ssid = ssid + if mac: + self.bssid = mac + else: + self.bssid = random_mac() + self.flags = flags + self.wpaf = wpaf + self.rsnf = rsnf + self.freq = freq + self.strength = random.randint(0, 100) + self.strength_id = GLib.timeout_add_seconds(10, self.strength_cb, None) + + self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props, WifiAp.PropertiesChanged) + ExportedObj.__init__(self, bus, path) + + def __del__(self): + if self.strength_id > 0: + GLib.source_remove(self.strength_id) + self.strength_id = 0 + + def strength_cb(self, ignored): + self.strength = random.randint(0, 100) + self.__notify(PP_STRENGTH) + return True + + # Properties interface + def __get_props(self): + props = {} + props[PP_FLAGS] = dbus.UInt32(self.flags) + props[PP_WPA_FLAGS] = dbus.UInt32(self.wpaf) + props[PP_RSN_FLAGS] = dbus.UInt32(self.rsnf) + props[PP_SSID] = dbus.ByteArray(self.ssid.encode('utf-8')) + props[PP_FREQUENCY] = dbus.UInt32(self.freq) + props[PP_HW_ADDRESS] = self.bssid + props[PP_MODE] = dbus.UInt32(2) # NM_802_11_MODE_INFRA + props[PP_MAX_BITRATE] = dbus.UInt32(54000) + props[PP_STRENGTH] = dbus.Byte(self.strength) + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_WIFI_AP, propname) + + @dbus.service.signal(IFACE_WIFI_AP, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIFI = 'org.freedesktop.NetworkManager.Device.Wireless' + +class ApNotFoundException(dbus.DBusException): + _dbus_error_name = IFACE_WIFI + '.AccessPointNotFound' + +PW_HW_ADDRESS = "HwAddress" +PW_PERM_HW_ADDRESS = "PermHwAddress" +PW_MODE = "Mode" +PW_BITRATE = "Bitrate" +PW_ACCESS_POINTS = "AccessPoints" +PW_ACTIVE_ACCESS_POINT = "ActiveAccessPoint" +PW_WIRELESS_CAPABILITIES = "WirelessCapabilities" + +class WifiDevice(Device): + def __init__(self, bus, iface): + self.mac = random_mac() + self.aps = [] + self.active_ap = None + + self.add_dbus_interface(IFACE_WIFI, self.__get_props, WifiDevice.PropertiesChanged) + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIFI) + + # methods + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='', out_signature='ao') + def GetAccessPoints(self): + # only include non-hidden APs + return to_path_array([a for a in self.aps if a.ssid]) + + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='', out_signature='ao') + def GetAllAccessPoints(self): + # include all APs including hidden ones + return to_path_array(self.aps) + + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='a{sv}', out_signature='') + def RequestScan(self, props): + pass + + @dbus.service.signal(IFACE_WIFI, signature='o') + def AccessPointAdded(self, ap_path): + pass + + def add_ap(self, ap): + self.aps.append(ap) + self.__notify(PW_ACCESS_POINTS) + self.AccessPointAdded(to_path(ap)) + + @dbus.service.signal(IFACE_WIFI, signature='o') + def AccessPointRemoved(self, ap_path): + pass + + def remove_ap(self, ap): + self.aps.remove(ap) + self.__notify(PW_ACCESS_POINTS) + self.AccessPointRemoved(to_path(ap)) + + # Properties interface + def __get_props(self): + props = {} + props[PW_HW_ADDRESS] = self.mac + props[PW_PERM_HW_ADDRESS] = self.mac + props[PW_MODE] = dbus.UInt32(3) # NM_802_11_MODE_INFRA + props[PW_BITRATE] = dbus.UInt32(21000) + props[PW_WIRELESS_CAPABILITIES] = dbus.UInt32(0xFF) + props[PW_ACCESS_POINTS] = to_path_array(self.aps) + props[PW_ACTIVE_ACCESS_POINT] = to_path(self.active_ap) + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_WIFI, propname) + + @dbus.service.signal(IFACE_WIFI, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + # test functions + def add_test_ap(self, ssid, mac): + ap = WifiAp(self._bus, ssid, mac, 0x1, 0x1cc, 0x1cc, 2412) + self.add_ap(ap) + return ap + + def remove_ap_by_path(self, path): + for ap in self.aps: + if ap.path == path: + self.remove_ap(ap) + return + raise ApNotFoundException("AP %s not found" % path) + + +################################################################### +IFACE_WIMAX_NSP = 'org.freedesktop.NetworkManager.WiMax.Nsp' + +PN_NAME = "Name" +PN_SIGNAL_QUALITY = "SignalQuality" +PN_NETWORK_TYPE = "NetworkType" + +class WimaxNsp(ExportedObj): + counter = 0 + + def __init__(self, bus, name): + path = "/org/freedesktop/NetworkManager/Nsp/%d" % WimaxNsp.counter + WimaxNsp.counter = WimaxNsp.counter + 1 + + self.name = name + self.strength = random.randint(0, 100) + self.strength_id = GLib.timeout_add_seconds(10, self.strength_cb, None) + + self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props, WimaxNsp.PropertiesChanged) + ExportedObj.__init__(self, bus, path) + + def __del__(self): + if self.strength_id > 0: + GLib.source_remove(self.strength_id) + self.strength_id = 0 + + def strength_cb(self, ignored): + self.strength = random.randint(0, 100) + self.__notify(PN_SIGNAL_QUALITY) + return True + + # Properties interface + def __get_props(self): + props = {} + props[PN_NAME] = self.name + props[PN_SIGNAL_QUALITY] = dbus.UInt32(self.strength) + props[PN_NETWORK_TYPE] = dbus.UInt32(0x1) # NM_WIMAX_NSP_NETWORK_TYPE_HOME + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_WIMAX_NSP, propname) + + @dbus.service.signal(IFACE_WIMAX_NSP, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIMAX = 'org.freedesktop.NetworkManager.Device.WiMax' + +class NspNotFoundException(dbus.DBusException): + _dbus_error_name = IFACE_WIMAX + '.NspNotFound' + +PX_NSPS = "Nsps" +PX_HW_ADDRESS = "HwAddress" +PX_CENTER_FREQUENCY = "CenterFrequency" +PX_RSSI = "Rssi" +PX_CINR = "Cinr" +PX_TX_POWER = "TxPower" +PX_BSID = "Bsid" +PX_ACTIVE_NSP = "ActiveNsp" + +class WimaxDevice(Device): + def __init__(self, bus, iface): + self.mac = random_mac() + self.bsid = random_mac() + self.nsps = [] + self.active_nsp = None + + self.add_dbus_interface(IFACE_WIMAX, self.__get_props, WimaxDevice.PropertiesChanged) + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIMAX) + + # methods + @dbus.service.method(dbus_interface=IFACE_WIMAX, in_signature='', out_signature='ao') + def GetNspList(self): + # include all APs including hidden ones + return to_path_array(self.nsps) + + @dbus.service.signal(IFACE_WIMAX, signature='o') + def NspAdded(self, nsp_path): + pass + + def add_nsp(self, nsp): + self.nsps.append(nsp) + self.__notify(PX_NSPS) + self.NspAdded(to_path(nsp)) + + @dbus.service.signal(IFACE_WIMAX, signature='o') + def NspRemoved(self, nsp_path): + pass + + def remove_nsp(self, nsp): + self.nsps.remove(nsp) + self.__notify(PX_NSPS) + self.NspRemoved(to_path(nsp)) + + # Properties interface + def __get_props(self): + props = {} + props[PX_HW_ADDRESS] = self.mac + props[PX_CENTER_FREQUENCY] = dbus.UInt32(2525) + props[PX_RSSI] = dbus.Int32(-48) + props[PX_CINR] = dbus.Int32(24) + props[PX_TX_POWER] = dbus.Int32(9) + props[PX_BSID] = self.bsid + props[PX_NSPS] = to_path_array(self.nsps) + props[PX_ACTIVE_NSP] = to_path(self.active_nsp) + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_WIMAX, propname) + + @dbus.service.signal(IFACE_WIMAX, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + # test functions + def add_test_nsp(self, name): + nsp = WimaxNsp(self._bus, name) + self.add_nsp(nsp) + return nsp + + def remove_nsp_by_path(self, path): + for nsp in self.nsps: + if nsp.path == path: + self.remove_nsp(nsp) + return + raise NspNotFoundException("NSP %s not found" % path) + +################################################################### +IFACE_ACTIVE_CONNECTION = 'org.freedesktop.NetworkManager.Connection.Active' + +PAC_CONNECTION = "Connection" +PAC_SPECIFIC_OBJECT = "SpecificObject" +PAC_ID = "Id" +PAC_UUID = "Uuid" +PAC_TYPE = "Type" +PAC_DEVICES = "Devices" +PAC_STATE = "State" +PAC_DEFAULT = "Default" +PAC_IP4CONFIG = "Ip4Config" +PAC_DHCP4CONFIG = "Dhcp4Config" +PAC_DEFAULT6 = "Default6" +PAC_IP6CONFIG = "Ip6Config" +PAC_DHCP6CONFIG = "Dhcp6Config" +PAC_VPN = "Vpn" +PAC_MASTER = "Master" + +class ActiveConnection(ExportedObj): + counter = 1 + + def __init__(self, bus, device, connection, specific_object): + object_path = "/org/freedesktop/NetworkManager/ActiveConnection/%d" % ActiveConnection.counter + ActiveConnection.counter = ActiveConnection.counter + 1 + + self.device = device + self.conn = connection + self.specific_object = specific_object + self.state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN + self.default = False + self.ip4config = None + self.dhcp4config = None + self.default6 = False + self.ip6config = None + self.dhcp6config = None + self.vpn = False + self.master = None + + self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props, ActiveConnection.PropertiesChanged) + ExportedObj.__init__(self, bus, object_path) + + # Properties interface + def __get_props(self): + props = {} + props[PAC_CONNECTION] = to_path(self.conn) + props[PAC_SPECIFIC_OBJECT] = to_path(self.specific_object) + conn_settings = self.conn.GetSettings() + s_con = conn_settings['connection'] + props[PAC_ID] = s_con['id'] + props[PAC_UUID] = s_con['uuid'] + props[PAC_TYPE] = s_con['type'] + props[PAC_DEVICES] = to_path_array([self.device]) + props[PAC_STATE] = dbus.UInt32(self.state) + props[PAC_DEFAULT] = self.default + props[PAC_IP4CONFIG] = to_path(self.ip4config) + props[PAC_DHCP4CONFIG] = to_path(self.dhcp4config) + props[PAC_DEFAULT6] = self.default6 + props[PAC_IP6CONFIG] = to_path(self.ip6config) + props[PAC_DHCP6CONFIG] = to_path(self.dhcp6config) + props[PAC_VPN] = self.vpn + props[PAC_MASTER] = to_path(self.master) + return props + + @dbus.service.signal(IFACE_ACTIVE_CONNECTION, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_TEST = 'org.freedesktop.NetworkManager.LibnmGlibTest' +IFACE_NM = 'org.freedesktop.NetworkManager' + +class PermissionDeniedException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.PermissionDenied' + +class UnknownDeviceException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.UnknownDevice' + +class UnknownConnectionException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.UnknownConnection' + +PM_DEVICES = 'Devices' +PM_ALL_DEVICES = 'AllDevices' +PM_NETWORKING_ENABLED = 'NetworkingEnabled' +PM_WWAN_ENABLED = 'WwanEnabled' +PM_WWAN_HARDWARE_ENABLED = 'WwanHardwareEnabled' +PM_WIRELESS_ENABLED = 'WirelessEnabled' +PM_WIRELESS_HARDWARE_ENABLED = 'WirelessHardwareEnabled' +PM_WIMAX_ENABLED = 'WimaxEnabled' +PM_WIMAX_HARDWARE_ENABLED = 'WimaxHardwareEnabled' +PM_ACTIVE_CONNECTIONS = 'ActiveConnections' +PM_PRIMARY_CONNECTION = 'PrimaryConnection' +PM_ACTIVATING_CONNECTION = 'ActivatingConnection' +PM_STARTUP = 'Startup' +PM_STATE = 'State' +PM_VERSION = 'Version' +PM_CONNECTIVITY = 'Connectivity' + +def set_device_ac_cb(device, ac): + device.set_active_connection(ac) + +class NetworkManager(ExportedObj): + def __init__(self, bus, object_path): + self._bus = bus; + self.devices = [] + self.active_connections = [] + self.primary_connection = None + self.activating_connection = None + self.state = NM_STATE_DISCONNECTED + self.connectivity = 1 + + self.add_dbus_interface(IFACE_NM, self.__get_props, NetworkManager.PropertiesChanged) + ExportedObj.__init__(self, bus, object_path) + + @dbus.service.signal(IFACE_NM, signature='u') + def StateChanged(self, new_state): + pass + + def set_state(self, new_state): + self.state = new_state + self.__notify(PM_STATE) + self.StateChanged(dbus.UInt32(self.state)) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao') + def GetDevices(self): + return to_path_array(self.devices) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao') + def GetAllDevices(self): + return to_path_array(self.devices) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='s', out_signature='o') + def GetDeviceByIpIface(self, ip_iface): + for d in self.devices: + # ignore iface/ip_iface distinction for now + if d.iface == ip_iface: + return to_path(d) + raise UnknownDeviceException("No device found for the requested iface.") + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='ooo', out_signature='o') + def ActivateConnection(self, conpath, devpath, specific_object): + try: + connection = settings.get_connection(conpath) + except Exception as e: + raise UnknownConnectionException("Connection not found") + + hash = connection.GetSettings() + s_con = hash['connection'] + + device = None + for d in self.devices: + if d.path == devpath: + device = d + break + if not device and s_con['type'] == 'vlan': + ifname = s_con['interface-name'] + device = VlanDevice(self._bus, ifname) + self.add_device(device) + if not device: + raise UnknownDeviceException("No device found for the requested iface.") + + # See if we need secrets. For the moment, we only support WPA + if '802-11-wireless-security' in hash: + s_wsec = hash['802-11-wireless-security'] + if (s_wsec['key-mgmt'] == 'wpa-psk' and 'psk' not in s_wsec): + secrets = agent_manager.get_secrets(hash, conpath, '802-11-wireless-security') + if secrets is None: + raise NoSecretsException("No secret agent available") + if '802-11-wireless-security' not in secrets: + raise NoSecretsException("No secrets provided") + s_wsec = secrets['802-11-wireless-security'] + if 'psk' not in s_wsec: + raise NoSecretsException("No secrets provided") + + ac = ActiveConnection(self._bus, device, connection, None) + self.active_connections.append(ac) + self.__notify(PM_ACTIVE_CONNECTIONS) + + if s_con['id'] == 'object-creation-failed-test': + self.active_connections.remove(ac) + self.__notify(PM_ACTIVE_CONNECTIONS) + ac.remove_from_connection() + else: + GLib.timeout_add(50, set_device_ac_cb, device, ac) + + return to_path(ac) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}oo', out_signature='oo') + def AddAndActivateConnection(self, connection, devpath, specific_object): + device = None + for d in self.devices: + if d.path == devpath: + device = d + break + if not device: + raise UnknownDeviceException("No device found for the requested iface.") + + conpath = settings.AddConnection(connection) + return (conpath, self.ActivateConnection(conpath, devpath, specific_object)) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='o', out_signature='') + def DeactivateConnection(self, active_connection): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='b', out_signature='') + def Sleep(self, do_sleep): + if do_sleep: + self.state = NM_STATE_ASLEEP + else: + self.state = NM_STATE_DISCONNECTED + self.__notify(PM_STATE) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='b', out_signature='') + def Enable(self, do_enable): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='a{ss}') + def GetPermissions(self): + return { "org.freedesktop.NetworkManager.enable-disable-network": "yes", + "org.freedesktop.NetworkManager.sleep-wake": "no", + "org.freedesktop.NetworkManager.enable-disable-wifi": "yes", + "org.freedesktop.NetworkManager.enable-disable-wwan": "yes", + "org.freedesktop.NetworkManager.enable-disable-wimax": "yes", + "org.freedesktop.NetworkManager.network-control": "yes", + "org.freedesktop.NetworkManager.wifi.share.protected": "yes", + "org.freedesktop.NetworkManager.wifi.share.open": "yes", + "org.freedesktop.NetworkManager.settings.modify.own": "yes", + "org.freedesktop.NetworkManager.settings.modify.system": "yes", + "org.freedesktop.NetworkManager.settings.modify.hostname": "yes", + "org.freedesktop.NetworkManager.settings.modify.global-dns": "no", + "org.freedesktop.NetworkManager.reload": "no", + } + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='ss', out_signature='') + def SetLogging(self, level, domains): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ss') + def GetLogging(self): + return ("info", "HW,RFKILL,CORE,DEVICE,WIFI,ETHER") + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='u') + def CheckConnectivity(self): + raise PermissionDeniedException("You fail") + + @dbus.service.signal(IFACE_NM, signature='o') + def DeviceAdded(self, devpath): + pass + + def add_device(self, device): + self.devices.append(device) + self.__notify(PM_DEVICES) + self.__notify(PM_ALL_DEVICES) + self.DeviceAdded(to_path(device)) + + @dbus.service.signal(IFACE_NM, signature='o') + def DeviceRemoved(self, devpath): + pass + + def remove_device(self, device): + self.devices.remove(device) + self.__notify(PM_DEVICES) + self.__notify(PM_ALL_DEVICES) + self.DeviceRemoved(to_path(device)) + + ################# D-Bus Properties interface + def __get_props(self): + props = {} + props[PM_DEVICES] = to_path_array(self.devices) + props[PM_ALL_DEVICES] = to_path_array(self.devices) + props[PM_NETWORKING_ENABLED] = True + props[PM_WWAN_ENABLED] = True + props[PM_WWAN_HARDWARE_ENABLED] = True + props[PM_WIRELESS_ENABLED] = True + props[PM_WIRELESS_HARDWARE_ENABLED] = True + props[PM_WIMAX_ENABLED] = True + props[PM_WIMAX_HARDWARE_ENABLED] = True + props[PM_ACTIVE_CONNECTIONS] = to_path_array(self.active_connections) + props[PM_PRIMARY_CONNECTION] = to_path(self.primary_connection) + props[PM_ACTIVATING_CONNECTION] = to_path(self.activating_connection) + props[PM_STARTUP] = False + props[PM_STATE] = dbus.UInt32(self.state) + props[PM_VERSION] = "0.9.9.0" + props[PM_CONNECTIVITY] = dbus.UInt32(self.connectivity) + return props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_NM, propname) + + @dbus.service.signal(IFACE_NM, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + ################# Testing methods + @dbus.service.method(IFACE_TEST, in_signature='', out_signature='') + def Quit(self): + mainloop.quit() + + @dbus.service.method(IFACE_TEST, in_signature='ssas', out_signature='o') + def AddWiredDevice(self, ifname, mac, subchannels): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WiredDevice(self._bus, ifname, mac, subchannels) + self.add_device(dev) + return to_path(dev) + + @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') + def AddWifiDevice(self, ifname): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WifiDevice(self._bus, ifname) + self.add_device(dev) + return to_path(dev) + + @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') + def AddWimaxDevice(self, ifname): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WimaxDevice(self._bus, ifname) + self.add_device(dev) + return to_path(dev) + + @dbus.service.method(IFACE_TEST, in_signature='o', out_signature='') + def RemoveDevice(self, path): + for d in self.devices: + if d.path == path: + self.remove_device(d) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='sss', out_signature='o') + def AddWifiAp(self, ifname, ssid, mac): + for d in self.devices: + if d.iface == ifname: + return to_path(d.add_test_ap(ssid, mac)) + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='so', out_signature='') + def RemoveWifiAp(self, ifname, ap_path): + for d in self.devices: + if d.iface == ifname: + d.remove_ap_by_path(ap_path) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='ss', out_signature='o') + def AddWimaxNsp(self, ifname, name): + for d in self.devices: + if d.iface == ifname: + return to_path(d.add_test_nsp(name)) + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='so', out_signature='') + def RemoveWimaxNsp(self, ifname, nsp_path): + for d in self.devices: + if d.iface == ifname: + d.remove_nsp_by_path(nsp_path) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='', out_signature='') + def AutoRemoveNextConnection(self): + settings.auto_remove_next_connection() + + @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='a{sa{sv}}b', out_signature='o') + def AddConnection(self, connection, verify_connection): + return settings.add_connection(connection, verify_connection) + + @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='sa{sa{sv}}b', out_signature='') + def UpdateConnection(self, path, connection, verify_connection): + return settings.update_connection(connection, path, verify_connection) + + @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='suu', out_signature='') + def SetDeviceState(self, path, state, reason): + for d in self.devices: + if d.path == path: + d.set_state_reason(state, reason) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='su', out_signature='') + def SetWiredSpeed(self, path, speed): + for d in self.devices: + if d.path == path: + d.set_wired_speed(speed) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='', out_signature='') + def Restart(self): + bus.release_name("org.freedesktop.NetworkManager") + bus.request_name("org.freedesktop.NetworkManager") + + +################################################################### +IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection' + +class InvalidPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.InvalidProperty' + +class MissingPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.MissingProperty' + +class InvalidSettingException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.InvalidSetting' + +class MissingSettingException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.MissingSetting' + +class Connection(ExportedObj): + def __init__(self, bus, object_path, settings, remove_func, verify_connection=True): + + if self.get_uuid(settings) is None: + if 'connection' not in settings: + settings['connection'] = { } + settings['connection']['uuid'] = uuid.uuid4() + self.verify(settings, verify_strict=verify_connection) + + self.path = object_path + self.settings = settings + self.remove_func = remove_func + self.visible = True + self.props = {} + self.props['Unsaved'] = False + + self.add_dbus_interface(IFACE_CONNECTION, self.__get_props, None) + ExportedObj.__init__(self, bus, object_path) + + def get_uuid(self, settings=None): + if settings is None: + settings = self.settings + if 'connection' in settings: + s_con = settings['connection'] + if 'uuid' in s_con: + return s_con['uuid'] + return None + + def verify(self, settings=None, verify_strict=True): + if settings is None: + settings = self.settings; + if 'connection' not in settings: + raise MissingSettingException('connection: setting is required') + s_con = settings['connection'] + if 'type' not in s_con: + raise MissingPropertyException('connection.type: property is required') + if 'uuid' not in s_con: + raise MissingPropertyException('connection.uuid: property is required') + if 'id' not in s_con: + raise MissingPropertyException('connection.id: property is required') + + if not verify_strict: + return; + t = s_con['type'] + if t not in ['802-3-ethernet', '802-11-wireless', 'vlan', 'wimax']: + raise InvalidPropertyException('connection.type: unsupported connection type "%s"' % (t)) + + def update_connection(self, settings, verify_connection): + self.verify(settings, verify_strict=verify_connection) + + old_uuid = self.get_uuid() + new_uuid = self.get_uuid(settings) + if old_uuid != new_uuid: + raise InvalidPropertyException('connection.uuid: cannot change the uuid from %s to %s' % (old_uuid, new_uuid)) + + self.settings = settings; + self.Updated() + + def __get_props(self): + return self.props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_CONNECTION, propname) + + # Connection methods + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='a{sa{sv}}') + def GetSettings(self): + if not self.visible: + raise PermissionDeniedException() + return self.settings + + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='b', out_signature='') + def SetVisible(self, vis): + self.visible = vis + self.Updated() + + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='') + def Delete(self): + self.remove_func(self) + self.Removed() + self.remove_from_connection() + + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='a{sa{sv}}', out_signature='') + def Update(self, settings): + self.update_connection(settings, TRUE) + + @dbus.service.signal(IFACE_CONNECTION, signature='') + def Removed(self): + pass + + @dbus.service.signal(IFACE_CONNECTION, signature='') + def Updated(self): + pass + +################################################################### +IFACE_SETTINGS = 'org.freedesktop.NetworkManager.Settings' + +class InvalidHostnameException(dbus.DBusException): + _dbus_error_name = IFACE_SETTINGS + '.InvalidHostname' + +class Settings(ExportedObj): + def __init__(self, bus, object_path): + self.connections = {} + self.bus = bus + self.counter = 1 + self.remove_next_connection = False + self.props = {} + self.props['Hostname'] = "foobar.baz" + self.props['CanModify'] = True + self.props['Connections'] = dbus.Array([], 'o') + + self.add_dbus_interface(IFACE_SETTINGS, self.__get_props, Settings.PropertiesChanged) + ExportedObj.__init__(self, bus, object_path) + + def auto_remove_next_connection(self): + self.remove_next_connection = True; + + def get_connection(self, path): + return self.connections[path] + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='', out_signature='ao') + def ListConnections(self): + return self.connections.keys() + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='a{sa{sv}}', out_signature='o') + def AddConnection(self, settings): + return self.add_connection(settings) + + def add_connection(self, settings, verify_connection=True): + path = "/org/freedesktop/NetworkManager/Settings/Connection/{0}".format(self.counter) + con = Connection(self.bus, path, settings, self.delete_connection, verify_connection) + + uuid = con.get_uuid() + if uuid in [c.get_uuid() for c in self.connections.values()]: + raise InvalidSettingException('cannot add duplicate connection with uuid %s' % (uuid)) + + self.counter = self.counter + 1 + self.connections[path] = con + self.props['Connections'] = dbus.Array(self.connections.keys(), 'o') + self.NewConnection(path) + self.__notify('Connections') + + if self.remove_next_connection: + self.remove_next_connection = False + self.connections[path].Delete() + + return path + + def update_connection(self, connection, path=None, verify_connection=True): + if path is None: + path = connection.path + if path not in self.connections: + raise UnknownConnectionException('Connection not found') + con = self.connections[path] + con.update_connection(connection, verify_connection) + + def delete_connection(self, connection): + del self.connections[connection.path] + self.props['Connections'] = dbus.Array(self.connections.keys(), 'o') + self.__notify('Connections') + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='s', out_signature='') + def SaveHostname(self, hostname): + # Arbitrary requirement to test error handling + if hostname.find('.') == -1: + raise InvalidHostnameException() + self.props['Hostname'] = hostname + self.__notify('Hostname') + + def __get_props(self): + return self.props + + def __notify(self, propname): + self._dbus_property_notify(IFACE_SETTINGS, propname) + + @dbus.service.signal(IFACE_SETTINGS, signature='o') + def NewConnection(self, path): + pass + + @dbus.service.signal(IFACE_SETTINGS, signature='a{sv}') + def PropertiesChanged(self, path): + pass + + @dbus.service.method(IFACE_SETTINGS, in_signature='', out_signature='') + def Quit(self): + mainloop.quit() + +################################################################### +IFACE_AGENT_MANAGER = 'org.freedesktop.NetworkManager.AgentManager' +IFACE_AGENT = 'org.freedesktop.NetworkManager.SecretAgent' + +PATH_SECRET_AGENT = '/org/freedesktop/NetworkManager/SecretAgent' + +FLAG_ALLOW_INTERACTION = 0x1 +FLAG_REQUEST_NEW = 0x2 +FLAG_USER_REQUESTED = 0x4 + +class NoSecretsException(dbus.DBusException): + _dbus_error_name = IFACE_AGENT_MANAGER + '.NoSecrets' + +class UserCanceledException(dbus.DBusException): + _dbus_error_name = IFACE_AGENT_MANAGER + '.UserCanceled' + +class AgentManager(dbus.service.Object): + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self.agents = {} + self.bus = bus + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='s', out_signature='', + sender_keyword='sender') + def Register(self, name, sender=None): + self.RegisterWithCapabilities(name, 0, sender) + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='su', out_signature='', + sender_keyword='sender') + def RegisterWithCapabilities(self, name, caps, sender=None): + self.agents[sender] = self.bus.get_object(sender, PATH_SECRET_AGENT) + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='', out_signature='', + sender_keyword='sender') + def Unregister(self, sender=None): + del self.agents[sender] + + def get_secrets(self, connection, path, setting_name): + if len(self.agents) == 0: + return None + + secrets = {} + for sender in self.agents: + agent = self.agents[sender] + try: + secrets = agent.GetSecrets(connection, path, setting_name, + dbus.Array([], 's'), + FLAG_ALLOW_INTERACTION | FLAG_USER_REQUESTED, + dbus_interface=IFACE_AGENT) + break + except dbus.DBusException as e: + if e.get_dbus_name() == IFACE_AGENT + '.UserCanceled': + raise UserCanceledException('User canceled') + continue + return secrets + +################################################################### +IFACE_OBJECT_MANAGER = 'org.freedesktop.DBus.ObjectManager' + +PATH_OBJECT_MANAGER = '/org/freedesktop' + +class ObjectManager(dbus.service.Object): + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self.objs = [] + self.bus = bus + + @dbus.service.method(dbus_interface=IFACE_OBJECT_MANAGER, + in_signature='', out_signature='a{oa{sa{sv}}}', + sender_keyword='sender') + def GetManagedObjects(self, sender=None): + managed_objects = {} + for obj in self.objs: + name, ifaces = obj.get_managed_ifaces() + managed_objects[name] = ifaces + return managed_objects + + def add_object(self, obj): + self.objs.append(obj) + name, ifaces = obj.get_managed_ifaces() + self.InterfacesAdded(name, ifaces) + + def remove_object(self, obj): + self.objs.remove(obj) + name, ifaces = obj.get_managed_ifaces() + self.InterfacesRemoved(name, ifaces.keys()) + + @dbus.service.signal(IFACE_OBJECT_MANAGER, signature='oa{sa{sv}}') + def InterfacesAdded(self, name, ifaces): + pass + + @dbus.service.signal(IFACE_OBJECT_MANAGER, signature='oas') + def InterfacesRemoved(self, name, ifaces): + pass + +################################################################### +IFACE_DNS_MANAGER = 'org.freedesktop.NetworkManager.DnsManager' + +class DnsManager(ExportedObj): + def __init__(self, bus, object_path): + self.props = {} + self.props['Mode'] = "dnsmasq" + self.props['RcManager'] = "symlink" + self.props['Configuration'] = dbus.Array([ + dbus.Dictionary( + { 'nameservers' : dbus.Array(['1.2.3.4', '5.6.7.8'], 's'), + 'priority' : dbus.Int32(100) }, + 'sv') ], + 'a{sv}') + + self.add_dbus_interface(IFACE_DNS_MANAGER, self.__get_props, None) + ExportedObj.__init__(self, bus, object_path) + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}') + def GetAll(self, iface): + if iface != IFACE_DNS_MANAGER: + raise UnknownInterfaceException() + return self.props + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') + def Get(self, iface, name): + if iface != IFACE_DNS_MANAGER: + raise UnknownInterfaceException() + if not name in self.props.keys(): + raise UnknownPropertyException() + return self.props[name] + + def __get_props(self): + return self.props + +################################################################### +def stdin_cb(io, condition): + mainloop.quit() + +def quit_cb(user_data): + mainloop.quit() + +def main(): + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + random.seed() + + global manager, settings, agent_manager, dns_manager, object_manager, bus + + bus = dbus.SessionBus() + object_manager = ObjectManager(bus, "/org/freedesktop") + manager = NetworkManager(bus, "/org/freedesktop/NetworkManager") + settings = Settings(bus, "/org/freedesktop/NetworkManager/Settings") + agent_manager = AgentManager(bus, "/org/freedesktop/NetworkManager/AgentManager") + dns_manager = DnsManager(bus, "/org/freedesktop/NetworkManager/DnsManager") + + if not bus.request_name("org.freedesktop.NetworkManager"): + sys.exit(1) + + # Watch stdin; if it closes, assume our parent has crashed, and exit + io = GLib.IOChannel(0) + GLib.io_add_watch(io, GLib.PRIORITY_LOW, GLib.IOCondition.HUP, stdin_cb) + + # also quit after inactivity to ensure we don't stick around if the above fails somehow + GLib.timeout_add_seconds(20, quit_cb, None) + + try: + mainloop.run() + except Exception as e: + pass + + sys.exit(0) + +if __name__ == '__main__': + main() + diff --git a/tests/network/nmtst-helpers.h b/tests/network/nmtst-helpers.h new file mode 100644 index 000000000..868da36e3 --- /dev/null +++ b/tests/network/nmtst-helpers.h @@ -0,0 +1,297 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * 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, 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. + * + * Copyright 2010 - 2014, 2018 Red Hat, Inc. + * + */ + +/* Static functions to help with testing */ + + +/* nmtst_create_minimal_connection is copied from nm-test-utils.h. */ + +static inline NMConnection * +nmtst_create_minimal_connection (const char *id, const char *uuid, const char *type, NMSettingConnection **out_s_con) +{ + NMConnection *con; + NMSetting *s_base = NULL; + NMSettingConnection *s_con; + gs_free char *uuid_free = NULL; + + g_assert (id); + + if (uuid) + g_assert (nm_utils_is_uuid (uuid)); + else + uuid = uuid_free = nm_utils_uuid_generate (); + + if (type) { + GType type_g; + + type_g = nm_setting_lookup_type (type); + + g_assert (type_g != G_TYPE_INVALID); + + s_base = g_object_new (type_g, NULL); + g_assert (NM_IS_SETTING (s_base)); + } + + con = nm_simple_connection_new (); + + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, type, + NULL); + nm_connection_add_setting (con, NM_SETTING (s_con)); + + if (s_base) + nm_connection_add_setting (con, s_base); + + if (out_s_con) + *out_s_con = s_con; + return con; +} + + +typedef struct { + GMainLoop *loop; + NMDevice *device; + NMClient *client; + + NMActiveConnection *ac; + + const gchar * const *client_props; + const gchar * const *device_props; + + int client_remaining; + int device_remaining; + int other_remaining; +} EventWaitInfo; + + +#define WAIT_CHECK_REMAINING() \ + if (info->client_remaining == 0 && info->device_remaining == 0 && info->other_remaining == 0) { \ + g_debug ("Got expected events, quitting mainloop"); \ + g_main_loop_quit (info->loop); \ + } \ + if (info->client_remaining < 0 || info->device_remaining < 0 || info->other_remaining < 0) { \ + g_error ("Pending events are negative: client: %d, device: %d, other: %d", info->client_remaining, info->device_remaining, info->other_remaining); \ + g_assert_not_reached (); \ + } + +#define WAIT_DECL() \ + EventWaitInfo info = {0}; \ + gint _timeout_id; +#define WAIT_DEVICE(_device, count, ...) \ + info.device = (_device); \ + info.device_remaining = (count); \ + { const gchar * const *props = (const char const *[]){ __VA_ARGS__, NULL }; \ + info.device_props = props; } \ + g_signal_connect ((_device), "notify", G_CALLBACK (device_notify_cb), &info); +#define WAIT_CLIENT(_client, count, ...) \ + info.client = (_client); \ + info.client_remaining = (count); \ + info.client_props = (const char *[]) {__VA_ARGS__, NULL}; \ + g_signal_connect ((_client), "notify", G_CALLBACK (client_notify_cb), &info); + +#define WAIT_DESTROY() \ + g_source_remove (_timeout_id); \ + if (info.device) \ + g_signal_handlers_disconnect_by_func (info.device, G_CALLBACK (device_notify_cb), &info); \ + if (info.client) \ + g_signal_handlers_disconnect_by_func (info.client, G_CALLBACK (client_notify_cb), &info); \ + g_main_loop_unref (info.loop); + +#define WAIT_FINISHED(timeout) \ + info.loop = g_main_loop_new (NULL, FALSE); \ + _timeout_id = g_timeout_add_seconds ((timeout), timeout_cb, &info); \ + g_main_loop_run (info.loop); \ + WAIT_DESTROY() + +static gboolean +timeout_cb (gpointer user_data) +{ + EventWaitInfo *info = user_data; + + if (info) + g_error ("Pending events are: client: %d, device: %d, other: %d", info->client_remaining, info->device_remaining, info->other_remaining); \ + g_assert_not_reached (); + return G_SOURCE_REMOVE; +} + +static void +device_notify_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + EventWaitInfo *info = user_data; + + g_assert (device == info->device); + + if (!g_strv_contains (info->device_props, g_param_spec_get_name (pspec))) { + g_debug ("Ignoring notification for device property %s", g_param_spec_get_name (pspec)); + return; + } + + g_debug ("Counting notification for device property %s", g_param_spec_get_name (pspec)); + + info->device_remaining--; + WAIT_CHECK_REMAINING() +} + +static void +client_notify_cb (NMClient *client, GParamSpec *pspec, gpointer user_data) +{ + EventWaitInfo *info = user_data; + + g_assert (client == info->client); + + if (!g_strv_contains (info->client_props, g_param_spec_get_name (pspec))) { + g_debug ("Ignoring notification for client property %s", g_param_spec_get_name (pspec)); + return; + } + + g_debug ("Counting notification for client property %s", g_param_spec_get_name (pspec)); + + info->client_remaining--; + WAIT_CHECK_REMAINING() +} + +static void +nmtst_set_device_state (NMTstcServiceInfo *sinfo, NMDevice *device, NMDeviceState state, NMDeviceStateReason reason) +{ + GError *error = NULL; + WAIT_DECL() + + g_debug ("Setting device %s state to %d with reason %d", nm_device_get_iface (device), state, reason); + + g_dbus_proxy_call_sync (sinfo->proxy, + "SetDeviceState", + g_variant_new ("(suu)", nm_object_get_path (NM_OBJECT (device)), state, reason), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + + WAIT_DEVICE(device, 1, "state-reason") + WAIT_FINISHED(5) +} + +static void +nmtst_set_wired_speed (NMTstcServiceInfo *sinfo, NMDevice *device, guint32 speed) +{ + GError *error = NULL; + WAIT_DECL() + + g_debug ("Setting device %s speed to %d", nm_device_get_iface (device), speed); + + g_dbus_proxy_call_sync (sinfo->proxy, + "SetWiredSpeed", + g_variant_new ("(su)", nm_object_get_path (NM_OBJECT (device)), speed), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + + g_assert_no_error (error); + + WAIT_DEVICE(device, 2, "speed", "carrier") + WAIT_FINISHED(5) +} + + +static void +device_removed_cb (NMClient *client, + NMDevice *device, + gpointer user_data) +{ + EventWaitInfo *info = user_data; + + g_assert (device); + g_assert (device == info->device); + + info->other_remaining--; + WAIT_CHECK_REMAINING() +} + +static void +nmtst_remove_device (NMTstcServiceInfo *sinfo, NMClient *client, NMDevice *device) +{ + GError *error = NULL; + WAIT_DECL() + + g_object_ref (device); + + g_dbus_proxy_call_sync (sinfo->proxy, + "RemoveDevice", + g_variant_new ("(s)", nm_object_get_path (NM_OBJECT (device))), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + + info.device = device; + info.client = client; + info.other_remaining = 1; + g_signal_connect (client, "device-removed", + G_CALLBACK (device_removed_cb), &info); + + WAIT_FINISHED(5) + + g_object_unref(device); + g_signal_handlers_disconnect_by_func (client, device_removed_cb, &info); +} + +static void +add_and_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + EventWaitInfo *info = user_data; + GError *error = NULL; + + info->ac = nm_client_add_and_activate_connection_finish (client, result, &error); + g_assert_no_error (error); + g_assert (info->ac != NULL); + + info->other_remaining--; + WAIT_CHECK_REMAINING() +} + +static NMActiveConnection* +nmtst_add_and_activate_connection (NMTstcServiceInfo *sinfo, NMClient *client, NMDevice *device, NMConnection *conn) +{ + WAIT_DECL() + + nm_client_add_and_activate_connection_async (client, conn, device, NULL, + NULL, add_and_activate_cb, &info); + + info.other_remaining = 1; + WAIT_CLIENT(client, 1, NM_CLIENT_ACTIVE_CONNECTIONS); + WAIT_DEVICE(device, 1, NM_DEVICE_ACTIVE_CONNECTION); + + g_object_unref (conn); + + WAIT_FINISHED(5) + + g_assert (info.ac != NULL); + + return info.ac; +} diff --git a/tests/network/test-network-panel.c b/tests/network/test-network-panel.c new file mode 100644 index 000000000..9b3c0cab4 --- /dev/null +++ b/tests/network/test-network-panel.c @@ -0,0 +1,382 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (c) 2010-2014, 2018 Red Hat, Inc. + * + * The Control Center 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. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Benjamin Berg <bberg@redhat.com> + */ + +#define G_LOG_DOMAIN "test-network-panel" + +#include "nm-macros-internal.h" + +#include <NetworkManager.h> +#include <nm-client.h> +#include <nm-utils.h> + +#include "nm-test-libnm-utils.h" + +#include <string.h> +#include <sys/types.h> +#include <signal.h> +#include <gtk/gtk.h> + +#include "cc-test-window.h" +#include "shell/cc-object-storage.h" + +#include "nmtst-helpers.h" + +typedef struct { + NMTstcServiceInfo *sinfo; + NMClient *client; + + NMDevice *main_ether; + + GtkWidget *shell; + CcPanel *panel; +} NetworkPanelFixture; + + +extern GType cc_network_panel_get_type (void); + +static void +fixture_set_up_empty (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + g_autoptr(GError) error = NULL; + + cc_object_storage_initialize (); + + /* Bring up the libnm service. */ + fixture->sinfo = nmtstc_service_init (); + + fixture->client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + fixture->shell = GTK_WIDGET (cc_test_window_new ()); + + fixture->panel = g_object_new (cc_network_panel_get_type (), + "shell", CC_SHELL (fixture->shell), + NULL); + + g_object_ref (fixture->panel); + cc_shell_set_active_panel (CC_SHELL (fixture->shell), fixture->panel); + + gtk_widget_show_all (fixture->shell); +} + +static void +fixture_tear_down (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + g_clear_object (&fixture->panel); + g_clear_pointer (&fixture->shell, gtk_widget_destroy); + + cc_object_storage_destroy (); + + g_clear_pointer (&fixture->sinfo, nmtstc_service_cleanup); +} + +static void +fixture_set_up_wired (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMDevice *second; + + fixture_set_up_empty (fixture, user_data); + + fixture->main_ether = nmtstc_service_add_wired_device (fixture->sinfo, + fixture->client, + "eth1000", + "52:54:00:ab:db:23", + NULL); + + /* Add/remove one to catch issues with signal disconnects. */ + second = nmtstc_service_add_wired_device (fixture->sinfo, + fixture->client, + "eth1001", + "52:54:00:ab:db:24", + NULL); + nmtst_remove_device (fixture->sinfo, fixture->client, second); +} + +/*****************************************************************************/ + +static void +test_device_add (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + const gchar *device_path; + + /* Tell the test service to add a new device. + * We use some weird numbers so that the devices will not exist on the + * host system. */ + fixture->main_ether = nmtstc_service_add_wired_device (fixture->sinfo, + fixture->client, + "eth1000", + "52:54:00:ab:db:23", + NULL); + device_path = nm_object_get_path (NM_OBJECT (fixture->main_ether)); + g_debug("Device added: %s\n", device_path); + + g_assert (gtk_test_find_label(fixture->shell, "Wired") != NULL); +} + +static void +test_second_device_add (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMDevice *device; + const gchar *device_path; + + test_device_add (fixture, user_data); + + device = nmtstc_service_add_wired_device (fixture->sinfo, + fixture->client, + "eth1001", + "52:54:00:ab:db:24", + NULL); + device_path = nm_object_get_path (NM_OBJECT (device)); + g_debug("Second device added: %s\n", device_path); + + g_assert_null (gtk_test_find_label (fixture->shell, "Wired")); + g_assert_nonnull (gtk_test_find_label (fixture->shell, "Ethernet (eth1000)")); + g_assert_nonnull (gtk_test_find_label (fixture->shell, "Ethernet (eth1001)")); +} + +static void +test_second_device_add_remove (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMDevice *device; + const gchar *device_path; + + test_device_add (fixture, user_data); + + device = nmtstc_service_add_wired_device (fixture->sinfo, + fixture->client, + "eth1001", + "52:54:00:ab:db:24", + NULL); + device_path = nm_object_get_path (NM_OBJECT (device)); + g_debug("Second device added: %s\n", device_path); + + nmtst_remove_device (fixture->sinfo, fixture->client, device); + g_debug("Second device removed again\n"); + + g_assert_nonnull (gtk_test_find_label (fixture->shell, "Wired")); + g_assert_null (gtk_test_find_label (fixture->shell, "Ethernet (eth1000)")); + g_assert_null (gtk_test_find_label (fixture->shell, "Ethernet (eth1001)")); +} + +/*****************************************************************************/ + +static void +add_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + EventWaitInfo *info = user_data; + NMRemoteConnection *remote_conn; + g_autoptr(GError) error = NULL; + + remote_conn = nm_client_add_connection_finish (client, result, &error); + g_assert_no_error (error); + g_assert_nonnull (remote_conn); + g_object_unref (remote_conn); + + info->other_remaining--; + WAIT_CHECK_REMAINING() +} + +static void +test_connection_add (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMConnection *conn; + g_autoptr(GError) error = NULL; + WAIT_DECL() + + conn = nmtst_create_minimal_connection ("test-inactive", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_device_connection_compatible (fixture->main_ether, conn, &error); + g_assert_no_error (error); + + nm_client_add_connection_async (fixture->client, conn, TRUE, NULL, add_cb, &info); + + info.other_remaining = 1; + WAIT_CLIENT(fixture->client, 1, NM_CLIENT_CONNECTIONS); + + g_object_unref (conn); + + WAIT_FINISHED(5) + + /* We have one (non-active) connection only, so we get a special case */ + g_assert_nonnull (gtk_test_find_label (fixture->shell, "Cable unplugged")); +} + +/*****************************************************************************/ + +static void +test_unconnected_carrier_plug (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + nmtst_set_wired_speed (fixture->sinfo, fixture->main_ether, 1234); + nmtst_set_device_state (fixture->sinfo, fixture->main_ether, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); + + g_assert_nonnull (gtk_test_find_label (fixture->shell, "1234 Mb/s")); +} + + +/*****************************************************************************/ + + +static void +test_connection_add_activate (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMConnection *conn; + NMActiveConnection *active_conn = NULL; + g_autoptr(GError) error = NULL; + GtkWidget *label, *sw; + + /* First set us into disconnected state with a carrier. */ + nmtst_set_wired_speed (fixture->sinfo, fixture->main_ether, 1234); + nmtst_set_device_state (fixture->sinfo, fixture->main_ether, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); + + conn = nmtst_create_minimal_connection ("test-active", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + + nm_device_connection_compatible (fixture->main_ether, conn, &error); + g_assert_no_error (error); + + active_conn = nmtst_add_and_activate_connection (fixture->sinfo, fixture->client, fixture->main_ether, conn); + g_object_unref (active_conn); + + label = gtk_test_find_label (fixture->shell, "1234 Mb/s"); + sw = gtk_test_find_sibling (label, GTK_TYPE_SWITCH); + g_assert_nonnull (sw); + g_assert_false (gtk_switch_get_state (GTK_SWITCH (sw))); + + /* Now set the state to connected and check the switch state */ + nmtst_set_device_state (fixture->sinfo, fixture->main_ether, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); + g_assert_true (gtk_switch_get_state (GTK_SWITCH (sw))); + + /* Let's toggle the switch back and check we get events */ + gtk_switch_set_active (GTK_SWITCH (sw), FALSE); + + /* Only one connection, so a generic label. */ + g_assert_nonnull (gtk_test_find_label (fixture->shell, "Connected - 1234 Mb/s")); +} + +static void +test_connection_multi_add_activate (NetworkPanelFixture *fixture, + gconstpointer user_data) +{ + NMConnection *conn; + GtkWidget *sw; + g_autoptr(GError) error = NULL; + + /* Add a single connection (just chainging up to other test). */ + test_connection_add (fixture, user_data); + + /* Basically same as test_connection_add_activate but with different assertions. */ + nmtst_set_wired_speed (fixture->sinfo, fixture->main_ether, 1234); + nmtst_set_device_state (fixture->sinfo, fixture->main_ether, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); + + conn = nmtst_create_minimal_connection ("test-active", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + + nm_device_connection_compatible (fixture->main_ether, conn, &error); + g_assert_no_error (error); + + g_object_unref (nmtst_add_and_activate_connection (fixture->sinfo, fixture->client, fixture->main_ether, conn)); + + g_assert_nonnull (gtk_test_find_label (fixture->shell, "test-inactive")); + g_assert_nonnull (gtk_test_find_label (fixture->shell, "test-active")); + g_assert_null (gtk_test_find_label (fixture->shell, "52:54:00:ab:db:23")); + + /* We have no switch if there are multiple connections */ + sw = gtk_test_find_sibling (gtk_test_find_label (fixture->shell, "test-active"), GTK_TYPE_SWITCH); + if (sw) + g_assert_false (gtk_widget_is_visible (sw)); + + /* Now set the state to connected and check the switch state */ + nmtst_set_device_state (fixture->sinfo, fixture->main_ether, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); + + /* Hardware address is shown at this point */ + g_assert_nonnull (gtk_test_find_label (fixture->shell, "52:54:00:ab:db:23")); +} + +int +main (int argc, char **argv) +{ + g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); + g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); + g_setenv ("LC_ALL", "C", TRUE); + + gtk_test_init (&argc, &argv, NULL); + + g_test_add ("/network-panel-wired/device-add", + NetworkPanelFixture, + NULL, + fixture_set_up_empty, + test_device_add, + fixture_tear_down); + + g_test_add ("/network-panel-wired/second-device-add", + NetworkPanelFixture, + NULL, + fixture_set_up_empty, + test_second_device_add, + fixture_tear_down); + + g_test_add ("/network-panel-wired/second-device-add-remove", + NetworkPanelFixture, + NULL, + fixture_set_up_empty, + test_second_device_add_remove, + fixture_tear_down); + + g_test_add ("/network-panel-wired/unconnected-carrier-plug", + NetworkPanelFixture, + NULL, + fixture_set_up_wired, + test_unconnected_carrier_plug, + fixture_tear_down); + + g_test_add ("/network-panel-wired/connection-add", + NetworkPanelFixture, + NULL, + fixture_set_up_wired, + test_connection_add, + fixture_tear_down); + + g_test_add ("/network-panel-wired/connection-add-activate", + NetworkPanelFixture, + NULL, + fixture_set_up_wired, + test_connection_add_activate, + fixture_tear_down); + + g_test_add ("/network-panel-wired/connection-multi-add-activate", + NetworkPanelFixture, + NULL, + fixture_set_up_wired, + test_connection_multi_add_activate, + fixture_tear_down); + + return g_test_run (); +} + diff --git a/tests/network/test-network-panel.py b/tests/network/test-network-panel.py new file mode 100644 index 000000000..f91958a7a --- /dev/null +++ b/tests/network/test-network-panel.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# Copyright © 2018 Red Hat, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Authors: Benjamin Berg <bberg@redhat.com> + +import os +import sys +import unittest + +try: + import dbusmock +except ImportError: + sys.stderr.write('You need python-dbusmock (http://pypi.python.org/pypi/python-dbusmock) for this test suite.\n') + sys.exit(1) + +# Add the shared directory to the search path +sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'shared')) + +from gtest import GTest +from x11session import X11SessionTestCase + +BUILDDIR = os.environ.get('BUILDDIR', os.path.join(os.path.dirname(__file__))) + + +class PanelTestCase(X11SessionTestCase, GTest): + g_test_exe = os.path.join(BUILDDIR, 'test-network-panel') + + +if __name__ == '__main__': + # avoid writing to stderr + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) diff --git a/panels/printers/canonicalization-test.txt b/tests/printers/canonicalization-test.txt index 10ceee17d..10ceee17d 100644 --- a/panels/printers/canonicalization-test.txt +++ b/tests/printers/canonicalization-test.txt diff --git a/tests/printers/meson.build b/tests/printers/meson.build new file mode 100644 index 000000000..bbf43ab0c --- /dev/null +++ b/tests/printers/meson.build @@ -0,0 +1,22 @@ + +test_units = [ + 'test-canonicalization', + 'test-shift' +] + +includes = [top_inc, include_directories('../../panels/printers')] +cflags = '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()) + +foreach unit: test_units + exe = executable( + unit, + [unit + '.c'], + include_directories : includes, + dependencies : common_deps, + link_with : [printers_panel_lib], + c_args : cflags + ) + + test(unit, exe) +endforeach + diff --git a/panels/printers/shift-test.txt b/tests/printers/shift-test.txt index b9eced439..b9eced439 100644 --- a/panels/printers/shift-test.txt +++ b/tests/printers/shift-test.txt diff --git a/panels/printers/test-canonicalization.c b/tests/printers/test-canonicalization.c index d5556600f..d5556600f 100644 --- a/panels/printers/test-canonicalization.c +++ b/tests/printers/test-canonicalization.c diff --git a/panels/printers/test-shift.c b/tests/printers/test-shift.c index e85fe9af3..e85fe9af3 100644 --- a/panels/printers/test-shift.c +++ b/tests/printers/test-shift.c diff --git a/tests/shared/gtest.py b/tests/shared/gtest.py new file mode 100644 index 000000000..bb7130daf --- /dev/null +++ b/tests/shared/gtest.py @@ -0,0 +1,113 @@ +#!/usr/bin/python3 +# Copyright © 2018 Red Hat, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Authors: Benjamin Berg <bberg@redhat.com> + +import os +import sys +import subprocess +import functools + +class _GTestSingleProp(object): + """Property which creates a bound method for calling the specified test.""" + def __init__(self, test): + self.test = test + + @staticmethod + def __func(self, test): + self._gtest_single(test) + + def __get__(self, obj, cls): + bound_method = self.__func.__get__(obj, cls) + partial_method = functools.partial(bound_method, self.test) + partial_method.__doc__ = bound_method.__doc__ + + return partial_method + + +class _GTestMeta(type): + def __new__(cls, name, bases, namespace, **kwds): + result = type.__new__(cls, name, bases, dict(namespace)) + + if result.g_test_exe is not None: + try: + _GTestMeta.make_tests(result.g_test_exe, result) + except Exception as e: + print('') + print(e) + print('Error generating separate test funcs, will call binary once.') + result.test_all = result._gtest_all + + return result + + @staticmethod + def make_tests(exe, result): + env = os.environ.copy() + env['G_MESSAGES_DEBUG'] = '' + test = subprocess.Popen([exe, '-l'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, env=env) + stdout, stderr = test.communicate() + + if test.returncode != 0: + raise AssertionError('Execution of GTest executable to query the tests returned non-zero exit code!') + + stdout = stdout.decode('utf-8') + + for i, test in enumerate(stdout.split('\n')): + if not test: + continue + + # Number it and make sure the function name is prefixed with 'test'. + # Keep the rest as is, we don't care about the fact that the function + # names cannot be typed in. + name = 'test_%03d_' % (i + 1) + test + setattr(result, name, _GTestSingleProp(test)) + + +class GTest(metaclass = _GTestMeta): + """Helper class to run GLib test. A test function will be created for each + test from the executable. + + Use by using this class as a mixin and setting g_test_exe to an appropriate + value. + """ + + #: The GTest based executable + g_test_exe = None + #: Timeout when running a single test + g_test_single_timeout = None + #: Timeout when running all tests in one go + g_test_all_timeout = None + + def _gtest_single(self, test): + assert(test) + p = subprocess.Popen([self.g_test_exe, '-q', '-p', test], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + try: + stdout, stderr = p.communicate(timeout=self.g_test_single_timeout) + except subprocess.TimeoutExpired: + p.kill() + stdout, stderr = p.communicate() + stdout += b'\n\nTest was aborted due to timeout' + + try: + stdout = stdout.decode('utf-8') + except UnicodeDecodeError: + pass + + if p.returncode != 0: + self.fail(stdout) + + def _gtest_all(self): + subprocess.check_call([self.g_test_exe], timeout=self.g_test_all_timeout) diff --git a/tests/shared/x11session.py b/tests/shared/x11session.py new file mode 100644 index 000000000..87e964943 --- /dev/null +++ b/tests/shared/x11session.py @@ -0,0 +1,101 @@ +# Copyright © 2018 Red Hat, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Authors: Benjamin Berg <bberg@redhat.com> + +import os +import sys +import subprocess +from dbusmock import DBusTestCase + +# Intended to be shared across projects, submitted for inclusion into +# dbusmock but might need to live elsewhere +# The pull request contains python 2 compatibility code. +# https://github.com/martinpitt/python-dbusmock/pull/44 + +class X11SessionTestCase(DBusTestCase): + #: The display the X server is running on + X_display = -1 + #: The X server to start + Xserver = 'Xvfb' + #: Further parameters for the X server + Xserver_args = ['-screen', '0', '1280x1024x24', '+extension', 'GLX'] + #: Where to redirect the X stdout and stderr to. Set to None for debugging + #: purposes if the X server is failing for some reason. + Xserver_output = subprocess.DEVNULL + + @classmethod + def setUpClass(klass): + klass.start_xorg() + klass.start_system_bus() + klass.start_session_bus() + + @classmethod + def start_xorg(klass): + r, w = os.pipe() + + # Xvfb seems to randomly crash in some workloads if "-noreset" is not given. + # https://bugzilla.redhat.com/show_bug.cgi?id=1565847 + klass.xorg = subprocess.Popen([klass.Xserver, '-displayfd', "%d" % w, '-noreset'] + klass.Xserver_args, + pass_fds=(w,), + stdout=klass.Xserver_output, + stderr=subprocess.STDOUT) + os.close(w) + + # The X server will write "%d\n", we need to make sure to read the "\n". + # If the server dies we get zero bytes reads as EOF is reached. + display = b'' + while True: + tmp = os.read(r, 1024) + display += tmp + + # Break out if the read was empty or the line feed was read + if not tmp or tmp[-1] == b'\n': + break + + os.close(r) + + try: + display = int(display.strip()) + except ValueError: + # This should never happen, the X server didn't return a proper integer. + # Most likely it died for some odd reason. + # Note: Set Xserver_output to None to debug Xvfb startup issues. + klass.stop_xorg() + raise AssertionError('X server reported back no or an invalid display number (%s)' % (display)) + + klass.X_display = display + # Export information into our environment for tests to use + os.environ['DISPLAY'] = ":%d" % klass.X_display + os.environ['WAYLAND'] = '' + + # Server should still be up and running at this point + assert klass.xorg.poll() is None + + return klass.X_display + + @classmethod + def stop_xorg(klass): + if hasattr(klass, 'xorg'): + klass.X_display = -1 + klass.xorg.terminate() + klass.xorg.wait() + del klass.xorg + + @classmethod + def tearDownClass(klass): + DBusTestCase.tearDownClass() + + klass.stop_xorg() |