staging.inyokaproject.org

Libreoffice Unity dynamische Quicklist

Status: Ungelöst | Ubuntu-Version: Ubuntu 12.10 (Quantal Quetzal)
Antworten |

Namco

Anmeldungsdatum:
17. März 2013

Beiträge: 2

Guten Abend sehr geehrte ubuntuusers Gemeinde,

ich hätte gerne eine dynamische Quicklist für Libreoffice im Unity Startmenü. Diese soll die zuletzt geöffneten Dokumente anzeigen. Da ich in den weiten des Internets nicht fündig geworden bin, habe ich angefangen selbst zu eine Lösung entwickleln ☺

Für alle, die immernoch nicht wissen, was das ganze überhaupt sein soll (man kann irgendwie keinen Screenshot machen, wenn man Rechtsklick auf ein Menüicon gemacht hat, deswegen Handyfoto):

Ungültiges Makro

Dieses Makro ist nicht verfügbar

So, nun wollte ich ein bash script schreiben, welches die zuletzt geöffneten Dokumente ausliest und anschließend eine entsprechende .desktop Datei schreibt. Die entsprechenden Informationen kann man ja

~/.config/libreoffice/3/user/registrymodifications.xcu

entnehmen. Der Zugriff darauf erfolgt per xmllint.

Der Starter selbst muss wohl auch noch ein Script werden, damit nach dem Beenden einer Libreoffice Anwendung die aktuell zuletzt geöffneten Dokumente geschrieben werden können.

Stand jetzt funktioniert: Ich kann die entsprechende Dateinamen auslesen und in eine .desktop Datei schreiben. Diese enthält einen statischen Teil, über den die einzelnen Libreoffice Anwendungen gestartet werden können und halt einen dynamischen mit den Dokumenten.

Was nicht funktioniert: Dateien, die Leerzeichen oder Umlaute enthalten bekommen falsche Pfade.

Ansonsten ist wohl vieles Verbesserungswürdig. Habe das erste mal mit xmllint und bash Programmierung zu tun gehabt. Besonders die String Manipulation hat mir immer wieder Rätsel aufgegeben.

