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")
47 self
.button_sort_alpha
= button
.Button("A-Z")
48 self
.button_sort_num
= button
.Button("0-9")
50 self
.body
.td(basic
.Label("Dossier"), style
=td_style
, align
=-1)
51 self
.body
.td(self
.input_dir
, style
=td_style
)
52 self
.body
.td(self
.button_sort_alpha
)
53 self
.body
.td(self
.button_sort_num
)
55 self
.body
.td(self
.list, colspan
=4, style
=td_style
)
56 self
.list.connect(CHANGE
, self
._item
_select
_changed
_, None)
57 self
.button_ok
.connect(CLICK
, self
._button
_okay
_clicked
_, None)
59 self
.body
.td(basic
.Label("Fichier"), style
=td_style
, align
=-1)
60 self
.body
.td(self
.input_file
, style
=td_style
)
61 self
.body
.td(self
.button_ok
, style
=td_style
, colspan
=2)
63 Dialog
.__init
__(self
, self
.title
, self
.body
)
65 # FileDialog.__init__(self,
66 # title_txt="Ouvrir une chanson",
67 # button_txt="Ouvrir",
70 # self.list.style.width = 700
71 # self.list.style.height = 250
74 self
.input_dir
.value
= self
.curdir
75 self
.input_dir
.pos
= len(self
.curdir
)
76 self
.input_dir
.vpos
= 0
80 for i
in os
.listdir(self
.curdir
):
81 if i
.startswith('.') : continue
82 if os
.path
.isdir(os
.path
.join(self
.curdir
, i
)): dirs
.append(i
)
85 self
.input_file
.value
= "Dossier innacessible !"
92 self
.list.add(i
, image
=self
.dir_img
, value
=i
)
96 if not i
.endswith('.xml') :
98 filepath
= os
.path
.join(self
.curdir
, i
)
99 xmlFiles
.append(filepath
)
100 # self.list.add(FileOpenDialog.getSongTitle(filepath), value=i)
103 printableLines
= self
.getPrintableLines(xmlFiles
)
104 for l
in printableLines
:
105 self
.list.add(l
[0], value
= l
[1])
107 self
.list.set_vertical_scroll(0)
109 def getPrintableLines(self
, xmlFiles
) :
110 index
= self
.getUpdatedIndex(xmlFiles
)
116 printableLines
.append(('%s - %s / %s' % (l
[2], l
[3], l
[4]), l
[0]))
118 return printableLines
122 def getSongTitle(file) :
123 it
= ElementTree
.iterparse(file, ['start', 'end'])
125 title
= os
.path
.basename(file)
128 if el
.tag
== 'credit' :
130 if el
.tag
== 'credit-words' and creditFound
:
133 if el
.tag
== 'part-list' :
134 # au delà de ce tag : aucune chance de trouver un titre
139 def getSongMetadata(file) :
141 metadata
['title'] = FileOpenDialog
.getSongTitle(file).encode('iso-8859-1')
142 metadata
['mtime'] = str(os
.stat(file).st_mtime
)
143 metadata
['file'] = os
.path
.basename(file)
144 song
= musicXml2Song(file)
145 metadata
['distinctNotes'] = len(song
.distinctNotes
)
147 histo
= song
.intervalsHistogram
148 coeffInter
= reduce(lambda a
, b
: a
+ b
,
149 [abs(k
) * v
for k
, v
in histo
.items()])
151 totInter
= reduce(lambda a
, b
: a
+b
, histo
.values())
152 totInter
= totInter
- histo
.get(0, 0)
153 difficulty
= int(round(float(coeffInter
) / totInter
, 0))
154 metadata
['difficulty'] = difficulty
158 def getUpdatedIndex(self
, xmlFiles
) :
159 indexTxtPath
= os
.path
.join(self
.curdir
, INDEX_TXT
)
162 if not os
.path
.exists(indexTxtPath
) :
163 musicXmlFound
= False
164 tmp
= tempfile
.TemporaryFile(mode
='r+')
165 for file in xmlFiles
:
167 metadata
= FileOpenDialog
.getSongMetadata(file)
169 except ValueError, e
:
171 if e
.args
and e
.args
[0] == 'not a musicxml file' :
174 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
180 indexFile
= open(indexTxtPath
, 'w')
181 indexFile
.write(tmp
.read())
186 indexTxt
= open(indexTxtPath
, 'r')
188 # check if index is up to date, and update entries if so.
189 for l
in filter(None, indexTxt
.readlines()) :
190 parts
= l
.split('\t')
191 fileBaseName
, modificationTime
= parts
[0], parts
[1]
192 filePath
= os
.path
.join(self
.curdir
, fileBaseName
)
194 if not os
.path
.exists(filePath
) :
197 indexedFiles
[fileBaseName
] = l
198 currentMtime
= str(os
.stat(filePath
).st_mtime
)
200 # check modification time missmatch
201 if currentMtime
!= modificationTime
:
203 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
205 except ValueError, e
:
207 if e
.args
and e
.args
[0] == 'not a musicxml file' :
210 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
211 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
212 indexedFiles
[fileBaseName
] = line
214 # check for new files.
215 for file in xmlFiles
:
216 fileBaseName
= os
.path
.basename(file)
217 if not indexedFiles
.has_key(fileBaseName
) :
219 metadata
= FileOpenDialog
.getSongMetadata(filePath
)
221 except ValueError, e
:
223 if e
.args
and e
.args
[0] == 'not a musicxml file' :
226 metadata
= FileOpenDialog
.getSongMetadata(file)
227 line
= '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
228 indexedFiles
[fileBaseName
] = line
230 # ok, the index is up to date !
232 index
= indexedFiles
.values()