oook – gestore documenti

Un po’ di tempo fa ho creato uno script per rintracciare velocemente i memos, le note che uno segna sui pezzi di carta, il retro delle buste (delle fatture da pagare, ricevo solo quel genere di posta) e poi butta via e le meravigliose idee sono perse per sempre nel gorgo del tempo 😦
Sì mi sono lasciato trasportare dalla foga e da un improvvisa e dubbia vena poetica, comunque i post a cui mi riferivo sono qui e qui.

Oggi sulla falsariga di memos voglio farvi vedere qualcosa di simile, anzi completamente differente. (Notate che qui avrei due riferimenti letterari da proporvi, Monty Python e Douglas N. Adams ma ve li risparmio entrambi).

Intanto introduco un pythonista nostrano davvero OK: Andrea Gavana. Andrea è poliedrico, la sua pagina web dovrebbe essere questa e da lì si può andare sul suo blog che secondo la tradizione dei veri autentici geeks non è aggiornato da tempo; magari ne ha fatto un altro o se lo è dimenticato o ha di meglio da fare, chissà?
Sì probabilmente è indaffarato con altre cose come AGW, pacchetto di grafica super, quasi al sapore di mela, adesso parte integrante di wx.
AGW sta per Advanced Generic Widgets e trovate tutto qui. Io userò un solo componente di AGW, l’AquaButton ma c’è una quasi infinity di roba sbaluccicosa: bravo Andrea 😀

oook

Quando io ero giovane i manuali erano libroni di difficile reperimento e consultazione scomoda. Adesso si trovano in giro per il Web, normalmente in formato PDF o HTML. Soprattutto per i PDF conviene averne una copia sul proprio hard disk, ma questo vale anche per gli HTML, per mettersi al riparo della sfiga (a proposito adesso sembra che le interruzioni Telecom siano finite, speriamo).
Se uno questi manuali li raccoglie tutti in una directory (quello che i giovani chiamano cartella) non dovrà ogni volta che deve consultarne uno fare la caccia al tesoro.
Poi quelli più metodici invece di creare una directory unica e metterci tutto dentro creeranno una struttura ad albero, cioè nella cartella principale (manuali o docs)  dentro la quale creeranno tante sottocartelle (python, lisp, shell, gimp, tutto il resto) e vivranno una vita con un po’ meno affanni e incazzature.

Qui entra in gioco il mio script oook.
Intanto il nome: potevo banalmente chiamarlo docs ma, lavorando a UUAM come aiutante dell’aiuto del bibliotecario mi è sembrato opportuno dedicargli l’opera. Non sapete di cosa sto parlando? Sospendete tutto, fiondatevi in biblioteca (in libreria i più abbienti e/o scialatori) e arraffate tutto quello che trovate del Mondo Disco di Terry Pratchett, mi ringrazierete! 😀
Bene, abbiamo perso qualcuno, non molti, praticamente tutti conoscono pTerry. Già che ci sono, un avviso agli spammer: Signori Robots Spammatori, quando dico Ankh-Morpork non mi riferisco al simbolo egizio new-agistico, dovrebbe capirsi dal contesto. O no? Tanto poi Akismet vi blocca: Akismet blocca tutto, ha bloccato anche gli auguri della mia mitica amica Sylvie!

Tornando allo script ci servono quattro piccole icone. Io uso queste, naturalmente si possono cambiare. I nomi, il tipo PNG e le dimensioni (26×26 pixel) sono fissi a meno di intervenire sul codice dello script.
Possono essere nella stessa directory dello script o in una sub-dir con nome imgs.

pdf.png html.png folder.png alt.png

Tutto ciò premesso ecco lo script:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys, wx
import wx.lib.agw.aquabutton as AB

C_HTML = '#F07746' # html
C_PDF  = '#FB7CDE' # pdf
C_DIR  = '#FAC83A' # dir
C_ALT  = '#FBB77C' # tutto il resto
BOFFS = 101 # offset id bottoni

