1 # -*- coding: utf-8 -*-
3 Boîte de dialogue pour sélection des chansons.
9 from pgu
.gui
import FileDialog
10 import pgu
.gui
.basic
as basic
11 import pgu
.gui
.input as input
12 import pgu
.gui
.button
as button
13 import pgu
.gui
.pguglobals
as pguglobals
14 import pgu
.gui
.table
as table
15 import pgu
.gui
.area
as area
16 from pgu
.gui
.const
import *
17 from pgu
.gui
.dialog
import Dialog
21 from xml
.etree
import ElementTree
22 from minwii
.musicxml
import musicXml2Song
24 INDEX_TXT
= 'index.txt'
26 class FileOpenDialog(FileDialog
):
30 def __init__(self
, path
):
32 if not path
: self
.curdir
= os
.getcwd()
33 else: self
.curdir
= path
34 self
.dir_img
= basic
.Image(
35 pguglobals
.app
.theme
.get(cls1
+'.folder', '', 'image'))
36 td_style
= {'padding_left': 4,
40 self
.title
= basic
.Label("Ouvrir un chanson", cls
="dialog.title.label")
41 self
.body
= table
.Table()
42 self
.list = area
.List(width
=700, height
=250)
43 self
.input_dir
= input.Input()
44 self
.input_file
= input.Input()
46 self
.button_ok
= button
.Button("Ouvrir")
48 self
.body
.td(basic
.Label("Dossier"), style
=td_style
, align
=-1)
49 self
.body
.td(self
.input_dir
, style
=td_style
)
51 self
.body
.td(self
.list, colspan
=3, style
=td_style
)
52 self
.list.connect(CHANGE
, self
._item
_select
_changed
_, None)
53 self
.button_ok
.connect(CLICK
, self
._button
_okay
_clicked
_, None)
55 self
.body
.td(basic
.Label("Fichier"), style
=td_style
, align
=-1)
56 self
.body
.td(self
.input_file
, style
=td_style
)
57 self
.body
.td(self
.button_ok
, style
=td_style
)
59 Dialog
.__init
__(self
, self
.title
, self
.body
)
61 # FileDialog.__init__(self,
62 # title_txt="Ouvrir une chanson",
63 # button_txt="Ouvrir",
66 # self.list.style.width = 700
67 # self.list.style.height = 250
70 self
.input_dir
.value
= self
.curdir
71 self
.input_dir
.pos
= len(self
.curdir
)
72 self
.input_dir
.vpos
= 0
76 for i
in os
.listdir(self
.curdir
):
77 if i
.startswith('.') : continue
78 if os
.path
.isdir(os
.path
.join(self
.curdir
, i
)): dirs
.append(i
)
81 self
.input_file
.value
= "Dossier innacessible !"
88 self
.list.add(i
, image
=self
.dir_img
, value
=i
)
92 if not i
.endswith('.xml') :
94 filepath
= os
.path
.join(self
.curdir
, i
)
95 xmlFiles
.append(filepath
)
96 # self.list.add(FileOpenDialog.getSongTitle(filepath), value=i)
99 printableLines
= self
.getPrintableLines(xmlFiles
)
100 for l
in printableLines
:
101 self
.list.add(l
[0], value
= l
[1])
103 self
.list.set_vertical_scroll(0)
105 def getPrintableLines(self
, xmlFiles
) :
106 index
= self
.getUpdatedIndex(xmlFiles
)
112 printableLines
.append(('%s - %s / %s' % (l
[2], l
[3], l
[4]), l
[0]))
114 return printableLines
118 def getSongTitle(file) :
119 it
= ElementTree
.iterparse(file, ['start', 'end'])
121 title
= os
.path
.basename(file)
124 if el
.tag
== 'credit' :
126 if el
.tag
== 'credit-words' and creditFound
:
129 if el
.tag
== 'part-list' :
130 # au delà de ce tag : aucune chance de trouver un titre
135 def getSongMetadata(file) :
137 metadata
['title'] = FileOpenDialog
.getSongTitle(file).encode('iso-8859-1')
138 metadata
['mtime'] = str(os
.stat(file).st_mtime
)
139 metadata
['file'] = os
.path
.basename(file)
140 song
= musicXml2Song(file)
141 metadata
['distinctNotes'] = len(song
.distinctNotes
)
143 histo
= song
.intervalsHistogram
144 coeffInter
= reduce(lambda a
, b
: a
+ b
,
145 [abs(k
) * v
for k
, v
in histo
.items()])
147 totInter
= reduce(lambda a
, b
: a
+b
, histo
.values())
148 totInter
= totInter
- histo
.get(0, 0)
149 difficulty
= int(round(float(coeffInter
) / totInter
, 0))
150 metadata
['difficulty'] = difficulty
154 def getUpdatedIndex(self
, xmlFiles
) :
155 indexTxtPath
= os
.path
.join(self
.curdir
, INDEX_TXT
)
158 if not os
.path
.exists(indexTxtPath
) :
159 musicXmlFound
= False
160 tmp
= tempfile
.TemporaryFile(mode
='r+')
161 for file in xmlFiles
:
163 metadata
= FileOpenDialog
.getSongMetadata(file)
165 except ValueError, e
:
167 if e
.args
and e
.args
[0] == 'not a musicxml file' :
170 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
176 indexFile
= open(indexTxtPath
, 'w')
177 indexFile
.write(tmp
.read())
182 indexTxt
= open(indexTxtPath
, 'r')
184 # check if index is up to date, and update entries if so.
185 for l
in filter(None, indexTxt
.readlines()) :
186 parts
= l
.split('\t')
187 fileBaseName
, modificationTime
= parts
[0], parts
[1]
188 filePath
= os
.path
.join(self
.curdir
, fileBaseName
)
190 if not os
.path
.exists(filePath
) :
193 indexedFiles
[fileBaseName
] = l
194 currentMtime
= str(os
.stat(filePath
).st_mtime
)
196 # check modification time missmatch
197 if currentMtime
!= modificationTime
:
199 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
201 except ValueError, e
:
203 if e
.args
and e
.args
[0] == 'not a musicxml file' :
206 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
207 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
208 indexedFiles
[fileBaseName
] = line
210 # check for new files.
211 for file in xmlFiles
:
212 fileBaseName
= os
.path
.basename(file)
213 if not indexedFiles
.has_key(fileBaseName
) :
215 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
217 except ValueError, e
:
219 if e
.args
and e
.args
[0] == 'not a musicxml file' :
222 metadata
= FileOpenDialog
.getSongMetadata(file)
223 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
224 indexedFiles
[fileBaseName
] = line
226 # ok, the index is up to date !
228 index
= indexedFiles
.values()