LINUX.ORG.RU

Утилита запуска команд в трее

 , ,


0

1

Ищу утилиту, которая будет сидеть в трее значком, по нажатию будет выдавать меню со списком консольных команд (какие я настрою) и по нажатию исполнять. Есть ли вообще такое в линуксе? Использую кеды, и есть множество виджетов для этого, но панель широкая и виджеты на ней огромные, а хотелось бы иметь мелкий значок в трее.

import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtGui.QMenu(parent)
        exitAction = menu.addAction("Exit")
        self.setContextMenu(menu)
def main():
    app = QtGui.QApplication(sys.argv)
    w = QtGui.QWidget()
    trayIcon = SystemTrayIcon(QtGui.QIcon("Bomb.xpm"), w)
    trayIcon.show()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()

Пишут, что этим кодом можно самому сделать такое приложение в трее, а уж потом команды какие хочешь, хоть целые сценарии пиши на питоне.

Loki13 ★★★★★
()
Ответ на: комментарий от Loki13
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application  - add answer PyQt5
#PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):

    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtWidgets.QMenu(parent)
        exitAction = menu.addAction("Exit")
        self.setContextMenu(menu)
        menu.triggered.connect(self.exit)

    def exit(self):
        QtCore.QCoreApplication.exit()

def main(image):
    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QWidget()
    trayIcon = SystemTrayIcon(QtGui.QIcon(image), w)

    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    on=r''# ADD PATH OF YOUR ICON HERE .png works
    main(on)

Правда вот тут код вроде поактуальнее и этот я даже проверил. Работает. Перед использованием сделать: pip install pyqt5

Даже ошибку нашел. В этом коде действие вешается на всё меню, а не на пункт. Правильно будет:

exitAction.triggered.connect(self.exit)

PS: Пока ковырял этот код, понял, что написать утилитку, как хочет ТС(распарсить конфик с командами и создать менюшку под них), дело, наверное двух-трех часов. Для питониста может даже и пол часа, я всё же только мимо проходил.

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 2)
Ответ на: комментарий от Loki13

Чет у меня тупняк какой-то с этим кодом)

Добавил второй пункт меню, свою функцию в addAction – при нажатии на пункт меню она отрабатывает но закрывает приложуху.)

Upd. нОгуглил фикс:

app.setQuitOnLastWindowClosed(False)
frunobulax ★★
()
Последнее исправление: frunobulax (всего исправлений: 1)
Ответ на: комментарий от Loki13

[code]kot@192:~$ pip install pyqt5

error: externally-managed-environment

× This environment is externally managed ╰─> To install Python packages system-wide, try zypper install python311-xyz, where xyz is the package you are trying to install.

If you wish to install a non-rpm packaged Python package,
create a virtual environment using python3.11 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.

If you wish to install a non-rpm packaged Python application,
it may be easiest to use `pipx install xyz`, which will manage a
virtual environment for you. Install pipx via `zypper install python311-pipx` .

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing –break-system-packages. hint: See PEP 668 for the detailed specification. DEPRECATION: Loading egg at /usr/lib64/python3.11/site-packages/TBB-2021.11.0-py3.11-linux-x86_64.egg is deprecated. pip 24.3 will enforce this behaviour change. A possible replacement is to use pip for package installation.. Discussion can be found at https://github.com/pypa/pip/issues/12330 [/code]

KOT040188 ★★
() автор топика
Ответ на: комментарий от KOT040188

Добавляешь(по образу и подобию) рядом с Exit свои команды в этот код. И запускаешь python3 traylauncher.py. Появляется значок в трее и по ПКМ можно выполнять команды.

Как запускать shell-команды из питона я уж думаю нагуглишь

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 1)
Ответ на: комментарий от Loki13

Интересно. А можно добавить значок, а то пустое место в трэе как-то некрасиво. Можно ли сделать вызов меню не на ПКМ, а на ЛКМ? Питон рулит, я даже «изучал» его на среднем заочном образовании, но я далёк от программирования)))

KOT040188 ★★
() автор топика
Ответ на: комментарий от KOT040188

Там в самом низу скрипта, написано как значок добавить.

if __name__ == '__main__': on=r"# ADD PATH OF YOUR ICON HERE .png works main(on)

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 1)
Ответ на: комментарий от KOT040188