Darüber hinaus wäre es wohl schöner, wenn eine vorhandene .desktop Datei angepasst wird, anstatt immer komplett neu zu schreiben. Aber das habe ich nicht hinbekommen.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
#!/bin/bash
#Wenn mit Parameter gestartet, entsprechende Datei öffnen.
#Nach Beenden von Libreoffice 3 Sekunden warten, um vorzubeugen, dass die zuletzt geöffneten Dokumente noch nicht geschrieben wurden.
if [ $# -gt 0 ]
	then
	libreoffice "$1"
	sleep 3
fi
#Per xmllint die zuletzt geöffneten Dokumente ermitteln
xmlStr=$(echo 'cat //item[@*[local-name()='"'path'"']="/org.openoffice.Office.Histories/Histories/org.openoffice.Office.Histories:HistoryInfo['"'PickList'"']/ItemList"]/node/@*[local-name()='"'name'"']' | xmllint --shell ~/.config/libreoffice/3/user/registrymodifications.xcu)

#index eines SubStrings ermitteln
strindex() { 
  x="${1%%$2*}"
  [[ $x = $1 ]] && index=-1 || index=${#x}
}

#Dateinamen aus String filtern
frontPattern="file://"
endPattern='"'
arrIndex=0
strindex "$xmlStr" "$frontPattern"
fileNameStart=$index

#Und in ein Array schreiben
while [ $fileNameStart -gt 0 ]
do
	xmlStr=${xmlStr:$fileNameStart + 7}
	strindex "$xmlStr" "$endPattern"
	fileNameEnd=$index
	files[$arrIndex]=${xmlStr:0:$fileNameEnd}
	xmlStr=${xmlStr:$fileNameEnd}
	strindex "$xmlStr" "$frontPattern"
	fileNameStart=$index

	files[$arrIndex]=${files[$arrIndex]//%C3%84/Ä}
	files[$arrIndex]=${files[$arrIndex]//%C3%96/Ö}
	files[$arrIndex]=${files[$arrIndex]//%C3%9C/Ü}
	files[$arrIndex]=${files[$arrIndex]//%C3%A4/ä}
	files[$arrIndex]=${files[$arrIndex]//%C3%B6/ö}
	files[$arrIndex]=${files[$arrIndex]//%C3%BC/ü}
	files[$arrIndex]=${files[$arrIndex]//%20/ }
	#echo ${files[$arrIndex]}
	arrIndex=$[arrIndex + 1]
done

#.desktop Datei schreiben
libreDesktopFile="${HOME}/.local/share/applications/libreoffice.desktop"
content="[Desktop Entry]\n
		Version=1.0\n
		Terminal=false\n
		Icon=libreoffice-startcenter\n
		Type=Application\n
		Categories=Office;X-Red-Hat-Base;X-SuSE-Core-Office;X-MandrivaLinux-Office-Other;\n
		Exec=libreoffice %U\n
		MimeType=application/vnd.openofficeorg.extension;\n
		Name=LibreOffice \n
		GenericName=Office \n
		GenericName[zu]=Ihhovisi\n
		Comment=The office productivity suite compatible to the open and standardized ODF document format. Supported by The Document Foundation.\n
		Comment[zu]=The office productivity suite compatible to the open and standardized ODF document format. Supported by The Document Foundation.\n
		\n
		X-Ayatana-Desktop-Shortcuts=Calc;Writer;Impress;Draw;"
counter=0;
for i in "${files[@]}"
do
	content="$content""$counter;"
	counter=$[counter + 1]
done
content="$content \n
		[Calc Shortcut Group]\n
		Name=Calc\n
		Exec=${HOME}/libreoffice-dynamic-quicklist.sh -calc %U\n
		TargetEnvironment=Unity\n
		\n
		[Writer Shortcut Group]\n
		Name=Writer\n
		Exec=${HOME}/libreoffice-dynamic-quicklist.sh -writer %U\n
		TargetEnvironment=Unity\n
		\n
		[Impress Shortcut Group]\n
		Name=Impress\n
		Exec=${HOME}/libreoffice-dynamic-quicklist.sh -impress %U\n
		TargetEnvironment=Unity\n
		\n
		[Draw Shortcut Group]\n
		Name=Draw\n
		Exec=${HOME}/libreoffice-dynamic-quicklist.sh -draw %U\n
		TargetEnvironment=Unity\n"
counter=0;
for i in "${files[@]}"
do
	content="$content""\n
			[$counter Shortcut Group]\n
			Name=$i\n
			Exec=${HOME}/libreoffice-dynamic-quicklist.sh '$i'\n
			TargetEnvironment=Unity\n"
	counter=$[counter + 1]
done		
echo -e $content > $libreDesktopFile

Ansonsten wollte ich das erstmal hier zum Besten geben, damit andere Leute, die sich vielleicht Ähnliches wünschen einen Ansatz haben und wir unser Wissen bündeln können ☺

Für Kritik, Anregungen und Fragen bin ich gerne offen. Werde die Tage noch damit weiter machen, aber vorher schaue ich mir glaub ich ein wenig das grundsätzliche Handwerkszeug der bash Programmierung an.

Schönen Abend noch.

Edit: So, hab nun soweit alles gefixed (Leerzeichen, Umlaute). Ob es schön, effizient oder sonstwas gelöst ist weiß ich nicht. Bei mir funktioniert jetzt jedenfalls alles.

Wenn es jemand testen will:

  • Script im Home Verzeichnis ablegen

  • mit sudo chmod +x libreoffice-dynamic-quicklist.sh ausführbar machen

  • einmal von der Konsole per ./libreoffice-dynamic-quicklist.sh starten

  • nun die erstellte libreoffice.desktop im Verzeichnis ~/.local/share/applications/ in den Starter ziehen

  • von nun an kann man die zuletzt geöffneten Dokumente per Rechtsklick aus der Quicklist wählen

Wenn man nun natürlich Dokumente über den Dateimanager öffnet oder Libreoffice über einen anderen Weg startet, wird die Quicklist erst upgedatet, wenn man diesen Starter wieder benutzt hat oder das Script manuell ausführt.

Hoffe es nutzt jemanden. Über Kritik, Anregungen und Fragen würde ich mich wie gesagt freuen.

Bilder

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Eine elegantere Variante wäre, das ganze in einer "richtigen" Programmiersprache (Python oder Vala bieten sich an) zu machen und die Launcher-API und GtkRecentManager zu verwenden.

Damit brauchst du keine .desktop-Datei ändern und kannst die Quicklist immer direkt aktualisieren, wenn in Libreoffice eine Datei gespeichert wird.

Namco

(Themenstarter)

Anmeldungsdatum:
17. März 2013

Beiträge: 2

Das klingt interessant. Gut möglich, dass ich mich in nächster Zeit mal da dran probiere. Mit Python hab ich rudimentäre Erfahrungen und was über APIs lernen kann ja auch nicht schaden 😀

Danke für die Info.

tnago

Anmeldungsdatum:
20. Januar 2011

Beiträge: 86

Hi, die ganze Sache interessiert mich auch ein wenig. Hab mich daher mal dran versucht. Muss aber dazu sagen, dass ich kein Informatiker bin. Schätze daher, dass der Code nicht optimal ist.

Hab das ganze ein wenig getestet, scheint zu funktionieren. Vielleicht kann ja Namco darauf aufbauen. Die Liste sortiert die Einträge auf Grundlage des Modifizierungszeitpunkts. Oben die neuesten.

Geschrieben in Phython.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
from gi.repository import Unity, Gio, GObject, Dbusmenu
import os
import gtk

#choose .desktop-file 
launcher = Unity.LauncherEntry.get_for_desktop_id ("libreoffice-writer.desktop")

#get recent manager
manager = gtk.recent_manager_get_default()

#mimetype der gesuchten dateien
mimetype = "application/vnd.oasis.opendocument.text"

ql = Dbusmenu.Menuitem.new()

def enthalten(liste, item):
	if len(liste) != 0:
		for l in liste:
			if l.match(item) == True :
				return True
	return False

#Liste nach Modifizierungszeitpunkt ordnen(Neue Eintraege zuoberst)
def ordnen(liste):
	info = liste[0]
	geordListe = []
	
	ageMax = 0
	for l in liste:
		if l.get_modified() >= ageMax:
			ageMax = l.get_modified()
	
	age = ageMax
	for i in range(len(liste)):
		for l in liste:
			if l.get_modified() >= ageMax:
				if enthalten(geordListe,l) == False:
					ageMax = l.get_modified()
					info = l
		geordListe.append(info)
		ageMax = 0
		#ageMax = age
		
	return geordListe
			
#libreoffice ausfuehren	
def check_item_activated(menuitem, a, ort):
	os.system("libreoffice "+ort)	
#Erstellt Eintrag in Quicklist	
def createItem(name, ort):
	item = Dbusmenu.Menuitem.new()
	item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, name)
	item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
	#bei Klick auf item check_.. aufrufen
	item.connect("item-activated", check_item_activated,ort)
	ql.child_append(item)	

def update():
	liste = manager.get_items()
	infoListe = []

	#sortiere, aus was nicht passender mimetyp
	for i in liste:
		if i.get_mime_type() == mimetype:
			infoListe.append(i)
	#Dokumente, die gelosscht wurden, bei Update aus Liste entfernen						
	for info in ordnen(infoListe):
		if info.exists():
			createItem(info.get_uri_display(),info.get_uri_display())
	#Trennstrich	
	separator = Dbusmenu.Menuitem.new ();
	separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, Dbusmenu.CLIENT_TYPES_SEPARATOR)
	separator.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
	ql.child_append (separator)	
	
#wird aufgerufen, falls gtk_recent_manager signal "changed" aussendet
def check_update(a):
	for c in ql.get_children():
		ql.child_delete(c)
	update()

manager.connect("changed",check_update)

update()

launcher.set_property("quicklist", ql)

loop = GObject.MainLoop()

loop.run()

mfg, tnago

Im Anhang die auführbare Datei

test.py (2.2 KiB)
Download test.py

Anndyy

Anmeldungsdatum:
5. Januar 2013

Beiträge: 21

Hi habe das hier grad entdeckt. Finde das ganze sehr interessant. Aber wie muss ich mit der ausführbaren datei umgehen?

tnago

Anmeldungsdatum:
20. Januar 2011

Beiträge: 86

Du musst die test.py einfach starten. Also im Terminal mit python test.py. Alternativ kannst du auch als erste Zeile

1
#!/usr/bin/env python

hinzufügen und die datei in den einstellungen ausführbar machen. Dann reicht ein Doppelklick aud test.py. Im Übrigen lässt sich das für beliebige Mimetypen durchführen. Wenn du bspw. das Ganz für die Calc-Dateien haben willst. Ändere einfach den Mimetype auf application/vnd.oasis.opendocument.spreadsheet und die .desktop-Datei auf libre-calc.desktop. Ruf dann die .py datei auf und schon werden die .ods dateien beim Rechtsklick auf den Calc-Starter angezeigt. Du musst halt den auszuführenden Befehel anpassen, falls du andere Programme als libreoffice bei Klick starten willst.

mfg, tnago

tnago

Anmeldungsdatum:
20. Januar 2011

Beiträge: 86

So, hab das Ganze noch etwas verbessert. Vor konnte nur ein Prozess gestartet werden, und sobald man diesen beendete, öffneten sich die zuvor gewählten. Hoffe das ist jetzt mit subprocess.Popen nicht mehr so.Außerdem werden die zuletzt verwendeten .ods,.odt,.odp,.odg jeweils beim passenden Icon Writer,Calc etc. angezeigt.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
from gi.repository import Unity, Gio, GObject, Dbusmenu
import subprocess
import gtk
#Ein Mimetype pro Launcher
#choose .desktop-file 
launcherWrite = Unity.LauncherEntry.get_for_desktop_id ("libreoffice-writer.desktop")
launcherCalc = Unity.LauncherEntry.get_for_desktop_id ("libreoffice-calc.desktop")
launcherImpress = Unity.LauncherEntry.get_for_desktop_id("libreoffice-impress.desktop")
launcherDraw = Unity.LauncherEntry.get_for_desktop_id("libreoffice-draw.desktop")

launcherListe = [launcherWrite,launcherCalc,launcherImpress,launcherDraw]

#get recent manager
manager = gtk.recent_manager_get_default()

#mimetyp der gesuchten dateien
mimetypes = ["application/vnd.oasis.opendocument.text","application/vnd.oasis.opendocument.spreadsheet","application/vnd.oasis.opendocument.presentation","application/vnd.oasis.opendocument.graphics"]


qlListe = []
for i in range(len(launcherListe)):
	qli = Dbusmenu.Menuitem.new()
	qlListe.append(qli)



def enthalten(liste, item):
	if len(liste) != 0:
		for l in liste:
			if l.match(item) == True :
					return True
	return False

#Liste nach Modifizierungszeitpunkt ordnen(Neue Eintraege zuoberst)
def ordnen(liste):
	info = liste[0]
	geordListe = []
	
	ageMax = 0
	for l in liste:
		if l.get_modified() >= ageMax:
			ageMax = l.get_modified()
	
	age = ageMax
	for i in range(len(liste)):
		for l in liste:
			if l.get_modified() >= ageMax:
				if enthalten(geordListe,l) == False:
					ageMax = l.get_modified()
					info = l
		geordListe.append(info)
		ageMax = 0
		
	return geordListe
			
#libreoffice ausfuehren	
def check_item_activated(menuitem, a, ort):
	process = subprocess.Popen("libreoffice "+ort,shell=True)
		
#Erstellt Eintrag in Quicklist	
def createItem(name, ort, qlnummer):
	item = Dbusmenu.Menuitem.new()
	item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, name)
	item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
	#bei Klick auf item check_.. aufrufen
	item.connect("item-activated", check_item_activated,ort)
	qlListe[qlnummer].child_append(item)	

#Aktualisieren
def update():
	liste = manager.get_items()
	infoListe = []
	for i in range(len(mimetypes)):
		infoListe.append([])

	#sortiere, aus was nicht passender mimetyp
	for i in liste:
		if i.exists():
			for e in range(len(mimetypes)):
				if i.get_mime_type() == mimetypes[e]:
					infoListe[e].append(i)
					
	#Dokumente, die geloescht wurden, bei Update aus Liste entfernen
	for i in range(len(infoListe)):
		if len(infoListe[i]) != 0 :
			for info in ordnen(infoListe[i]):
				createItem(info.get_uri_display(),info.get_uri_display(),i)
			
	
	#Trennstriche hinzufuegen
	for i in range(len(qlListe)):
		if len(infoListe[i]) != 0:
			separator = Dbusmenu.Menuitem.new ();
			separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, Dbusmenu.CLIENT_TYPES_SEPARATOR)
			separator.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
			qlListe[i].child_append (separator)
	
	
#wird aufgerufen, falls gtk_recent_manager signal "changed" aussendet
def check_update(a):
	for i in range(len(qlListe)):
		for c in qlListe[i].get_children():
			qlListe[i].child_delete(c)
	update()
	
update()

manager.connect("changed",check_update)

for i in range(len(launcherListe)):
	launcherListe[i].set_property("quicklist", qlListe[i])

loop = GObject.MainLoop()

loop.run()

Starten dann per Doppelklick auf die Datei möglich.

mfg, tnago

libreoffice.py (3.3 KiB)
Download libreoffice.py
Antworten |