lvcgui.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. from sikuli.Sikuli import *
  2. import devices
  3. import config
  4. import time
  5. class MVCGui(object):
  6. # ** APP UI IMAGES **
  7. # ADD FILES
  8. _INITIAL_DROP_ZONE = 'fresh_start_dropzone.png'
  9. _CHOOSE_FILES = 'choose_a_file.png'
  10. _DROP_ZONE = 'file_drop_zone.png'
  11. _CONVERSIONS_FINISHED = 'conversions_finished.png'
  12. # BIG BOTTOM BUTTONS
  13. _START_CONVERSION = 'convert_now.png'
  14. _STOP_CONVERSION = 'stop_all.png'
  15. _RESET = 'clear_and_start_over.png'
  16. # INDIVIDUAL FILE OPTIONS
  17. # processing
  18. _IN_PROGRESS = 'progress_bar.png'
  19. _DELETE_FILE = 'delete_icon.png'
  20. _CLEAR_FINISHED = 'clear_finished.png'
  21. _CONVERSION_COMPLETE = 'completed.png'
  22. _CONVERSION_FAILED = 'failed.png'
  23. _PAUSE = 'pause_button.png'
  24. _RESUME = 'resume_button.png'
  25. _QUEUED = 'queued.png'
  26. _ERROR = 'error_icon.png'
  27. _SHOW_FILE = 'show_file.png'
  28. # CONVERSION OPTIONS SECTION
  29. _SEND_ITUNES = 'send_to_itunes.png'
  30. _APPLE_MENU = 'apple_dropdown.png'
  31. _ANDROID_MENU = 'android_dropdown.png'
  32. _OTHER_MENU = 'other_dropdown.png'
  33. _CUSTOM_MENU = 'custom_menu.png'
  34. # CUSTOM MENU OPTIONS
  35. _PREFS_CHECKBOX_CHECKED = 'checkbox_checked.png'
  36. _PREFS_CHECKBOX_UNCHECKED = 'checkbox_unchecked.png'
  37. _SAVE_TO_OPTION = 'save_to_pulldown.png'
  38. _OUTPUT_DIRECTORY = 'default_dir_selected.png'
  39. _SAVE_TO_DEFAULT = 'save_to_default_selected.png'
  40. _CONVERT_TO_OPTION = 'convert_to_menu.png'
  41. _CUSTOM_SIZE = 'custom_size.png'
  42. _WIDTH = 'custom_width.png'
  43. _HEIGHT = 'custom_height.png'
  44. _UPSIZE = 'dont_upsize'
  45. _ASPECT = 'custom_aspect.png'
  46. _ASPECT_43 = '43_aspect.png'
  47. _ASPECT_32 = '32_aspect.png'
  48. _ASPECT_169 = '169_aspect.png'
  49. # SELECTED CONVERSION OPTION
  50. _APPLE_SELECTED = 'apple_selected.png'
  51. _ANDROID_SELECTED = 'android_selected.png'
  52. # SYSTEM UI
  53. _SYS_TEXT_ENTRY_BUTTON = 'type_a_filename.png'
  54. # TEST IMAGES for VERIFICATION
  55. _custom_size_test = '150x175size.png'
  56. def __init__(self):
  57. '''
  58. Constructor
  59. '''
  60. config.set_image_dirs()
  61. self.os_name = config.get_os_name()
  62. # CMD or CTRL Key
  63. if self.os_name == 'osx':
  64. self.CMDCTRL = Key.CMD
  65. else:
  66. self.CMDCTRL = Key.CTRL
  67. def lvc_focus(self):
  68. App.focus("Libre Video Converter")
  69. def lvc_quit(self):
  70. App.close("Libre Video Converter")
  71. def item_region(self, item):
  72. find(item)
  73. reg = Region.getLastMatch()
  74. item_reg = Region(reg.x - 30, reg.y - 30, 400, 50)
  75. return(item_reg)
  76. def choose_directory(self, dirname):
  77. self.type_a_path(dirname)
  78. def type_a_path(self, dirname):
  79. if config.get_os_name() == "win":
  80. if not exists("Location", 5):
  81. click(self.SYS_TEXT_ENTRY_BUTTON)
  82. time.sleep(2)
  83. type(dirname + "\n")
  84. type(Key.ENTER)
  85. def browse_for_files(self, dirname, testdata):
  86. click(Pattern(self._CHOOSE_FILES))
  87. # osx freaks out if you start typing too fast
  88. time.sleep(2)
  89. self.type_a_path(dirname)
  90. keyDown(self.CMDCTRL)
  91. for f in testdata:
  92. click(f)
  93. keyUp(self.CMDCTRL)
  94. def add_directory_of_files(self, dirname):
  95. click(self._CHOOSE_FILES)
  96. self.choose_directory(dirname)
  97. type(Key.ENTER)
  98. def drag_and_drop_files(self, dirname, testdata):
  99. click(self._CHOOSE_FILES)
  100. # y is drop destination
  101. y = getLastMatch()
  102. type(dirname)
  103. type(Key.ENTER)
  104. keyDown(self.CMDCTRL)
  105. for f in testdata:
  106. find(f)
  107. # the drag start is the last file we find and select
  108. x = getLastMatch()
  109. click(getLastMatch())
  110. dragDrop(x, y)
  111. keyUp(self.CMDCTRL)
  112. # close the file browser dialog
  113. type(Key.ESC)
  114. def remove_files(self, *items):
  115. for item in items:
  116. r = self.item_region(item)
  117. r.click(self._DELETE_FILE)
  118. assert r.waitVanish(item)
  119. def start_conversions(self):
  120. click(self._START_CONVERSION)
  121. def stop_conversions(self):
  122. click(self._STOP_CONVERSION)
  123. def clear_and_start_over(self):
  124. click(self._RESET)
  125. def pause_conversions(self, *items):
  126. for item in items:
  127. r = self.item_region(item)
  128. r.click(self._PAUSE)
  129. assert r.exists(self._RESUME)
  130. def clear_finished_files(self, items, wait=30):
  131. """Clears out the completed individual conversions.
  132. """
  133. for item in items:
  134. r = self.item_region(item)
  135. r.exists(self._CLEAR_FINISHED, wait)
  136. click(r.getLastMatch())
  137. assert waitVanish(item, 2)
  138. def show_file(self, item):
  139. for item in items:
  140. r = self.item_region(item)
  141. r.click(self._SHOW_FILE)
  142. # FIXME Verify the file is there and close the window
  143. def choose_device_conversion(self, device):
  144. device_group = devices.dev_attr(device, 'group')
  145. menu_img = getattr(self, "".join(["_",device_group.upper(),"_","MENU"]))
  146. click(menu_img)
  147. click(device)
  148. def open_custom_menu(self):
  149. if not exists(self._OUTPUT_DIRECTORY):
  150. click(self._CUSTOM_MENU)
  151. def choose_save_location(self, location='default'):
  152. self.open_custom_menu()
  153. if location == 'default' and not exists(self._SAVE_TO_DEFAULT):
  154. click(self._SAVE_TO_OPTION)
  155. click(self._SAVE_TO_DEFAULT)
  156. else:
  157. click(self._SAVE_TO_OPTION)
  158. self.choose_directory(location)
  159. def set_pref_checkbox(self, option, setting):
  160. """Check or uncheck the box for a preference setting.
  161. Valid values are ['on' and 'off']
  162. """
  163. valid_settings = ['on', 'off']
  164. if setting not in valid_settings:
  165. print("valid setting value not proviced, must be 'on' or 'off'")
  166. # CHECK THE BOX
  167. pref_image = getattr(self, "".join(["_",option]))
  168. find(pref_image)
  169. reg = Region(getLastMatch())
  170. # location of associated checkbox
  171. box = Region(reg.getX()-15, sr_loc.getY()-10, pref_reg.getW(), 30)
  172. if setting == "off":
  173. if box.exists(self._PREFS_CHECKBOX_CHECKED):
  174. click(box.getLastMatch())
  175. if setting == "on":
  176. if box.exists(self._PREFS_CHECKBOX_NOT_CHECKED):
  177. click(box.getLastMatch())
  178. def choose_custom_size(self, setting, width=None, height=None):
  179. self.open_custom_menu(self)
  180. if not width or not height:
  181. setting = 'off'
  182. self.set_pref_checkbox(self._CUSTOM_SIZE, setting)
  183. if setting == 'on':
  184. type(Key.TAB)
  185. type(width)
  186. type(Key.TAB)
  187. type(height)
  188. def choose_dont_upsize(self, setting):
  189. self.open_custom_menu(self)
  190. self.set_pref_checkbox(self._UPSIZE, setting)
  191. def choose_aspect_ratio(self, setting, ratio=None):
  192. self.open_custom_menu(self)
  193. if ratio is None:
  194. setting = 'off'
  195. self.set_pref_checkbox(self._ASPECT, setting)
  196. if setting == 'on':
  197. ratio_img = getattr(self, "".join(["_", "ASPECT", ratio]))
  198. click(ratio_img)
  199. def choose_format(self, output):
  200. self.open_custom_menu(self)
  201. mouseMove(self._CONVERT_TO_OPTION.right(30))
  202. mouseDown(Button.LEFT)
  203. mouseMove(output)
  204. mouseUp(Button.LEFT)
  205. def choose_itunes(self, setting):
  206. self.set_pref_checkbox(self._SEND_ITUNES, setting)
  207. def remove_queued_conversions(self):
  208. while exists(self._QUEUED):
  209. qreg = Region(getLastMatch())
  210. q_item = Region(reg.getX()+30, sr_loc.getY()-20, 500, 30)
  211. q_item.click(self._DELETE_FILE)
  212. def verify_device_format_selected(self, device):
  213. device_group = devices.dev_attr(device, 'group')
  214. if device_group == 'Format':
  215. if exists(device):
  216. return True
  217. else:
  218. # all devices are mp4 by default
  219. if exists(device) and exists("MP4"):
  220. return True
  221. def verify_size(self, item, width, height):
  222. self.show_ffmpeg_output(item)
  223. expected_size_parameter = "-s "+width+"x"+height
  224. type(self.CMDCTRL, 'f')
  225. type('-s '+width+'x'+'height')
  226. # copy the ffmpeg size command to the clipboard
  227. type(self.CMDCTRL, 'c')
  228. size_param = Env.getClipboard()
  229. if size_param == expected_size_parameter:
  230. return True
  231. def verify_device_size_default(self, width, height):
  232. self.open_custom_menu()
  233. self.set_pref_checkbox(self._CUSTOM_SIZE, setting)
  234. click('Width')
  235. type(self.CMDCTRL)
  236. displayed_width = Env.getClipboard()
  237. click('Height')
  238. type(self.CMDCTRL)
  239. displayed_height = Env.getClipboard()
  240. if displayed_height == height and displayed_width == width:
  241. return True
  242. def verify_converting(self, item):
  243. r = self.item_region(item)
  244. if r.exists(self._IN_PROGRESS):
  245. return True
  246. def verify_paused(self, item):
  247. r = self.item_region(item)
  248. if r.exists(self._RESUME):
  249. return True
  250. def verify_completed(self, item, wait=10):
  251. """Verify an individual conversion has completed.
  252. """
  253. r = self.item_region(item)
  254. if r.exists(self._CONVERSION_COMPLETE, wait):
  255. return True
  256. def verify_completed_removed(self):
  257. if not exists(self._CONVERSION_COMPLETE):
  258. return True
  259. def verify_conversions_finished(self):
  260. """This verifies the entire group of conversions are complete.
  261. """
  262. if exists(self._CONVERSIONS_FINISHED):
  263. return True
  264. def verify_failed(self, item, wait=20):
  265. r = self.item_region(item)
  266. try:
  267. r.exists(self._CONVERSION_FAILED, wait)
  268. return True
  269. except:
  270. return False
  271. def verify_failed_removed(self):
  272. if not exists(self._CONVERSION_FAILED):
  273. return True
  274. def verify_file_in_list(self, item):
  275. r = self.item_region(item)
  276. if r.exists(item):
  277. return True
  278. def verify_file_not_in_list(self, item):
  279. if not exists(item):
  280. return True
  281. def verify_queued(self, item):
  282. r = self.item_region(item)
  283. if r.exists(self._QUEUED):
  284. return True
  285. def verify_in_progress(self, item=None):
  286. if item:
  287. r = self.item_region(item)
  288. if r.exists(self._IN_PROGRESS): return True
  289. else:
  290. if exists(self._IN_PROGRESS): return True
  291. def verify_itunes(self, item):
  292. pass
  293. def verify_output_dir(self, item, directory):
  294. r = self.item_region(item)
  295. r.click(self._SHOW_FILE)
  296. type(Key.ESC)
  297. # FIXME need to get what the output name is going to be.
  298. output_file = os.path.join(directory, item)
  299. if os.path.isfile(output_file):
  300. return True
  301. def show_ffmpeg_output(self, item):
  302. r = self.item_region(item)
  303. self.verify_completed(item, 30)
  304. r.click(self._SHOW_FFMPEG)
  305. if exists("STARTING CONVERSION"):
  306. return True