You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1505 lines
51 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3. """Youtubedlg module responsible for the options window. """
  4. from __future__ import unicode_literals
  5. import os
  6. import gettext
  7. import wx
  8. from .version import __version__
  9. from .info import (
  10. __descriptionfull__,
  11. __licensefull__,
  12. __projecturl__,
  13. __appname__,
  14. __author__
  15. )
  16. from .utils import (
  17. TwoWayOrderedDict as twodict,
  18. os_path_exists
  19. )
  20. class OptionsFrame(wx.Frame):
  21. """Youtubedlg options frame class.
  22. Attributes:
  23. FRAME_TITLE (string): Options window title.
  24. *_TAB (string): Constant string with the name of each tab.
  25. Args:
  26. parent (mainframe.MainFrame): Parent class.
  27. """
  28. FRAME_TITLE = _("Options")
  29. GENERAL_TAB = _("General")
  30. VIDEO_TAB = _("Video")
  31. AUDIO_TAB = _("Audio")
  32. PLAYLIST_TAB = _("Playlist")
  33. OUTPUT_TAB = _("Output")
  34. SUBTITLES_TAB = _("Subtitles")
  35. FILESYS_TAB = _("Filesystem")
  36. SHUTDOWN_TAB = _("Shutdown")
  37. AUTH_TAB = _("Authentication")
  38. CONNECTION_TAB = _("Connection")
  39. LOG_TAB = _("Log")
  40. CMD_TAB = _("Commands")
  41. LOCALIZATION_TAB = _("Localization")
  42. def __init__(self, parent):
  43. wx.Frame.__init__(self, parent, title=self.FRAME_TITLE, size=parent.opt_manager.options['opts_win_size'])
  44. self.opt_manager = parent.opt_manager
  45. self.log_manager = parent.log_manager
  46. self.app_icon = parent.app_icon
  47. if self.app_icon is not None:
  48. self.SetIcon(self.app_icon)
  49. self._was_shown = False
  50. # Create GUI
  51. panel = wx.Panel(self)
  52. notebook = wx.Notebook(panel)
  53. # Create Tabs
  54. tab_args = (self, notebook)
  55. self.tabs = (
  56. (GeneralTab(*tab_args), self.GENERAL_TAB),
  57. (VideoTab(*tab_args), self.VIDEO_TAB),
  58. (AudioTab(*tab_args), self.AUDIO_TAB),
  59. (PlaylistTab(*tab_args), self.PLAYLIST_TAB),
  60. (OutputTab(*tab_args), self.OUTPUT_TAB),
  61. (SubtitlesTab(*tab_args), self.SUBTITLES_TAB),
  62. (FilesystemTab(*tab_args), self.FILESYS_TAB),
  63. (ShutdownTab(*tab_args), self.SHUTDOWN_TAB),
  64. (AuthenticationTab(*tab_args), self.AUTH_TAB),
  65. (ConnectionTab(*tab_args), self.CONNECTION_TAB),
  66. (LogTab(*tab_args), self.LOG_TAB),
  67. (CMDTab(*tab_args), self.CMD_TAB),
  68. (LocalizationTab(*tab_args), self.LOCALIZATION_TAB)
  69. )
  70. # Add tabs on notebook
  71. for tab, label in self.tabs:
  72. notebook.AddPage(tab, label)
  73. sizer = wx.BoxSizer()
  74. sizer.Add(notebook, 1, wx.EXPAND)
  75. panel.SetSizer(sizer)
  76. self.Bind(wx.EVT_CLOSE, self._on_close)
  77. self.load_all_options()
  78. def _on_close(self, event):
  79. """Event handler for wx.EVT_CLOSE event.
  80. This method is used to save the options and hide the options window.
  81. """
  82. self.save_all_options()
  83. self.Hide()
  84. def reset(self):
  85. """Resets the default options. """
  86. self.opt_manager.load_default()
  87. self.load_all_options()
  88. def load_all_options(self):
  89. """Load options from optionsmanager.OptionsManager
  90. on each tab. """
  91. for tab, _ in self.tabs:
  92. tab.load_options()
  93. def save_all_options(self):
  94. """Save options back to optionsmanager.OptionsManager
  95. from each tab. """
  96. for tab, _ in self.tabs:
  97. tab.save_options()
  98. def Show(self, *args, **kwargs):
  99. # CenterOnParent can't go to main frame's __init__ as main frame may change
  100. # own position and options frame won't be centered on main frame anymore.
  101. if not self._was_shown:
  102. self._was_shown = True
  103. self.CenterOnParent()
  104. return wx.Frame.Show(self, *args, **kwargs)
  105. class TabPanel(wx.Panel):
  106. """Main tab class from which each tab inherits.
  107. Contains methods to create widgets, load options etc..
  108. Attributes:
  109. Each of this attributes is the Default one. In order to use a
  110. different size you must overwrite the corresponding attribute
  111. on the child object.
  112. CHECKBOX_SIZE (tuple): wx.Checkbox size (width, height). On Windows
  113. we change the height value in order to look the same with Linux.
  114. BUTTONS_SIZE (tuple): wx.Button size (width, height)
  115. TEXTCTRL_SIZE (tuple): wx.TextCtrl size (width, height)
  116. SPINCTRL_SIZE (tuple): wx.SpinCtrl size (width, height)
  117. SIZE_* (int): Constant size number.
  118. Args:
  119. parent (OptionsFrame): The parent of all tabs.
  120. notebook (wx.Notebook): The container for each tab.
  121. """
  122. CHECKBOX_SIZE = (-1, -1)
  123. if os.name == 'nt':
  124. CHECKBOX_SIZE = (-1, 25)
  125. BUTTONS_SIZE = (-1, -1)
  126. TEXTCTRL_SIZE = (-1, -1)
  127. SPINCTRL_SIZE = (70, 20)
  128. SIZE_80 = 80
  129. SIZE_50 = 50
  130. SIZE_40 = 40
  131. SIZE_30 = 30
  132. SIZE_20 = 20
  133. SIZE_15 = 15
  134. SIZE_10 = 10
  135. SIZE_5 = 5
  136. def __init__(self, parent, notebook):
  137. wx.Panel.__init__(self, notebook)
  138. self.opt_manager = parent.opt_manager
  139. self.log_manager = parent.log_manager
  140. self.app_icon = parent.app_icon
  141. self.reset_handler = parent.reset
  142. def create_button(self, label, event_handler=None):
  143. """Creates and returns an wx.Button.
  144. Args:
  145. label (string): wx.Button label.
  146. event_handler (function): Can be any function with one parameter
  147. the event item.
  148. Note:
  149. In order to change the button size you need to overwrite the
  150. BUTTONS_SIZE attribute on the child class.
  151. """
  152. button = wx.Button(self, label=label, size=self.BUTTONS_SIZE)
  153. if event_handler is not None:
  154. button.Bind(wx.EVT_BUTTON, event_handler)
  155. return button
  156. def create_checkbox(self, label, event_handler=None):
  157. """Creates and returns an wx.CheckBox.
  158. Args:
  159. label (string): wx.CheckBox label.
  160. event_handler (function): Can be any function with one parameter
  161. the event item.
  162. Note:
  163. In order to change the checkbox size you need to overwrite the
  164. CHECKBOX_SIZE attribute on the child class.
  165. """
  166. checkbox = wx.CheckBox(self, label=label, size=self.CHECKBOX_SIZE)
  167. if event_handler is not None:
  168. checkbox.Bind(wx.EVT_CHECKBOX, event_handler)
  169. return checkbox
  170. def create_textctrl(self, style=None):
  171. """Creates and returns an wx.TextCtrl.
  172. Args:
  173. style (long): Can be any valid wx.TextCtrl style.
  174. Note:
  175. In order to change the textctrl size you need to overwrite the
  176. TEXTCTRL_SIZE attribute on the child class.
  177. """
  178. if style is None:
  179. textctrl = wx.TextCtrl(self, size=self.TEXTCTRL_SIZE)
  180. else:
  181. textctrl = wx.TextCtrl(self, size=self.TEXTCTRL_SIZE, style=style)
  182. return textctrl
  183. def create_combobox(self, choices, size=(-1, -1), event_handler=None):
  184. """Creates and returns an wx.ComboBox.
  185. Args:
  186. choices (list): List of strings that contains the choices for the
  187. wx.ComboBox widget.
  188. size (tuple): wx.ComboBox size (width, height).
  189. event_handler (function): Can be any function with one parameter
  190. the event item.
  191. """
  192. combobox = wx.ComboBox(self, choices=choices, size=size)
  193. if event_handler is not None:
  194. combobox.Bind(wx.EVT_COMBOBOX, event_handler)
  195. return combobox
  196. def create_dirdialog(self, label, path=''):
  197. """Creates and returns an wx.DirDialog.
  198. Args:
  199. label (string): wx.DirDialog widget title.
  200. """
  201. dlg = wx.DirDialog(self, label, path, wx.DD_CHANGE_DIR)
  202. return dlg
  203. def create_radiobutton(self, label, event_handler=None, style=None):
  204. """Creates and returns an wx.RadioButton.
  205. Args:
  206. label (string): wx.RadioButton label.
  207. event_handler (function): Can be any function with one parameter
  208. the event item.
  209. style (long): Can be any valid wx.RadioButton style.
  210. """
  211. if style is None:
  212. radiobutton = wx.RadioButton(self, label=label)
  213. else:
  214. radiobutton = wx.RadioButton(self, label=label, style=style)
  215. if event_handler is not None:
  216. radiobutton.Bind(wx.EVT_RADIOBUTTON, event_handler)
  217. return radiobutton
  218. def create_spinctrl(self, spin_range=(0, 999)):
  219. """Creates and returns an wx.SpinCtrl.
  220. Args:
  221. spin_range (tuple): wx.SpinCtrl range (min, max).
  222. Note:
  223. In order to change the size of the spinctrl widget you need
  224. to overwrite the SPINCTRL_SIZE attribute on the child class.
  225. """
  226. spinctrl = wx.SpinCtrl(self, size=self.SPINCTRL_SIZE)
  227. spinctrl.SetRange(*spin_range)
  228. return spinctrl
  229. def create_statictext(self, label):
  230. """Creates and returns an wx.StaticText.
  231. Args:
  232. label (string): wx.StaticText label.
  233. """
  234. statictext = wx.StaticText(self, label=label)
  235. return statictext
  236. def create_popup(self, text, title, style):
  237. """Creates an wx.MessageBox.
  238. Args:
  239. text (string): wx.MessageBox message.
  240. title (string): wx.MessageBox title.
  241. style (long): Can be any valid wx.MessageBox style.
  242. """
  243. wx.MessageBox(text, title, style)
  244. def _set_sizer(self):
  245. """Sets the sizer for the current panel.
  246. You need to overwrite this method on the child class in order
  247. to set the panels sizers.
  248. """
  249. pass
  250. def _disable_items(self):
  251. """Disables widgets.
  252. If you want any widgets to be disabled by default you specify
  253. them in this method.
  254. Example:
  255. mybutton.Disable()
  256. """
  257. pass
  258. def _auto_buttons_width(self, *buttons):
  259. """Re-adjust *buttons width so that all the buttons have the same
  260. width and all the labels fit on their buttons. """
  261. max_width = -1
  262. widths = [button.GetSize()[0] for button in buttons]
  263. for current_width in widths:
  264. if current_width > max_width:
  265. max_width = current_width
  266. for button in buttons:
  267. button.SetMinSize((max_width, button.GetSize()[1]))
  268. self.Layout()
  269. def load_options(self):
  270. """Load options from the optionsmanager.OptionsManager object
  271. to the current tab. """
  272. pass
  273. def save_options(self):
  274. """Save options of the current tab back to
  275. optionsmanager.OptionsManager object. """
  276. pass
  277. class LogTab(TabPanel):
  278. """Options frame log tab.
  279. Attributes:
  280. Constant strings for the widgets.
  281. """
  282. ENABLE_LABEL = _("Enable Log")
  283. WRITE_LABEL = _("Write Time")
  284. CLEAR_LABEL = _("Clear Log")
  285. VIEW_LABEL = _("View Log")
  286. PATH_LABEL = _("Path: {0}")
  287. LOGSIZE_LABEL = _("Log Size: {0} Bytes")
  288. RESTART_LABEL = _("Restart")
  289. RESTART_MSG = _("Please restart {0}")
  290. def __init__(self, *args, **kwargs):
  291. super(LogTab, self).__init__(*args, **kwargs)
  292. self.enable_checkbox = self.create_checkbox(self.ENABLE_LABEL, self._on_enable)
  293. self.time_checkbox = self.create_checkbox(self.WRITE_LABEL, self._on_time)
  294. self.clear_button = self.create_button(self.CLEAR_LABEL, self._on_clear)
  295. self.view_button = self.create_button(self.VIEW_LABEL, self._on_view)
  296. self.log_path = self.create_statictext(self.PATH_LABEL.format(self._get_logpath()))
  297. self.log_size = self.create_statictext(self.LOGSIZE_LABEL.format(self._get_logsize()))
  298. self._auto_buttons_width(self.clear_button, self.view_button)
  299. self._set_sizer()
  300. self._disable_items()
  301. def _set_sizer(self):
  302. main_sizer = wx.BoxSizer(wx.VERTICAL)
  303. main_sizer.AddSpacer(self.SIZE_20)
  304. main_sizer.Add(self.enable_checkbox, flag=wx.ALIGN_CENTER_HORIZONTAL)
  305. main_sizer.AddSpacer(self.SIZE_5)
  306. main_sizer.Add(self.time_checkbox, flag=wx.ALIGN_CENTER_HORIZONTAL)
  307. main_sizer.AddSpacer(self.SIZE_15)
  308. buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
  309. buttons_sizer.Add(self.clear_button)
  310. buttons_sizer.AddSpacer(self.SIZE_20)
  311. buttons_sizer.Add(self.view_button)
  312. main_sizer.Add(buttons_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL)
  313. main_sizer.AddSpacer(self.SIZE_20)
  314. main_sizer.Add(self.log_path, flag=wx.ALIGN_CENTER_HORIZONTAL)
  315. main_sizer.AddSpacer(self.SIZE_10)
  316. main_sizer.Add(self.log_size, flag=wx.ALIGN_CENTER_HORIZONTAL)
  317. self.SetSizer(main_sizer)
  318. def _disable_items(self):
  319. if self.log_manager is None:
  320. self.time_checkbox.Disable()
  321. self.clear_button.Disable()
  322. self.view_button.Disable()
  323. self.log_path.Hide()
  324. self.log_size.Hide()
  325. def _get_logpath(self):
  326. """Returns the path to the log file. """
  327. if self.log_manager is None:
  328. return ''
  329. return self.log_manager.log_file
  330. def _get_logsize(self):
  331. """Returns the size(Bytes) of the log file. """
  332. if self.log_manager is None:
  333. return 0
  334. return self.log_manager.log_size()
  335. def _set_logsize(self):
  336. """Updates the self.log_size widget with the current log file size ."""
  337. self.log_size.SetLabel(self.LOGSIZE_LABEL.format(self._get_logsize()))
  338. def _on_time(self, event):
  339. """Event handler for self.time_checkbox. """
  340. self.log_manager.add_time = self.time_checkbox.GetValue()
  341. def _on_enable(self, event):
  342. """Event handler for self.enable_checkbox. """
  343. self.create_popup(self.RESTART_MSG.format(__appname__),
  344. self.RESTART_LABEL,
  345. wx.OK | wx.ICON_INFORMATION)
  346. def _on_clear(self, event):
  347. """Event handler for self.clear_button. """
  348. self.log_manager.clear()
  349. self.log_size.SetLabel(self.LOGSIZE_LABEL.format(self._get_logsize()))
  350. def _on_view(self, event):
  351. """Event handler for self.view_button. """
  352. logger_gui = LogGUI(self)
  353. logger_gui.Show()
  354. logger_gui.load(self.log_manager.log_file)
  355. def load_options(self):
  356. self.enable_checkbox.SetValue(self.opt_manager.options['enable_log'])
  357. self.time_checkbox.SetValue(self.opt_manager.options['log_time'])
  358. self._set_logsize()
  359. def save_options(self):
  360. self.opt_manager.options['enable_log'] = self.enable_checkbox.GetValue()
  361. self.opt_manager.options['log_time'] = self.time_checkbox.GetValue()
  362. class ShutdownTab(TabPanel):
  363. """Options frame shutdown tab.
  364. Attributes:
  365. TEXTCTRL_SIZE (tuple): Overwrites the TEXTCTRL_SIZE attribute of
  366. the TabPanel class.
  367. *_LABEL (string): Constant string label for the widgets.
  368. """
  369. TEXTCTRL_SIZE = (250, 25)
  370. SHUTDOWN_LABEL = _("Shutdown when finished")
  371. SUDO_LABEL = _("SUDO password")
  372. def __init__(self, *args, **kwargs):
  373. super(ShutdownTab, self).__init__(*args, **kwargs)
  374. self.shutdown_checkbox = self.create_checkbox(self.SHUTDOWN_LABEL, self._on_shutdown_check)
  375. self.sudo_text = self.create_statictext(self.SUDO_LABEL)
  376. self.sudo_box = self.create_textctrl(wx.TE_PASSWORD)
  377. self._set_sizer()
  378. self._disable_items()
  379. def _disable_items(self):
  380. if os.name == 'nt':
  381. self.sudo_text.Hide()
  382. self.sudo_box.Hide()
  383. def _set_sizer(self):
  384. main_sizer = wx.BoxSizer(wx.VERTICAL)
  385. main_sizer.AddSpacer(self.SIZE_40)
  386. main_sizer.Add(self.shutdown_checkbox, flag=wx.ALIGN_CENTER_HORIZONTAL)
  387. main_sizer.AddSpacer(self.SIZE_20)
  388. main_sizer.Add(self.sudo_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  389. main_sizer.AddSpacer(self.SIZE_5)
  390. main_sizer.Add(self.sudo_box, flag=wx.ALIGN_CENTER_HORIZONTAL)
  391. self.SetSizer(main_sizer)
  392. def _on_shutdown_check(self, event):
  393. """Event handler for self.shutdown_checkbox. """
  394. self.sudo_box.Enable(self.shutdown_checkbox.GetValue())
  395. def load_options(self):
  396. self.shutdown_checkbox.SetValue(self.opt_manager.options['shutdown'])
  397. self.sudo_box.SetValue(self.opt_manager.options['sudo_password'])
  398. self._on_shutdown_check(None)
  399. def save_options(self):
  400. self.opt_manager.options['shutdown'] = self.shutdown_checkbox.GetValue()
  401. self.opt_manager.options['sudo_password'] = self.sudo_box.GetValue()
  402. class PlaylistTab(TabPanel):
  403. """Options frame playlist tab.
  404. Attributes:
  405. *_LABEL (string): Constant string label for the widgets.
  406. """
  407. START_LABEL = _("Playlist Start")
  408. STOP_LABEL = _("Playlist Stop")
  409. MAX_LABEL = _("Max Downloads")
  410. def __init__(self, *args, **kwargs):
  411. super(PlaylistTab, self).__init__(*args, **kwargs)
  412. self.start_spinctrl = self.create_spinctrl((1, 999))
  413. self.stop_spinctrl = self.create_spinctrl()
  414. self.max_spinctrl = self.create_spinctrl()
  415. self.start_text = self.create_statictext(self.START_LABEL)
  416. self.stop_text = self.create_statictext(self.STOP_LABEL)
  417. self.max_text = self.create_statictext(self.MAX_LABEL)
  418. self._set_sizer()
  419. def _set_sizer(self):
  420. main_sizer = wx.BoxSizer(wx.VERTICAL)
  421. main_sizer.AddSpacer(self.SIZE_20)
  422. main_sizer.Add(self.start_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  423. main_sizer.AddSpacer(self.SIZE_5)
  424. main_sizer.Add(self.start_spinctrl, flag=wx.ALIGN_CENTER_HORIZONTAL)
  425. main_sizer.AddSpacer(self.SIZE_15)
  426. main_sizer.Add(self.stop_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  427. main_sizer.AddSpacer(self.SIZE_5)
  428. main_sizer.Add(self.stop_spinctrl, flag=wx.ALIGN_CENTER_HORIZONTAL)
  429. main_sizer.AddSpacer(self.SIZE_15)
  430. main_sizer.Add(self.max_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  431. main_sizer.AddSpacer(self.SIZE_5)
  432. main_sizer.Add(self.max_spinctrl, flag=wx.ALIGN_CENTER_HORIZONTAL)
  433. self.SetSizer(main_sizer)
  434. def load_options(self):
  435. self.start_spinctrl.SetValue(self.opt_manager.options['playlist_start'])
  436. self.stop_spinctrl.SetValue(self.opt_manager.options['playlist_end'])
  437. self.max_spinctrl.SetValue(self.opt_manager.options['max_downloads'])
  438. def save_options(self):
  439. self.opt_manager.options['playlist_start'] = self.start_spinctrl.GetValue()
  440. self.opt_manager.options['playlist_end'] = self.stop_spinctrl.GetValue()
  441. self.opt_manager.options['max_downloads'] = self.max_spinctrl.GetValue()
  442. class ConnectionTab(TabPanel):
  443. """Options frame connection tab.
  444. Attributes:
  445. SPINCTRL_SIZE (tuple): Overwrites the SPINCTRL_SIZE attribute of
  446. the TabPanel class.
  447. *_LABEL (string): Constant string label for widgets.
  448. """
  449. SPINCTRL_SIZE = (60, -1)
  450. RETRIES_LABEL = _("Retries")
  451. USERAGENT_LABEL = _("User Agent")
  452. REF_LABEL = _("Referer")
  453. PROXY_LABEL = _("Proxy")
  454. def __init__(self, *args, **kwargs):
  455. super(ConnectionTab, self).__init__(*args, **kwargs)
  456. self.retries_spinctrl = self.create_spinctrl((1, 999))
  457. self.useragent_box = self.create_textctrl()
  458. self.referer_box = self.create_textctrl()
  459. self.proxy_box = self.create_textctrl()
  460. self.retries_text = self.create_statictext(self.RETRIES_LABEL)
  461. self.useragent_text = self.create_statictext(self.USERAGENT_LABEL)
  462. self.referer_text = self.create_statictext(self.REF_LABEL)
  463. self.proxy_text = self.create_statictext(self.PROXY_LABEL)
  464. self._set_sizer()
  465. def _set_sizer(self):
  466. main_sizer = wx.BoxSizer(wx.HORIZONTAL)
  467. vertical_sizer = wx.BoxSizer(wx.VERTICAL)
  468. vertical_sizer.AddSpacer(self.SIZE_10)
  469. retries_sizer = wx.BoxSizer(wx.HORIZONTAL)
  470. retries_sizer.Add(self.retries_text)
  471. retries_sizer.AddSpacer(self.SIZE_5)
  472. retries_sizer.Add(self.retries_spinctrl)
  473. vertical_sizer.Add(retries_sizer)
  474. vertical_sizer.AddSpacer(self.SIZE_10)
  475. vertical_sizer.Add(self.useragent_text)
  476. vertical_sizer.AddSpacer(self.SIZE_5)
  477. vertical_sizer.Add(self.useragent_box, flag=wx.EXPAND)
  478. vertical_sizer.AddSpacer(self.SIZE_10)
  479. vertical_sizer.Add(self.referer_text)
  480. vertical_sizer.AddSpacer(self.SIZE_5)
  481. vertical_sizer.Add(self.referer_box, flag=wx.EXPAND)
  482. vertical_sizer.AddSpacer(self.SIZE_10)
  483. vertical_sizer.Add(self.proxy_text)
  484. vertical_sizer.AddSpacer(self.SIZE_5)
  485. vertical_sizer.Add(self.proxy_box, flag=wx.EXPAND)
  486. main_sizer.AddSpacer(self.SIZE_10)
  487. main_sizer.Add(vertical_sizer, 1, flag=wx.RIGHT, border=self.SIZE_40)
  488. self.SetSizer(main_sizer)
  489. def load_options(self):
  490. self.proxy_box.SetValue(self.opt_manager.options['proxy'])
  491. self.referer_box.SetValue(self.opt_manager.options['referer'])
  492. self.retries_spinctrl.SetValue(self.opt_manager.options['retries'])
  493. self.useragent_box.SetValue(self.opt_manager.options['user_agent'])
  494. def save_options(self):
  495. self.opt_manager.options['proxy'] = self.proxy_box.GetValue()
  496. self.opt_manager.options['referer'] = self.referer_box.GetValue()
  497. self.opt_manager.options['retries'] = self.retries_spinctrl.GetValue()
  498. self.opt_manager.options['user_agent'] = self.useragent_box.GetValue()
  499. class AuthenticationTab(TabPanel):
  500. """Options frame authentication tab.
  501. Attributes:
  502. TEXTCTRL_SIZE (tuple): Overwrites the TEXTCTRL_SIZE attribute of the
  503. TabPanel class.
  504. *_LABEL (string): Constant string label for the widgets.
  505. """
  506. TEXTCTRL_SIZE = (250, 25)
  507. USERNAME_LABEL = _("Username")
  508. PASSWORD_LABEL = _("Password")
  509. VIDEOPASS_LABEL = _("Video Password (vimeo, smotri)")
  510. def __init__(self, *args, **kwargs):
  511. super(AuthenticationTab, self).__init__(*args, **kwargs)
  512. self.username_box = self.create_textctrl()
  513. self.password_box = self.create_textctrl(wx.TE_PASSWORD)
  514. self.videopass_box = self.create_textctrl(wx.TE_PASSWORD)
  515. self.username_text = self.create_statictext(self.USERNAME_LABEL)
  516. self.password_text = self.create_statictext(self.PASSWORD_LABEL)
  517. self.videopass_text = self.create_statictext(self.VIDEOPASS_LABEL)
  518. self._set_sizer()
  519. def _set_sizer(self):
  520. main_sizer = wx.BoxSizer(wx.VERTICAL)
  521. main_sizer.AddSpacer(self.SIZE_15)
  522. main_sizer.Add(self.username_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  523. main_sizer.AddSpacer(self.SIZE_5)
  524. main_sizer.Add(self.username_box, flag=wx.ALIGN_CENTER_HORIZONTAL)
  525. main_sizer.AddSpacer(self.SIZE_15)
  526. main_sizer.Add(self.password_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  527. main_sizer.AddSpacer(self.SIZE_5)
  528. main_sizer.Add(self.password_box, flag=wx.ALIGN_CENTER_HORIZONTAL)
  529. main_sizer.AddSpacer(self.SIZE_15)
  530. main_sizer.Add(self.videopass_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  531. main_sizer.AddSpacer(self.SIZE_5)
  532. main_sizer.Add(self.videopass_box, flag=wx.ALIGN_CENTER_HORIZONTAL)
  533. self.SetSizer(main_sizer)
  534. def load_options(self):
  535. self.username_box.SetValue(self.opt_manager.options['username'])
  536. self.password_box.SetValue(self.opt_manager.options['password'])
  537. self.videopass_box.SetValue(self.opt_manager.options['video_password'])
  538. def save_options(self):
  539. self.opt_manager.options['username'] = self.username_box.GetValue()
  540. self.opt_manager.options['password'] = self.password_box.GetValue()
  541. self.opt_manager.options['video_password'] = self.videopass_box.GetValue()
  542. class AudioTab(TabPanel):
  543. """Options frame audio tab.
  544. Attributes:
  545. AUDIO_QUALITY (TwoWayOrderedDict): Contains audio qualities.
  546. AUDIO_FORMATS (list): Contains audio formats.
  547. See optionsmanager.OptionsManager 'audio_format' option
  548. for available values.
  549. *_LABEL (string): Constant string label for the widgets.
  550. """
  551. AUDIO_QUALITY = twodict([("0", _("high")), ("5", _("mid")), ("9", _("low"))])
  552. AUDIO_FORMATS = ["mp3", "wav", "aac", "m4a", "vorbis", "opus"]
  553. TO_AUDIO_LABEL = _("Convert to Audio")
  554. KEEP_VIDEO_LABEL = _("Keep Video")
  555. AUDIO_FORMAT_LABEL = _("Audio Format")
  556. AUDIO_QUALITY_LABEL = _("Audio Quality")
  557. def __init__(self, *args, **kwargs):
  558. super(AudioTab, self).__init__(*args, **kwargs)
  559. self.to_audio_checkbox = self.create_checkbox(self.TO_AUDIO_LABEL, self._on_audio_check)
  560. self.keep_video_checkbox = self.create_checkbox(self.KEEP_VIDEO_LABEL)
  561. self.audioformat_combo = self.create_combobox(self.AUDIO_FORMATS, (160, 30))
  562. self.audioquality_combo = self.create_combobox(self.AUDIO_QUALITY.values(), (100, 25))
  563. self.audioformat_text = self.create_statictext(self.AUDIO_FORMAT_LABEL)
  564. self.audioquality_text = self.create_statictext(self.AUDIO_QUALITY_LABEL)
  565. self._set_sizer()
  566. def _set_sizer(self):
  567. main_sizer = wx.BoxSizer(wx.VERTICAL)
  568. main_sizer.AddSpacer(self.SIZE_15)
  569. main_sizer.Add(self.to_audio_checkbox, flag=wx.ALIGN_CENTER_HORIZONTAL)
  570. main_sizer.AddSpacer(self.SIZE_5)
  571. main_sizer.Add(self.keep_video_checkbox, flag=wx.ALIGN_CENTER_HORIZONTAL)
  572. main_sizer.AddSpacer(self.SIZE_10)
  573. main_sizer.Add(self.audioformat_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  574. main_sizer.AddSpacer(self.SIZE_5)
  575. main_sizer.Add(self.audioformat_combo, flag=wx.ALIGN_CENTER_HORIZONTAL)
  576. main_sizer.AddSpacer(self.SIZE_10)
  577. main_sizer.Add(self.audioquality_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  578. main_sizer.AddSpacer(self.SIZE_5)
  579. main_sizer.Add(self.audioquality_combo, flag=wx.ALIGN_CENTER_HORIZONTAL)
  580. self.SetSizer(main_sizer)
  581. def _on_audio_check(self, event):
  582. """Event handler for self.to_audio_checkbox. """
  583. self.audioformat_combo.Enable(self.to_audio_checkbox.GetValue())
  584. self.audioquality_combo.Enable(self.to_audio_checkbox.GetValue())
  585. def load_options(self):
  586. self.to_audio_checkbox.SetValue(self.opt_manager.options['to_audio'])
  587. self.keep_video_checkbox.SetValue(self.opt_manager.options['keep_video'])
  588. self.audioformat_combo.SetValue(self.opt_manager.options['audio_format'])
  589. self.audioquality_combo.SetValue(self.AUDIO_QUALITY[self.opt_manager.options['audio_quality']])
  590. self._on_audio_check(None)
  591. def save_options(self):
  592. self.opt_manager.options['to_audio'] = self.to_audio_checkbox.GetValue()
  593. self.opt_manager.options['keep_video'] = self.keep_video_checkbox.GetValue()
  594. self.opt_manager.options['audio_format'] = self.audioformat_combo.GetValue()
  595. self.opt_manager.options['audio_quality'] = self.AUDIO_QUALITY[self.audioquality_combo.GetValue()]
  596. class VideoTab(TabPanel):
  597. """Options frame video tab.
  598. Attributes:
  599. FORMATS (TwoWayOrderedDict): Contains video formats. This list
  600. contains all the available video formats without the 'default'
  601. and 'none' options.
  602. VIDEO_FORMATS (list): List that contains all the video formats
  603. plus the 'default' one.
  604. SECOND_VIDEO_FORMATS (list): List that contains all the video formats
  605. plus the 'none' one.
  606. COMBOBOX_SIZE (tuple): Overwrites the COMBOBOX_SIZE attribute of the
  607. TabPanel class.
  608. *_LABEL (string): Constant string label for the widgets.
  609. """
  610. FORMATS = twodict([
  611. ("17", "3gp [176x144]"),
  612. ("36", "3gp [320x240]"),
  613. ("5", "flv [400x240]"),
  614. ("34", "flv [640x360]"),
  615. ("35", "flv [854x480]"),
  616. ("43", "webm [640x360]"),
  617. ("44", "webm [854x480]"),
  618. ("45", "webm [1280x720]"),
  619. ("46", "webm [1920x1080]"),
  620. ("18", "mp4 [640x360]"),
  621. ("22", "mp4 [1280x720]"),
  622. ("37", "mp4 [1920x1080]"),
  623. ("38", "mp4 [4096x3072]"),
  624. ("160", "mp4 144p (DASH)"),
  625. ("133", "mp4 240p (DASH)"),
  626. ("134", "mp4 360p (DASH)"),
  627. ("135", "mp4 480p (DASH)"),
  628. ("136", "mp4 720p (DASH)"),
  629. ("137", "mp4 1080p (DASH)"),
  630. ("264", "mp4 1440p (DASH)"),
  631. ("138", "mp4 2160p (DASH)"),
  632. ("242", "webm 240p (DASH)"),
  633. ("243", "webm 360p (DASH)"),
  634. ("244", "webm 480p (DASH)"),
  635. ("247", "webm 720p (DASH)"),
  636. ("248", "webm 1080p (DASH)"),
  637. ("271", "webm 1440p (DASH)"),
  638. ("272", "webm 2160p (DASH)"),
  639. ("82", "mp4 360p (3D)"),
  640. ("83", "mp4 480p (3D)"),
  641. ("84", "mp4 720p (3D)"),
  642. ("85", "mp4 1080p (3D)"),
  643. ("100", "webm 360p (3D)"),
  644. ("101", "webm 480p (3D)"),
  645. ("102", "webm 720p (3D)"),
  646. ("139", "m4a 48k (DASH AUDIO)"),
  647. ("140", "m4a 128k (DASH AUDIO)"),
  648. ("141", "m4a 256k (DASH AUDIO)"),
  649. ("171", "webm 48k (DASH AUDIO)"),
  650. ("172", "webm 256k (DASH AUDIO)")
  651. ])
  652. VIDEO_FORMATS = [_("default")] + FORMATS.values()
  653. SECOND_VIDEO_FORMATS = [_("none")] + FORMATS.values()
  654. COMBOBOX_SIZE = (200, 30)
  655. VIDEO_FORMAT_LABEL = _("Video Format")
  656. SEC_VIDEOFORMAT_LABEL = _("Mix Format")
  657. def __init__(self, *args, **kwargs):
  658. super(VideoTab, self).__init__(*args, **kwargs)
  659. self.videoformat_combo = self.create_combobox(self.VIDEO_FORMATS,
  660. self.COMBOBOX_SIZE,
  661. self._on_videoformat)
  662. self.sec_videoformat_combo = self.create_combobox(self.SECOND_VIDEO_FORMATS,
  663. self.COMBOBOX_SIZE)
  664. self.videoformat_text = self.create_statictext(self.VIDEO_FORMAT_LABEL)
  665. self.sec_videoformat_text = self.create_statictext(self.SEC_VIDEOFORMAT_LABEL)
  666. self._set_sizer()
  667. def _set_sizer(self):
  668. main_sizer = wx.BoxSizer(wx.VERTICAL)
  669. main_sizer.AddSpacer(self.SIZE_30)
  670. main_sizer.Add(self.videoformat_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  671. main_sizer.AddSpacer(self.SIZE_5)
  672. main_sizer.Add(self.videoformat_combo, flag=wx.ALIGN_CENTER_HORIZONTAL)
  673. main_sizer.AddSpacer(self.SIZE_10)
  674. main_sizer.Add(self.sec_videoformat_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  675. main_sizer.AddSpacer(self.SIZE_5)
  676. main_sizer.Add(self.sec_videoformat_combo, flag=wx.ALIGN_CENTER_HORIZONTAL)
  677. self.SetSizer(main_sizer)
  678. def _on_videoformat(self, event):
  679. """Event handler for self.videoformat_combo. """
  680. condition = (self.videoformat_combo.GetValue() != self.VIDEO_FORMATS[0])
  681. self.sec_videoformat_combo.Enable(condition)
  682. def load_options(self):
  683. self.videoformat_combo.SetValue(self.FORMATS.get(self.opt_manager.options['video_format'], self.VIDEO_FORMATS[0]))
  684. self.sec_videoformat_combo.SetValue(self.FORMATS.get(self.opt_manager.options['second_video_format'], self.SECOND_VIDEO_FORMATS[0]))
  685. self._on_videoformat(None)
  686. def save_options(self):
  687. self.opt_manager.options['video_format'] = self.FORMATS.get(self.videoformat_combo.GetValue(), '0')
  688. self.opt_manager.options['second_video_format'] = self.FORMATS.get(self.sec_videoformat_combo.GetValue(), '0')
  689. class OutputTab(TabPanel):
  690. """Options frame output tab.
  691. Attributes:
  692. TEXTCTRL_SIZE (tuple): Overwrites the TEXTCTRL_SIZE attribute of
  693. the TabPanel class.
  694. * (string): Constant string label for the widgets.
  695. """
  696. TEXTCTRL_SIZE = (300, 20)
  697. RESTRICT_LABEL = _("Restrict filenames (ASCII)")
  698. ID_AS_NAME = _("ID as Name")
  699. TITLE_AS_NAME = _("Title as Name")
  700. CUST_TITLE = _("Custom Template (youtube-dl)")
  701. def __init__(self, *args, **kwargs):
  702. super(OutputTab, self).__init__(*args, **kwargs)
  703. self.res_names_checkbox = self.create_checkbox(self.RESTRICT_LABEL)
  704. self.id_rbtn = self.create_radiobutton(self.ID_AS_NAME, self._on_pick, wx.RB_GROUP)
  705. self.title_rbtn = self.create_radiobutton(self.TITLE_AS_NAME, self._on_pick)
  706. self.custom_rbtn = self.create_radiobutton(self.CUST_TITLE, self._on_pick)
  707. self.title_template = self.create_textctrl()
  708. self._set_sizer()
  709. def _set_sizer(self):
  710. main_sizer = wx.BoxSizer(wx.HORIZONTAL)
  711. vertical_sizer = wx.BoxSizer(wx.VERTICAL)
  712. vertical_sizer.AddSpacer(self.SIZE_15)
  713. vertical_sizer.Add(self.res_names_checkbox)
  714. vertical_sizer.AddSpacer(self.SIZE_5)
  715. vertical_sizer.Add(self.id_rbtn)
  716. vertical_sizer.AddSpacer(self.SIZE_5)
  717. vertical_sizer.Add(self.title_rbtn)
  718. vertical_sizer.AddSpacer(self.SIZE_5)
  719. vertical_sizer.Add(self.custom_rbtn)
  720. vertical_sizer.AddSpacer(self.SIZE_10)
  721. vertical_sizer.Add(self.title_template)
  722. main_sizer.Add(vertical_sizer, flag=wx.LEFT, border=self.SIZE_5)
  723. self.SetSizer(main_sizer)
  724. def _on_pick(self, event):
  725. """Event handler for the radiobuttons. """
  726. self.title_template.Enable(self.custom_rbtn.GetValue())
  727. def _get_output_format(self):
  728. """Returns output_format string type base on the radiobuttons.
  729. See optionsmanager.OptionsManager 'output_format' option for more
  730. informations.
  731. """
  732. if self.id_rbtn.GetValue():
  733. return 'id'
  734. elif self.title_rbtn.GetValue():
  735. return 'title'
  736. elif self.custom_rbtn.GetValue():
  737. return 'custom'
  738. def _set_output_format(self, output_format):
  739. """Enables the corresponding radiobutton base on the output_format. """
  740. if output_format == 'id':
  741. self.id_rbtn.SetValue(True)
  742. elif output_format == 'title':
  743. self.title_rbtn.SetValue(True)
  744. elif output_format == 'custom':
  745. self.custom_rbtn.SetValue(True)
  746. def load_options(self):
  747. self._set_output_format(self.opt_manager.options['output_format'])
  748. self.title_template.SetValue(self.opt_manager.options['output_template'])
  749. self.res_names_checkbox.SetValue(self.opt_manager.options['restrict_filenames'])
  750. self._on_pick(None)
  751. def save_options(self):
  752. self.opt_manager.options['output_format'] = self._get_output_format()
  753. self.opt_manager.options['output_template'] = self.title_template.GetValue()
  754. self.opt_manager.options['restrict_filenames'] = self.res_names_checkbox.GetValue()
  755. class FilesystemTab(TabPanel):
  756. """Options frame filesystem tab.
  757. Attributes:
  758. FILESIZES (TwoWayOrderedDict): Contains filesize units.
  759. *_LABEL (string): Constant string label for the widgets.
  760. """
  761. FILESIZES = twodict([
  762. ("", "Bytes"),
  763. ("k", "Kilobytes"),
  764. ("m", "Megabytes"),
  765. ("g", "Gigabytes"),
  766. ("t", "Terabytes"),
  767. ("p", "Petabytes"),
  768. ("e", "Exabytes"),
  769. ("z", "Zettabytes"),
  770. ("y", "Yottabytes")
  771. ])
  772. IGN_ERR_LABEL = _("Ignore Errors")
  773. OPEN_DIR_LABEL = _("Open destination folder")
  774. WRT_INFO_LABEL = _("Write info to (.json) file")
  775. WRT_DESC_LABEL = _("Write description to file")
  776. WRT_THMB_LABEL = _("Write thumbnail to disk")
  777. FILESIZE_LABEL = _("Filesize")
  778. MIN_LABEL = _("Min")
  779. MAX_LABEL = _("Max")
  780. def __init__(self, *args, **kwargs):
  781. super(FilesystemTab, self).__init__(*args, **kwargs)
  782. self.ign_err_checkbox = self.create_checkbox(self.IGN_ERR_LABEL)
  783. self.open_dir_checkbox = self.create_checkbox(self.OPEN_DIR_LABEL)
  784. self.write_info_checkbox = self.create_checkbox(self.WRT_INFO_LABEL)
  785. self.write_desc_checkbox = self.create_checkbox(self.WRT_DESC_LABEL)
  786. self.write_thumbnail_checkbox = self.create_checkbox(self.WRT_THMB_LABEL)
  787. self.min_filesize_spinner = self.create_spinctrl((0, 1024))
  788. self.max_filesize_spinner = self.create_spinctrl((0, 1024))
  789. self.min_filesize_combo = self.create_combobox(self.FILESIZES.values())
  790. self.max_filesize_combo = self.create_combobox(self.FILESIZES.values())
  791. self.min_text = self.create_statictext(self.MIN_LABEL)
  792. self.max_text = self.create_statictext(self.MAX_LABEL)
  793. self._set_sizer()
  794. def _set_sizer(self):
  795. main_sizer = wx.BoxSizer(wx.HORIZONTAL)
  796. main_sizer.Add(self._set_left_sizer(), 1, wx.LEFT, border=self.SIZE_5)
  797. main_sizer.Add(self._set_right_sizer(), 1, wx.EXPAND)
  798. self.SetSizer(main_sizer)
  799. def _set_left_sizer(self):
  800. """Sets and returns the left BoxSizer. """
  801. sizer = wx.BoxSizer(wx.VERTICAL)
  802. sizer.AddSpacer(self.SIZE_15)
  803. sizer.Add(self.ign_err_checkbox)
  804. sizer.AddSpacer(self.SIZE_5)
  805. sizer.Add(self.open_dir_checkbox)
  806. sizer.AddSpacer(self.SIZE_5)
  807. sizer.Add(self.write_desc_checkbox)
  808. sizer.AddSpacer(self.SIZE_5)
  809. sizer.Add(self.write_thumbnail_checkbox)
  810. sizer.AddSpacer(self.SIZE_5)
  811. sizer.Add(self.write_info_checkbox)
  812. return sizer
  813. def _set_right_sizer(self):
  814. """Sets and returns the right BoxSizer. """
  815. static_box = wx.StaticBox(self, label=self.FILESIZE_LABEL)
  816. sizer = wx.StaticBoxSizer(static_box, wx.VERTICAL)
  817. sizer.AddSpacer(self.SIZE_20)
  818. sizer.Add(self.min_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  819. sizer.AddSpacer(self.SIZE_5)
  820. hor_sizer = wx.BoxSizer(wx.HORIZONTAL)
  821. hor_sizer.Add(self.min_filesize_spinner)
  822. hor_sizer.AddSpacer(self.SIZE_10)
  823. hor_sizer.Add(self.min_filesize_combo)
  824. sizer.Add(hor_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL)
  825. sizer.AddSpacer(self.SIZE_10)
  826. sizer.Add(self.max_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  827. sizer.AddSpacer(self.SIZE_5)
  828. hor_sizer = wx.BoxSizer(wx.HORIZONTAL)
  829. hor_sizer.Add(self.max_filesize_spinner)
  830. hor_sizer.AddSpacer(self.SIZE_10)
  831. hor_sizer.Add(self.max_filesize_combo)
  832. sizer.Add(hor_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL)
  833. return sizer
  834. def load_options(self):
  835. self.open_dir_checkbox.SetValue(self.opt_manager.options['open_dl_dir'])
  836. self.write_info_checkbox.SetValue(self.opt_manager.options['write_info'])
  837. self.ign_err_checkbox.SetValue(self.opt_manager.options['ignore_errors'])
  838. self.write_desc_checkbox.SetValue(self.opt_manager.options['write_description'])
  839. self.write_thumbnail_checkbox.SetValue(self.opt_manager.options['write_thumbnail'])
  840. self.min_filesize_spinner.SetValue(self.opt_manager.options['min_filesize'])
  841. self.max_filesize_spinner.SetValue(self.opt_manager.options['max_filesize'])
  842. self.min_filesize_combo.SetValue(self.FILESIZES[self.opt_manager.options['min_filesize_unit']])
  843. self.max_filesize_combo.SetValue(self.FILESIZES[self.opt_manager.options['max_filesize_unit']])
  844. def save_options(self):
  845. self.opt_manager.options['write_thumbnail'] = self.write_thumbnail_checkbox.GetValue()
  846. self.opt_manager.options['write_description'] = self.write_desc_checkbox.GetValue()
  847. self.opt_manager.options['ignore_errors'] = self.ign_err_checkbox.GetValue()
  848. self.opt_manager.options['write_info'] = self.write_info_checkbox.GetValue()
  849. self.opt_manager.options['open_dl_dir'] = self.open_dir_checkbox.GetValue()
  850. self.opt_manager.options['min_filesize'] = self.min_filesize_spinner.GetValue()
  851. self.opt_manager.options['max_filesize'] = self.max_filesize_spinner.GetValue()
  852. self.opt_manager.options['min_filesize_unit'] = self.FILESIZES[self.min_filesize_combo.GetValue()]
  853. self.opt_manager.options['max_filesize_unit'] = self.FILESIZES[self.max_filesize_combo.GetValue()]
  854. class SubtitlesTab(TabPanel):
  855. """Options frame subtitles tab.
  856. Attributes:
  857. SUBS_LANG (TwoWayOrderedDict): Contains subtitles languages.
  858. *_LABEL (string): Constant string label for the widgets.
  859. """
  860. SUBS_LANG = twodict([
  861. ("en", _("English")),
  862. ("gr", _("Greek")),
  863. ("pt", _("Portuguese")),
  864. ("fr", _("French")),
  865. ("it", _("Italian")),
  866. ("ru", _("Russian")),
  867. ("es", _("Spanish")),
  868. ("tr", _("Turkish")),
  869. ("de", _("German"))
  870. ])
  871. DL_SUBS_LABEL = _("Download subtitle file by language")
  872. DL_ALL_SUBS_LABEL = _("Download all available subtitles")
  873. DL_AUTO_SUBS_LABEL = _("Download automatic subtitle file (YOUTUBE ONLY)")
  874. EMBED_SUBS_LABEL = _("Embed subtitles in the video (only mp4 videos)")
  875. SUBS_LANG_LABEL = _("Subtitles Language")
  876. def __init__(self, *args, **kwargs):
  877. super(SubtitlesTab, self).__init__(*args, **kwargs)
  878. self.write_subs_checkbox = self.create_checkbox(self.DL_SUBS_LABEL, self._on_subs_pick)
  879. self.write_all_subs_checkbox = self.create_checkbox(self.DL_ALL_SUBS_LABEL, self._on_subs_pick)
  880. self.write_auto_subs_checkbox = self.create_checkbox(self.DL_AUTO_SUBS_LABEL, self._on_subs_pick)
  881. self.embed_subs_checkbox = self.create_checkbox(self.EMBED_SUBS_LABEL)
  882. self.subs_lang_combo = self.create_combobox(self.SUBS_LANG.values(), (140, 30))
  883. self.subs_lang_text = self.create_statictext(self.SUBS_LANG_LABEL)
  884. self._set_sizer()
  885. self._disable_items()
  886. def _disable_items(self):
  887. self.embed_subs_checkbox.Disable()
  888. self.subs_lang_combo.Disable()
  889. def _set_sizer(self):
  890. main_sizer = wx.BoxSizer(wx.HORIZONTAL)
  891. vertical_sizer = wx.BoxSizer(wx.VERTICAL)
  892. vertical_sizer.AddSpacer(self.SIZE_15)
  893. vertical_sizer.Add(self.write_subs_checkbox)
  894. vertical_sizer.AddSpacer(self.SIZE_5)
  895. vertical_sizer.Add(self.write_all_subs_checkbox)
  896. vertical_sizer.AddSpacer(self.SIZE_5)
  897. vertical_sizer.Add(self.write_auto_subs_checkbox)
  898. vertical_sizer.AddSpacer(self.SIZE_5)
  899. vertical_sizer.Add(self.embed_subs_checkbox)
  900. vertical_sizer.AddSpacer(self.SIZE_10)
  901. vertical_sizer.Add(self.subs_lang_text, flag=wx.LEFT, border=self.SIZE_5)
  902. vertical_sizer.AddSpacer(self.SIZE_5)
  903. vertical_sizer.Add(self.subs_lang_combo, flag=wx.LEFT, border=self.SIZE_10)
  904. main_sizer.Add(vertical_sizer, flag=wx.LEFT, border=self.SIZE_5)
  905. self.SetSizer(main_sizer)
  906. def _on_subs_pick(self, event):
  907. """Event handler for the write_subs checkboxes. """
  908. if self.write_subs_checkbox.GetValue():
  909. self.write_all_subs_checkbox.Disable()
  910. self.write_auto_subs_checkbox.Disable()
  911. self.embed_subs_checkbox.Enable()
  912. self.subs_lang_combo.Enable()
  913. elif self.write_all_subs_checkbox.GetValue():
  914. self.write_subs_checkbox.Disable()
  915. self.write_auto_subs_checkbox.Disable()
  916. elif self.write_auto_subs_checkbox.GetValue():
  917. self.write_subs_checkbox.Disable()
  918. self.write_all_subs_checkbox.Disable()
  919. self.embed_subs_checkbox.Enable()
  920. else:
  921. self.embed_subs_checkbox.Disable()
  922. self.embed_subs_checkbox.SetValue(False)
  923. self.subs_lang_combo.Disable()
  924. self.write_subs_checkbox.Enable()
  925. self.write_all_subs_checkbox.Enable()
  926. self.write_auto_subs_checkbox.Enable()
  927. def load_options(self):
  928. self.subs_lang_combo.SetValue(self.SUBS_LANG[self.opt_manager.options['subs_lang']])
  929. self.write_subs_checkbox.SetValue(self.opt_manager.options['write_subs'])
  930. self.embed_subs_checkbox.SetValue(self.opt_manager.options['embed_subs'])
  931. self.write_all_subs_checkbox.SetValue(self.opt_manager.options['write_all_subs'])
  932. self.write_auto_subs_checkbox.SetValue(self.opt_manager.options['write_auto_subs'])
  933. self._on_subs_pick(None)
  934. def save_options(self):
  935. self.opt_manager.options['subs_lang'] = self.SUBS_LANG[self.subs_lang_combo.GetValue()]
  936. self.opt_manager.options['write_subs'] = self.write_subs_checkbox.GetValue()
  937. self.opt_manager.options['embed_subs'] = self.embed_subs_checkbox.GetValue()
  938. self.opt_manager.options['write_all_subs'] = self.write_all_subs_checkbox.GetValue()
  939. self.opt_manager.options['write_auto_subs'] = self.write_auto_subs_checkbox.GetValue()
  940. class GeneralTab(TabPanel):
  941. """Options frame general tab.
  942. Attributes:
  943. BUTTONS_SIZE (tuple): Overwrites the BUTTONS_SIZE attribute of the
  944. TabPanel class.
  945. *_LABEL (string): Constant string label for the widgets.
  946. """
  947. BUTTONS_SIZE = (110, 35)
  948. ABOUT_LABEL = _("About")
  949. OPEN_LABEL = _("Open")
  950. RESET_LABEL = _("Reset Options")
  951. SAVEPATH_LABEL = _("Save Path")
  952. SETTINGS_DIR_LABEL = _("Settings File: {0}")
  953. PICK_DIR_LABEL = _("Choose Directory")
  954. def __init__(self, *args, **kwargs):
  955. super(GeneralTab, self).__init__(*args, **kwargs)
  956. self.savepath_box = self.create_textctrl()
  957. self.about_button = self.create_button(self.ABOUT_LABEL, self._on_about)
  958. self.open_button = self.create_button(self.OPEN_LABEL, self._on_open)
  959. self.reset_button = self.create_button(self.RESET_LABEL, self._on_reset)
  960. self.savepath_text = self.create_statictext(self.SAVEPATH_LABEL)
  961. cfg_file = self.SETTINGS_DIR_LABEL.format(self.opt_manager.settings_file)
  962. self.cfg_file_dir = self.create_statictext(cfg_file)
  963. self._set_sizer()
  964. def _set_sizer(self):
  965. main_sizer = wx.BoxSizer(wx.VERTICAL)
  966. main_sizer.AddSpacer(self.SIZE_20)
  967. main_sizer.Add(self.savepath_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  968. main_sizer.AddSpacer(self.SIZE_10)
  969. savepath_sizer = wx.BoxSizer(wx.HORIZONTAL)
  970. savepath_sizer.Add(self.savepath_box, 1, wx.LEFT | wx.RIGHT, self.SIZE_80)
  971. main_sizer.Add(savepath_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
  972. main_sizer.AddSpacer(self.SIZE_20)
  973. buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
  974. buttons_sizer.Add(self.about_button)
  975. buttons_sizer.Add(self.open_button, flag=wx.LEFT | wx.RIGHT, border=self.SIZE_50)
  976. buttons_sizer.Add(self.reset_button)
  977. main_sizer.Add(buttons_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL)
  978. main_sizer.AddSpacer(self.SIZE_20)
  979. main_sizer.Add(self.cfg_file_dir, flag=wx.ALIGN_CENTER_HORIZONTAL)
  980. self.SetSizer(main_sizer)
  981. def _on_reset(self, event):
  982. """Event handler of the self.reset_button. """
  983. self.reset_handler()
  984. def _on_open(self, event):
  985. """Event handler of the self.open_button. """
  986. dlg = self.create_dirdialog(self.PICK_DIR_LABEL, self.savepath_box.GetValue())
  987. if dlg.ShowModal() == wx.ID_OK:
  988. self.savepath_box.SetValue(dlg.GetPath())
  989. dlg.Destroy()
  990. def _on_about(self, event):
  991. """Event handler of the self.about_button. """
  992. info = wx.AboutDialogInfo()
  993. if self.app_icon is not None:
  994. info.SetIcon(self.app_icon)
  995. info.SetName(__appname__)
  996. info.SetVersion(__version__)
  997. info.SetDescription(__descriptionfull__)
  998. info.SetWebSite(__projecturl__)
  999. info.SetLicense(__licensefull__)
  1000. info.AddDeveloper(__author__)
  1001. wx.AboutBox(info)
  1002. def load_options(self):
  1003. self.savepath_box.SetValue(self.opt_manager.options['save_path'])
  1004. def save_options(self):
  1005. self.opt_manager.options['save_path'] = self.savepath_box.GetValue()
  1006. class CMDTab(TabPanel):
  1007. """Options frame command tab.
  1008. Attributes:
  1009. CMD_LABEL (string): Constant string label for the widgets.
  1010. """
  1011. CMD_LABEL = _("Command line arguments (e.g. --help)")
  1012. def __init__(self, *args, **kwargs):
  1013. super(CMDTab, self).__init__(*args, **kwargs)
  1014. self.cmd_args_box = self.create_textctrl()
  1015. self.cmd_args_text = self.create_statictext(self.CMD_LABEL)
  1016. self._set_sizer()
  1017. def _set_sizer(self):
  1018. main_sizer = wx.BoxSizer(wx.VERTICAL)
  1019. main_sizer.AddSpacer(self.SIZE_50)
  1020. main_sizer.Add(self.cmd_args_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  1021. main_sizer.AddSpacer(self.SIZE_10)
  1022. cmdbox_sizer = wx.BoxSizer(wx.HORIZONTAL)
  1023. cmdbox_sizer.Add(self.cmd_args_box, 1, wx.LEFT | wx.RIGHT, border=self.SIZE_80)
  1024. main_sizer.Add(cmdbox_sizer, flag=wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
  1025. self.SetSizer(main_sizer)
  1026. def load_options(self):
  1027. self.cmd_args_box.SetValue(self.opt_manager.options['cmd_args'])
  1028. def save_options(self):
  1029. self.opt_manager.options['cmd_args'] = self.cmd_args_box.GetValue()
  1030. class LocalizationTab(TabPanel):
  1031. """Options frame localization tab.
  1032. Attributes:
  1033. COMBOBOX_SIZE (tuple): Tuple that contains the size(width, height)
  1034. of the combobox widget.
  1035. LOCALE_NAMES (TwoWayOrderedDict): Stores the locale names.
  1036. *_LABEL (string): Constant string label for the widgets.
  1037. """
  1038. COMBOBOX_SIZE = (150, 30)
  1039. LOCALE_NAMES = twodict([
  1040. ('ar_AR', 'Arabic'),
  1041. ('cs_CZ', 'Czech'),
  1042. ('en_US', 'English'),
  1043. ('fr_FR', 'French'),
  1044. ('de_DE', 'German'),
  1045. ('it_IT', 'Italian'),
  1046. ('he_IS', 'Hebrew'),
  1047. ('hu_HU', 'Hungarian'),
  1048. ('pt_BR', 'Portuguese'),
  1049. ('ru_RU', 'Russian'),
  1050. ('es_ES', 'Spanish'),
  1051. ('es_MX', 'Mexican Spanish'),
  1052. ('tr_TR', 'Turkish')
  1053. ])
  1054. RESTART_LABEL = _("Restart")
  1055. LOCALE_LABEL = _("Localization Language")
  1056. RESTART_MSG = _("In order for the changes to take effect please restart {0}")
  1057. def __init__(self, *args, **kwargs):
  1058. super(LocalizationTab, self).__init__(*args, **kwargs)
  1059. self.locale_text = self.create_statictext(self.LOCALE_LABEL)
  1060. self.locale_box = self.create_combobox(self.LOCALE_NAMES.values(), self.COMBOBOX_SIZE, self._on_locale)
  1061. self._set_sizer()
  1062. def _set_sizer(self):
  1063. main_sizer = wx.BoxSizer(wx.VERTICAL)
  1064. main_sizer.AddSpacer(self.SIZE_50)
  1065. main_sizer.Add(self.locale_text, flag=wx.ALIGN_CENTER_HORIZONTAL)
  1066. main_sizer.AddSpacer(self.SIZE_10)
  1067. main_sizer.Add(self.locale_box, flag=wx.ALIGN_CENTER_HORIZONTAL)
  1068. self.SetSizer(main_sizer)
  1069. def _on_locale(self, event):
  1070. """Event handler for the self.locale_box widget. """
  1071. self.create_popup(self.RESTART_MSG.format(__appname__),
  1072. self.RESTART_LABEL,
  1073. wx.OK | wx.ICON_INFORMATION)
  1074. def load_options(self):
  1075. self.locale_box.SetValue(self.LOCALE_NAMES[self.opt_manager.options['locale_name']])
  1076. def save_options(self):
  1077. self.opt_manager.options['locale_name'] = self.LOCALE_NAMES[self.locale_box.GetValue()]
  1078. class LogGUI(wx.Frame):
  1079. """Simple window for reading the STDERR.
  1080. Attributes:
  1081. TITLE (string): Frame title.
  1082. FRAME_SIZE (tuple): Tuple that holds the frame size (width, height).
  1083. Args:
  1084. parent (wx.Window): Frame parent.
  1085. """
  1086. TITLE = _("Log Viewer")
  1087. FRAME_SIZE = (650, 200)
  1088. def __init__(self, parent=None):
  1089. wx.Frame.__init__(self, parent, title=self.TITLE, size=self.FRAME_SIZE)
  1090. panel = wx.Panel(self)
  1091. self._text_area = wx.TextCtrl(
  1092. panel,
  1093. style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL
  1094. )
  1095. sizer = wx.BoxSizer()
  1096. sizer.Add(self._text_area, 1, wx.EXPAND)
  1097. panel.SetSizerAndFit(sizer)
  1098. def load(self, filename):
  1099. """Load file content on the text area. """
  1100. if os_path_exists(filename):
  1101. self._text_area.LoadFile(filename)