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.

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