Merge branch 'main' into gnome-44-max
This commit is contained in:
commit
c6e4656492
|
|
@ -1,18 +1,10 @@
|
|||
diff --git a/gnome-44-max/bin/setup b/gnome-44-max/bin/setup
|
||||
index 7ee291a..3bd001b 100755
|
||||
index e34efb5..ee5e694 100755
|
||||
--- a/gnome-44-max/bin/setup
|
||||
+++ b/gnome-44-max/bin/setup
|
||||
@@ -11,6 +11,7 @@ check_command() {
|
||||
|
||||
check_command "flatpak"
|
||||
check_command "gnome-extensions"
|
||||
+check_command "glib-compile-schemas"
|
||||
|
||||
# This script gets packaged with the release and should do the bulk of the setup work. This allows this setup to be tied
|
||||
# to a specific release of the code, and guarantees it will never run along-side newer or older binaries.
|
||||
@@ -78,8 +79,10 @@ echo "Copying the manifest file to ${DATA_DIR}"
|
||||
mkdir -p $DATA_DIR
|
||||
cp manifest $DATA_DIR
|
||||
@@ -79,8 +79,10 @@ echo "Copying the manifest file to ${BREEZY_GNOME_DATA_DIR}"
|
||||
mkdir -p $BREEZY_GNOME_DATA_DIR
|
||||
cp manifest $BREEZY_GNOME_DATA_DIR
|
||||
|
||||
-echo "Installing the breezydesktop@xronlinux.com GNOME extension"
|
||||
-gnome-extensions install --force breezydesktop@xronlinux.com.shell-extension.zip
|
||||
|
|
@ -21,8 +13,8 @@ index 7ee291a..3bd001b 100755
|
|||
+gnome-extensions install --force "$EXTENSION_UUID.shell-extension.zip"
|
||||
+glib-compile-schemas "$GNOME_SHELL_DATA_DIR/extensions/$EXTENSION_UUID/schemas"
|
||||
|
||||
echo "Installing the Breezy Desktop UI Flatpak (this may take a couple minutes the first time)"
|
||||
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
echo "Installing the Breezy Desktop UI application"
|
||||
cp -r breezy_ui/data/* $XDG_DATA_HOME
|
||||
diff --git a/gnome-44-max/src/cursor.js b/gnome-44-max/src/cursor.js
|
||||
index 36ad7ee..41102a0 100644
|
||||
--- a/gnome-44-max/src/cursor.js
|
||||
|
|
@ -78,7 +70,7 @@ index 44b3f5f..fa65a4a 100644
|
|||
}
|
||||
|
||||
diff --git a/gnome-44-max/src/extension.js b/gnome-44-max/src/extension.js
|
||||
index cd17162..435154d 100644
|
||||
index 5f62bfd..d06f91c 100644
|
||||
--- a/gnome-44-max/src/extension.js
|
||||
+++ b/gnome-44-max/src/extension.js
|
||||
@@ -1,19 +1,21 @@
|
||||
|
|
@ -135,7 +127,7 @@ index cd17162..435154d 100644
|
|||
|
||||
// Set/destroyed by enable/disable
|
||||
this._cursor_manager = null;
|
||||
@@ -593,6 +594,6 @@ export default class BreezyDesktopExtension extends Extension {
|
||||
@@ -619,6 +620,6 @@ export default class BreezyDesktopExtension extends Extension {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +256,7 @@ index 497274e..6c98cdb 100644
|
|||
}
|
||||
\ No newline at end of file
|
||||
diff --git a/gnome-44-max/src/metadata.json b/gnome-44-max/src/metadata.json
|
||||
index b9b5ebf..c888f94 100644
|
||||
index 125954e..c888f94 100644
|
||||
--- a/gnome-44-max/src/metadata.json
|
||||
+++ b/gnome-44-max/src/metadata.json
|
||||
@@ -5,7 +5,7 @@
|
||||
|
|
@ -353,7 +345,7 @@ index 7883b9b..5478d2a 100644
|
|||
}
|
||||
\ No newline at end of file
|
||||
diff --git a/gnome-44-max/src/xrEffect.js b/gnome-44-max/src/xrEffect.js
|
||||
index aab805c..922ec0f 100644
|
||||
index 6b1421b..7d36c46 100644
|
||||
--- a/gnome-44-max/src/xrEffect.js
|
||||
+++ b/gnome-44-max/src/xrEffect.js
|
||||
@@ -1,13 +1,15 @@
|
||||
|
|
@ -378,7 +370,7 @@ index aab805c..922ec0f 100644
|
|||
+const Me = ExtensionUtils.getCurrentExtension();
|
||||
+
|
||||
+const Globals = Me.imports.globals;
|
||||
+const {
|
||||
+const {
|
||||
dataViewEnd,
|
||||
dataViewUint8,
|
||||
dataViewBigUint,
|
||||
|
|
@ -400,7 +392,7 @@ index aab805c..922ec0f 100644
|
|||
|
||||
// the driver should be using the same data layout version
|
||||
const DATA_LAYOUT_VERSION = 3;
|
||||
@@ -221,7 +223,7 @@ function checkParityByte(dataView) {
|
||||
@@ -232,7 +234,7 @@ function checkParityByte(dataView) {
|
||||
return parityByte === parity;
|
||||
}
|
||||
|
||||
|
|
@ -409,7 +401,7 @@ index aab805c..922ec0f 100644
|
|||
Properties: {
|
||||
'supported-device-detected': GObject.ParamSpec.boolean(
|
||||
'supported-device-detected',
|
||||
@@ -361,8 +363,13 @@ export const XREffect = GObject.registerClass({
|
||||
@@ -372,8 +374,13 @@ export const XREffect = GObject.registerClass({
|
||||
if (!this._initialized) {
|
||||
this.set_uniform_float(this.get_uniform_location('screenTexture'), 1, [0]);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ const Globals = Me.imports.globals;
|
|||
const { CursorManager } = Me.imports.cursormanager;
|
||||
const { Logger } = Me.imports.logger;
|
||||
const { MonitorManager } = Me.imports.monitormanager;
|
||||
const { SystemBackground } = Me.imports.systembackground;
|
||||
const { isValidKeepAlive } = Me.imports.time;
|
||||
const { IPC_FILE_PATH, XREffect } = Me.imports.xrEffect;
|
||||
|
||||
|
|
@ -251,24 +252,25 @@ class BreezyDesktopExtension {
|
|||
this._cursor_manager = new CursorManager(Main.layoutManager.uiGroup, refreshRate);
|
||||
this._cursor_manager.enable();
|
||||
|
||||
this._overlay = new St.Bin();
|
||||
this._overlay.opacity = 255;
|
||||
const overlayContent = new Clutter.Actor({clip_to_allocation: true});
|
||||
|
||||
this._overlay = new St.Bin({
|
||||
child: overlayContent
|
||||
});
|
||||
this._overlay.set_position(targetMonitor.x, targetMonitor.y);
|
||||
this._overlay.set_size(targetMonitor.width, targetMonitor.height);
|
||||
Globals.logger.log_debug(`BreezyDesktopExtension _effect_enable overlay size: \
|
||||
${targetMonitor.width}x${targetMonitor.height} at ${targetMonitor.x},${targetMonitor.y}`);
|
||||
|
||||
const overlayContent = new Clutter.Actor({clip_to_allocation: true});
|
||||
global.stage.add_child(this._overlay);
|
||||
Shell.util_set_hidden_from_pick(this._overlay, true);
|
||||
|
||||
this._background = new SystemBackground();
|
||||
overlayContent.add_child(this._background);
|
||||
|
||||
const uiClone = new Clutter.Clone({ source: Main.layoutManager.uiGroup, clip_to_allocation: true });
|
||||
uiClone.x = -targetMonitor.x;
|
||||
uiClone.y = -targetMonitor.y;
|
||||
overlayContent.add_child(uiClone);
|
||||
|
||||
this._overlay.set_child(overlayContent);
|
||||
|
||||
Shell.util_set_hidden_from_pick(this._overlay, true);
|
||||
global.stage.add_child(this._overlay);
|
||||
|
||||
// In GS 45, use of "actor" was renamed to "child".
|
||||
const clutterContainer = Clutter.Container !== undefined;
|
||||
this._actor_added_connection = global.stage.connect(
|
||||
|
|
|
|||
|
|
@ -283,7 +283,6 @@ var MonitorManager = GObject.registerClass({
|
|||
|
||||
this._monitorsChangedConnection = null;
|
||||
this._displayConfigProxy = null;
|
||||
this._backendManager = null;
|
||||
this._monitorProperties = null;
|
||||
this._changeHookFn = null;
|
||||
this._needsConfigCheck = this.use_optimal_monitor_config;
|
||||
|
|
@ -295,7 +294,6 @@ var MonitorManager = GObject.registerClass({
|
|||
|
||||
enable() {
|
||||
Globals.logger.log_debug('MonitorManager enable');
|
||||
this._backendManager = global.backend.get_monitor_manager();
|
||||
newDisplayConfig(this.extension_path, ((proxy, error) => {
|
||||
if (error) {
|
||||
return;
|
||||
|
|
@ -313,7 +311,6 @@ var MonitorManager = GObject.registerClass({
|
|||
|
||||
this._monitorsChangedConnection = null;
|
||||
this._displayConfigProxy = null;
|
||||
this._backendManager = null;
|
||||
this._monitorProperties = null;
|
||||
this._changeHookFn = null;
|
||||
}
|
||||
|
|
@ -405,7 +402,7 @@ var MonitorManager = GObject.registerClass({
|
|||
const monitorProperties = [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const [monitorName, connectorName, vendor, product, serial, refreshRate] = result[i];
|
||||
const monitorIndex = this._backendManager.get_monitor_for_connector(connectorName);
|
||||
const monitorIndex = global.backend.get_monitor_manager().get_monitor_for_connector(connectorName);
|
||||
Globals.logger.log_debug(`Found monitor ${monitorName}, vendor ${vendor}, product ${product}, serial ${serial}, connector ${connectorName}, index ${monitorIndex}`);
|
||||
if (monitorIndex >= 0) {
|
||||
monitorProperties[monitorIndex] = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
const Cogl = imports.gi.Cogl;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Meta = imports.gi.Meta;
|
||||
|
||||
const DEFAULT_BACKGROUND_COLOR = new Cogl.Color({red: 40, green: 40, blue: 40, alpha: 255});
|
||||
|
||||
let _systemBackground;
|
||||
|
||||
var SystemBackground = GObject.registerClass({
|
||||
Signals: {'loaded': {}},
|
||||
}, class SystemBackground extends Meta.BackgroundActor {
|
||||
_init() {
|
||||
if (_systemBackground == null) {
|
||||
_systemBackground = new Meta.Background({meta_display: global.display});
|
||||
_systemBackground.set_color(DEFAULT_BACKGROUND_COLOR);
|
||||
}
|
||||
|
||||
super._init({
|
||||
meta_display: global.display,
|
||||
monitor: 0,
|
||||
});
|
||||
this.content.background = _systemBackground;
|
||||
|
||||
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
|
||||
this.emit('loaded');
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] SystemBackground.loaded');
|
||||
}
|
||||
});
|
||||
|
|
@ -326,8 +326,11 @@ var XREffect = GObject.registerClass({
|
|||
constructor(params = {}) {
|
||||
super(params);
|
||||
|
||||
this._is_display_distance_at_end = false;
|
||||
this._distance_ease_timeline = null;
|
||||
this.connect('notify::toggle-display-distance-start', this._handle_display_distance_properties_change.bind(this));
|
||||
this.connect('notify::toggle-display-distance-end', this._handle_display_distance_properties_change.bind(this));
|
||||
this.connect('notify::display-distance', this._handle_display_distance_properties_change.bind(this));
|
||||
this._handle_display_distance_properties_change();
|
||||
|
||||
const calibrating = GdkPixbuf.Pixbuf.new_from_file(`${Globals.extension_dir}/textures/calibrating.png`);
|
||||
this.calibratingImage = new Clutter.Image();
|
||||
|
|
@ -340,6 +343,12 @@ var XREffect = GObject.registerClass({
|
|||
customBanner.width, customBanner.height, customBanner.rowstride);
|
||||
}
|
||||
|
||||
_handle_display_distance_properties_change() {
|
||||
const distance_from_end = Math.abs(this.display_distance - this.toggle_display_distance_end);
|
||||
const distance_from_start = Math.abs(this.display_distance - this.toggle_display_distance_start);
|
||||
this._is_display_distance_at_end = distance_from_end < distance_from_start;
|
||||
}
|
||||
|
||||
_change_distance() {
|
||||
if (this._distance_ease_timeline?.is_playing()) this._distance_ease_timeline.stop();
|
||||
|
||||
|
|
@ -353,7 +362,6 @@ var XREffect = GObject.registerClass({
|
|||
this._distance_ease_timeline.get_progress() *
|
||||
(toggle_display_distance_target - this._distance_ease_start);
|
||||
});
|
||||
this._is_display_distance_at_end = !this._is_display_distance_at_end;
|
||||
|
||||
this._distance_ease_timeline.start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5a7ddc2c18df268476dd123b9af84091e3bf49bb
|
||||
Subproject commit d270ebfd2e3202133fea75e1513f1571960bdafd
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
USER_HOME=$(realpath ~)
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# https://stackoverflow.com/a/246128
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||
|
||||
if [ -z "$XDG_DATA_HOME" ]; then
|
||||
XDG_DATA_HOME="$USER_HOME/.local/share"
|
||||
fi
|
||||
|
||||
if [ -z "$XDG_BIN_HOME" ]; then
|
||||
XDG_BIN_HOME="$USER_HOME/.local/bin"
|
||||
fi
|
||||
|
||||
|
||||
# create temp directory
|
||||
tmp_dir=$(mktemp -d -t breezy-gnome-XXXXXXXXXX)
|
||||
pushd $tmp_dir > /dev/null
|
||||
echo "Created temp directory: ${tmp_dir}"
|
||||
|
||||
echo "Extracting to: ${tmp_dir}/breezy_ui"
|
||||
tar -xf $SCRIPT_DIR/../../out/breezyUI-${ARCH}.tar.gz
|
||||
|
||||
echo "Installing the Breezy Desktop UI application"
|
||||
cp -r breezy_ui/data/* $XDG_DATA_HOME
|
||||
cp -r breezy_ui/bin/* $XDG_BIN_HOME
|
||||
|
||||
# update copied files to use the local XDG paths
|
||||
ESCAPED_XDG_DATA_HOME=$(printf '%s\n' "$XDG_DATA_HOME" | sed -e 's/[\/&]/\\&/g')
|
||||
sed -i -e "s/\/usr\/local\/share/$ESCAPED_XDG_DATA_HOME/g" $XDG_BIN_HOME/breezydesktop
|
||||
sed -i "/Exec/c\Exec=$XDG_BIN_HOME/breezydesktop" $XDG_DATA_HOME/applications/com.xronlinux.BreezyDesktop.desktop
|
||||
|
||||
glib-compile-schemas $XDG_DATA_HOME/glib-2.0/schemas
|
||||
update-desktop-database $XDG_DATA_HOME/applications
|
||||
gtk-update-icon-cache
|
||||
|
||||
popd > /dev/null
|
||||
rm -rf $tmp_dir
|
||||
|
|
@ -37,6 +37,7 @@ mkdir -p $PACKAGE_APPS_DIR
|
|||
mkdir -p $PACKAGE_SCHEMAS_DIR
|
||||
|
||||
cp src/*.py $PACKAGE_BREEZY_SRC_DIR
|
||||
cp -r lib $PACKAGE_BREEZY_SRC_DIR
|
||||
cp -L modules/PyXRLinuxDriverIPC/xrdriveripc.py $PACKAGE_BREEZY_SRC_DIR
|
||||
cp $UI_BUILD_PATH/src/breezydesktop.gresource $PACKAGE_BREEZY_DIR
|
||||
cp -r po/mo/* $PACKAGE_LOCALE_DIR
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
pydbus
|
||||
======
|
||||
.. image:: https://travis-ci.org/LEW21/pydbus.svg?branch=master
|
||||
:target: https://travis-ci.org/LEW21/pydbus
|
||||
.. image:: https://badge.fury.io/py/pydbus.svg
|
||||
:target: https://badge.fury.io/py/pydbus
|
||||
|
||||
Pythonic DBus library.
|
||||
|
||||
Changelog: https://github.com/LEW21/pydbus/releases
|
||||
|
||||
Requirements
|
||||
------------
|
||||
* Python 2.7+ - but works best on 3.4+ (help system is nicer there)
|
||||
* PyGI_ (not packaged on pypi, you need to install it from your distribution's repository - it's usually called python-gi, python-gobject or pygobject)
|
||||
* GLib_ 2.46+ and girepository_ 1.46+ (Ubuntu 16.04+) - for object publication support
|
||||
|
||||
.. _PyGI: https://wiki.gnome.org/Projects/PyGObject
|
||||
.. _GLib: https://developer.gnome.org/glib/
|
||||
.. _girepository: https://wiki.gnome.org/Projects/GObjectIntrospection
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Send a desktop notification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SessionBus
|
||||
|
||||
bus = SessionBus()
|
||||
notifications = bus.get('.Notifications')
|
||||
|
||||
notifications.Notify('test', 0, 'dialog-information', "Hello World!", "pydbus works :)", [], {}, 5000)
|
||||
|
||||
List systemd units
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
for unit in systemd.ListUnits():
|
||||
print(unit)
|
||||
|
||||
Start or stop systemd unit
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
job1 = systemd.StopUnit("ssh.service", "fail")
|
||||
job2 = systemd.StartUnit("ssh.service", "fail")
|
||||
|
||||
Watch for new systemd jobs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
from gi.repository import GLib
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
systemd.JobNew.connect(print)
|
||||
GLib.MainLoop().run()
|
||||
|
||||
# or
|
||||
|
||||
systemd.onJobNew = print
|
||||
GLib.MainLoop().run()
|
||||
|
||||
View object's API
|
||||
~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SessionBus
|
||||
|
||||
bus = SessionBus()
|
||||
notifications = bus.get('.Notifications')
|
||||
|
||||
help(notifications)
|
||||
|
||||
More examples & documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Tutorial_ contains more examples and docs.
|
||||
|
||||
.. _Tutorial: https://github.com/LEW21/pydbus/blob/master/doc/tutorial.rst
|
||||
|
||||
Copyright Information
|
||||
---------------------
|
||||
|
||||
Copyright (C) 2014, 2015, 2016 Linus Lewandowski <linus@lew21.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
pip
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
Metadata-Version: 2.0
|
||||
Name: pydbus
|
||||
Version: 0.6.0
|
||||
Summary: Pythonic DBus library
|
||||
Home-page: https://github.com/LEW21/pydbus
|
||||
Author: Linus Lewandowski
|
||||
Author-email: linus@lew21.net
|
||||
License: LGPLv2+
|
||||
Keywords: dbus
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
|
||||
pydbus
|
||||
======
|
||||
.. image:: https://travis-ci.org/LEW21/pydbus.svg?branch=master
|
||||
:target: https://travis-ci.org/LEW21/pydbus
|
||||
.. image:: https://badge.fury.io/py/pydbus.svg
|
||||
:target: https://badge.fury.io/py/pydbus
|
||||
|
||||
Pythonic DBus library.
|
||||
|
||||
Changelog: https://github.com/LEW21/pydbus/releases
|
||||
|
||||
Requirements
|
||||
------------
|
||||
* Python 2.7+ - but works best on 3.4+ (help system is nicer there)
|
||||
* PyGI_ (not packaged on pypi, you need to install it from your distribution's repository - it's usually called python-gi, python-gobject or pygobject)
|
||||
* GLib_ 2.46+ and girepository_ 1.46+ (Ubuntu 16.04+) - for object publication support
|
||||
|
||||
.. _PyGI: https://wiki.gnome.org/Projects/PyGObject
|
||||
.. _GLib: https://developer.gnome.org/glib/
|
||||
.. _girepository: https://wiki.gnome.org/Projects/GObjectIntrospection
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Send a desktop notification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SessionBus
|
||||
|
||||
bus = SessionBus()
|
||||
notifications = bus.get('.Notifications')
|
||||
|
||||
notifications.Notify('test', 0, 'dialog-information', "Hello World!", "pydbus works :)", [], {}, 5000)
|
||||
|
||||
List systemd units
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
for unit in systemd.ListUnits():
|
||||
print(unit)
|
||||
|
||||
Start or stop systemd unit
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
job1 = systemd.StopUnit("ssh.service", "fail")
|
||||
job2 = systemd.StartUnit("ssh.service", "fail")
|
||||
|
||||
Watch for new systemd jobs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SystemBus
|
||||
from gi.repository import GLib
|
||||
|
||||
bus = SystemBus()
|
||||
systemd = bus.get(".systemd1")
|
||||
|
||||
systemd.JobNew.connect(print)
|
||||
GLib.MainLoop().run()
|
||||
|
||||
# or
|
||||
|
||||
systemd.onJobNew = print
|
||||
GLib.MainLoop().run()
|
||||
|
||||
View object's API
|
||||
~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from pydbus import SessionBus
|
||||
|
||||
bus = SessionBus()
|
||||
notifications = bus.get('.Notifications')
|
||||
|
||||
help(notifications)
|
||||
|
||||
More examples & documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Tutorial_ contains more examples and docs.
|
||||
|
||||
.. _Tutorial: https://github.com/LEW21/pydbus/blob/master/doc/tutorial.rst
|
||||
|
||||
Copyright Information
|
||||
---------------------
|
||||
|
||||
Copyright (C) 2014, 2015, 2016 Linus Lewandowski <linus@lew21.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
pydbus-0.6.0.dist-info/DESCRIPTION.rst,sha256=pKEYrpPtLiD4ksnqzDs6ZepA9c3uoy5Mjvuxoi1_pEU,3033
|
||||
pydbus-0.6.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
pydbus-0.6.0.dist-info/METADATA,sha256=JKSoIIJKdCLkuWiXdKtv4bSyMt9rA7BM3_RJbxqk5y4,3838
|
||||
pydbus-0.6.0.dist-info/RECORD,,
|
||||
pydbus-0.6.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
pydbus-0.6.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110
|
||||
pydbus-0.6.0.dist-info/metadata.json,sha256=fouQjd0oTDJrVRvQO8dwqvMZbNib8Ui4TgArvHoxzmQ,916
|
||||
pydbus-0.6.0.dist-info/top_level.txt,sha256=X1ybDik1ZA7yilKlt-MUQCPJBNlAW9Jp6bHoAYgAgN0,7
|
||||
pydbus-0.6.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
||||
pydbus/__init__.py,sha256=5ouUtYT15bJ-LaEFea3ZccXkhlZHyf1ykwKLNnFMlIs,148
|
||||
pydbus/__pycache__/__init__.cpython-312.pyc,,
|
||||
pydbus/__pycache__/_inspect3.cpython-312.pyc,,
|
||||
pydbus/__pycache__/auto_names.cpython-312.pyc,,
|
||||
pydbus/__pycache__/bus.cpython-312.pyc,,
|
||||
pydbus/__pycache__/bus_names.cpython-312.pyc,,
|
||||
pydbus/__pycache__/exitable.cpython-312.pyc,,
|
||||
pydbus/__pycache__/generic.cpython-312.pyc,,
|
||||
pydbus/__pycache__/identifier.cpython-312.pyc,,
|
||||
pydbus/__pycache__/method_call_context.cpython-312.pyc,,
|
||||
pydbus/__pycache__/proxy.cpython-312.pyc,,
|
||||
pydbus/__pycache__/proxy_method.cpython-312.pyc,,
|
||||
pydbus/__pycache__/proxy_property.cpython-312.pyc,,
|
||||
pydbus/__pycache__/proxy_signal.cpython-312.pyc,,
|
||||
pydbus/__pycache__/publication.cpython-312.pyc,,
|
||||
pydbus/__pycache__/registration.cpython-312.pyc,,
|
||||
pydbus/__pycache__/request_name.cpython-312.pyc,,
|
||||
pydbus/__pycache__/subscription.cpython-312.pyc,,
|
||||
pydbus/__pycache__/timeout.cpython-312.pyc,,
|
||||
pydbus/_inspect3.py,sha256=lDzzSThwvbMQ3PwY-SVpWByu___QPhbSvPY0xwQScc8,708
|
||||
pydbus/auto_names.py,sha256=elJqIT2dIhioBYUMvIqtH6Pt_tFCf29QSzp0QXbndy8,519
|
||||
pydbus/bus.py,sha256=dMJAqRq85TJAz8iDZSg8COhjy8sabrofZ2jjSe6Pxds,1565
|
||||
pydbus/bus_names.py,sha256=vdkfHdQy_9FzMWkJaXJZpDpvktV9N2TFyRzLE8X1cDI,3533
|
||||
pydbus/exitable.py,sha256=FblBVEUjz6DyqgJpOVlE8-TMeVaC1ZPf9wyi7ejQ-gI,982
|
||||
pydbus/generic.py,sha256=2K9VNwu-TkMWws818H2BiyLsoX99fZuJgbmoNtVLzjE,2589
|
||||
pydbus/identifier.py,sha256=iVrw6rDMyNiQouNUAMpvEhGCz1Bog-R0HwzmvsHs0LY,383
|
||||
pydbus/method_call_context.py,sha256=ilIh0jJmmdoJX26UF1uV9eYvdQXXgYoyxzNHKvIJcJA,1039
|
||||
pydbus/proxy.py,sha256=Og9VbKJ4sZvr4dI7cBwVKsklWAqfnEmAlSpoaPJIs-g,4203
|
||||
pydbus/proxy_method.py,sha256=I741zD_vBixhpeKArTVLaUDTQsZGJ98xaX2SGORJkb0,3089
|
||||
pydbus/proxy_property.py,sha256=WUkOV4V8DuvmN1-yAD54IJklZqgJex2eTV2KZ20PJ1k,1066
|
||||
pydbus/proxy_signal.py,sha256=D60OxO635erbIknziTzX3QDChhImmjzgUpwjVe8gy6A,2112
|
||||
pydbus/publication.py,sha256=oJKPraVVv0YPLWN2-y0KjjjW1Lu4NNTg9lNoVneYLlY,1391
|
||||
pydbus/registration.py,sha256=GWBv2lDDLrkYCr9WsaEFS1hZstuXB7OgHdEnvC0Shc4,5565
|
||||
pydbus/request_name.py,sha256=jpWNd8H8rlRdJQiNAud-di1jU6gE31JvLOtoXQm_lHE,883
|
||||
pydbus/subscription.py,sha256=MBXKRIvLvSgYLIT7A0a3Qn6aAvT6Rcx1b6xudTsr7mQ,2166
|
||||
pydbus/timeout.py,sha256=G4o9dVwN7hb4MaPUHlcGpQKtlUSaTGjBTBC7nuza9mI,303
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.29.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Natural Language :: English", "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7"], "extensions": {"python.details": {"contacts": [{"email": "linus@lew21.net", "name": "Linus Lewandowski", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/LEW21/pydbus"}}}, "generator": "bdist_wheel (0.29.0)", "keywords": ["dbus"], "license": "LGPLv2+", "metadata_version": "2.0", "name": "pydbus", "summary": "Pythonic DBus library", "version": "0.6.0"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
pydbus
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
from .bus import SystemBus, SessionBus, connect
|
||||
from gi.repository.GLib import Variant
|
||||
|
||||
__all__ = ["SystemBus", "SessionBus", "connect", "Variant"]
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
from collections import OrderedDict
|
||||
from inspect import getargspec
|
||||
|
||||
class _empty:
|
||||
pass
|
||||
|
||||
class Signature:
|
||||
empty = _empty
|
||||
|
||||
def __init__(self, parameters=None, return_annotation=_empty):
|
||||
self.parameters = OrderedDict(((param.name, param) for param in parameters))
|
||||
self.return_annotation = return_annotation
|
||||
|
||||
class Parameter:
|
||||
empty = _empty
|
||||
|
||||
POSITIONAL_ONLY = 0
|
||||
POSITIONAL_OR_KEYWORD = 1
|
||||
KEYWORD_ONLY = 999
|
||||
|
||||
def __init__(self, name, kind, default=_empty, annotation=_empty):
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
self.annotation = annotation
|
||||
|
||||
def signature(f):
|
||||
parameters = [Parameter(arg, Parameter.POSITIONAL_OR_KEYWORD) for arg in getargspec(f).args]
|
||||
return Signature(parameters = parameters)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from gi.repository import Gio
|
||||
|
||||
def auto_bus_name(bus_name):
|
||||
if bus_name[0] == ".":
|
||||
#Default namespace
|
||||
bus_name = "org.freedesktop" + bus_name
|
||||
|
||||
if not Gio.dbus_is_name(bus_name):
|
||||
raise ValueError("invalid bus name")
|
||||
|
||||
return bus_name
|
||||
|
||||
def auto_object_path(bus_name, object_path=None):
|
||||
if object_path is None:
|
||||
# They always name it like that.
|
||||
object_path = "/" + bus_name.replace(".", "/")
|
||||
|
||||
if object_path[0] != "/":
|
||||
object_path = "/" + bus_name.replace(".", "/") + "/" + object_path
|
||||
|
||||
return object_path
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from gi.repository import Gio
|
||||
from .proxy import ProxyMixin
|
||||
from .request_name import RequestNameMixin
|
||||
from .bus_names import OwnMixin, WatchMixin
|
||||
from .subscription import SubscriptionMixin
|
||||
from .registration import RegistrationMixin
|
||||
from .publication import PublicationMixin
|
||||
|
||||
def pydbus_property(self):
|
||||
try:
|
||||
return self._pydbus
|
||||
except AttributeError:
|
||||
self._pydbus = Bus(self)
|
||||
return self._pydbus
|
||||
|
||||
Gio.DBusConnection.pydbus = property(pydbus_property)
|
||||
|
||||
def bus_get(type):
|
||||
return Gio.bus_get_sync(type, None).pydbus
|
||||
|
||||
def connect(address):
|
||||
c = Gio.DBusConnection.new_for_address_sync(address, Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT | Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION, None, None)
|
||||
c.pydbus.autoclose = True
|
||||
return c.pydbus
|
||||
|
||||
class Bus(ProxyMixin, RequestNameMixin, OwnMixin, WatchMixin, SubscriptionMixin, RegistrationMixin, PublicationMixin):
|
||||
Type = Gio.BusType
|
||||
|
||||
def __init__(self, gio_con):
|
||||
self.con = gio_con
|
||||
self.autoclose = False
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if self.autoclose:
|
||||
self.con.close_sync(None)
|
||||
|
||||
@property
|
||||
def dbus(self):
|
||||
try:
|
||||
return self._dbus
|
||||
except AttributeError:
|
||||
self._dbus = self.get(".DBus")[""]
|
||||
return self._dbus
|
||||
|
||||
@property
|
||||
def polkit_authority(self):
|
||||
try:
|
||||
return self._polkit_authority
|
||||
except AttributeError:
|
||||
self._polkit_authority = self.get(".PolicyKit1", "Authority")[""]
|
||||
return self._polkit_authority
|
||||
|
||||
def SystemBus():
|
||||
return bus_get(Bus.Type.SYSTEM)
|
||||
|
||||
def SessionBus():
|
||||
return bus_get(Bus.Type.SESSION)
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
from gi.repository import Gio
|
||||
from .exitable import ExitableWithAliases
|
||||
import warnings
|
||||
|
||||
class NameOwner(ExitableWithAliases("unown")):
|
||||
Flags = Gio.BusNameOwnerFlags
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, con, name, flags, name_aquired_handler, name_lost_handler):
|
||||
id = Gio.bus_own_name_on_connection(con, name, flags, name_aquired_handler, name_lost_handler)
|
||||
self._at_exit(lambda: Gio.bus_unown_name(id))
|
||||
|
||||
class NameWatcher(ExitableWithAliases("unwatch")):
|
||||
Flags = Gio.BusNameWatcherFlags
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, con, name, flags, name_appeared_handler, name_vanished_handler):
|
||||
id = Gio.bus_watch_name_on_connection(con, name, flags, name_appeared_handler, name_vanished_handler)
|
||||
self._at_exit(lambda: Gio.bus_unwatch_name(id))
|
||||
|
||||
class OwnMixin(object):
|
||||
__slots__ = ()
|
||||
NameOwnerFlags = NameOwner.Flags
|
||||
|
||||
def own_name(self, name, flags=0, name_aquired=None, name_lost=None):
|
||||
"""[DEPRECATED] Asynchronously aquires a bus name.
|
||||
|
||||
Starts acquiring name on the bus specified by bus_type and calls
|
||||
name_acquired and name_lost when the name is acquired respectively lost.
|
||||
|
||||
To receive name_aquired and name_lost callbacks, you need an event loop.
|
||||
https://github.com/LEW21/pydbus/blob/master/doc/tutorial.rst#setting-up-an-event-loop
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : string
|
||||
Bus name to aquire
|
||||
flags : NameOwnerFlags, optional
|
||||
name_aquired : callable, optional
|
||||
Invoked when name is acquired
|
||||
name_lost : callable, optional
|
||||
Invoked when name is lost
|
||||
|
||||
Returns
|
||||
-------
|
||||
NameOwner
|
||||
An object you can use as a context manager to unown the name later.
|
||||
|
||||
See Also
|
||||
--------
|
||||
See https://developer.gnome.org/gio/2.44/gio-Owning-Bus-Names.html#g-bus-own-name
|
||||
for more information.
|
||||
"""
|
||||
warnings.warn("own_name() is deprecated, use request_name() instead.", DeprecationWarning)
|
||||
|
||||
name_aquired_handler = (lambda con, name: name_aquired()) if name_aquired is not None else None
|
||||
name_lost_handler = (lambda con, name: name_lost()) if name_lost is not None else None
|
||||
return NameOwner(self.con, name, flags, name_aquired_handler, name_lost_handler)
|
||||
|
||||
class WatchMixin(object):
|
||||
__slots__ = ()
|
||||
NameWatcherFlags = NameWatcher.Flags
|
||||
|
||||
def watch_name(self, name, flags=0, name_appeared=None, name_vanished=None):
|
||||
"""Asynchronously watches a bus name.
|
||||
|
||||
Starts watching name on the bus specified by bus_type and calls
|
||||
name_appeared and name_vanished when the name is known to have a owner
|
||||
respectively known to lose its owner.
|
||||
|
||||
To receive name_appeared and name_vanished callbacks, you need an event loop.
|
||||
https://github.com/LEW21/pydbus/blob/master/doc/tutorial.rst#setting-up-an-event-loop
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : string
|
||||
Bus name to watch
|
||||
flags : NameWatcherFlags, optional
|
||||
name_appeared : callable, optional
|
||||
Invoked when name is known to exist
|
||||
Called as name_appeared(name_owner).
|
||||
name_vanished : callable, optional
|
||||
Invoked when name is known to not exist
|
||||
|
||||
Returns
|
||||
-------
|
||||
NameWatcher
|
||||
An object you can use as a context manager to unwatch the name later.
|
||||
|
||||
See Also
|
||||
--------
|
||||
See https://developer.gnome.org/gio/2.44/gio-Watching-Bus-Names.html#g-bus-watch-name
|
||||
for more information.
|
||||
"""
|
||||
name_appeared_handler = (lambda con, name, name_owner: name_appeared(name_owner)) if name_appeared is not None else None
|
||||
name_vanished_handler = (lambda con, name: name_vanished()) if name_vanished is not None else None
|
||||
return NameWatcher(self.con, name, flags, name_appeared_handler, name_vanished_handler)
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import inspect
|
||||
|
||||
class Exitable(object):
|
||||
__slots__ = ("_at_exit_cbs")
|
||||
|
||||
def _at_exit(self, cb):
|
||||
try:
|
||||
self._at_exit_cbs
|
||||
except AttributeError:
|
||||
self._at_exit_cbs = []
|
||||
|
||||
self._at_exit_cbs.append(cb)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type = None, exc_value = None, traceback = None):
|
||||
if self._exited:
|
||||
return
|
||||
|
||||
for cb in reversed(self._at_exit_cbs):
|
||||
call_with_exc = True
|
||||
try:
|
||||
inspect.getcallargs(cb, exc_type, exc_value, traceback)
|
||||
except TypeError:
|
||||
call_with_exc = False
|
||||
|
||||
if call_with_exc:
|
||||
cb(exc_type, exc_value, traceback)
|
||||
else:
|
||||
cb()
|
||||
|
||||
self._at_exit_cbs = None
|
||||
|
||||
@property
|
||||
def _exited(self):
|
||||
try:
|
||||
return self._at_exit_cbs is None
|
||||
except AttributeError:
|
||||
return True
|
||||
|
||||
def ExitableWithAliases(*exit_methods):
|
||||
class CustomExitable(Exitable):
|
||||
pass
|
||||
|
||||
def exit(self):
|
||||
self.__exit__()
|
||||
|
||||
for exit_method_name in exit_methods:
|
||||
setattr(CustomExitable, exit_method_name, exit)
|
||||
|
||||
return CustomExitable
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
"""Generic programming utilities.
|
||||
|
||||
Utilities implemented in this file are not dependent
|
||||
on dbus, they can be used everywhere.
|
||||
"""
|
||||
|
||||
class subscription(object):
|
||||
__slots__ = ("callback_list", "callback")
|
||||
|
||||
def __init__(self, callback_list, callback):
|
||||
self.callback_list = callback_list
|
||||
self.callback = callback
|
||||
self.callback_list.append(callback)
|
||||
|
||||
def unsubscribe(self):
|
||||
self.callback_list.remove(self.callback)
|
||||
self.callback_list = None
|
||||
self.callback = None
|
||||
|
||||
def disconnect(self):
|
||||
"""An alias for unsubscribe()"""
|
||||
self.unsubscribe()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if not self.callback is None:
|
||||
self.unsubscribe()
|
||||
|
||||
class bound_signal(object):
|
||||
__slots__ = ("__signal__", "__self__") # bound method uses ("__func__", "__self__")
|
||||
|
||||
def __init__(self, signal, instance):
|
||||
self.__signal__ = signal
|
||||
self.__self__ = instance
|
||||
|
||||
@property
|
||||
def callbacks(self):
|
||||
return self.__signal__.map[self.__self__]
|
||||
|
||||
def connect(self, callback):
|
||||
"""Subscribe to the signal."""
|
||||
return self.__signal__.connect(self.__self__, callback)
|
||||
|
||||
def emit(self, *args):
|
||||
"""Emit the signal."""
|
||||
self.__signal__.emit(self.__self__, *args)
|
||||
|
||||
def __call__(self, *args):
|
||||
"""Emit the signal."""
|
||||
self.emit(*args)
|
||||
|
||||
def __repr__(self):
|
||||
return "<bound signal " + self.__signal__.__qualname__ + " of " + repr(self.__self__) + ">"
|
||||
|
||||
class signal(object):
|
||||
"""Static signal object
|
||||
|
||||
You're expected to set it as a class property::
|
||||
|
||||
class A:
|
||||
SomethingHappened = signal()
|
||||
|
||||
Declared this way, it can be used on class instances
|
||||
to connect signal observers::
|
||||
|
||||
a = A()
|
||||
a.SomethingHappened.connect(func)
|
||||
|
||||
and emit the signal::
|
||||
|
||||
a.SomethingHappened()
|
||||
|
||||
You may pass any parameters to the emiting function
|
||||
- they will be forwarded to all subscribed callbacks.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.map = {}
|
||||
self.__qualname__ = "<anonymous signal>" # function uses <lambda> ;)
|
||||
self.__doc__ = "Signal."
|
||||
|
||||
def connect(self, object, callback):
|
||||
"""Subscribe to the signal."""
|
||||
return subscription(self.map.setdefault(object, []), callback)
|
||||
|
||||
def emit(self, object, *args):
|
||||
"""Emit the signal."""
|
||||
for cb in self.map.get(object, []):
|
||||
cb(*args)
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
return bound_signal(self, instance)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
raise AttributeError("can't set attribute")
|
||||
|
||||
def __repr__(self):
|
||||
return "<signal " + self.__qualname__ + " at 0x" + format(id(self), "x") + ">"
|
||||
|
||||
bound_method = type(signal().emit) # TODO find a prettier way to get this type
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
try:
|
||||
isident = str.isidentifier
|
||||
except:
|
||||
import re
|
||||
|
||||
isidentre = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$")
|
||||
def isident(s):
|
||||
return isidentre.match(s) is not None
|
||||
|
||||
def filter_identifier(name):
|
||||
name = name.replace("-", "_")
|
||||
|
||||
safe_name = ""
|
||||
for c in name:
|
||||
if not safe_name:
|
||||
if isident(c):
|
||||
safe_name += c
|
||||
else:
|
||||
if isident("a" + c):
|
||||
safe_name += c
|
||||
return safe_name
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
from gi.repository import GLib
|
||||
from collections import namedtuple
|
||||
|
||||
AuthorizationResult = namedtuple("AuthorizationResult", "is_authorized is_challenge details")
|
||||
|
||||
class MethodCallContext(object):
|
||||
def __init__(self, gdbus_method_invocation):
|
||||
self._mi = gdbus_method_invocation
|
||||
|
||||
@property
|
||||
def bus(self):
|
||||
return self._mi.get_connection().pydbus
|
||||
|
||||
@property
|
||||
def sender(self):
|
||||
return self._mi.get_sender()
|
||||
|
||||
@property
|
||||
def object_path(self):
|
||||
return self._mi.get_object_path()
|
||||
|
||||
@property
|
||||
def interface_name(self):
|
||||
return self._mi.get_interface_name()
|
||||
|
||||
@property
|
||||
def method_name(self):
|
||||
return self._mi.get_method_name()
|
||||
|
||||
def check_authorization(self, action_id, details, interactive=False):
|
||||
return AuthorizationResult(*self.bus.polkit_authority.CheckAuthorization(('system-bus-name', {'name': GLib.Variant("s", self.sender)}), action_id, details, 1 if interactive else 0, ''))
|
||||
|
||||
def is_authorized(self, action_id, details, interactive=False):
|
||||
return self.check_authorization(action_id, details, interactive).is_authorized
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
from gi.repository import GLib
|
||||
from xml.etree import ElementTree as ET
|
||||
from .auto_names import *
|
||||
|
||||
from .proxy_method import ProxyMethod
|
||||
from .proxy_property import ProxyProperty
|
||||
from .proxy_signal import ProxySignal, OnSignal
|
||||
from .timeout import timeout_to_glib
|
||||
|
||||
class ProxyMixin(object):
|
||||
__slots__ = ()
|
||||
|
||||
def get(self, bus_name, object_path=None, **kwargs):
|
||||
"""Get a remote object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bus_name : string
|
||||
Name of the service that exposes this object.
|
||||
You may start with "." - then org.freedesktop will be automatically prepended.
|
||||
object_path : string, optional
|
||||
Path of the object. If not provided, bus_name translated to path format is used.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ProxyObject implementing all the Interfaces exposed by the remote object.
|
||||
Note that it inherits from multiple Interfaces, so the method you want to use
|
||||
may be shadowed by another one, eg. from a newer version of the interface.
|
||||
Therefore, to interact with only a single interface, use:
|
||||
>>> bus.get("org.freedesktop.systemd1")["org.freedesktop.systemd1.Manager"]
|
||||
or simply
|
||||
>>> bus.get(".systemd1")[".Manager"]
|
||||
which will give you access to the one specific interface.
|
||||
"""
|
||||
# Python 2 sux
|
||||
for kwarg in kwargs:
|
||||
if kwarg not in ("timeout",):
|
||||
raise TypeError(self.__qualname__ + " got an unexpected keyword argument '{}'".format(kwarg))
|
||||
timeout = kwargs.get("timeout", None)
|
||||
|
||||
bus_name = auto_bus_name(bus_name)
|
||||
object_path = auto_object_path(bus_name, object_path)
|
||||
|
||||
ret = self.con.call_sync(
|
||||
bus_name, object_path,
|
||||
'org.freedesktop.DBus.Introspectable', "Introspect", None, GLib.VariantType.new("(s)"),
|
||||
0, timeout_to_glib(timeout), None)
|
||||
|
||||
if not ret:
|
||||
raise KeyError("no such object; you might need to pass object path as the 2nd argument for get()")
|
||||
|
||||
xml, = ret.unpack()
|
||||
|
||||
try:
|
||||
introspection = ET.fromstring(xml)
|
||||
except:
|
||||
raise KeyError("object provides invalid introspection XML")
|
||||
|
||||
return CompositeInterface(introspection)(self, bus_name, object_path)
|
||||
|
||||
class ProxyObject(object):
|
||||
def __init__(self, bus, bus_name, path, object=None):
|
||||
self._bus = bus
|
||||
self._bus_name = bus_name
|
||||
self._path = path
|
||||
self._object = object if object else self
|
||||
|
||||
def Interface(iface):
|
||||
|
||||
class interface(ProxyObject):
|
||||
@staticmethod
|
||||
def _Introspect():
|
||||
print(iface.attrib["name"] + ":")
|
||||
for member in iface:
|
||||
print("\t" + member.tag + " " + member.attrib["name"])
|
||||
print()
|
||||
|
||||
interface.__qualname__ = interface.__name__ = iface.attrib["name"]
|
||||
interface.__module__ = "DBUS"
|
||||
|
||||
for member in iface:
|
||||
member_name = member.attrib["name"]
|
||||
if member.tag == "method":
|
||||
setattr(interface, member_name, ProxyMethod(interface.__name__, member))
|
||||
elif member.tag == "property":
|
||||
setattr(interface, member_name, ProxyProperty(interface.__name__, member))
|
||||
elif member.tag == "signal":
|
||||
signal = ProxySignal(interface.__name__, member)
|
||||
setattr(interface, member_name, signal)
|
||||
setattr(interface, "on" + member_name, OnSignal(signal))
|
||||
|
||||
return interface
|
||||
|
||||
def CompositeInterface(introspection):
|
||||
class CompositeObject(ProxyObject):
|
||||
def __getitem__(self, iface):
|
||||
if iface == "" or iface[0] == ".":
|
||||
iface = self._path.replace("/", ".")[1:] + iface
|
||||
matching_bases = [base for base in type(self).__bases__ if base.__name__ == iface]
|
||||
|
||||
if len(matching_bases) == 0:
|
||||
raise KeyError(iface)
|
||||
assert(len(matching_bases) == 1)
|
||||
|
||||
iface_class = matching_bases[0]
|
||||
return iface_class(self._bus, self._bus_name, self._path, self)
|
||||
|
||||
@classmethod
|
||||
def _Introspect(cls):
|
||||
for iface in cls.__bases__:
|
||||
try:
|
||||
iface._Introspect()
|
||||
except:
|
||||
pass
|
||||
|
||||
ifaces = sorted([x for x in introspection if x.tag == "interface"], key=lambda x: int(x.attrib["name"].startswith("org.freedesktop.DBus.")))
|
||||
if not ifaces:
|
||||
raise KeyError("object does not export any interfaces; you might need to pass object path as the 2nd argument for get()")
|
||||
CompositeObject.__bases__ = tuple(Interface(iface) for iface in ifaces)
|
||||
CompositeObject.__name__ = "<CompositeObject>"
|
||||
CompositeObject.__qualname__ = "<CompositeObject>(" + "+".join(x.__name__ for x in CompositeObject.__bases__) + ")"
|
||||
CompositeObject.__module__ = "DBUS"
|
||||
return CompositeObject
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
from gi.repository import GLib
|
||||
from .generic import bound_method
|
||||
from .identifier import filter_identifier
|
||||
from .timeout import timeout_to_glib
|
||||
|
||||
try:
|
||||
from inspect import Signature, Parameter
|
||||
put_signature_in_doc = False
|
||||
except:
|
||||
from ._inspect3 import Signature, Parameter
|
||||
put_signature_in_doc = True
|
||||
|
||||
class DBUSSignature(Signature):
|
||||
|
||||
def __str__(self):
|
||||
result = []
|
||||
for param in self.parameters.values():
|
||||
p = param.name if not param.name.startswith("arg") else ""
|
||||
if type(param.annotation) == str:
|
||||
p += ":" + param.annotation
|
||||
result.append(p)
|
||||
|
||||
rendered = '({})'.format(', '.join(result))
|
||||
|
||||
if self.return_annotation is not Signature.empty:
|
||||
rendered += ' -> {}'.format(self.return_annotation)
|
||||
|
||||
return rendered
|
||||
|
||||
class ProxyMethod(object):
|
||||
def __init__(self, iface_name, method):
|
||||
self._iface_name = iface_name
|
||||
self.__name__ = method.attrib["name"]
|
||||
self.__qualname__ = self._iface_name + "." + self.__name__
|
||||
|
||||
self._inargs = [(arg.attrib.get("name", ""), arg.attrib["type"]) for arg in method if arg.tag == "arg" and arg.attrib["direction"] == "in"]
|
||||
self._outargs = [arg.attrib["type"] for arg in method if arg.tag == "arg" and arg.attrib["direction"] == "out"]
|
||||
self._sinargs = "(" + "".join(x[1] for x in self._inargs) + ")"
|
||||
self._soutargs = "(" + "".join(self._outargs) + ")"
|
||||
|
||||
self_param = Parameter("self", Parameter.POSITIONAL_ONLY)
|
||||
pos_params = []
|
||||
for i, a in enumerate(self._inargs):
|
||||
name = filter_identifier(a[0])
|
||||
|
||||
if not name:
|
||||
name = "arg" + str(i)
|
||||
|
||||
param = Parameter(name, Parameter.POSITIONAL_ONLY, annotation=a[1])
|
||||
|
||||
pos_params.append(param)
|
||||
ret_type = Signature.empty if len(self._outargs) == 0 else self._outargs[0] if len(self._outargs) == 1 else "(" + ", ".join(self._outargs) + ")"
|
||||
|
||||
self.__signature__ = DBUSSignature([self_param] + pos_params, return_annotation=ret_type)
|
||||
|
||||
if put_signature_in_doc:
|
||||
self.__doc__ = self.__name__ + str(self.__signature__)
|
||||
|
||||
def __call__(self, instance, *args, **kwargs):
|
||||
argdiff = len(args) - len(self._inargs)
|
||||
if argdiff < 0:
|
||||
raise TypeError(self.__qualname__ + " missing {} required positional argument(s)".format(-argdiff))
|
||||
elif argdiff > 0:
|
||||
raise TypeError(self.__qualname__ + " takes {} positional argument(s) but {} was/were given".format(len(self._inargs), len(args)))
|
||||
|
||||
# Python 2 sux
|
||||
for kwarg in kwargs:
|
||||
if kwarg not in ("timeout",):
|
||||
raise TypeError(self.__qualname__ + " got an unexpected keyword argument '{}'".format(kwarg))
|
||||
timeout = kwargs.get("timeout", None)
|
||||
|
||||
ret = instance._bus.con.call_sync(
|
||||
instance._bus_name, instance._path,
|
||||
self._iface_name, self.__name__, GLib.Variant(self._sinargs, args), GLib.VariantType.new(self._soutargs),
|
||||
0, timeout_to_glib(timeout), None).unpack()
|
||||
|
||||
if len(self._outargs) == 0:
|
||||
return None
|
||||
elif len(self._outargs) == 1:
|
||||
return ret[0]
|
||||
else:
|
||||
return ret
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
return bound_method(self, instance)
|
||||
|
||||
def __repr__(self):
|
||||
return "<function " + self.__qualname__ + " at 0x" + format(id(self), "x") + ">"
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
from gi.repository import GLib
|
||||
|
||||
class ProxyProperty(object):
|
||||
def __init__(self, iface_name, property):
|
||||
self._iface_name = iface_name
|
||||
self.__name__ = property.attrib["name"]
|
||||
self.__qualname__ = self._iface_name + "." + self.__name__
|
||||
|
||||
self._type = property.attrib["type"]
|
||||
access = property.attrib["access"]
|
||||
self._readable = access.startswith("read")
|
||||
self._writeable = access.endswith("write")
|
||||
self.__doc__ = "(" + self._type + ") " + access
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
if not self._readable:
|
||||
raise AttributeError("unreadable attribute")
|
||||
|
||||
return instance._object["org.freedesktop.DBus.Properties"].Get(self._iface_name, self.__name__)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if instance is None or not self._writeable:
|
||||
raise AttributeError("can't set attribute")
|
||||
|
||||
instance._object["org.freedesktop.DBus.Properties"].Set(self._iface_name, self.__name__, GLib.Variant(self._type, value))
|
||||
|
||||
def __repr__(self):
|
||||
return "<property " + self.__qualname__ + " at 0x" + format(id(self), "x") + ">"
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
from .generic import bound_signal
|
||||
|
||||
class ProxySignal(object):
|
||||
def __init__(self, iface_name, signal):
|
||||
self._iface_name = iface_name
|
||||
self.__name__ = signal.attrib["name"]
|
||||
self.__qualname__ = self._iface_name + "." + self.__name__
|
||||
|
||||
self._args = [arg.attrib["type"] for arg in signal if arg.tag == "arg"]
|
||||
self.__doc__ = "Signal. Callback: (" + ", ".join(self._args) + ")"
|
||||
|
||||
def connect(self, object, callback):
|
||||
"""Subscribe to the signal."""
|
||||
def signal_fired(sender, object, iface, signal, params):
|
||||
callback(*params)
|
||||
return object._bus.subscribe(sender=object._bus_name, object=object._path, iface=self._iface_name, signal=self.__name__, signal_fired=signal_fired)
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
return bound_signal(self, instance)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
raise AttributeError("can't set attribute")
|
||||
|
||||
def __repr__(self):
|
||||
return "<signal " + self.__qualname__ + " at 0x" + format(id(self), "x") + ">"
|
||||
|
||||
class OnSignal(object):
|
||||
def __init__(self, signal):
|
||||
self.signal = signal
|
||||
self.__name__ = "on" + signal.__name__
|
||||
self.__qualname__ = signal._iface_name + "." + self.__name__
|
||||
self.__doc__ = "Assign a callback to subscribe to the signal. Assing None to unsubscribe. Callback: (" + ", ".join(signal._args) + ")"
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
try:
|
||||
return getattr(instance, "_on" + self.signal.__name__)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
def __set__(self, instance, value):
|
||||
if instance is None:
|
||||
raise AttributeError("can't set attribute")
|
||||
|
||||
try:
|
||||
old = getattr(instance, "_sub" + self.signal.__name__)
|
||||
old.unsubscribe()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if value is None:
|
||||
delattr(instance, "_on" + self.signal.__name__)
|
||||
delattr(instance, "_sub" + self.signal.__name__)
|
||||
return
|
||||
|
||||
sub = self.signal.connect(instance, value)
|
||||
setattr(instance, "_on" + self.signal.__name__, value)
|
||||
setattr(instance, "_sub" + self.signal.__name__, sub)
|
||||
|
||||
def __repr__(self):
|
||||
return "<descriptor " + self.__qualname__ + " at 0x" + format(id(self), "x") + ">"
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
from gi.repository import Gio
|
||||
from .exitable import ExitableWithAliases
|
||||
from .auto_names import *
|
||||
|
||||
class Publication(ExitableWithAliases("unpublish")):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, bus, bus_name, *objects, **kwargs): # allow_replacement=True, replace=False
|
||||
# Python 2 sux
|
||||
for kwarg in kwargs:
|
||||
if kwarg not in ("allow_replacement", "replace",):
|
||||
raise TypeError(self.__qualname__ + " got an unexpected keyword argument '{}'".format(kwarg))
|
||||
allow_replacement = kwargs.get("allow_replacement", True)
|
||||
replace = kwargs.get("replace", False)
|
||||
|
||||
bus_name = auto_bus_name(bus_name)
|
||||
|
||||
for object_info in objects:
|
||||
path, object, node_info = (None, None, None)
|
||||
|
||||
if type(object_info) == tuple:
|
||||
if len(object_info) == 3:
|
||||
path, object, node_info = object_info
|
||||
if len(object_info) == 2:
|
||||
path, object = object_info
|
||||
if len(object_info) == 1:
|
||||
object = object_info[0]
|
||||
else:
|
||||
object = object_info
|
||||
|
||||
path = auto_object_path(bus_name, path)
|
||||
self._at_exit(bus.register_object(path, object, node_info).__exit__)
|
||||
|
||||
# Request name only after registering all the objects.
|
||||
self._at_exit(bus.request_name(bus_name, allow_replacement=allow_replacement, replace=replace).__exit__)
|
||||
|
||||
class PublicationMixin(object):
|
||||
__slots__ = ()
|
||||
|
||||
def publish(self, bus_name, *objects):
|
||||
"""Expose objects on the bus."""
|
||||
return Publication(self, bus_name, *objects)
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
from __future__ import print_function
|
||||
import sys, traceback
|
||||
from gi.repository import GLib, Gio
|
||||
from . import generic
|
||||
from .exitable import ExitableWithAliases
|
||||
from functools import partial
|
||||
from .method_call_context import MethodCallContext
|
||||
import logging
|
||||
|
||||
try:
|
||||
from inspect import signature, Parameter
|
||||
except:
|
||||
from ._inspect3 import signature, Parameter
|
||||
|
||||
class ObjectWrapper(ExitableWithAliases("unwrap")):
|
||||
__slots__ = ["object", "outargs", "readable_properties", "writable_properties"]
|
||||
|
||||
def __init__(self, object, interfaces):
|
||||
self.object = object
|
||||
|
||||
self.outargs = {}
|
||||
for iface in interfaces:
|
||||
for method in iface.methods:
|
||||
self.outargs[iface.name + "." + method.name] = [arg.signature for arg in method.out_args]
|
||||
|
||||
self.readable_properties = {}
|
||||
self.writable_properties = {}
|
||||
for iface in interfaces:
|
||||
for prop in iface.properties:
|
||||
if prop.flags & Gio.DBusPropertyInfoFlags.READABLE:
|
||||
self.readable_properties[iface.name + "." + prop.name] = prop.signature
|
||||
if prop.flags & Gio.DBusPropertyInfoFlags.WRITABLE:
|
||||
self.writable_properties[iface.name + "." + prop.name] = prop.signature
|
||||
|
||||
for iface in interfaces:
|
||||
for signal in iface.signals:
|
||||
s_name = signal.name
|
||||
def EmitSignal(iface, signal):
|
||||
return lambda *args: self.SignalEmitted(iface.name, signal.name, GLib.Variant("(" + "".join(s.signature for s in signal.args) + ")", args))
|
||||
self._at_exit(getattr(object, signal.name).connect(EmitSignal(iface, signal)).__exit__)
|
||||
|
||||
if "org.freedesktop.DBus.Properties" not in (iface.name for iface in interfaces):
|
||||
try:
|
||||
def onPropertiesChanged(iface, changed, invalidated):
|
||||
changed = {key: GLib.Variant(self.readable_properties[iface + "." + key], val) for key, val in changed.items()}
|
||||
args = GLib.Variant("(sa{sv}as)", (iface, changed, invalidated))
|
||||
self.SignalEmitted("org.freedesktop.DBus.Properties", "PropertiesChanged", args)
|
||||
self._at_exit(object.PropertiesChanged.connect(onPropertiesChanged).__exit__)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
SignalEmitted = generic.signal()
|
||||
|
||||
def call_method(self, connection, sender, object_path, interface_name, method_name, parameters, invocation):
|
||||
try:
|
||||
try:
|
||||
outargs = self.outargs[interface_name + "." + method_name]
|
||||
method = getattr(self.object, method_name)
|
||||
except KeyError:
|
||||
if interface_name == "org.freedesktop.DBus.Properties":
|
||||
if method_name == "Get":
|
||||
method = self.Get
|
||||
outargs = ["v"]
|
||||
elif method_name == "GetAll":
|
||||
method = self.GetAll
|
||||
outargs = ["a{sv}"]
|
||||
elif method_name == "Set":
|
||||
method = self.Set
|
||||
outargs = []
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
raise
|
||||
|
||||
sig = signature(method)
|
||||
|
||||
kwargs = {}
|
||||
if "dbus_context" in sig.parameters and sig.parameters["dbus_context"].kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
|
||||
kwargs["dbus_context"] = MethodCallContext(invocation)
|
||||
|
||||
result = method(*parameters, **kwargs)
|
||||
|
||||
if len(outargs) == 0:
|
||||
invocation.return_value(None)
|
||||
elif len(outargs) == 1:
|
||||
invocation.return_value(GLib.Variant("(" + "".join(outargs) + ")", (result,)))
|
||||
else:
|
||||
invocation.return_value(GLib.Variant("(" + "".join(outargs) + ")", result))
|
||||
|
||||
except Exception as e:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.exception("Exception while handling %s.%s()", interface_name, method_name)
|
||||
|
||||
#TODO Think of a better way to translate Python exception types to DBus error types.
|
||||
e_type = type(e).__name__
|
||||
if not "." in e_type:
|
||||
e_type = "unknown." + e_type
|
||||
invocation.return_dbus_error(e_type, str(e))
|
||||
|
||||
def Get(self, interface_name, property_name):
|
||||
type = self.readable_properties[interface_name + "." + property_name]
|
||||
result = getattr(self.object, property_name)
|
||||
return GLib.Variant(type, result)
|
||||
|
||||
def GetAll(self, interface_name):
|
||||
ret = {}
|
||||
for name, type in self.readable_properties.items():
|
||||
ns, local = name.rsplit(".", 1)
|
||||
if ns == interface_name:
|
||||
ret[local] = GLib.Variant(type, getattr(self.object, local))
|
||||
return ret
|
||||
|
||||
def Set(self, interface_name, property_name, value):
|
||||
self.writable_properties[interface_name + "." + property_name]
|
||||
setattr(self.object, property_name, value)
|
||||
|
||||
class ObjectRegistration(ExitableWithAliases("unregister")):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, bus, path, interfaces, wrapper, own_wrapper=False):
|
||||
if own_wrapper:
|
||||
self._at_exit(wrapper.__exit__)
|
||||
|
||||
def func(interface_name, signal_name, parameters):
|
||||
bus.con.emit_signal(None, path, interface_name, signal_name, parameters)
|
||||
|
||||
self._at_exit(wrapper.SignalEmitted.connect(func).__exit__)
|
||||
|
||||
try:
|
||||
ids = [bus.con.register_object(path, interface, wrapper.call_method, None, None) for interface in interfaces]
|
||||
except TypeError as e:
|
||||
if str(e).startswith("argument vtable: Expected Gio.DBusInterfaceVTable"):
|
||||
raise Exception("GLib 2.46 is required to publish objects; it is impossible in older versions.")
|
||||
else:
|
||||
raise
|
||||
|
||||
self._at_exit(lambda: [bus.con.unregister_object(id) for id in ids])
|
||||
|
||||
class RegistrationMixin:
|
||||
__slots__ = ()
|
||||
|
||||
def register_object(self, path, object, node_info):
|
||||
if node_info is None:
|
||||
try:
|
||||
node_info = type(object).dbus
|
||||
except AttributeError:
|
||||
node_info = type(object).__doc__
|
||||
|
||||
if type(node_info) != list and type(node_info) != tuple:
|
||||
node_info = [node_info]
|
||||
|
||||
node_info = [Gio.DBusNodeInfo.new_for_xml(ni) for ni in node_info]
|
||||
interfaces = sum((ni.interfaces for ni in node_info), [])
|
||||
|
||||
wrapper = ObjectWrapper(object, interfaces)
|
||||
return ObjectRegistration(self, path, interfaces, wrapper, own_wrapper=True)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from .exitable import ExitableWithAliases
|
||||
|
||||
class NameOwner(ExitableWithAliases("unown")):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, bus, name, allow_replacement, replace):
|
||||
flags = 4 | (1 if allow_replacement else 0) | (2 if replace else 0)
|
||||
res = bus.dbus.RequestName(name, flags)
|
||||
if res == 1:
|
||||
self._at_exit(lambda: bus.dbus.ReleaseName(name))
|
||||
return # OK
|
||||
if res == 3:
|
||||
raise RuntimeError("name already exists on the bus")
|
||||
if res == 4:
|
||||
raise RuntimeError("you're already the owner of this name")
|
||||
raise RuntimeError("cannot take ownership of the name")
|
||||
|
||||
class RequestNameMixin(object):
|
||||
__slots__ = ()
|
||||
|
||||
def request_name(self, name, allow_replacement=True, replace=False):
|
||||
"""Aquires a bus name.
|
||||
|
||||
Returns
|
||||
-------
|
||||
NameOwner
|
||||
An object you can use as a context manager to unown the name later.
|
||||
"""
|
||||
return NameOwner(self, name, allow_replacement, replace)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
from gi.repository import Gio
|
||||
from .exitable import ExitableWithAliases
|
||||
|
||||
class Subscription(ExitableWithAliases("unsubscribe", "disconnect")):
|
||||
Flags = Gio.DBusSignalFlags
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, con, sender, iface, member, object, arg0, flags, callback):
|
||||
id = con.signal_subscribe(sender, iface, member, object, arg0, flags, callback)
|
||||
self._at_exit(lambda: con.signal_unsubscribe(id))
|
||||
|
||||
class SubscriptionMixin(object):
|
||||
__slots__ = ()
|
||||
SubscriptionFlags = Subscription.Flags
|
||||
|
||||
def subscribe(self, sender=None, iface=None, signal=None, object=None, arg0=None, flags=0, signal_fired=None):
|
||||
"""Subscribes to matching signals.
|
||||
|
||||
Subscribes to signals on connection and invokes signal_fired callback
|
||||
whenever the signal is received.
|
||||
|
||||
To receive signal_fired callback, you need an event loop.
|
||||
https://github.com/LEW21/pydbus/blob/master/doc/tutorial.rst#setting-up-an-event-loop
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sender : string, optional
|
||||
Sender name to match on (unique or well-known name) or None to listen from all senders.
|
||||
iface : string, optional
|
||||
Interface name to match on or None to match on all interfaces.
|
||||
signal : string, optional
|
||||
Signal name to match on or None to match on all signals.
|
||||
object : string, optional
|
||||
Object path to match on or None to match on all object paths.
|
||||
arg0 : string, optional
|
||||
Contents of first string argument to match on or None to match on all kinds of arguments.
|
||||
flags : SubscriptionFlags, optional
|
||||
signal_fired : callable, optional
|
||||
Invoked when there is a signal matching the requested data.
|
||||
Parameters: sender, object, iface, signal, params
|
||||
|
||||
Returns
|
||||
-------
|
||||
Subscription
|
||||
An object you can use as a context manager to unsubscribe from the signal later.
|
||||
|
||||
See Also
|
||||
--------
|
||||
See https://developer.gnome.org/gio/2.44/GDBusConnection.html#g-dbus-connection-signal-subscribe
|
||||
for more information.
|
||||
"""
|
||||
callback = (lambda con, sender, object, iface, signal, params: signal_fired(sender, object, iface, signal, params.unpack())) if signal_fired is not None else lambda *args: None
|
||||
return Subscription(self.con, sender, iface, signal, object, arg0, flags, callback)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from gi.repository import GLib, GObject
|
||||
|
||||
def timeout_to_glib(timeout):
|
||||
if timeout is None:
|
||||
try:
|
||||
return GLib.MAXINT
|
||||
except AttributeError:
|
||||
# GLib < 2.46
|
||||
return GObject.G_MAXINT
|
||||
else:
|
||||
try:
|
||||
timeout = timeout.total_seconds()
|
||||
except AttributeError:
|
||||
pass
|
||||
return int(timeout * 1000)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
project('breezydesktop',
|
||||
version: '1.0.0',
|
||||
version: run_command('cat', join_paths('..', 'VERSION'), check: true).stdout().strip(),
|
||||
meson_version: '>= 0.62.0',
|
||||
default_options: [ 'warning_level=2', 'werror=false', ],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-02 09:15-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:35-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -27,11 +27,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -331,22 +331,22 @@ msgid ""
|
|||
"script. Report this issue if it persists."
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr ""
|
||||
|
|
@ -421,22 +421,22 @@ msgstr ""
|
|||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr ""
|
||||
|
|
|
|||
30
ui/po/de.po
30
ui/po/de.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 20:54-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
|
||||
|
|
@ -29,11 +29,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Diese Funktion wird von Ihrem Gerät derzeit nicht unterstützt."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Bezahlter Tarifstatus"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Funktionsverfügbarkeit"
|
||||
|
||||
|
|
@ -354,22 +354,22 @@ msgstr ""
|
|||
"das Setup-Skript bitte erneut aus. Melden Sie dieses Problem, falls es "
|
||||
"beständig ist."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Lizenzdetails"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Spenden"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Ein Token anfordern"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Token verifizieren"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Lizenzdetails"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Kein Gerät verbunden"
|
||||
|
|
@ -470,22 +470,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Menü"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Einige Funktionen laufen bald ab"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Details anzeigen"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Produktivitätsfunktionen sind deaktiviert"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Erzwingt Zurrücksetzung"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Über BreezyDesktop"
|
||||
|
|
|
|||
30
ui/po/es.po
30
ui/po/es.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 20:55-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
|
@ -28,11 +28,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Esta función no es compatible con tu dispositivo en este momento."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Estado del Nivel de Membresía Pagada"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Disponibilidad de Características"
|
||||
|
||||
|
|
@ -353,22 +353,22 @@ msgstr ""
|
|||
"Su configuración de Breezy GNOME es inválida o incompleta. Vuelva a ejecutar "
|
||||
"el script de configuración. Informe sobre este problema si persiste."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Detalles de la Licencia"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Donar"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Solicitar un token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Verificar token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Detalles de la Licencia"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "No hay dispositivo conectado"
|
||||
|
|
@ -467,22 +467,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Menú"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Algunas funciones expirarán pronto"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Ver detalles"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Las funciones de productividad están deshabilitadas"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Reinicio forzoso"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Acerca de BreezyDesktop"
|
||||
|
|
|
|||
34
ui/po/fr.po
34
ui/po/fr.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 20:54-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: French <traduc@traduc.org>\n"
|
||||
|
|
@ -31,11 +31,11 @@ msgstr ""
|
|||
"Cette fonctionnalité n'est actuellement pas prise en charge par votre "
|
||||
"appareil."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Statut de l'abonnement payant"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Disponibilité des fonctionnalités"
|
||||
|
||||
|
|
@ -337,11 +337,11 @@ msgstr "Par défaut"
|
|||
|
||||
#: src/gtk/connected-device.ui:396
|
||||
msgid "Text Scaling"
|
||||
msgstr ""
|
||||
msgstr "Mise à l'échelle du texte"
|
||||
|
||||
#: src/gtk/connected-device.ui:397
|
||||
msgid "Scaling text below 1.0 will simulate a higher resolution display"
|
||||
msgstr ""
|
||||
msgstr "Une mise à l'échelle du texte en dessous de 1.0 simulera un affichage de plus haute résolution"
|
||||
|
||||
#: src/gtk/failed-verification.ui:13
|
||||
msgid "Breezy Desktop GNOME invalid setup"
|
||||
|
|
@ -356,22 +356,22 @@ msgstr ""
|
|||
"exécuter à nouveau le script de configuration. Signalez ce problème s'il "
|
||||
"persiste."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Détails de la licence"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Faire un don"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Demander un jeton d'authentification"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Vérifier le jeton d'authentification"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Détails de la licence"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Aucun appareil connecté"
|
||||
|
|
@ -470,22 +470,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Menu"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Certaines fonctionnalités expirent bientôt"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Afficher les détails"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Les fonctionnalités de productivité sont désactivées"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Réinitialiser"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "À propos de BreezyDesktop"
|
||||
|
|
|
|||
30
ui/po/it.po
30
ui/po/it.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 21:14-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Italian <tp@lists.linux.it>\n"
|
||||
|
|
@ -27,11 +27,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -331,22 +331,22 @@ msgid ""
|
|||
"script. Report this issue if it persists."
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr ""
|
||||
|
|
@ -421,22 +421,22 @@ msgstr ""
|
|||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr ""
|
||||
|
|
|
|||
34
ui/po/ja.po
34
ui/po/ja.po
|
|
@ -11,7 +11,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 20:55-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
|
||||
|
|
@ -31,11 +31,11 @@ msgstr "メガネを3Dモードに切り替え、表示の幅を2倍にします
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "この機能は現在接続されているデバイスではサポートされていません。"
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "有料ティアの状態"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "利用できる機能"
|
||||
|
||||
|
|
@ -338,7 +338,9 @@ msgstr "テキストスケーリング"
|
|||
|
||||
#: src/gtk/connected-device.ui:397
|
||||
msgid "Scaling text below 1.0 will simulate a higher resolution display"
|
||||
msgstr "テキストを1.0未満にスケーリングすると、高解像度ディスプレイをシミュレートします。"
|
||||
msgstr ""
|
||||
"テキストを1.0未満にスケーリングすると、高解像度ディスプレイをシミュレートしま"
|
||||
"す。"
|
||||
|
||||
#: src/gtk/failed-verification.ui:13
|
||||
msgid "Breezy Desktop GNOME invalid setup"
|
||||
|
|
@ -352,22 +354,22 @@ msgstr ""
|
|||
"Breezy GNOMEのセットアップが無効または不完全です。セットアップスクリプトを再"
|
||||
"実行してください。問題が解決しない場合は、この問題を報告してください。"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "ライセンスの詳細"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "寄付"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "トークンをリクエストする"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "トークンを検証する"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "ライセンスの詳細"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "デバイスが接続されていません"
|
||||
|
|
@ -466,22 +468,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "メニュー"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "一部の機能はもうすぐ期限が切れます"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "詳細を表示"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "プロダクティビティ機能が無効になっています"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "強制リセット"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Breezy Desktopについて"
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
30
ui/po/pl.po
30
ui/po/pl.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-16 10:26-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
|
||||
|
|
@ -28,11 +28,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -332,22 +332,22 @@ msgid ""
|
|||
"script. Report this issue if it persists."
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr ""
|
||||
|
|
@ -422,22 +422,22 @@ msgstr ""
|
|||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-19 09:39-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge."
|
||||
|
|
@ -30,11 +30,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Este recurso não é atualmente suportado para o seu dispositivo."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Status do Nível Pago"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Disponibilidade de Recursos"
|
||||
|
||||
|
|
@ -339,7 +339,8 @@ msgstr "Redimensionamento de Texto"
|
|||
|
||||
#: src/gtk/connected-device.ui:397
|
||||
msgid "Scaling text below 1.0 will simulate a higher resolution display"
|
||||
msgstr "Redimensionar o texto abaixo de 1.0 simulará uma tela de resolução mais alta"
|
||||
msgstr ""
|
||||
"Redimensionar o texto abaixo de 1.0 simulará uma tela de resolução mais alta"
|
||||
|
||||
#: src/gtk/failed-verification.ui:13
|
||||
msgid "Breezy Desktop GNOME invalid setup"
|
||||
|
|
@ -354,22 +355,22 @@ msgstr ""
|
|||
"execute novamente o script de configuração. Relate este problema se "
|
||||
"persistir."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Detalhes da Licença"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Doar"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Solicitar um token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Verificar token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Detalhes da Licença"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Nenhum dispositivo conectado"
|
||||
|
|
@ -466,22 +467,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Menu"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Algumas funcionalidades expirarão em breve"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Ver detalhes"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "As funcionalidades de produtividade estão desabilitadas"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Forçar redefinição"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Sobre o BreezyDesktop"
|
||||
|
|
|
|||
30
ui/po/ru.po
30
ui/po/ru.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-17 09:39-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Russian <gnu@d07.ru>\n"
|
||||
|
|
@ -29,11 +29,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Эта функция в настоящее время не поддерживается для вашего устройства."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Статус платного уровня"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Статус функций"
|
||||
|
||||
|
|
@ -355,22 +355,22 @@ msgstr ""
|
|||
"перезапустите скрипт настройки. Сообщите об этой проблеме, если она "
|
||||
"сохраняется."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Подробности лицензии"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Донатить"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Запросить токен"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Проверить токен"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Подробности лицензии"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Устройство не подключено"
|
||||
|
|
@ -468,22 +468,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Меню"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Некоторые функции скоро истекут"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Просмотреть детали"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Функции повышения производительности отключены"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Сброс"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "О BreezyDesktop"
|
||||
|
|
|
|||
30
ui/po/sv.po
30
ui/po/sv.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-16 10:31-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||
|
|
@ -29,11 +29,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Din enhet stöder inte den här funktionen för tillfället."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Betalningsstatus"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Funktions tillgänglighet"
|
||||
|
||||
|
|
@ -349,22 +349,22 @@ msgstr ""
|
|||
"Din Breezy GNOME inställning är ogiltig eller ofullständig. Var god kör "
|
||||
"inställning skriptet igen. Rapportera detta problem om det fortsätter."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Licensdetaljer"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Donera"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Begär en token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Verifiera token"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Licensdetaljer"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Inget enhet ansluten"
|
||||
|
|
@ -462,22 +462,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Meny"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Vissa funktioner upphör snart"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Se detaljer"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Produktivitets funktioner är inaktiverade"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Tvinga Reset"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Om BreezyDesktop"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-17 10:08-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
|
||||
|
|
@ -28,11 +28,11 @@ msgstr "Переключає окуляри в режим «бок о бок»
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr "Ця функція наразі не підтримується на вашому пристрої."
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr "Статус платного рівня"
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr "Статус функцій"
|
||||
|
||||
|
|
@ -352,22 +352,22 @@ msgstr ""
|
|||
"Ваша настройка Breezy GNOME є невірною або неповною. Будь ласка, запустіть "
|
||||
"скрипт настройки повторно. Повідомте про цю проблему, якщо вона не зникає."
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr "Деталі ліцензії"
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr "Донатити"
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr "Запитати токен"
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr "Перевірити токен"
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr "Деталі ліцензії"
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr "Жоден пристрій не підключено"
|
||||
|
|
@ -465,22 +465,22 @@ msgstr "Breezy Desktop"
|
|||
msgid "Menu"
|
||||
msgstr "Меню"
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr "Деякі функції закінчуються незабаром"
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr "Переглянути деталі"
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr "Функції продуктивного режиму відключені"
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr "Скинути"
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr "Про BreezyDesktop"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-01 13:21-0700\n"
|
||||
"POT-Creation-Date: 2024-10-03 21:26-0700\n"
|
||||
"PO-Revision-Date: 2024-08-02 20:55-0700\n"
|
||||
"Last-Translator: <wayne@xronlinux.com>\n"
|
||||
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
|
||||
|
|
@ -26,11 +26,11 @@ msgstr ""
|
|||
msgid "This feature is not currently supported for your device."
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:57
|
||||
#: src/licensedialogcontent.py:63
|
||||
msgid "Paid Tier Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/licensedialog.py:63
|
||||
#: src/licensedialogcontent.py:71
|
||||
msgid "Feature Availability"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -330,22 +330,22 @@ msgid ""
|
|||
"script. Report this issue if it persists."
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:55
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:27
|
||||
#: src/gtk/license-dialog-content.ui:15
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:44
|
||||
#: src/gtk/license-dialog-content.ui:31
|
||||
msgid "Request a token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:52
|
||||
#: src/gtk/license-dialog-content.ui:39
|
||||
msgid "Verify token"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/license-dialog.ui:5 src/gtk/window.ui:91
|
||||
msgid "License Details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/no-device.ui:13
|
||||
msgid "No device connected"
|
||||
msgstr ""
|
||||
|
|
@ -420,22 +420,22 @@ msgstr ""
|
|||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:35
|
||||
#: src/gtk/window.ui:43
|
||||
msgid "Some features expire soon"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:36 src/gtk/window.ui:43
|
||||
#: src/gtk/window.ui:51 src/gtk/window.ui:76
|
||||
msgid "View details"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:42
|
||||
#: src/gtk/window.ui:68
|
||||
msgid "Productivity features are disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:59
|
||||
#: src/gtk/window.ui:95
|
||||
msgid "Force Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/gtk/window.ui:63
|
||||
#: src/gtk/window.ui:99
|
||||
msgid "About BreezyDesktop"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<file preprocess="xml-stripblanks">gtk/connected-device.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/failed-verification.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/license-dialog.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/license-dialog-content.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/no-device.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/no-driver.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/no-extension.ui</file>
|
||||
|
|
|
|||
|
|
@ -26,14 +26,20 @@ import locale
|
|||
import gettext
|
||||
|
||||
VERSION = '@VERSION@'
|
||||
pkgdatadir = '@pkgdatadir@'
|
||||
localedir = '@localedir@'
|
||||
|
||||
xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share'))
|
||||
appdir = os.getenv('APPDIR', xdg_data_home)
|
||||
locale_dir = os.path.join(appdir, 'locale')
|
||||
pkgdatadir = os.path.join(appdir, 'breezydesktop')
|
||||
sys.path.insert(1, pkgdatadir)
|
||||
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
locale.bindtextdomain('breezydesktop', localedir)
|
||||
locale.textdomain('breezydesktop')
|
||||
gettext.install('breezydesktop', localedir)
|
||||
locale.setlocale(locale.LC_ALL, locale.getlocale())
|
||||
locale.bindtextdomain('breezydesktop', locale_dir)
|
||||
gettext.install('breezydesktop', locale_dir)
|
||||
gettext.bindtextdomain('breezydesktop', locale_dir)
|
||||
gettext.textdomain('breezydesktop')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import gi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="LicenseDialogContent" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="margin-top">10</property>
|
||||
<child>
|
||||
<object class="AdwActionRow" id="donation_info">
|
||||
<property name="title" translatable="yes">Donate</property>
|
||||
<property name="subtitle">ko-fi.com/wheaney</property>
|
||||
<child type="suffix">
|
||||
<object class="GtkLinkButton">
|
||||
<property name="icon-name">go-next-symbolic</property>
|
||||
<property name="uri">https://ko-fi.com/wheaney</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="property"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="request_token">
|
||||
<property name="visible">0</property>
|
||||
<property name="title" translatable="yes">Request a token</property>
|
||||
<property name="input-purpose">6</property>
|
||||
<property name="show-apply-button">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="verify_token">
|
||||
<property name="visible">0</property>
|
||||
<property name="title" translatable="yes">Verify token</property>
|
||||
<property name="input-hints">16</property>
|
||||
<property name="show-apply-button">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="features">
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="tiers">
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
|
@ -12,59 +12,5 @@
|
|||
<property name="icon-name">view-refresh-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="margin-top">10</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Donate</property>
|
||||
<property name="subtitle">ko-fi.com/wheaney</property>
|
||||
<property name="subtitle-selectable">True</property>
|
||||
<child type="suffix">
|
||||
<object class="GtkLinkButton">
|
||||
<property name="icon-name">go-next-symbolic</property>
|
||||
<property name="uri">https://ko-fi.com/wheaney</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="property"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="request_token">
|
||||
<property name="visible">0</property>
|
||||
<property name="title" translatable="yes">Request a token</property>
|
||||
<property name="input-purpose">6</property>
|
||||
<property name="show-apply-button">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="verify_token">
|
||||
<property name="visible">0</property>
|
||||
<property name="title" translatable="yes">Verify token</property>
|
||||
<property name="input-hints">16</property>
|
||||
<property name="show-apply-button">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="features">
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="tiers">
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
|
|
|||
|
|
@ -30,17 +30,53 @@
|
|||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="AdwBanner" id="license_action_needed_banner">
|
||||
<object class="GtkInfoBar" id="license_action_needed_banner">
|
||||
<property name="revealed">0</property>
|
||||
<property name="title" translatable="yes">Some features expire soon</property>
|
||||
<property name="button-label" translatable="yes">View details</property>
|
||||
<property name="show-close-button">False</property>
|
||||
<property name="message-type">warning</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Some features expire soon</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="license_action_needed_button">
|
||||
<property name="label" translatable="yes">View details</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwBanner" id="missing_breezy_features_banner">
|
||||
<object class="GtkInfoBar" id="missing_breezy_features_banner">
|
||||
<property name="revealed">0</property>
|
||||
<property name="title" translatable="yes">Productivity features are disabled</property>
|
||||
<property name="button-label" translatable="yes">View details</property>
|
||||
<property name="show-close-button">False</property>
|
||||
<property name="message-type">error</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Productivity features are disabled</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="missing_breezy_features_button">
|
||||
<property name="label" translatable="yes">View details</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
|
|
|||
|
|
@ -1,87 +1,14 @@
|
|||
from gi.repository import Adw, Gtk, GLib
|
||||
from .nolicense import NoLicense
|
||||
from .statemanager import StateManager
|
||||
from .licensetierrow import LicenseTierRow
|
||||
from .licensefeaturerow import LicenseFeatureRow
|
||||
from .xrdriveripc import XRDriverIPC
|
||||
import gettext
|
||||
|
||||
_ = gettext.gettext
|
||||
from gi.repository import Gtk
|
||||
from .licensedialogcontent import LicenseDialogContent
|
||||
|
||||
@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/license-dialog.ui')
|
||||
class LicenseDialog(Gtk.Dialog):
|
||||
__gtype_name__ = 'LicenseDialog'
|
||||
|
||||
tiers = Gtk.Template.Child()
|
||||
features = Gtk.Template.Child()
|
||||
request_token = Gtk.Template.Child()
|
||||
verify_token = Gtk.Template.Child()
|
||||
refresh_license_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self):
|
||||
super(Gtk.Dialog, self).__init__()
|
||||
self.init_template()
|
||||
|
||||
self.ipc = XRDriverIPC.get_instance()
|
||||
StateManager.get_instance().connect('notify::license-action-needed', self._handle_license)
|
||||
self._handle_license(StateManager.get_instance())
|
||||
|
||||
self.request_token.connect('apply', self._on_request_token)
|
||||
self.verify_token.connect('apply', self._on_verify_token)
|
||||
self.refresh_license_button.connect('clicked', self._refresh_license)
|
||||
|
||||
self.no_license = NoLicense(hide_refresh_button = True)
|
||||
|
||||
def _refresh_license(self, widget):
|
||||
self.refresh_license_button.set_sensitive(False)
|
||||
self.ipc.write_control_flags({'refresh_device_license': True})
|
||||
GLib.timeout_add_seconds(3, self._handle_license)
|
||||
|
||||
def _handle_license(self, state_manager = None, val = None):
|
||||
GLib.idle_add(self._handle_license_idle, state_manager or StateManager.get_instance())
|
||||
|
||||
def _handle_license_idle(self, state_manager):
|
||||
self.refresh_license_button.set_sensitive(False)
|
||||
|
||||
license_view = state_manager.state['ui_view'].get('license', {})
|
||||
self.request_token.set_visible(not state_manager.confirmed_token)
|
||||
self.verify_token.set_visible(not state_manager.confirmed_token)
|
||||
|
||||
for child in self.tiers:
|
||||
self.tiers.remove(child)
|
||||
|
||||
for child in self.features:
|
||||
self.features.remove(child)
|
||||
|
||||
if license_view:
|
||||
tiers_group = Adw.PreferencesGroup(title=_("Paid Tier Status"), margin_top=20)
|
||||
self.tiers.append(tiers_group)
|
||||
|
||||
for tier_name, tier_details in license_view['tiers'].items():
|
||||
tiers_group.add(LicenseTierRow(tier_name, tier_details))
|
||||
|
||||
features_group = Adw.PreferencesGroup(title=_("Feature Availability"), margin_top=20)
|
||||
self.features.append(features_group)
|
||||
|
||||
for feature_name, feature_details in license_view['features'].items():
|
||||
features_group.add(LicenseFeatureRow(feature_name, feature_details))
|
||||
else:
|
||||
self.tiers.append(self.no_license)
|
||||
|
||||
self.refresh_license_button.set_sensitive(True)
|
||||
|
||||
def _on_request_token(self, widget):
|
||||
email_address = self.request_token.get_text()
|
||||
self.request_token.set_editable(False)
|
||||
if not self.ipc.request_token(email_address):
|
||||
self.request_token.set_editable(True)
|
||||
|
||||
def _on_verify_token(self, widget):
|
||||
token = self.verify_token.get_text()
|
||||
self.request_token.set_editable(False)
|
||||
self.verify_token.set_editable(False)
|
||||
if self.ipc.verify_token(token):
|
||||
self.ipc.write_control_flags({'refresh_device_license': True})
|
||||
else:
|
||||
self.request_token.set_editable(True)
|
||||
self.verify_token.set_editable(True)
|
||||
self.content = LicenseDialogContent(self.refresh_license_button)
|
||||
self.get_content_area().append(self.content)
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
from gi.repository import Adw, Gtk, GLib
|
||||
from .nolicense import NoLicense
|
||||
from .statemanager import StateManager
|
||||
from .licensetierrow import LicenseTierRow
|
||||
from .licensefeaturerow import LicenseFeatureRow
|
||||
from .xrdriveripc import XRDriverIPC
|
||||
import gettext
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/license-dialog-content.ui')
|
||||
class LicenseDialogContent(Gtk.Box):
|
||||
__gtype_name__ = 'LicenseDialogContent'
|
||||
|
||||
tiers = Gtk.Template.Child()
|
||||
features = Gtk.Template.Child()
|
||||
request_token = Gtk.Template.Child()
|
||||
verify_token = Gtk.Template.Child()
|
||||
donation_info = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, refresh_license_button):
|
||||
super(Gtk.Box, self).__init__()
|
||||
self.init_template()
|
||||
|
||||
# check if it has a set_subtitle_selectable method
|
||||
if hasattr(self.donation_info, 'set_subtitle_selectable'):
|
||||
self.donation_info.set_subtitle_selectable(True)
|
||||
|
||||
self.refresh_license_button = refresh_license_button
|
||||
self.refresh_license_button.connect('clicked', self._refresh_license)
|
||||
|
||||
self.ipc = XRDriverIPC.get_instance()
|
||||
StateManager.get_instance().connect('notify::license-action-needed', self._handle_license)
|
||||
self._handle_license(StateManager.get_instance())
|
||||
|
||||
self.request_token.connect('apply', self._on_request_token)
|
||||
self.verify_token.connect('apply', self._on_verify_token)
|
||||
|
||||
self.no_license = NoLicense(hide_refresh_button = True)
|
||||
|
||||
def _refresh_license(self, widget):
|
||||
self.refresh_license_button.set_sensitive(False)
|
||||
self.ipc.write_control_flags({'refresh_device_license': True})
|
||||
GLib.timeout_add_seconds(3, self._handle_license)
|
||||
|
||||
def _handle_license(self, state_manager = None, val = None):
|
||||
GLib.idle_add(self._handle_license_idle, state_manager or StateManager.get_instance())
|
||||
|
||||
def _handle_license_idle(self, state_manager):
|
||||
self.refresh_license_button.set_sensitive(False)
|
||||
|
||||
license_view = state_manager.state['ui_view'].get('license', {})
|
||||
self.request_token.set_visible(not state_manager.confirmed_token)
|
||||
self.verify_token.set_visible(not state_manager.confirmed_token)
|
||||
|
||||
for child in self.tiers:
|
||||
self.tiers.remove(child)
|
||||
|
||||
for child in self.features:
|
||||
self.features.remove(child)
|
||||
|
||||
if license_view:
|
||||
tiers_group = Adw.PreferencesGroup(title=_("Paid Tier Status"), margin_top=20)
|
||||
self.tiers.append(tiers_group)
|
||||
|
||||
for tier_name, tier_details in license_view['tiers'].items():
|
||||
row = LicenseTierRow(tier_name, tier_details)
|
||||
if row.get_title() != "":
|
||||
tiers_group.add(row)
|
||||
|
||||
features_group = Adw.PreferencesGroup(title=_("Feature Availability"), margin_top=20)
|
||||
self.features.append(features_group)
|
||||
|
||||
for feature_name, feature_details in license_view['features'].items():
|
||||
features_group.add(LicenseFeatureRow(feature_name, feature_details))
|
||||
else:
|
||||
self.tiers.append(self.no_license)
|
||||
|
||||
self.refresh_license_button.set_sensitive(True)
|
||||
|
||||
def _on_request_token(self, widget):
|
||||
email_address = self.request_token.get_text()
|
||||
self.request_token.set_editable(False)
|
||||
if not self.ipc.request_token(email_address):
|
||||
self.request_token.set_editable(True)
|
||||
|
||||
def _on_verify_token(self, widget):
|
||||
token = self.verify_token.get_text()
|
||||
self.request_token.set_editable(False)
|
||||
self.verify_token.set_editable(False)
|
||||
if self.ipc.verify_token(token):
|
||||
self.ipc.write_control_flags({'refresh_device_license': True})
|
||||
else:
|
||||
self.request_token.set_editable(True)
|
||||
self.verify_token.set_editable(True)
|
||||
|
|
@ -56,7 +56,7 @@ class LicenseTierRow(Adw.ExpanderRow):
|
|||
'supporter': _('Gaming'),
|
||||
'subscriber': _('Productivity')
|
||||
}
|
||||
return tier_names[tier]
|
||||
return tier_names.get(tier) or ""
|
||||
|
||||
def _period_description(self, period):
|
||||
period_descriptions = {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import gettext
|
||||
import gi
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')
|
||||
sys.path.insert(0, lib_dir)
|
||||
|
||||
import gi
|
||||
import logging
|
||||
import argparse
|
||||
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
|
|
@ -32,16 +34,6 @@ gi.require_version('Adw', '1')
|
|||
gi.require_version('Gio', '2.0')
|
||||
gi.require_version('GLib', '2.0')
|
||||
|
||||
user_home = os.path.expanduser('~')
|
||||
xdg_data_home = os.environ.get('XDG_DATA_HOME') or os.path.join(user_home, '.local', 'share')
|
||||
locale_dir = os.environ.get('LOCALE_DIR', os.path.join(xdg_data_home, 'locale'))
|
||||
|
||||
locale.setlocale(locale.LC_ALL, locale.getdefaultlocale())
|
||||
locale.bindtextdomain('breezydesktop', locale_dir)
|
||||
gettext.bindtextdomain('breezydesktop', locale_dir)
|
||||
gettext.textdomain('breezydesktop')
|
||||
|
||||
|
||||
from gi.repository import Adw, Gtk, Gio
|
||||
from .licensedialog import LicenseDialog
|
||||
from .statemanager import StateManager
|
||||
|
|
@ -75,14 +67,16 @@ XRDriverIPC.set_instance(XRDriverIPC(logger, config_dir))
|
|||
class BreezydesktopApplication(Adw.Application):
|
||||
"""The main application singleton class."""
|
||||
|
||||
def __init__(self, skip_verification):
|
||||
def __init__(self, version, skip_verification):
|
||||
super().__init__(application_id='com.xronlinux.BreezyDesktop',
|
||||
flags=Gio.ApplicationFlags.DEFAULT_FLAGS)
|
||||
self.version = version
|
||||
|
||||
self.create_action('quit', self.on_quit_action, ['<primary>q'])
|
||||
self.create_action('about', self.on_about_action)
|
||||
self.create_action('license', self.on_license_action)
|
||||
self.create_action('reset_driver', self.on_reset_driver_action)
|
||||
self._skip_verification = skip_verification
|
||||
self._skip_verification = skip_verification or False
|
||||
|
||||
# always do this on start-up since the driver sometimes fails to update the license on boot,
|
||||
# prevent showing a license warning unnecessarily
|
||||
|
|
@ -107,7 +101,7 @@ class BreezydesktopApplication(Adw.Application):
|
|||
modal=True,
|
||||
program_name='Breezy Desktop',
|
||||
logo_icon_name='com.xronlinux.BreezyDesktop',
|
||||
version='1.0.0',
|
||||
version=self.version,
|
||||
authors=['Wayne Heaney'],
|
||||
copyright='© 2024 Wayne Heaney')
|
||||
about.present()
|
||||
|
|
@ -151,5 +145,5 @@ def main(version):
|
|||
parser.add_argument("-sv", "--skip-verification", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
app = BreezydesktopApplication(args.skip_verification)
|
||||
app = BreezydesktopApplication(version, args.skip_verification)
|
||||
return app.run(None)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ breezydesktop_sources = [
|
|||
'failedverification.py',
|
||||
'license.py',
|
||||
'licensedialog.py',
|
||||
'licensedialogcontent.py',
|
||||
'licensefeaturerow.py',
|
||||
'licensetierrow.py',
|
||||
'main.py',
|
||||
|
|
|
|||
|
|
@ -36,10 +36,14 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
|
|||
|
||||
main_content = Gtk.Template.Child()
|
||||
license_action_needed_banner = Gtk.Template.Child()
|
||||
license_action_needed_button = Gtk.Template.Child()
|
||||
missing_breezy_features_banner = Gtk.Template.Child()
|
||||
missing_breezy_features_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, skip_verification, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self._skip_verification = skip_verification
|
||||
|
||||
self.state_manager = StateManager.get_instance()
|
||||
self.state_manager.connect('device-update', self._handle_state_update)
|
||||
|
|
@ -54,8 +58,8 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
|
|||
self.no_extension = NoExtension()
|
||||
self.no_license = NoLicense()
|
||||
|
||||
self.license_action_needed_banner.connect('button-clicked', self._on_license_button_clicked)
|
||||
self.missing_breezy_features_banner.connect('button-clicked', self._on_license_button_clicked)
|
||||
self.license_action_needed_button.connect('clicked', self._on_license_button_clicked)
|
||||
self.missing_breezy_features_button.connect('clicked', self._on_license_button_clicked)
|
||||
|
||||
self._handle_state_update(self.state_manager, None)
|
||||
|
||||
|
|
@ -77,14 +81,14 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
|
|||
|
||||
if not self._skip_verification and not verify_installation():
|
||||
self.main_content.append(self.failed_verification)
|
||||
elif not ExtensionsManager.get_instance().is_installed():
|
||||
self.main_content.append(self.no_extension)
|
||||
elif not self.state_manager.driver_running:
|
||||
self.main_content.append(self.no_driver)
|
||||
elif not self.state_manager.license_present:
|
||||
self.main_content.append(self.no_license)
|
||||
elif not state_manager.connected_device_name:
|
||||
self.main_content.append(self.no_device)
|
||||
elif not ExtensionsManager.get_instance().is_installed():
|
||||
self.main_content.append(self.no_extension)
|
||||
else:
|
||||
self.main_content.append(self.connected_device)
|
||||
self.connected_device.set_device_name(state_manager.connected_device_name)
|
||||
|
|
|
|||
Loading…
Reference in New Issue