Ну там же даже код есть как сделать. Я вообще сам не питонист(плюсовик), я сделал бы за несколько часов, но ради ответа на форуме - не буду. И так работы много. Возможно кто из питонистов подскажет как это делается правильно. А вообще, ты и сам за несколько часов разберешься, а для меня моё время более ценное, чем твоё.

Loki13 ★★★★★
()
Ответ на: комментарий от KOT040188

self.activated.connect(self.showMenuOnTrigger)

Мне кажется вот это вот в init добавить(не заменить) и само тело showMenuOnTrigger добавить. По идее как-то так(опять же, я не настоящий сварщик). Проверить сегодня уже сам не смогу.

Loki13 ★★★★★
()
Ответ на: комментарий от Loki13

Пробовал и так и сяк, при нажатии ЛКМ скрипт закрывается.

[code]kot@192:~/bin/script$ python3 traylauncher.py QSystemTrayIcon::setVisible: No Icon set Traceback (most recent call last): File «/home/kot/bin/script/traylauncher.py», line 18, in showMenuOnTrigger if reason == QSystemTrayIcon.Trigger: ^^^^^^^^^^^^^^^ NameError: name ‘QSystemTrayIcon’ is not defined. Did you mean: ‘SystemTrayIcon’? Аварийный останов (образ памяти сброшен на диск) [/code]

KOT040188 ★★
() автор топика
Последнее исправление: KOT040188 (всего исправлений: 1)
Ответ на: комментарий от KOT040188
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application  - add answer PyQt5
#PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):

    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtWidgets.QMenu(parent)
        exitAction = menu.addAction("Exit")
        noexitAction = menu.addAction("No Exit")
        self.setContextMenu(menu)
        exitAction.triggered.connect(self.exit)

        self.activated.connect(self.showMenuOnTrigger)

    def exit(self):
        QtCore.QCoreApplication.exit()

    def showMenuOnTrigger(self, reason):
        if reason == QtWidgets.QSystemTrayIcon.Trigger:
            self.contextMenu().popup(QtGui.QCursor.pos())

def main(image):
    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QWidget()
    trayIcon = SystemTrayIcon(QtGui.QIcon(image), w)

    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    on=r''# ADD PATH OF YOUR ICON HERE .png works
    main(on)

if reason == QtWidgets.QSystemTrayIcon.Trigger: self.contextMenu().popup(QtGui.QCursor.pos())

За 5 минут нашел как исправить. Просто надо было квалификаторов добавить к классам, они в этом коде не импортируются глобально. Всего 5 минут заняло, а ведь я не питонист даже.

PS: У тебя это может даже будет корректно работать. У меня такой вызов глючит, т.к. у меня тайловый hyprland и трей в waybar'е. У меня такой вызов меню на пол экрана расфигаривает.

Loki13 ★★★★★
()
Ответ на: комментарий от Loki13

Спасибо, работает. Только я не совсем понял как же добавлять новые пункты.

И ещё вопрос, можно ли пунктам меню добавить значки?

KOT040188 ★★
() автор топика
Последнее исправление: KOT040188 (всего исправлений: 2)
Ответ на: комментарий от KOT040188

В смысле добавлять пункты? Ну прямо там в коде и добавляй новые пункты и к ним обработчики.

runAction = menu.addAction(«Run»)

runAction.triggered.connect(self.run)

def run(self): #... run something here

Как-то так.

А значки вроде вот тут пишут, что можно, но мне лень разбираться

https://stackoverflow.com/questions/51799699/pyqt4-icons-not-displayed-in-qmenu

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 1)
Ответ на: комментарий от KOT040188
def run(self):        
        subprocess.run(["ls", "-l"]) # вот сюда

А сверху добавь import subprocess

Это легко гуглилось по фразе «python execute shell command»

Дальше, умываю руки. Сделал всё что мог. Мне уже проще было создать проект на гитхабе и написать эту чертову утилиту за те самые 2-3 часа.

PS: Ну поразвлекался хоть с питоном немного

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 1)

В телеге помогли, готовый вариант со значками. Единственная что некрасиво, это меню открывается по ЛКМ прямо от курсора, а надо от верха значка как открывается по ПКМ.

KOT040188 ★★
() автор топика