def getoookdirs():
	global homedir, imgsdir, oookdir

	homedir = os.path.abspath(os.path.dirname(sys.argv[0]))
	imgsdir = os.path.join(homedir, 'imgs')
	if not os.path.isdir(imgsdir):
		imgsdir = homedir
	if len(sys.argv) > 1:
		oookdir = os.path.abspath(sys.argv[1])
	else:
		oookdir = homedir
	if not os.path.isdir(oookdir):
		sys.exit(1)

def makeoook():
	global oookdir, objlst

	nostart = ['.', 'no-list']
	noend = ['.py', '.info', '.info.txt', '_files']

	objlst = sorted(os.listdir(oookdir), key = str.lower)
	if len(objlst) == 0:
		return False

	oklist =[] #start
	for ele in objlst:
		no = False
		for c in nostart:
			no = ele[:len(c)] == c
			if no: break
		if not no:
			oklist.append(ele)
	if len(oklist) == 0:
		return False

	objlst =[] #end
	for ele in oklist:
		no = False
		for c in noend:
			no = ele[-len(c):] == c
			if no: break
		if not no:
			objlst.append(ele)
	if len(objlst) == 0:
		return False
	if len(objlst) > 12:
		objlst = objlst[:12]

	return True

class oookFrame(wx.Frame):
	def __init__(self):
		global homedir, imgsdir, oookdir
		global objlst

		tit = os.path.basename(oookdir)
		stile = wx.SYSTEM_MENU | \
				wx.CAPTION | wx.CLOSE_BOX | \
				wx.FULL_REPAINT_ON_RESIZE
		wx.Frame.__init__(self, None, -1, tit, style = stile)
		self.pn = wx.Panel(id=1, name='pn', parent=self)
		self.pn.SetBackgroundColour(wx.WHITE)

		imgsok = os.path.isfile(os.path.join(imgsdir, 'html.png'))
		if imgsok:
			i_html = wx.Image(os.path.join(imgsdir, 'html.png'),
								wx.BITMAP_TYPE_PNG).ConvertToBitmap()
			i_pdf = wx.Image(os.path.join(imgsdir, 'pdf.png'),
								wx.BITMAP_TYPE_PNG).ConvertToBitmap()
			i_alt = wx.Image(os.path.join(imgsdir, 'alt.png'),
								wx.BITMAP_TYPE_PNG).ConvertToBitmap()
			i_dir = wx.Image(os.path.join(imgsdir, 'folder.png'),
								wx.BITMAP_TYPE_PNG).ConvertToBitmap()
		else:
			i_html = i_pdf = i_alt = i_dir = ''

		for c in range(len(objlst)):
			txt = objlst[c]
			if len(txt) > 32:
				txt = txt[:31]
			ext = os.path.splitext(objlst[c])[1]
			if ext == '.html':
				img = i_html
				color = C_HTML
			elif ext == '.pdf':
				img = i_pdf
				color = C_PDF
			elif os.path.isdir(os.path.join(oookdir, objlst[c])):
				img = i_dir
				color = C_DIR
			else:
				img = i_alt
				color = C_ALT
			self.btn = AB.AquaButton(self.pn, -1, img, txt)
			self.btn.SetId(BOFFS + c)
			self.btn.SetPosition((5, 5 + 40 * c))
			self.btn.SetBackgroundColour(color)
			self.btn.SetForegroundColour('black')
			self.btn.SetSize((240,50))
			self.btn.Bind(wx.EVT_BUTTON, self.OnClick)
			self.btn.Bind(wx.EVT_RIGHT_UP, self.OnRup)

		h = 10 + len(objlst) * 40
		self.SetSize((250, h))

	def OnClick(self, event):
		global objlst, oookdir

		bid = event.GetId()
		w = objlst[bid - BOFFS]
		wp = os.path.join(oookdir, w)
		if os.path.isfile(wp):
			os.system('xdg-open "%s"' %wp)
		elif os.path.isdir(wp):
			who = os.path.abspath(sys.argv[0])
			os.system('python "%s" "%s"' %(who, wp))

	def OnRup(self, event):
		global objlst, oookdir

		bid = event.GetId()
		w = os.path.join(oookdir,
						 os.path.splitext(objlst[bid - BOFFS])[0])
		w = '%s%s' %(w, '.info')
		if not os.path.exists(w):
			f = open(w, 'w')
			f.close()
		os.system('xdg-open "%s"' %w)

