PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/MainWindow.rb

https://bitbucket.org/abom/qurename
Ruby | 397 lines | 346 code | 32 blank | 19 comment | 33 complexity | 2d47e9dc15249b924ff3504cdae26008 MD5 | raw file
Possible License(s): GPL-2.0
  1. # Main Window
  2. # Copyright (C) <2008-2010> Abdelrahman ghanem <abom.jdev@gmail.com>
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. # You should have received a copy of the GNU General Public License along
  14. # with this program; if not, write to the Free Software Foundation, Inc.,
  15. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. require 'rubygems'
  17. require 'lib/quren'
  18. require 'lib/tagger'
  19. require 'lib/arabic_normalization'
  20. require 'UiMainWindow'
  21. require 'LanguagesDialog'
  22. require 'EditTagDialog'
  23. class MWindow < Qt::MainWindow
  24. slots 'rename()',
  25. 'preview(bool)',
  26. 'update_preview(int)',
  27. 'browse()',
  28. 'edit_tags()',
  29. 'lang()',
  30. 'about()',
  31. 'load_files!(int)',
  32. 'view_file_name()',
  33. 'play()',
  34. 'stop()',
  35. 'opendir_fromtree()',
  36. 'reload_paths(const QString&)'
  37. def initialize parent=nil
  38. super parent
  39. @mwin=Ui_MainWindow.new
  40. @mwin.setupUi self
  41. @mwin.pb.visible=false
  42. @mwin.lstfiles.setColumnHidden 2,true
  43. @mwin.lstfiles.setColumnHidden 3,true
  44. @quren=QuRen.new
  45. @tagger=Tagger.new
  46. @langdialog=LanguagesDialog.new
  47. load_langs!
  48. ok?
  49. connect(@mwin.comboext,SIGNAL('currentIndexChanged(int)'),
  50. self,SLOT('load_files!(int)'))
  51. connect(@mwin.combolang, SIGNAL('currentIndexChanged(int)'),
  52. self, SLOT('update_preview(int)'))
  53. connect(@mwin.action_Preview,SIGNAL('toggled(bool)'),
  54. self,SLOT('preview(bool)'))
  55. connect(@mwin.lstfiles,SIGNAL('itemSelectionChanged()'),
  56. self,SLOT('view_file_name()'))
  57. connect(@mwin.btnbrowse,SIGNAL('clicked()'),
  58. self,SLOT('browse()'))
  59. connect(@mwin.btnopendir,SIGNAL('clicked()'),
  60. self,SLOT('opendir_fromtree()'))
  61. connect(@mwin.action_rename,SIGNAL('triggered()'),
  62. self,SLOT('rename()'))
  63. connect(@mwin.action_Edit_Tags,SIGNAL('triggered()'),
  64. self,SLOT('edit_tags()'))
  65. connect(@mwin.action_Languages,SIGNAL('triggered()'),
  66. self,SLOT('lang()'))
  67. connect(@mwin.action_About,SIGNAL('triggered()'),
  68. self,SLOT('about()'))
  69. connect(@mwin.action_Play,SIGNAL('triggered()'),
  70. self,SLOT('play()'))
  71. connect(@mwin.action_Stop,SIGNAL('triggered()'),
  72. self,SLOT('stop()'))
  73. @player=Phonon::MediaObject.new
  74. @audio_output=Phonon::AudioOutput.new(Phonon::MusicCategory)
  75. Phonon.createPath(@player,@audio_output)
  76. @player.tickInterval=1000
  77. connect(@player, SIGNAL('finished()'),
  78. self, SLOT('stop()'))
  79. @mwin.lstfiles.sortItems(0,Qt::AscendingOrder)
  80. @mwin.action_Stop.enabled=false
  81. @mwin.treeDirs.header.defaultSectionSize=200
  82. @dir_model=Qt::FileSystemModel.new
  83. @dir_model.setFilter(Qt::Dir::AllDirs)
  84. @mwin.treeDirs.model=@dir_model
  85. @filesystemwatcher=Qt::FileSystemWatcher.new
  86. @dir_model.rootPath='/'
  87. connect(@filesystemwatcher,SIGNAL('directoryChanged(const QString&)'),
  88. self,SLOT('reload_paths(const QString&)'))
  89. end
  90. def load_langs!
  91. @mwin.combolang.clear
  92. files=@quren.get_files 'langs','xml'
  93. files.each do |file|
  94. if File.extname(file)=='.xml'
  95. @mwin.combolang.addItem file.gsub('.xml','')
  96. end
  97. end
  98. end
  99. def load_exts!
  100. current_ext_idx = @mwin.comboext.currentIndex
  101. @mwin.comboext.clear
  102. exts=@quren.get_exts @mwin.txtpath.text
  103. return if exts.nil?
  104. exts.each do |ext|
  105. @mwin.comboext.addItem ext
  106. end
  107. @mwin.comboext.currentIndex = current_ext_idx unless current_ext_idx==-1
  108. end
  109. def ok?
  110. dir=@mwin.txtpath.text
  111. ext=@mwin.comboext.currentText
  112. if dir!='' and !ext.nil?
  113. en_actions true
  114. return true
  115. else
  116. en_actions false
  117. return false
  118. end
  119. end
  120. def load_files! idx=0
  121. ok?
  122. @mwin.lstfiles.clear
  123. @files=@quren.get_files @mwin.txtpath.text,@mwin.comboext.currentText
  124. return if @files.length==0
  125. idx=0
  126. @files.each do |file|
  127. item=Qt::TreeWidgetItem.new @mwin.lstfiles
  128. idx+=1
  129. item.setText 0,idx.to_s
  130. item.setText 1,file
  131. end
  132. re_cols
  133. statusBar.showMessage(tr("Files with extension #{@mwin.comboext.currentText} loaded"))
  134. end
  135. def stop_fs_watch(&block)
  136. dirs=@filesystemwatcher.directories
  137. #puts dirs
  138. #FIXME: can't stop fs watch,
  139. #alot of 'return' in block exits the scope, so
  140. #addPaths dosn't emitted
  141. @filesystemwatcher.removePaths(dirs)
  142. block.call
  143. @filesystemwatcher.addPaths(dirs)
  144. end
  145. def open_dir(dir)
  146. prev_dir=@mwin.txtpath.text
  147. if @filesystemwatcher.directories.at(0)==prev_dir
  148. @filesystemwatcher.removePath(prev_dir)
  149. end
  150. @filesystemwatcher.addPath(dir)
  151. index=@dir_model.index(dir)
  152. @mwin.treeDirs.currentIndex=index
  153. @mwin.treeDirs.scrollTo(index,Qt::AbstractItemView::PositionAtCenter)
  154. @mwin.txtpath.text=dir
  155. load_exts!
  156. load_files!
  157. end
  158. def reload_paths(changed)
  159. load_exts!
  160. load_files!
  161. end
  162. def browse
  163. dir=Qt::FileDialog.getExistingDirectory self,tr('Choose Directory'),'/'
  164. return if dir.nil?
  165. open_dir(dir)
  166. end
  167. def opendir_fromtree
  168. selected=@mwin.treeDirs.selectedIndexes
  169. if selected.count>0
  170. path=@dir_model.filePath(selected.at(0))
  171. if File.directory?(path)
  172. open_dir(path)
  173. else
  174. open_dir(File.dirname(path))
  175. end
  176. end
  177. end
  178. def re_cols
  179. for i in 0..4
  180. @mwin.lstfiles.resizeColumnToContents(i)
  181. end
  182. end
  183. def preview bool
  184. return if !ok?
  185. @quren.workd=@mwin.txtpath.text
  186. @quren.langf="langs/#{@mwin.combolang.currentText}.xml"
  187. @quren.ext=@mwin.comboext.currentText
  188. @quren.sep=@mwin.txtsep.text
  189. if bool
  190. prev=@quren.do_ren(true)
  191. return if !@quren.ok?
  192. statusBar.showMessage(tr("Preview...."))
  193. @mwin.action_Edit_Tags.enabled=false
  194. @mwin.action_rename.enabled=false
  195. @mwin.lstfiles.clear
  196. @mwin.lstfiles.setColumnHidden 2,false
  197. @mwin.lstfiles.setColumnHidden 3,false
  198. @mwin.lstfiles.setColumnHidden 0,true
  199. @mwin.lstfiles.setColumnHidden 1,true
  200. prev.each do |key,value|
  201. item=Qt::TreeWidgetItem.new(@mwin.lstfiles)
  202. item.setText 2,key
  203. item.setText 3,value
  204. end
  205. re_cols
  206. else
  207. @mwin.action_Edit_Tags.enabled=true
  208. @mwin.action_rename.enabled=true
  209. @mwin.lstfiles.setColumnHidden 2,true
  210. @mwin.lstfiles.setColumnHidden 3,true
  211. @mwin.lstfiles.setColumnHidden 0,false
  212. @mwin.lstfiles.setColumnHidden 1,false
  213. load_files!
  214. end
  215. end
  216. def update_preview(index)
  217. if @mwin.action_Preview.checked
  218. preview(true)
  219. end
  220. end
  221. def view_file_name
  222. item=@mwin.lstfiles.currentItem
  223. return if item.nil?
  224. if @mwin.lstfiles.isColumnHidden(0)
  225. statusBar.showMessage(item.text(2)+tr(' Will be..... ')+item.text(3))
  226. return
  227. end
  228. statusBar.showMessage(File.join(@mwin.txtpath.text,item.text(1))) if item.text(1)
  229. end
  230. def rename
  231. stop_fs_watch do
  232. return if !ok?
  233. @quren.workd=@mwin.txtpath.text
  234. @quren.langf="langs/#{@mwin.combolang.currentText}.xml"
  235. @quren.ext=@mwin.comboext.currentText
  236. @quren.sep=@mwin.txtsep.text
  237. fcount=@quren.get_files.length
  238. return if !@quren.ok?
  239. @mwin.pb.visible=true
  240. @mwin.pb.maximum=fcount
  241. @quren.do_ren do |i|
  242. Qt::Application.processEvents
  243. @mwin.pb.value=i
  244. end
  245. @mwin.pb.visible=false
  246. load_files!
  247. statusBar.showMessage(tr("Done, #{fcount} file(s) renamed."))
  248. end
  249. end
  250. def lang
  251. @langdialog.exec
  252. load_langs!
  253. if @mwin.action_Preview.checked
  254. preview(true)
  255. end
  256. end
  257. def can_edit_for_all?
  258. @quren.ok?
  259. end
  260. def edit_tags
  261. stop_fs_watch do
  262. @tagdialog=EditTagDialog.new self
  263. item=@mwin.lstfiles.currentItem
  264. return if !ok? or item.nil?
  265. @quren.workd=@mwin.txtpath.text
  266. @quren.langf="langs/#{@mwin.combolang.currentText}.xml"
  267. @quren.ext=@mwin.comboext.currentText
  268. file=item.text(1)
  269. fpath=File.join @quren.workd,file
  270. if @quren.ext.downcase=='mp3' or @quren.ext.downcase=='ogg'
  271. @tagger.file=fpath
  272. @tagger.get!
  273. if !@tagger.vaild?
  274. Qt::MessageBox.critical(self,"Error",
  275. tr("File is invaild or has no tag!"))
  276. return
  277. end
  278. @tagdialog.file=fpath
  279. @tagdialog.clear
  280. @tagdialog.fill_fields!
  281. @tagdialog.exec
  282. else
  283. Qt::MessageBox.information(self,tr("Can't be!"),tr('You can edit tags for ogg and mp3 only!'))
  284. end
  285. if !can_edit_for_all?
  286. Qt::MessageBox.warning(self,tr('Apply for all'),
  287. tr("Can't apply changes for all!, you may rename them first."))
  288. return
  289. end
  290. if @tagdialog.result==Qt::Dialog::Accepted
  291. if @tagdialog.apply_for_all
  292. prog=0
  293. fcount=@quren.get_files.length
  294. @mwin.pb.visible=true
  295. @mwin.pb.maximum=fcount
  296. @quren.get_files.each do |file|
  297. Qt::Application.processEvents
  298. statusBar.showMessage(tr("Saving tags to... #{file}"))
  299. idx=@quren.idx_from_file file
  300. sura=@quren.sura_from_idx @quren.tidx(idx)
  301. sura=idx+" #{@mwin.txtsep.text} "+sura
  302. fpath=File.join @quren.workd,file
  303. @tagger.file=fpath
  304. @tagger.title=sura
  305. @tagger.artist=@tagdialog.shiekh
  306. @tagger.album=@tagdialog.mushaf
  307. @tagger.year=@tagdialog.year
  308. @tagger.comment=@tagdialog.comment
  309. @tagger.cover_image=@tagdialog.cover_image
  310. @tagger.cover_image_desc=@tagdialog.cover_image_desc
  311. @tagger.mimetype=@tagdialog.mimetype
  312. @tagger.set!
  313. prog+=1
  314. @mwin.pb.value=prog
  315. end
  316. statusBar.showMessage(tr("Done, tags saved to #{fcount} file(s)."))
  317. end
  318. end
  319. @mwin.pb.visible=false
  320. end
  321. end
  322. def en_actions bool
  323. if bool
  324. @mwin.action_rename.enabled=true
  325. @mwin.action_Preview.enabled=true
  326. @mwin.action_Edit_Tags.enabled=true
  327. else
  328. @mwin.action_rename.enabled=false
  329. @mwin.action_Preview.enabled=false
  330. @mwin.action_Edit_Tags.enabled=false
  331. end
  332. end
  333. def play
  334. item=@mwin.lstfiles.currentItem
  335. return if item.nil?
  336. file=File.join(@mwin.txtpath.text,item.text(1))
  337. if File.exists?(file)
  338. @player.currentSource=Phonon::MediaSource.new(file)
  339. @player.play
  340. @mwin.action_Play.enabled=false
  341. @mwin.action_Stop.enabled=true
  342. end
  343. end
  344. def stop
  345. if @player.currentSource.fileName
  346. @player.stop
  347. @mwin.action_Play.enabled=true
  348. @mwin.action_Stop.enabled=false
  349. end
  350. end
  351. def about
  352. Qt::MessageBox.about(self,tr("About"),
  353. tr("<b>QuRename</b> <br/>Version: 0.1.9<br/> <br/>License: GPL V2 or Later<br/><br/>
  354. <br/>Repo: <a href='http://bitbucket.org/abom/qurename/'>bitbucket.org/abom/qurename/</a><br/>
  355. <br/>QuRename is a tool to rename the quran files
  356. in one click,instead of renaming them one by one,
  357. for ex: rename 001.mp3 to 001 - Al-Al-Fatiha.mp3...etc,
  358. also it can edit tags for ogg and mp3 file formats.<br/>
  359. <br/>Copyright (c) 2008-2010 Abdelrahman Ghanem (abom)
  360. <br><a href='mailto:abom.jdev@gmail.com'>abom.jdev@gmail.com</a>
  361. <br><br><b>Thanks to:</b><br>Ahmed Youssef (StrikerX)
  362. <a href='mailto:xmonader@gmail.com'>xmonader@gmail.com</a><br>
  363. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;English Sewar Names, and more!"))
  364. end
  365. end