class Test_Xml_Writing(unittest.TestCase): def setUp(self): self.pm = Profile_Manager("No Profile", "newganmanager/testing/") self.pm.prf_cfg["img_dir"] = "newganmanager/test/" self.data = [ ["African", "African1", "1915714540"], ["Caucasian", "Caucasian2", "1915576430"] ] self.xml_data = self.pm.write_xml(self.data) def test_write_xml_template_string_formatting(self): for xml_player, player in zip(self.xml_data, self.data): self.assertEqual("<record from=\""+player[1]+"/"+player[2]+"\" to=\"graphics/pictures/person/"+player[0]+"/portrait\"/>", xml_player) def test_write_xml_players_mapped_in_file(self): with open(self.pm.prf_cfg['img_dir']+"config.xml", 'r', encoding="UTF-8") as fp: xml_file = fp.read() for player in self.data: self.assertIn("<record from=\""+player[1]+"/"+player[2]+"\" to=\"graphics/pictures/person/"+player[0]+"/portrait\"/>", xml_file) def test_write_xml_no_file_endings(self): with open(self.pm.prf_cfg['img_dir']+"config.xml", 'r', encoding="UTF-8") as fp: xml_file = fp.read() self.assertNotIn(".png", xml_file) def tearDown(self): shutil.rmtree("newganmanager/testing/.config/") shutil.copytree("newganmanager/.config/", "newganmanager/testing/.config/") shutil.rmtree("newganmanager/testing/.user/") shutil.copytree("newganmanager/.user/", "newganmanager/testing/.user/") with open("newganmanager/test/config.xml", "w") as cfg: cfg.write('OUTSIDE')
class Test_Mapper_Overwrite_Mapping(unittest.TestCase): def setUp(self): # TODO: we need prf_map, prf_imgs and prf_eth_map self.rtfparser = RTF_Parser() shutil.copyfile("newganmanager/.user/default_cfg.json", "newganmanager/testing/.user/cfg.json") self.pm = Profile_Manager("No Profile", "newganmanager/testing") self.mapper = Mapper("newganmanager/test/", self.pm) self.pm.prf_cfg["img_dir"] = "newganmanager/test/" # data: UID, first_nat, sec_nat, eth-code self.data_simple = self.rtfparser.parse_rtf( "newganmanager/test/test_simple.rtf") self.data_all_cases = self.rtfparser.parse_rtf( "newganmanager/test/test_allcases.rtf") self.data_subset1 = self.rtfparser.parse_rtf( "newganmanager/test/allcases_subset1.rtf") self.data_subset2 = self.rtfparser.parse_rtf( "newganmanager/test/allcases_subset2.rtf") self.data_exclusive = self.rtfparser.parse_rtf( "newganmanager/test/test_exclusive.rtf") for eth in [ "African", "Asian", "EECA", "Italmed", "SAMed", "South American", "SpanMed", "YugoGreek", "MENA", "MESA", "Caucasian", "Central European", "Scandinavian", "Seasian" ]: map = [eth + str(i) for i in range(20)] self.mapper.eth_map[eth] = set(map) def tearDown(self): shutil.rmtree("newganmanager/testing/.config/") shutil.copytree("newganmanager/.config/", "newganmanager/testing/.config/") shutil.rmtree("newganmanager/testing/.user/") shutil.copytree("newganmanager/.user/", "newganmanager/testing/.user/") with open("newganmanager/test/config.xml", "w") as cfg: cfg.write('OUTSIDE') def test_overwrite_mapping_simple(self): mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.assertEqual("SpanMed", mapping[0][1]) self.assertEqual("1915714540", mapping[0][0]) self.assertEqual("MESA", mapping[1][1]) self.assertEqual("1915576430", mapping[1][0]) def test_overwrite_mapping_all_cases(self): mapping = self.mapper.generate_mapping(self.data_all_cases, "Overwrite") self.assertEqual("SpanMed", mapping[0][1]) self.assertEqual("1915714540", mapping[0][0]) self.assertEqual("MESA", mapping[1][1]) self.assertEqual("1915576430", mapping[1][0]) self.assertEqual("Italmed", mapping[2][1]) self.assertEqual("1915576432", mapping[2][0]) self.assertEqual("EECA", mapping[3][1]) self.assertEqual("1915576433", mapping[3][0]) self.assertEqual("SAMed", mapping[4][1]) self.assertEqual("1915576434", mapping[4][0]) self.assertEqual("South American", mapping[5][1]) self.assertEqual("1915576435", mapping[5][0]) self.assertEqual("YugoGreek", mapping[6][1]) self.assertEqual("1915576436", mapping[6][0]) self.assertEqual("African", mapping[7][1]) self.assertEqual("1915576437", mapping[7][0]) self.assertEqual("African", mapping[8][1]) self.assertEqual("1915576438", mapping[8][0]) self.assertEqual("African", mapping[9][1]) self.assertEqual("1915576439", mapping[9][0]) self.assertEqual("African", mapping[10][1]) self.assertEqual("1915576440", mapping[10][0]) self.assertEqual("African", mapping[11][1]) self.assertEqual("1915576441", mapping[11][0]) self.assertEqual("Asian", mapping[12][1]) self.assertEqual("1915576442", mapping[12][0]) self.assertEqual("MENA", mapping[13][1]) self.assertEqual("1915576444", mapping[13][0]) self.assertEqual("Seasian", mapping[14][1]) self.assertEqual("1915576445", mapping[14][0]) self.assertEqual("Scandinavian", mapping[15][1]) self.assertEqual("1915576446", mapping[15][0]) self.assertEqual("Caucasian", mapping[16][1]) self.assertEqual("1915576447", mapping[16][0]) self.assertEqual("Central European", mapping[17][1]) self.assertEqual("1915576448", mapping[17][0]) self.assertEqual("MESA", mapping[18][1]) self.assertEqual("1915576450", mapping[18][0]) def test_overwrite_mapping_double(self): simple_mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.pm.write_xml(simple_mapping) next_mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.pm.write_xml(next_mapping) self.assertNotEqual(simple_mapping, next_mapping) def test_overwrite_mapping_double_exclusive(self): simple_mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.pm.write_xml(simple_mapping) next_mapping = self.mapper.generate_mapping(self.data_exclusive, "Overwrite") self.pm.write_xml(next_mapping) self.assertEqual(simple_mapping, next_mapping[2:]) self.assertEqual(len(next_mapping), 4) def test_overwrite_mapping_complete_subset(self): simple_mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.pm.write_xml(simple_mapping) next_mapping = self.mapper.generate_mapping(self.data_all_cases, "Overwrite") self.pm.write_xml(next_mapping) self.assertNotEqual(simple_mapping, next_mapping[:2]) def test_overwrite_mapping_complete_subset_reverse(self): next_mapping = self.mapper.generate_mapping(self.data_all_cases, "Overwrite") self.pm.write_xml(next_mapping) simple_mapping = self.mapper.generate_mapping(self.data_simple, "Overwrite") self.pm.write_xml(simple_mapping) self.assertNotEqual(simple_mapping, next_mapping[:2]) self.assertEqual(next_mapping[2:], simple_mapping[2:]) def test_overwrite_mapping_partial_subset(self): sub2_mapping = self.mapper.generate_mapping(self.data_subset2, "Overwrite") self.pm.write_xml(sub2_mapping) sub1_mapping = self.mapper.generate_mapping(self.data_subset1, "Overwrite") self.pm.write_xml(sub1_mapping) self.assertNotEqual(sub1_mapping[:5], sub2_mapping[:5]) self.assertIn(sub2_mapping[5], sub1_mapping) self.assertIn(sub2_mapping[6], sub1_mapping) self.assertIn(sub2_mapping[7], sub1_mapping) self.assertIn(sub2_mapping[8], sub1_mapping) self.assertIn(sub2_mapping[9], sub1_mapping) self.assertEqual(len(sub1_mapping), 12) def test_overwrite_mapping_partial_subset_reverse(self): sub1_mapping = self.mapper.generate_mapping(self.data_subset1, "Overwrite") self.pm.write_xml(sub1_mapping) sub2_mapping = self.mapper.generate_mapping(self.data_subset2, "Overwrite") self.pm.write_xml(sub2_mapping) self.assertNotEqual(sub1_mapping[:5], sub2_mapping[:5]) self.assertEqual(len(sub2_mapping), 12)
class NewGANManager(toga.App): def __init__(self, log): super().__init__() self.logger = log def startup(self): """ Construct and show the Toga application. Usually, you would add your application to a main content box. We then create a main window (with a name matching the app), and show the main window. """ self.logger.info( "Starting Application\n------------------------------------------------" ) self.logger.info(str(self.paths.app)) self.facepack_dirs = set([ "African", "Asian", "Caucasian", "Central European", "EECA", "Italmed", "MENA", "MESA", "SAMed", "Scandinavian", "Seasian", "South American", "SpanMed", "YugoGreek" ]) self.mode_info = { "Overwrite": "Overwrites already replaced faces", "Preserve": "Preserves already replaced faces", "Generate": "Generates mapping from scratch." } os.makedirs(str(self.paths.app) + "/.config", exist_ok=True) if not os.path.isfile(str(self.paths.app) + "/.user/cfg.json"): shutil.copyfile( str(self.paths.app) + "/.user/default_cfg.json", str(self.paths.app) + "/.user/cfg.json") self.logger.info("Loading current profile") self.profile_manager = Profile_Manager( Config_Manager().get_latest_prf( str(self.paths.app) + "/.user/cfg.json"), str(self.paths.app)) self.profile_manager.migrate_config() self.logger.info("Creating GUI") self.main_box = toga.Box() self.logger.info("Created main box") self.hook = "https://discord.com/api/webhooks/796137178328989768/ETMNtPVb-PHuZPayC5G5MZD24tdDi5jmG6jAgjZXg0FDOXjy-VIabATXPco05qLIr4ro" # CREATE MENUBAR troubleshooting = toga.Command( lambda e=None, u= "https://github.com/Maradonna90/NewGAN-Manager/wiki/Troubleshooting": self.open_link(u), label='Troubleshooting', group=toga.Group.HELP, section=1) usage = toga.Command( lambda e=None, u="https://www.youtube.com/watch?v=iJqZNp0nomM": self.open_link(u), label='User Guide', group=toga.Group.HELP, section=0) faq = toga.Command( lambda e=None, u= "https://github.com/Maradonna90/NewGAN-Manager/wiki/FAQ": self. open_link(u), label='FAQ', group=toga.Group.HELP, section=2) discord = toga.Command( lambda e=None, u="https://discord.gg/UfRpJVc": self.open_link(u), label='Discord', group=toga.Group.HELP, section=3) self.commands.add(discord, faq, troubleshooting, usage) label_width = 125 # TOP Profiles prf_box = toga.Box() self.logger.info("Created prf_box") prf_inp = toga.TextInput() self.logger.info("Created prf_inp") self.prfsel_box = toga.Box() prf_lab = toga.Label(text="Create Profile: ") prf_lab.style.update(width=label_width) prfsel_lab = toga.Label(text="Select Profile: ") prfsel_lab.style.update(width=label_width) self.prfsel_lst = SourceSelection(items=list( self.profile_manager.config["Profile"].keys()), on_select=self._set_profile_status) self.prfsel_lst.value = self.profile_manager.cur_prf prfsel_btn = toga.Button( label="Delete", on_press=lambda e=None, c=self.prfsel_lst: self._delete_profile(c)) prf_btn = toga.Button(label="Create", on_press=lambda e=None, d=prf_inp, c=self. prfsel_lst: self._create_profile(d, c)) self.main_box.add(prf_box) prf_box.add(prf_lab) prf_box.add(prf_inp) prf_box.add(prf_btn) prf_lab.style.update(padding_top=7) prf_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.main_box.add(self.prfsel_box) self.prfsel_box.add(prfsel_lab) self.prfsel_box.add(self.prfsel_lst) self.prfsel_box.add(prfsel_btn) self.prfsel_lst.style.update(direction=ROW, padding=(0, 20), flex=1) prfsel_lab.style.update(padding_top=7) # MID Path selections dir_box = toga.Box() dir_lab = toga.Label(text="Select Image Directory: ") dir_lab.style.update(width=label_width) self.dir_inp = toga.TextInput( readonly=True, initial=self.profile_manager.prf_cfg['img_dir']) self.dir_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.dir_btn = toga.Button(label="...", on_press=self.action_select_folder_dialog, enabled=False) rtf_box = toga.Box() rtf_lab = toga.Label(text="RTF File: ") rtf_lab.style.update(width=label_width) self.rtf_inp = toga.TextInput( readonly=True, initial=self.profile_manager.prf_cfg['rtf']) self.rtf_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.rtf_btn = toga.Button(label="...", on_press=self.action_open_file_dialog, enabled=False) self.main_box.add(dir_box) self.main_box.add(rtf_box) dir_box.add(dir_lab) dir_box.add(self.dir_inp) dir_box.add(self.dir_btn) rtf_box.add(rtf_lab) rtf_box.add(self.rtf_inp) rtf_box.add(self.rtf_btn) dir_lab.style.update(padding_top=7) rtf_lab.style.update(padding_top=7) gen_mode_box = toga.Box() self.genmde_lab = toga.Label(text="Mode: ") self.genmde_lab.style.update(width=label_width) self.genmdeinfo_lab = toga.Label(text=self.mode_info["Generate"]) self.gendup = toga.Switch(label="Allow Duplicates?") self.genmde_lst = SourceSelection(items=list(self.mode_info.keys()), on_select=self.update_label) self.genmde_lst.value = "Generate" self.genmde_lst.style.update(direction=ROW, padding=(0, 20), flex=1) self.genmde_lab.style.update(padding_top=7) self.genmdeinfo_lab.style.update(padding_top=7) self.gendup.style.update(padding_top=7, padding_left=20) gen_mode_box.add(self.genmde_lab) gen_mode_box.add(self.genmde_lst) gen_mode_box.add(self.genmdeinfo_lab) gen_mode_box.add(self.gendup) self.main_box.add(gen_mode_box) # BOTTOM Generation gen_box = toga.Box() self.gen_btn = toga.Button(label="Replace Faces", on_press=self._replace_faces, enabled=False) self.gen_btn.style.update(padding_bottom=20) self.gen_lab = toga.Label(text="") # self.gen_prg = toga.ProgressBar(max=110) self.gen_prg = Progressbar(label=self.gen_lab) gen_box.add(self.gen_btn) gen_box.add(self.gen_lab) gen_box.add(self.gen_prg) self.main_box.add(gen_box) self.gen_prg.style.update(width=570, alignment="center") self.gen_lab.style.update(padding_top=20, padding_bottom=20, width=100, alignment="center") # Report bad image rep_box = toga.Box() self.rep_lab = toga.Label(text="Player UID: ") self.rep_lab.style.update(width=label_width) self.rep_inp = toga.TextInput(on_change=self.change_image) self.rep_img = toga.ImageView(toga.Image("resources/logo.png")) self.rep_img.style.update(height=180) self.rep_img.style.update(width=180) self.rep_btn = toga.Button(label="Report", on_press=self.send_report, enabled=False) rep_box.add(self.rep_lab) rep_box.add(self.rep_inp) rep_box.add(self.rep_img) rep_box.add(self.rep_btn) self.main_box.add(rep_box) self.rep_lab.style.update(padding_top=10) self.rep_inp.style.update(direction=ROW, padding=(0, 20), flex=1) # END config self.prfsel_box.style.update(padding_bottom=20) dir_box.style.update(padding_bottom=20) prf_box.style.update(padding_bottom=20) rtf_box.style.update(padding_bottom=20) gen_mode_box.style.update(padding_bottom=20) rep_box.style.update(padding_top=20) gen_box.style.update(direction=COLUMN, alignment='center') self.main_box.style.update(direction=COLUMN, padding=30, alignment='center') self.main_window = toga.MainWindow(title=self.formal_name, size=(1000, 600)) self.main_window.content = self.main_box self.main_window.show() self.check_for_update() def open_link(self, url): webbrowser.open(url) def update_label(self, widget): self.logger.info("Updating generation label") self.genmdeinfo_lab.text = self.mode_info[widget.value] def set_btns(self, value): if self.profile_manager.cur_prf == "No Profile": self.gen_btn.enabled = False self.dir_btn.enabled = False self.rtf_btn.enabled = False self.rep_btn.enabled = False else: self.gen_btn.enabled = value self.dir_btn.enabled = value self.rtf_btn.enabled = value self.rep_btn.enabled = value def _set_profile_status(self, e): self.logger.info("switch profile: {}".format(e.value)) if e.value is None: self.logger.info("catch none {}".format( self.profile_manager.cur_prf)) elif e.value == self.profile_manager.cur_prf: self.logger.info("catch same values") else: name = e.value self.profile_manager.load_profile(name) self._refresh_inp() self.set_btns(True) Config_Manager().save_config( str(self.paths.app) + "/.user/cfg.json", self.profile_manager.config) def _refresh_inp(self, clear=False): self.logger.info("Refresh Input Buttons") if clear: self.dir_inp.clear() self.rtf_inp.clear() else: self.dir_inp.value = self.profile_manager.prf_cfg['img_dir'] self.rtf_inp.value = self.profile_manager.prf_cfg['rtf'] def _create_profile(self, ent, c): name = ent.value self.profile_manager.create_profile(name) ent.clear() c.add_item(name) def _delete_profile(self, c): prf = c.value self.profile_manager.delete_profile(prf) c.remove_item(prf) self._refresh_inp(True) self.set_btns(False) def _throw_error(self, msg): self.logger.info("Error window {}:".format(msg)) self.main_window.error_dialog('Error', msg) def _show_info(self, msg): self.logger.info("Info window: {}".format(msg)) self.main_window.info_dialog("Info", msg) def action_select_folder_dialog(self, widget): self.logger.info("Select Folder...") try: path_names = self.main_window.select_folder_dialog( title="Select image root folder") self.dir_inp.value = path_names[0] + "/" self.profile_manager.prf_cfg['img_dir'] = path_names[0] + "/" Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) except Exception: pass def action_open_file_dialog(self, widget): self.logger.info("Select File...") try: fname = self.main_window.open_file_dialog(title="Open RTF file", multiselect=False, file_types=['rtf']) self.logger.info("Created file-dialog") if fname is not None: fname = str(fname) self.rtf_inp.value = fname self.profile_manager.prf_cfg['rtf'] = fname self.logger.info("RTF file: " + fname) Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) else: self.profile_manager.prf_cfg['rtf'] = "" self.rtf_inp.value = "" Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) except Exception: self.logger.error("Fatal error in main loop", exc_info=True) pass def _replace_faces(self, widget): self.logger.info("Start Replace Faces") # get values from UI elements rtf = self.profile_manager.prf_cfg['rtf'] img_dir = self.profile_manager.prf_cfg['img_dir'] profile = self.profile_manager.cur_prf mode = self.genmde_lst.value if not os.path.isfile(rtf): self._throw_error("The RTF file doesn't exist!") self.gen_prg.stop() self.profile_manager.prf_cfg['rtf'] = '' return if not os.path.isdir(img_dir): self._throw_error("The image directory doesn't exist!") self.gen_prg.stop() self.profile_manager.prf_cfg['img_dir'] = '' return # Check if valid image_directory contains all the needed subfolders img_dirs = set() for entry in os.scandir(img_dir): if entry.is_dir(): img_dirs.add(entry.name) for fp_dir in self.facepack_dirs: if fp_dir not in img_dirs: self._throw_error( "Folder {} is missing in the image directory".format( fp_dir)) self.gen_prg.stop() return self.logger.info("rtf: {}".format(rtf)) self.logger.info("img_dir: {}".format(img_dir)) self.logger.info("profile: {}".format(profile)) self.logger.info("mode: {}".format(mode)) self.set_btns(False) self.gen_prg.start() self.gen_prg.update_label("Parsing RTF") # yield 0.1 rtf_parser = RTF_Parser() if not rtf_parser.is_rtf_valid(rtf): self._throw_error("The RTF file is invalid!") self.gen_prg.stop() return rtf_data = rtf_parser.parse_rtf(rtf) self.gen_prg.update_progress(20) self.gen_prg.update_label("Map player to ethnicity") # yield 0.1 mapping_data = Mapper(img_dir, self.profile_manager).generate_mapping( rtf_data, mode, self.gendup.is_on) self.gen_prg.update_progress(60) self.gen_prg.update_label("Generate config.xml") # yield 0.1 self.profile_manager.write_xml(mapping_data) # save profile metadata (used pics and config.xml) self.gen_prg.update_label("Save metadata for profile") self.gen_prg.update_progress(10) # yield 0.1 Config_Manager().save_config( str(self.paths.app) + "/.user/" + profile + ".json", self.profile_manager.prf_cfg) self.gen_prg.update_progress(10) # yield 0.1 self.gen_prg.update_label("Finished! :)") # yield 0.1 self._show_info("Finished! :)") self.gen_prg.stop() self.set_btns(True) def change_image(self, id): self.logger.info("try to change image preview") uid = id.value if len(uid) >= 7: try: img_path = XML_Parser().get_imgpath_from_uid( self.profile_manager.prf_cfg['img_dir'] + "config.xml", uid) img_path = self.profile_manager.prf_cfg[ 'img_dir'] + img_path + ".png" self.rep_img.image = toga.Image(img_path) self.logger.info( "change image preview to: {}".format(img_path)) except Exception as e: self.logger.info("changing image preview failed!") self.logger.info(e) return return def send_report(self, e): uid = self.rep_inp.value if len(uid) >= 7: rep = Reporter( self.hook, self.profile_manager.prf_cfg['img_dir'] + "config.xml") res = rep.send_report(uid) if res: self._show_info("Thanks for Reporting!") self.rep_img.image = toga.Image("resources/logo.png") self.rep_inp.value = "" else: self._throw_error( "Player with ID {} doesn't exist!".format(uid)) self.rep_img.image = toga.Image("resources/logo.png") self.rep_inp.value = "" def check_for_update(self): r = requests.get( "https://raw.githubusercontent.com/Maradonna90/NewGAN-Manager/master/version" ) if r.text.strip() != self.version: self._show_info("There is a new version. Please Update!") self.open_link( "https://github.com/Maradonna90/NewGAN-Manager/releases/latest" )
class NewGANManager(toga.App): def __init__(self, log): super().__init__() self.logger = log def startup(self): """ Construct and show the Toga application. Usually, you would add your application to a main content box. We then create a main window (with a name matching the app), and show the main window. """ self.logger.info( "Starting Application\n------------------------------------------------" ) self.logger.info(str(self.paths.app)) self.mode_info = { "Overwrite": "Overwrites already replaced faces", "Preserve": "Preserves already replaced faces", "Generate": "Generates mapping from scratch." } os.makedirs(str(self.paths.app) + "/.config", exist_ok=True) self.logger.info("Loading current profile") self.profile_manager = Profile_Manager( Config_Manager().get_latest_prf( str(self.paths.app) + "/.user/cfg.json"), str(self.paths.app)) self.profile_manager.migrate_config() self.logger.info("Creating GUI") self.main_box = toga.Box() self.logger.info("Created main box") label_width = 125 # TOP Profiles prf_box = toga.Box() self.logger.info("Created prf_box") prf_inp = toga.TextInput() self.logger.info("Created prf_inp") self.prfsel_box = toga.Box() prf_lab = toga.Label(text="Create Profile: ") prf_lab.style.update(width=label_width) prfsel_lab = toga.Label(text="Select Profile: ") prfsel_lab.style.update(width=label_width) self.prfsel_lst = SourceSelection(items=list( self.profile_manager.config["Profile"].keys()), on_select=self._set_profile_status) self.prfsel_lst.value = self.profile_manager.cur_prf prfsel_btn = toga.Button( label="Delete", on_press=lambda e=None, c=self.prfsel_lst: self._delete_profile(c)) prf_btn = toga.Button(label="Create", on_press=lambda e=None, d=prf_inp, c=self. prfsel_lst: self._create_profile(d, c)) self.main_box.add(prf_box) prf_box.add(prf_lab) prf_box.add(prf_inp) prf_box.add(prf_btn) prf_lab.style.update(padding_top=7) prf_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.main_box.add(self.prfsel_box) self.prfsel_box.add(prfsel_lab) self.prfsel_box.add(self.prfsel_lst) self.prfsel_box.add(prfsel_btn) self.prfsel_lst.style.update(direction=ROW, padding=(0, 20), flex=1) prfsel_lab.style.update(padding_top=7) # MID Path selections dir_box = toga.Box() dir_lab = toga.Label(text="Select Image Directory: ") dir_lab.style.update(width=label_width) self.dir_inp = toga.TextInput( readonly=True, initial=self.profile_manager.prf_cfg['img_dir']) self.dir_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.dir_btn = toga.Button(label="...", on_press=self.action_select_folder_dialog, enabled=False) rtf_box = toga.Box() rtf_lab = toga.Label(text="RTF File: ") rtf_lab.style.update(width=label_width) self.rtf_inp = toga.TextInput( readonly=True, initial=self.profile_manager.prf_cfg['rtf']) self.rtf_inp.style.update(direction=ROW, padding=(0, 20), flex=1) self.rtf_btn = toga.Button(label="...", on_press=self.action_open_file_dialog, enabled=False) self.main_box.add(dir_box) self.main_box.add(rtf_box) dir_box.add(dir_lab) dir_box.add(self.dir_inp) dir_box.add(self.dir_btn) rtf_box.add(rtf_lab) rtf_box.add(self.rtf_inp) rtf_box.add(self.rtf_btn) dir_lab.style.update(padding_top=7) rtf_lab.style.update(padding_top=7) gen_mode_box = toga.Box() self.genmde_lab = toga.Label(text="Mode: ") self.genmde_lab.style.update(width=label_width) self.genmdeinfo_lab = toga.Label(text=self.mode_info["Generate"]) self.genmde_lst = SourceSelection(items=list(self.mode_info.keys()), on_select=self.update_label) self.genmde_lst.value = "Generate" self.genmde_lst.style.update(direction=ROW, padding=(0, 20), flex=1) self.genmde_lab.style.update(padding_top=7) self.genmdeinfo_lab.style.update(padding_top=7) gen_mode_box.add(self.genmde_lab) gen_mode_box.add(self.genmde_lst) gen_mode_box.add(self.genmdeinfo_lab) self.main_box.add(gen_mode_box) # BOTTOM Generation gen_box = toga.Box() self.gen_btn = toga.Button(label="Replace Faces", on_press=self._replace_faces, enabled=False) self.gen_btn.style.update(padding_bottom=20) self.gen_lab = toga.Label(text="") # self.gen_prg = toga.ProgressBar(max=110) self.gen_prg = Progressbar(label=self.gen_lab) gen_box.add(self.gen_btn) gen_box.add(self.gen_lab) gen_box.add(self.gen_prg) self.main_box.add(gen_box) self.gen_prg.style.update(width=570, alignment="center") self.gen_lab.style.update(padding_top=20, padding_bottom=20, width=100, alignment="center") # Report bad image rep_box = toga.Box() self.rep_lab = toga.Label(text="Player UID: ") self.rep_lab.style.update(width=label_width) self.rep_inp = toga.TextInput(on_change=self.change_image) self.rep_img = toga.ImageView(toga.Image("resources/logo.png")) self.rep_img.style.update(height=180) self.rep_img.style.update(width=180) self.rep_btn = toga.Button(label="Report", on_press=self.send_report, enabled=False) rep_box.add(self.rep_lab) rep_box.add(self.rep_inp) rep_box.add(self.rep_img) rep_box.add(self.rep_btn) self.main_box.add(rep_box) self.rep_lab.style.update(padding_top=10) self.rep_inp.style.update(direction=ROW, padding=(0, 20), flex=1) # END config self.prfsel_box.style.update(padding_bottom=20) dir_box.style.update(padding_bottom=20) prf_box.style.update(padding_bottom=20) rtf_box.style.update(padding_bottom=20) gen_mode_box.style.update(padding_bottom=20) rep_box.style.update(padding_top=20) gen_box.style.update(direction=COLUMN, alignment='center') self.main_box.style.update(direction=COLUMN, padding=30, alignment='center') self.main_window = toga.MainWindow(title=self.formal_name, size=(1000, 600)) self.main_window.content = self.main_box self.main_window.show() def update_label(self, widget): self.logger.info("Updating generation label") self.genmdeinfo_lab.text = self.mode_info[widget.value] def set_btns(self, value): if self.profile_manager.cur_prf == "No Profile": self.gen_btn.enabled = False self.dir_btn.enabled = False self.rtf_btn.enabled = False self.rep_btn.enabled = False else: self.gen_btn.enabled = value self.dir_btn.enabled = value self.rtf_btn.enabled = value self.rep_btn.enabled = value def _set_profile_status(self, e): self.logger.info("switch profile: {}".format(e.value)) if e.value is None: self.logger.info("catch none {}".format( self.profile_manager.cur_prf)) elif e.value == self.profile_manager.cur_prf: self.logger.info("catch same values") else: name = e.value self.profile_manager.load_profile(name) self._refresh_inp() self.set_btns(True) Config_Manager().save_config( str(self.paths.app) + "/.user/cfg.json", self.profile_manager.config) def _refresh_inp(self, clear=False): self.logger.info("Refresh Input Buttons") if clear: self.dir_inp.clear() self.rtf_inp.clear() else: self.dir_inp.value = self.profile_manager.prf_cfg['img_dir'] self.rtf_inp.value = self.profile_manager.prf_cfg['rtf'] def _create_profile(self, ent, c): name = ent.value self.profile_manager.create_profile(name) ent.clear() c.add_item(name) def _delete_profile(self, c): prf = c.value self.profile_manager.delete_profile(prf) c.remove_item(prf) self._refresh_inp(True) self.set_btns(False) def _throw_error(self, msg): self.logger.info("Error window {}:".format(msg)) self.main_window.error_dialog('Error', msg) def _show_info(self, msg): self.logger.info("Info window: {}".format(msg)) self.main_window.info_dialog("Info", msg) def action_select_folder_dialog(self, widget): self.logger.info("Select Folder...") try: path_names = self.main_window.select_folder_dialog( title="Select image root folder") self.dir_inp.value = path_names[0] + "/" self.profile_manager.prf_cfg['img_dir'] = path_names[0] + "/" Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) except Exception: pass def action_open_file_dialog(self, widget): self.logger.info("Select File...") try: fname = self.main_window.open_file_dialog(title="Open RTF file", multiselect=False, file_types=['rtf']) self.logger.info("Created file-dialog") if fname is not None: self.rtf_inp.value = fname self.profile_manager.prf_cfg['rtf'] = fname Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) else: self.profile_manager.prf_cfg['rtf'] = "" self.rtf_inp.value = "" Config_Manager().save_config( str(self.paths.app) + "/.user/" + self.profile_manager.cur_prf + ".json", self.profile_manager.prf_cfg) except Exception: self.logger.error("Fatal error in main loop", exc_info=True) pass def _replace_faces(self, widget): self.logger.info("Start Replace Faces") # get values from UI elements rtf = self.profile_manager.prf_cfg['rtf'] img_dir = self.profile_manager.prf_cfg['img_dir'] profile = self.profile_manager.cur_prf mode = self.genmde_lst.value if not os.path.isfile(rtf): self._throw_error("The RTF file doesn't exist!") self.gen_prg.stop() self.profile_manager.prf_cfg['rtf'] = '' return if not os.path.isdir(img_dir): self._throw_error("The image directory doesn't exist!") self.gen_prg.stop() self.profile_manager.prf_cfg['img_dir'] = '' return self.logger.info("rtf: {}".format(rtf)) self.logger.info("img_dir: {}".format(img_dir)) self.logger.info("profile: {}".format(profile)) self.logger.info("mode: {}".format(mode)) self.gen_prg.start() self.gen_prg.update_label("Parsing RTF") yield 0.1 rtf_data = RTF_Parser().parse_rtf(rtf) self.gen_prg.update_progress(20) self.gen_prg.update_label("Map player to ethnicity") yield 0.1 mapping_data = Mapper(img_dir, self.profile_manager).generate_mapping( rtf_data, mode) self.gen_prg.update_progress(60) self.gen_prg.update_label("Generate config.xml") yield 0.1 self.profile_manager.write_xml(mapping_data) # save profile metadata (used pics and config.xml) self.gen_prg.update_label("Save metadata for profile") self.gen_prg.update_progress(10) yield 0.1 Config_Manager().save_config( str(self.paths.app) + "/.user/" + profile + ".json", self.profile_manager.prf_cfg) self.gen_prg.update_progress(10) yield 0.1 self.gen_prg.update_label("Finished! :)") yield 0.1 self._show_info("Finished! :)") self.gen_prg.stop() def change_image(self, id): self.logger.info("try to change image preview") uid = id.value try: img_name = self.prf_cfg["imgs"][uid] img_eth = self.prf_cfg["ethnics"][uid] img_path = self.prf_cfg["img_dir"] + "/" + img_eth + "/" + img_name self.rep_img.image = toga.Image(img_path) self.logger.info("change image preview to: {}".format(img_path)) except Exception: self.logger.info("changing image preview failed!") return def send_report(self, e): uid = self.rep_inp.value img_name = self.prf_cfg["imgs"][uid] img_eth = self.prf_cfg["ethnics"][uid] img_path = img_eth + "/" + img_name img_file = self.rep_img.image.path self.logger.info("send report: {}".format(img_file)) hook = Webhook( "https://discord.com/api/webhooks/770397581149863946/Wls0g6LEyTXEpOqzfLn2YuDRKANFSAFpwKe62VL9IxpwsQDWFjYHVfy19hrYiv5p0X2a" ) embed = Embed( description='A user reported the following face', color=0x5CDBF0, timestamp='now' # sets the timestamp to current time ) file = File(img_file) embed.add_field(name='File', value=img_path) hook.send(embed=embed, file=file) self._show_info("Thanks for Reporting!")