Как создать единый лаунчер, который занимается файловым мониторингом?

11

Я хотел бы создать панель запуска, которая выполняет те же действия, что и значок корзины, где отображаются разные быстрые списки в зависимости от наличия в корзине элементов.

Я хотел бы что-то вроде: если папка Aсуществует, показать A,B,Cв быстром списке, если папка Aне существует, показать D,E,Fв быстром списке.

Рей Леонард Аморато
источник
3
Я смотрел на это раньше, и это, вероятно, должно быть сделано через протокол уведомлений при запуске . И установив StartupNotify в true в файле .desktop. Но я не уверен оттуда.
Пол ван Шейк
1
Проверьте: wiki.ubuntu.com/Unity/LauncherAPI Есть примеры динамических быстрых списков
S Prasanth

Ответы:

3

Следующие работы:

  1. Создайте 2 файла: mylauncher.desktop и mylauncher.py с содержимым, как указано ниже.
  2. Сделайте mylauncher.desktop исполняемым.
  3. Добавьте mylauncher.desktop в панель запуска Unity.
  4. Отредактируйте Foldernames и Folderlocations в mylauncher.py по мере необходимости.
  5. Запустите python mylauncher.pyв фоновом режиме. Вы должны будете добавить это к одному из ваших сценариев запуска.

Источник: https://wiki.ubuntu.com/Unity/LauncherAPI


Содержимое mylauncher.desktop:

[Desktop Entry]
Name=My Launcher
Comment=A,B,C if A else D,E,F
Exec=nautilus %U
Icon=nautilus
Terminal=false
StartupNotify=true
Type=Application
OnlyShowIn=GNOME;Unity;
Actions=;

Содержимое mylauncher.py:

updateinterval = 1 #Update interval in seconds. Set it to a +ve integer.
#In Foldernames and Folderlocations, spaces shouldn't be preceded by \.
Foldernames = ["A", "B", "C", "D", "E", "F"]
Folderlocations = ["/home/prasanth/A", "/home/prasanth/B", "/home/prasanth/C", "/home/prasanth/D", "/home/prasanth/E", "/home/prasanth/F"]
#####################################

from gi.repository import Unity, Gio, GObject, Dbusmenu
import os, subprocess

def nautilusopen(junk1, junk2, location): #Function that opens `location` in nautilus. Equivalent to `nautilus location` in bash.
    subprocess.Popen(['nautilus', "%s" % location])

launcher = Unity.LauncherEntry.get_for_desktop_id("mylauncher.desktop") #You won't have to modify this, except if you rename `mylauncher.desktop`

#Code block A: This code block builds 6 quicklist entries, 3 for when A is found and 3 for when it isn't
QLentries = [Dbusmenu.Menuitem.new() for i in Foldernames]
for i in xrange(6):
    QLentries[i].property_set(Dbusmenu.MENUITEM_PROP_LABEL, "Goto %s" % Foldernames[i])
    QLentries[i].connect("item-activated", nautilusopen, Folderlocations[i])
    QLentries[i].property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
################

#Code block B: This code block creates 2 quicklists 1 for when A is found and 1 for when it isn't. Then it adds the first 3 quicklist entries to QLifA and the next 3 to QLifnotA
QLifA = Dbusmenu.Menuitem.new() #Quicklist if A is found
QLifnotA = Dbusmenu.Menuitem.new() #Quicklist if A is not found.
for i in xrange(3):
    QLifA.child_append(QLentries[i])
for i in xrange(3, 6):
    QLifnotA.child_append(QLentries[i])
################

#The rest of the code simply monitors the file system for A's existence and switches appropriately between QLifA and QLifnotA
prevState = None
def updateql():
    global prevState
    currentState = 'A' if os.path.exists(Folderlocations[0]) else 'notA' #currentState is 'A' if Folderlocations[0] (which is /home/prasanth/A) exists, 'notA' otherwise
    if currentState != prevState:
        if currentState == 'A':
            launcher.set_property("quicklist", QLifA)
        else:
            launcher.set_property("quicklist", QLifnotA)
        prevState = currentState
    return True

#GObject.timeout_add_seconds(updateinterval, updateql)
#mainloop = GObject.MainLoop()
#mainloop.run()

#If the 3-line commented block above worked as expected, the remainder of this script would be unnecessary. Unfortunately, it doesn't.
import signal
def alarmhandler(signum, frame):
    raise Exception('Alarm has rung')
signal.signal(signal.SIGALRM, alarmhandler)

mainloop = GObject.MainLoop()

while True:
    try:
        updateql()
        signal.alarm(updateinterval)
        mainloop.run()
    except KeyboardInterrupt:
        continue

РЕДАКТИРОВАТЬ: Используйте следующее как mylauncher.py для целей, упомянутых в комментариях. Изменения в соответствии с вашими потребностями должны быть простыми, и в случае, если это не упоминается в комментариях.

from gi.repository import Unity, Gio, GObject, Dbusmenu
import os, subprocess

updateinterval = 1 #Update interval in seconds. Set it to a +ve integer.

