Как добавить динамический список приложений для недавно использованных файлов в Unity Launcher?

Это была бы замечательная возможность получить доступ к недавно использованным документам из LibreOffice с помощью динамического быстрого списка в панели запуска. Существует довольно большой опыт создания пользовательских статических быстрых списков.

Но есть ли кто-нибудь, кто мог бы дать некоторую конструктивную ориентацию о том, как создать динамический быстрый список для недавно использованных документов в lo?

В вики Ubuntu есть очень краткое описание того, как создавать быстрые списки с python или vala. У меня нет опыта ни в одном из двух, и я не нашел исчерпывающих примеров сценариев для динамических быстрых списков. Поэтому я ищу какой-то более простой способ реализовать это или кого-то, кто уже сделал / видел это.

1 ответ

Решение

Добавление динамического "недавно использованного" раздела в панель запуска приложения

Полная интеграция приложения с упомянутыми динамическими списками быстрого доступа, скорее всего, должна выполняться изнутри приложения. В конце концов, самая прямая информация об используемых файлах поступает из самого приложения.

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

Тогда что?

Это не значит, что мы не можем достичь практически одинакового результата, возможно, даже более гибким и общим способом "извне". Вся необходимая информация доступна в динамически обновляемом файле: ~/.local/share/recently-used.xbel, из которого мы можем получить полную историю открытых файлов, соответствующую информацию о дате и времени и используемое приложение.

Кроме того, добавить динамически обновляемый раздел в панель запуска можно очень хорошо, как часть "традиционного" (статического) раздела. Ключ решения заключается в том, чтобы создать процесс, который позаботится о вышеупомянутых действиях, не добавляя заметную нагрузку на вашу систему.
Как упомянуто в ссылке из вопроса, в любом случае потребуется некоторый фоновый процесс, чтобы отслеживать изменения и передавать инструкции.

Сценарий ниже в значительной степени делает именно это.

Решение; фоновый скрипт

Значения в приведенном ниже скрипте специально установлены для LibreOffice и его документы. Без какого-либо редактирования его можно использовать для добавления недавно использованного раздела в LibreOffice-Writer пусковая. Он покажет последние 10 использованных документов, открытых любым из LibreOffice -модулями.

Однако решение можно использовать для добавления раздела "недавно использовавшийся" во многие приложения с .desktop файл в /usr/share/applications, Поскольку файл ~/.local/share/recently-used.xbel является Gtk связанные, скорее всего, приложения с Gtk Окно будет наших потенциальных кандидатов (то есть, если приложение открывает и редактирует файлы). Кроме того, количество файлов для отображения является произвольным.

Как это выглядит

Решение добавляет раздел к целевой панели запуска в панели запуска Unity, показывающий произвольное количество недавно использованных файлов, например:

  • показать последние семь файлов:

  • или последние десять файлов:

  • Однако с той же легкостью мы можем дать gedit запуск динамического раздела, показывающего последние семь файлов, открытых с gedit (см. изображение ниже)

Как пользоваться

