Compare commits

...

4 Commits

Author SHA1 Message Date
deltragon db058ed917
Merge 5dcfe196f4 into a3ca7b7639 2024-10-15 14:07:29 +03:00
openSUSE Lietuviškai a3ca7b7639
Translated using Weblate (Lithuanian)
Currently translated at 100.0% (135 of 135 strings)

Translation: Safe Eyes/Translations
Translate-URL: https://hosted.weblate.org/projects/safe-eyes/translations/lt/
2024-10-14 08:16:28 +02:00
Moo 5761f0ff13
Translated using Weblate (Lithuanian)
Currently translated at 89.6% (121 of 135 strings)

Translation: Safe Eyes/Translations
Translate-URL: https://hosted.weblate.org/projects/safe-eyes/translations/lt/
2024-10-11 23:39:14 +02:00
deltragon 5dcfe196f4
Smartpause: add support for ext-idle-notify-v1 using pywayland 2024-07-12 22:16:32 +02:00
6 changed files with 161 additions and 20 deletions

View File

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2024-07-02 12:09+0000\n"
"PO-Revision-Date: 2024-10-14 06:16+0000\n"
"Last-Translator: openSUSE Lietuviškai <opensuse.lietuviu.kalba@gmail.com>\n"
"Language-Team: Lithuanian <https://hosted.weblate.org/projects/safe-eyes/"
"translations/lt/>\n"
@ -14,13 +14,13 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.7-dev\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && ("
"n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.8-dev\n"
# Short break
msgid "Gently close your eyes"
msgstr ""
msgstr "Švelniai užsimerkite"
# Short break
msgid "Roll your eyes a few times to each side"
@ -113,11 +113,11 @@ msgstr "Licencija"
# About dialog
msgid "List of Contributors"
msgstr ""
msgstr "Talkininkų sąrašas"
# About dialog
msgid "Help us translate this app"
msgstr ""
msgstr "Padėkite mums išversti šią programą"
# Break screen
msgid "Skip"
@ -537,57 +537,60 @@ msgstr "Pristabdyti mediją"
# plugin/limitconsecutiveskipping
msgid "Limit Consecutive Skipping"
msgstr ""
msgstr "Apriboti nuoseklų praleidinėjimą"
# plugin/limitconsecutiveskipping
msgid "How many skips or postpones are allowed in a row"
msgstr ""
msgstr "Kiek leidžiama praleisti arba atidėti kartų iš eilės"
# plugin/limitconsecutiveskipping
msgid "Limit how many breaks can be skipped or postponed in a row"
msgstr ""
msgstr "Apriboti, kiek kartų galima iš eilės praleisti arba atidėti pertraukų"
# plugin/limitconsecutiveskipping
#, python-format
msgid "Skipped or postponed %(num)d/%(allowed)d breaks in a row"
msgstr ""
msgstr "Paeiliui praleistos arba atidėtos pertraukos: %(num)d/%(allowed)d"
# safeeyes/platform/io.github.slgobinath.SafeEyes.desktop
msgid "RSI Prevention"
msgstr ""
msgstr "Apsaugokite savo akis nuo įtampos"
msgid ""
"Please install service providing tray icons for your desktop environment."
msgstr ""
"Prašome įdiegti savo darbalaukio aplinkos sistemos ženkliukų dėklo paslaugą."
#, python-format
msgid "Next long break at %s"
msgstr ""
msgstr "Kita ilga pertrauka: %s"
#, python-format
msgid "Next breaks at %(short)s/%(long)s"
msgstr ""
msgstr "Kitos pertraukos: %(short)s/%(long)s"
#, python-format
msgid "The required plugin '%s' is missing dependencies!"
msgstr ""
msgstr "Reikalingam papildiniui „%s“ trūksta priklausomybių!"
msgid ""
"Please install the dependencies or disable the plugin. To hide this message, "
"you can also deactivate the plugin in the settings."
msgstr ""
"Prašome įdiegti priklausomybes arba pašalinti papildinį. Norėdami paslėpti "
"šį pranešimą, taip pat galite išjungti šį papildinį nuostatose."
msgid "Click here for more information"
msgstr ""
msgstr "Norėdami sužinoti daugiau, spauskite čia"
msgid "Disable plugin temporarily"
msgstr ""
msgstr "Laikinai išjungti papildinį"
msgid "Disable permanently"
msgstr ""
msgstr "Išjungti visam laikui"
msgid "License:"
msgstr ""
msgstr "Licencija:"
# Short break
#~ msgid "Tightly close your eyes"

View File

@ -5,7 +5,7 @@
"version": "0.0.3"
},
"dependencies": {
"python_modules": [],
"python_modules": ["pywayland"],
"shell_commands": [],
"operating_systems": [],
"desktop_environments": [],

View File

@ -25,6 +25,11 @@ def validate(plugin_config, plugin_settings):
command = "dbus-send"
elif utility.DESKTOP_ENVIRONMENT == "sway":
command = "swayidle"
elif utility.IS_WAYLAND:
if not utility.module_exist("pywayland"):
return _("Please install the Python module '%s'") % "pywayland"
# no command needed with pywayland
return None
else:
command = "xprintidle"
if not utility.command_exist(command):

View File

@ -0,0 +1,93 @@
# Safe Eyes is a utility to remind you to take break frequently
# to protect your eyes from eye strain.
# Copyright (C) 2017 Gobinath
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This file is heavily inspired by https://github.com/juienpro/easyland/blob/efc26a0b22d7bdbb0f8436183428f7036da4662a/src/easyland/idle.py
import logging
import threading
import datetime
from pywayland.client import Display
from pywayland.protocol.wayland.wl_seat import WlSeat
from pywayland.protocol.ext_idle_notify_v1 import (
ExtIdleNotificationV1,
ExtIdleNotifierV1
)
class ExtIdleNotify:
_idle_notifier = None
_seat = None
_notification = None
_notifier_set = False
_running = True
_thread = None
_idle_since = None
def __init__(self):
self._display = Display()
self._display.connect()
def stop(self):
self._running = False
self._notification.destroy()
self._notification = None
self._seat = None
self._thread.join()
def run(self):
self._thread = threading.Thread(target=self._run, name="ExtIdleNotify", daemon=False)
self._thread.start()
def _run(self):
reg = self._display.get_registry()
reg.dispatcher['global'] = self._global_handler
while self._running:
self._display.dispatch(block=True)
self._display.disconnect()
def _global_handler(self, reg, id_num, iface_name, version):
if iface_name == 'wl_seat':
self._seat = reg.bind(id_num, WlSeat, version)
if iface_name == "ext_idle_notifier_v1":
self._idle_notifier = reg.bind(id_num, ExtIdleNotifierV1, version)
if self._idle_notifier and self._seat and not self._notifier_set:
self._notifier_set = True
timeout_sec = 1
self._notification = self._idle_notifier.get_idle_notification(timeout_sec * 1000, self._seat)
self._notification.dispatcher['idled'] = self._idle_notifier_handler
self._notification.dispatcher['resumed'] = self._idle_notifier_resume_handler
def _idle_notifier_handler(self, notification):
self._idle_since = datetime.datetime.now()
def _idle_notifier_resume_handler(self, notification):
self._idle_since = None
def get_idle_time_seconds(self):
if self._idle_since is None:
return 0
result = datetime.datetime.now() - self._idle_since
return result.total_seconds()

View File

@ -46,11 +46,16 @@ waiting_time = 2
is_wayland_and_gnome = False
use_swayidle = False
use_ext_idle_notify = False
swayidle_process = None
swayidle_lock = threading.Lock()
swayidle_idle = 0
swayidle_active = 0
ext_idle_notify_lock = threading.Lock()
ext_idle_notification_obj = None
# swayidle
def __swayidle_running():
return (swayidle_process is not None and
swayidle_process.poll() is None)
@ -88,6 +93,33 @@ def __swayidle_idle_time():
return idle_time
return 0
# ext idle
def __start_ext_idle_monitor():
global ext_idle_notification_obj
from .ext_idle_notify import ExtIdleNotify
ext_idle_notification_obj = ExtIdleNotify()
ext_idle_notification_obj.run()
def __stop_ext_idle_monitor():
global ext_idle_notification_obj
with ext_idle_notify_lock:
if ext_idle_notification_obj is not None:
ext_idle_notification_obj.stop()
ext_idle_notification_obj = None;
def __ext_idle_idle_time():
global ext_idle_notification_obj
with ext_idle_notify_lock:
if ext_idle_notification_obj is None:
__start_ext_idle_monitor()
else:
return ext_idle_notification_obj.get_idle_time_seconds()
return 0
# gnome
def __gnome_wayland_idle_time():
"""
Determine system idle time in seconds, specifically for gnome with wayland.
@ -119,6 +151,8 @@ def __system_idle_time():
return __gnome_wayland_idle_time()
elif use_swayidle:
return __swayidle_idle_time()
elif use_ext_idle_notify:
return __ext_idle_idle_time()
# Convert to seconds
return int(subprocess.check_output(['xprintidle']).decode('utf-8')) / 1000
except BaseException:
@ -159,6 +193,7 @@ def init(ctx, safeeyes_config, plugin_config):
global postpone_if_active
global is_wayland_and_gnome
global use_swayidle
global use_ext_idle_notify
logging.debug('Initialize Smart Pause plugin')
context = ctx
enable_safeeyes = context['api']['enable_safeeyes']
@ -172,6 +207,7 @@ def init(ctx, safeeyes_config, plugin_config):
waiting_time = min(2, idle_time) # If idle time is 1 sec, wait only 1 sec
is_wayland_and_gnome = context['desktop'] == 'gnome' and context['is_wayland']
use_swayidle = context['desktop'] == 'sway'
use_ext_idle_notify = context['is_wayland'] and not use_swayidle and not is_wayland_and_gnome
def __start_idle_monitor():
@ -245,6 +281,9 @@ def on_stop():
idle_condition.notify_all()
idle_condition.release()
if use_ext_idle_notify:
__stop_ext_idle_monitor()
def update_next_break(break_obj, dateTime):
"""

View File

@ -4,6 +4,7 @@ import setuptools
requires = [
'pywayland',
'babel',
'psutil',
'croniter',