Adicionando uma seção dinâmica "recentemente usada" ao lançador de um aplicativo
A integração completa de uma aplicação com a lista dinâmica -entries provavelmente precisa ser feita de dentro da aplicação. Afinal, as informações mais diretas sobre os arquivos usados vêm do próprio aplicativo.
No entanto, como a edição do código-fonte está fora do escopo do que estamos fazendo, esse não seria o caminho a seguir.
Então o que?
Isso não significa que não possamos alcançar exatamente o mesmo resultado, talvez até de maneira mais flexível e geral, a partir de "fora". Todas as informações de que precisamos estão disponíveis no arquivo atualizado dinamicamente: ~/.local/share/recently-used.xbel
, do qual podemos recuperar o histórico completo de arquivos abertos, a data correspondente & amp; informações de tempo e o aplicativo que foi usado.
Além disso, adicionar uma seção atualizada dinamicamente a um lançador pode muito bem ser feito como parte da seção "tradicional" (estática). A chave da solução é, então, criar um processo que cuide das ações acima, sem adicionar uma carga perceptível ao sistema.
Como mencionado em o link da questão, alguns processo em segundo plano seria necessário de qualquer maneira para acompanhe as alterações e passe as instruções.
O script abaixo está fazendo exatamente isso.
A solução; um script de plano de fundo
Os valores no script abaixo são especificamente definidos para LibreOffice
e seus documentos. Sem qualquer edição, ele pode ser usado para adicionar uma seção usada recentemente ao LibreOffice-Writer
launcher. Ele mostrará os 10 últimos documentos usados, abertos por qualquer um dos LibreOffice
-modules.
A solução pode, no entanto, ser usada para adicionar uma seção "recentemente usada" a muitas aplicações com um arquivo .desktop
em /usr/share/applications
. Como o arquivo ~/.local/share/recently-used.xbel
é Gtk
relacionado, provavelmente, os aplicativos com uma janela Gtk
serão nossos candidatos em potencial (ou seja, se o aplicativo abrir e editar arquivos). Além disso, o número de arquivos a mostrar é arbitrário.
Como fica
A solução adiciona uma seção ao inicializador de destino no iniciador do Unity, mostrando um número arbitrário de arquivos usados recentemente, por exemplo:
-
mostra os últimos sete arquivos:
-
ou os últimos dez arquivos:
-
Com a mesma facilidade, no entanto, podemos dar ao
gedit
launcher uma seção dinâmica, mostrando os últimos sete arquivos, abertos comgedit
(veja a imagem abaixo)
Como usar
Supondo que você tenha o LibreOffice pré-instalado (a versão baixada não possui um arquivo .desktop
referenciando em /usr/share/applications
que é necessário pelo script, mas em outro lugar, por favor mencione se você precisa configurar o LO baixado separadamente versão)
-
Copie o script abaixo em um arquivo vazio, salve-o como
dynamic_recent.py
ParaLibreOffice
, o nome do processo ésoffice
, já definido corretamente no script.#!/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="''+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
-
Na seção principal do script, você pode definir várias opções:
# --- 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"
A maioria das opções fala por si, se você quiser adicionar a seção dinâmica ao
LO-Writer
launcher, deixe tudo como está. Caso contrário, defina o lançador apropriado. -
Teste- execute o script executando a partir de um terminal:
python3 /path/to/dynamic_recent.py
-
O script copiou o arquivo global
.desktop
para~/.local/share/applications
(nesse caso,~/.local/share/applications/libreoffice-writer.desktop
). Arraste a cópia local para o lançador (caso contrário, você precisará fazer logout / entrada). -
Se tudo funcionar bem, adicione-o aos aplicativos de inicialização: Dash & gt; Aplicativos de inicialização & gt; Adicionar. Adicione o comando:
python3 /path/to/dynamic_recent.py
Para usá-lo em outros aplicativos
Como mencionado, você pode facilmente usar o script para adicionar uma seção dinâmica "recentemente usada" ao (s) lançador (es) de outra aplicação. Para fazer isso, veja a configuração de gedit
do exemplo para a seção head do script:
# --- 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"
Como funciona
-
O script examina periodicamente o arquivo
~/.local/share/recently-used.xbel
para encontrar arquivos correspondentes, abertos comLibreOffice
(processname:soffice
)Ele usa um algoritmo bastante rápido para fazer isso, "disparando" através do arquivo em uma única passagem, para recuperar as linhas necessárias (duas por "registro"). O resultado é que o script está com pouco suco.
-
Depois que as linhas relevantes são recuperadas do arquivo, as linhas são classificadas por data / hora, criando um "top ten" (ou qualquer outro número) dos arquivos usados mais recentemente do aplicativo correspondente.
-
SOMENTE se essa lista for alterada, o arquivo
.desktop
será atualizado.
Eu pude notar nem medir qualquer carga adicional no meu sistema, executando o script em segundo plano.
Testado em 14.04 / 15.10
Como restaurar o inicializador original
Basta remover a cópia local do lançador em ~/.local/share/applications
Notas
-
Caso você use o Editor de listas rápidas da Unity para editar seus lançadores (listas rápidas), deve evitar a edição de lançadores com uma seção "usada pela última vez" dinamicamente a partir desta resposta. As edições que você faz com o Editor da Quicklist serão imediatamente sobrescritas pelo script.
-
Você pode editar sua lista rápida manualmente, mas certifique-se de adicionar um novo item antes (no lado esquerdo de)
divider1
naActions=
- lineActions=Window;Document;
divider1;aap.sh;Todo;pscript_2.py;currdate;bulkmail_llJacob;verhaal;test doc;
Todos os itens à direita de
divider1
pertencem à seção atualizada dinamicamente.
Edição importante
Algumas melhorias importantes foram feitas:
- O script agora somente verifica o arquivo
.xbel
enquanto o aplicativo de destino é executado (já que não haverá alterações na lista usada recentemente se o aplicativo não for executado). O roteiro já estava com pouco suco, mas agora, ficar de olho apenas se o aplicativo for executado significa muito menos para o seu sistema. - No 15.04+, o arquivo
.xbel
tinha duas menções de novos arquivos; um com e um sem extensão. O efeito disso agora é eliminado.