Предполагая, что у вас предустановлен LibreOffice (загруженная версия не имеет ссылки .desktop файл в /usr/share/applications который нужен сценарию, но где-то еще, пожалуйста, укажите, нужно ли вам устанавливать отдельно загруженную версию LO)

  1. Скопируйте приведенный ниже скрипт в пустой файл и сохраните его как dynamic_recent.py За LibreOffice имя процесса soffice уже правильно установлен в скрипте.

    #!/usr/bin/env python3
    import subprocess
    import os
    import time
    import shutil
    
    # --- set the number of docs to show in recently used
    n = 7
    # --- set the process name of the targeted application
    application = "soffice"
    #--- ONLY change the value below into "xdg-open" if you do not use LO preinstalled
    #    else the value should be the same as in application = (above)
    open_cmd = "soffice"
    # --- set the targeted .desktop file (e.g. "gedit.desktop")
    target = "libreoffice-writer.desktop"
    
    # --- don't change anything below
    home = os.environ["HOME"]+"/.local/share"
    loc = home+"/applications/"+target
    recdata = home+"/recently-used.xbel"
    
    def runs(app):
        try:
            # see if the application is running
            app = subprocess.check_output(["pgrep", app]).decode("utf-8")
        except subprocess.CalledProcessError:
            return False
        else:
            return True
    
    def get_lines():
        # retrieve information from the records:
        # -> get bookmark line *if* the application is in the exec= line
        with open(recdata) as infile:
            db = []
            for l in infile:
                if '<bookmark href="file://' in l:
                    sub = l
                elif 'exec="&apos;'+application in l:
                    db.append(sub)
        # fix bug in xbel -file in 15.04
        relevant = [l.split('="') for l in set(db) if all([not "/tmp" in l, "." in l])]
        relevant = [[it[1][7:-7], it[-2][:-10]] for it in relevant]
        relevant.sort(key=lambda x: x[1])
        return [item[0].replace("%20", " ") for item in relevant[::-1][:n]]
    
    def create_section(line):
        # create shortcut section
        name = line.split("/")[-1]
        return [[
            "[Desktop Action "+name+"]",
            "Name="+name,
            "Exec="+open_cmd+" '"+line+"'",
            "\n",
            ], name]
    
    def setup_dirs():
        # copy the global .desktop file to /usr/share/applications/
        glo = "/usr/share/applications/"+target
        if not os.path.exists(loc):
            shutil.copy(glo,loc)
    
    def edit_launcher(newdyn, target, actionlist):
        # read the current .desktop file
        ql = [list(item) for item in list(enumerate(open(loc).read().splitlines()))]
        # find the Actions= line
        currlinks = [l for l in ql if "Actions=" in l[1]]
        # split the line (if it exists)  by the divider as delimiter 
        linkline = currlinks[0][1].split("divider1")[0] if currlinks else None
        # define the shortcut sections, belonging to the dynamic section (below the divider)
        lowersection = [l for l in ql if "[Desktop Action divider1]" in l]
        # compose the new Actions= line
        addlinks = (";").join(actionlist) + ";"
        if linkline:
            newlinks = linkline + addlinks
            ql[currlinks[0][0]][1] = newlinks
            # get rid of the "dynamic" section  
            ql = ql[:lowersection[0][0]] if lowersection else ql
            # define the new file
            ql = [it[1] for it in ql]+newdyn
            with open(loc, "wt") as out:
                for l in ql:
                    out.write(l+"\n")
        else:
            newlinks = "Acrions="+addlinks
    
    setup_dirs()
    lines1 = []
    
    while True:
        time.sleep(2)
        # if the application does not run, no need for a check of .xbel
        if runs(application):
            lines2 = get_lines()
            # (only) if the list of recently used changed: edit the quicklist
            if lines1 != lines2:
                actionlist = ["divider1"]
                newdyn = [
                    "[Desktop Action divider1]",
                    "Name=" + 37*".",
                    "\n",
                    ]
                for line in lines2:
                    data = create_section(line)
                    actionlist.append(data[1])
                    section = data[0]
                    for l in section:
                        newdyn.append(l)
                edit_launcher(newdyn, target, actionlist)           
            lines1 = lines2
    
  2. В разделе заголовка скрипта вы можете установить ряд параметров:

    # --- set the number of docs to show in recently used
    n = 7
    # --- set the process name of the targeted application
    application = "soffice"
    #--- ONLY change the value below into "xdg-open" if you do not use LO preinstalled
    #    else the value should be the same as in application = (above)
    open_cmd = "soffice"
    # --- set the targeted .desktop file (e.g. "gedit.desktop")
    target = "libreoffice-writer.desktop"
    

    Большинство опций говорят сами за себя, если вы хотите добавить динамический раздел в LO-Writer лаунчер, оставь все как есть. Если нет, установите соответствующий лаунчер.

  3. Тест - запустить скрипт, запустив его из терминала:

    python3 /path/to/dynamic_recent.py
    
  4. Скрипт скопировал глобальный .desktop подать в ~/.local/share/applications (в этом случае ~/.local/share/applications/libreoffice-writer.desktop). Перетащите локальную копию на панель запуска (иначе вам потребуется выйти / войти).

  5. Если все работает нормально, добавьте его в Startup Applications: Dash > Startup Applications > Add. Добавьте команду:

    python3 /path/to/dynamic_recent.py
    

Чтобы использовать его в других приложениях

Как уже упоминалось, вы можете легко использовать сценарий, чтобы добавить динамический раздел "недавно использованный" в средства запуска других приложений. Для этого см. gedit Пример настройки для головной части скрипта:

# --- set the number of docs to show in recently used
n = 7
# --- set the process name of the targeted application
application = "gedit"
#--- ONLY change the value below into "xdg-open" if you do not use LO preinstalled
#    else the value should be the same as in application = (above)
open_cmd = "gedit"
# --- set the targeted .desktop file (e.g. "gedit.desktop")
target = "gedit.desktop"

Как это устроено

  • Скрипт периодически просматривает файл ~/.local/share/recently-used.xbel найти подходящие файлы, открытые с LibreOffice (Имя процесса: soffice)

    Для этого используется довольно быстрый алгоритм, "стреляющий" через файл за один проход, чтобы получить нужные строки (по две на "запись"). В результате в сценарии очень мало сока.

  • Как только соответствующие строки извлекаются из файла, строки сортируются по дате / времени, создавая "первую десятку" (или любое другое число) наиболее недавно использованных файлов соответствующего приложения.

  • ТОЛЬКО если этот список изменен, .desktop Файл обновлен.

Я не мог заметить или измерить какую-либо дополнительную нагрузку на мою систему, запустив скрипт в фоновом режиме.

Проверено 14.04 / 15.10

Как восстановить оригинальный лаунчер

Просто удалите локальную копию программы запуска в ~/.local/share/applications

Заметки

  • В случае, если вы используете Unity Quicklist Editor для редактирования ваших пусковых установок (быстрых списков), вам следует избегать редактирования пусковых установок с динамически обновляемым разделом "последний использованный" из этого ответа. Изменения, которые вы делаете с помощью редактора QUicklist, будут немедленно перезаписаны сценарием.

  • Вы можете редактировать свой быстрый список вручную, но убедитесь, что вы добавили новый элемент раньше (слева) divider1 в Actions= - линия

    Actions=Window;Document; divider1 ;aap.sh;Todo;pscript_2.py;currdate;bulkmail_llJacob;verhaal;test doc;

    Все предметы справа от divider1 принадлежат к динамически обновляемому разделу.


Основное редактирование

Некоторые важные улучшения были сделаны:

  1. Скрипт теперь только проверяет .xbel файл во время работы целевого приложения (поскольку в недавно использованном списке не будет изменений, если приложение не будет запущено). В сценарии уже не хватало сока, но теперь, если следить за тем, работает ли приложение, значит, для вашей системы еще меньше.
  2. В 15.04+ получается .xbel файл имел двойные упоминания о новых файлах; один с, а другой без расширения. Эффект от этого теперь устранен.

Другие вопросы по тегам