#Quicklist entries if already mounted:
ifMountedEntry1text = """Unmount A""" #Text shown in the quicklist menu for this entry.
ifMountedEntry1command = """unmount A""" #Bash command to execute when entry 1 is clicked. Doubt if `unmount A` will work. Modify appropriately.

ifMountedEntry2text = """Open A""" #Maybe you'll want to open A directly from the launcher. Included just so you get a hang of how this works.
ifMountedEntry2command = """nautilus A"""
#Extend as required.

#Quicklist entries if not already mounted:
ifnotMountedEntry1text = """Mount A"""
ifnotMountedEntry1command = """mount A""" #Again modify `mount A` appropriately.
#Extend as required.

#My old file monitoring should work. But in case you want to change the criteria for modifying quicklists, it is better to do the following:
filemonitoringcommand = """if [ -d /folder/to/monitor/ ]; then echo True; else echo False; fi;""" #<Bash command>/<location to script> which prints 'True' if A is mounted, 'False' otherwise.
#####################

def systemcall(junk1, junk2, command):
    os.system(command)

launcher = Unity.LauncherEntry.get_for_desktop_id("mylauncher.desktop") #You won't have to modify this, except if you rename `mylauncher.desktop`

#Quicklist if already mounted:
QLifMounted = Dbusmenu.Menuitem.new()

ifMountedEntry1 = Dbusmenu.Menuitem.new()
ifMountedEntry1.property_set(Dbusmenu.MENUITEM_PROP_LABEL, ifMountedEntry1text) #Sets the text shown in the quicklist menu for this entry.
ifMountedEntry1.connect("item-activated", systemcall, ifMountedEntry1command) #Sets the corresponding bash command.
ifMountedEntry1.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
QLifMounted.child_append(ifMountedEntry1) #Adds the first entry to the quicklist

ifMountedEntry2 = Dbusmenu.Menuitem.new()
ifMountedEntry2.property_set(Dbusmenu.MENUITEM_PROP_LABEL, ifMountedEntry2text)
ifMountedEntry2.connect("item-activated", systemcall, ifMountedEntry2command)
ifMountedEntry2.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
QLifMounted.child_append(ifMountedEntry2)
#Extend as required.

#Quicklist if not already mounted:
QLifnotMounted = Dbusmenu.Menuitem.new()

ifnotMountedEntry1 = Dbusmenu.Menuitem.new()
ifnotMountedEntry1.property_set(Dbusmenu.MENUITEM_PROP_LABEL, ifnotMountedEntry1text)
ifnotMountedEntry1.connect("item-activated", systemcall, ifnotMountedEntry1command)
ifnotMountedEntry1.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
QLifnotMounted.child_append(ifnotMountedEntry1)
#Extend as required.

#The rest of the code uses `filemonitoringcommand` to monitor the filesystem and dynamically modifies (or rather switches between) quicklists.
prevState = None
def updateql():
    global prevState
    currentState = 'True' in os.popen(filemonitoringcommand).read()
    if currentState != prevState:
        if currentState == True:
            launcher.set_property("quicklist", QLifMounted) #If already mounted, sets QLifMounted as the quicklist.
        else:
            launcher.set_property("quicklist", QLifnotMounted) #Otherwise sets QLifnotMounted as the quicklist.
        prevState = currentState
    return True

#GObject.timeout_add_seconds(updateinterval, updateql)
#mainloop = GObject.MainLoop()
#mainloop.run()

#If the 3-line commented block above worked as expected, the remainder of this script would be unnecessary. Unfortunately, it doesn't.
import signal
def alarmhandler(signum, frame):
    raise Exception('Alarm has rung')
signal.signal(signal.SIGALRM, alarmhandler)

mainloop = GObject.MainLoop()

while True:
    try:
        updateql()
        signal.alarm(updateinterval)
        mainloop.run()
    except KeyboardInterrupt:
        continue
S Prasanth
источник
Я пробовал это, но это не работает для меня. Быстрый список не меняется. Я использую Ubuntu 12.10 64-bit.
Рей Леонард Аморато
Я использую 12.04 32 бит. Сценарий python должен быть запущен ПОСЛЕ добавления значка запуска в панель запуска.
S Prasanth
Выполните следующие действия. 1) Поместите mylauncher.desktop в ~ / .local / share / Applications 2) Нажмите супер-клавишу и найдите «My Launcher». 3) Перетащите значок запуска, который появляется на модуль запуска Unity. 4) Запустите скрипт Python. Это должно работать.
S Prasanth
@ReyLeonardAmorato Мне просто любопытно. Это сработало?
S Prasanth
Здравствуй. Извините, я не мог найти время, чтобы выйти в интернет в последнее время, но ваш последний метод работал на меня. Однако то, что я хотел, немного отличается от того, что делает скрипт. Я хотел бы отслеживать местоположение папки (сценарий уже делает это), и если папка «A» существует, показать «unmount» в быстром списке. Показать 'mount' в противном случае. Я не разбираюсь в сценариях Python, поэтому не знаю, как изменить предоставленный вами сценарий. Было бы здорово, если бы вы могли помочь с этим последним битом.
Рей Леонард Аморато