#main
getoookdirs()
if not makeoook():
	sys.exit(2)

app = wx.PySimpleApp()
frame = oookFrame()
frame.Show()
app.MainLoop()

La riga 5 importa il pulsante AquaButton. Le due funzioni getoookdirs() e makeoook() creano la lista degli oggetti da elencare. La directory è quella indicata sulla linea di comando o, in assenza di indicazioni, quella in cui si trova lo script. Vengono esclusi gli oggetti il cui nome inizia o termina con uno degli elementi delle liste nostart e noend (righe 30 e 31). Se la lista ha più di 12 elementi viene troncata ai primi 12: la cartella va suddivisa! (oppure cambiare il numero alle righe 58 e 59).
Per ogni oggetto viene quindi creato un pulsante (righe dalla 89 alla 113). I pulsanti sono differenziati per colore e immagine in quattro categorie (html, pdf, cartelle, tutto il resto). Ogni pulsante risponde al click del tasto sinistro del mouse aprendo il documento relativo se si tratta di un file, aprendo una copia del widget se è una cartella (directory), righe 118-128. Facendo click con il tasto destro viene aperto un file di testo con il nome del pulsante e estensione .info in cui è possibile segnare annotazioni, cosa che con i libri di carta… (righe 130-140).

 

Lo script è per Linux, per Windows sarebbero necessarie piccolissime modifiche quali tener conto della barra del titolo nelle dimensioni della finestra (riga 115), nell’eseguire il comando os.system, righe 128 e 140, utilizzando shex.exe come illustrato per memos.

Conclusioni

In questo periodo di feste diffuse non sono riuscito a organizzare le directories in cui raccogliere i documenti, ma nei prossimi giorni…
E di solito applicando qualcosa dal vero saltano fuori piccoli bug, che inducono a una nuova release, forse, se del caso.
Uno dei propositi dell’anno nuovo era quello di non usare più funzioni deprecate, os.system e % nel format: qui ci sono ancora ma solo perché tecnicamente è dell’anno vecchio 😉

Poi, forse Python –sempre Python– comincia a stufarmi, ci vorrebbe qualcosa di nuovo. Anche non nuovo ma diverso, forse…

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • glipari  Il 4 gennaio 2011 alle 00:19

    scusa, c’è una ragione particolare per avere il limite a 12 entry? (o anche a un numero diverso…)

  • juhan  Il 4 gennaio 2011 alle 08:43

    Il 12 è arbitrario. Arriva da queste deboli considerazioni:
    1) un pulsante ha altezza di 40 px; 12 * 40 = 480;
    2) sono convinto che bisogna organizzarsi e 12 manuali sono già tanti;
    3) si potrebbe raddoppiare, triplicare, n-plicare il 12 aggiungendo altre colonne; siccome è facile e sono indaffarato su altre cose lo lascio come esercizio 😉
    In ogni caso non lo sto ancora usando benché fosse finito da due settimane, poi se del caso lo correggo/integro.

  • Infinity77  Il 19 febbraio 2011 alle 14:32

    Grazie dei complimenti, sono capitato per caso sul tuo blog e vedo che AGW sta diventando famoso 😀

    Andrea.

Trackback

  • […] già fatto un qualcosa di simile, il 3 gennaio 2011, lo trovate su questo blog, qui: oook – gestore documenti. Poi recentemente ne ho preparato uno simile, per altre cose e mi è venuta l’idea di usarlo […]

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: