def read(self): fname = 'config.pkl' """ Read config file """ self.logger.debug(f'config read {self.cache_dir} {fname}') # Verify main directory exists if not os.path.exists(self.cache_dir): self.logger.warning(f"{self.cache_dir} folder not found.") TKHelper.fatal_error( f"{self.cache_dir} folder not found. Please use Config button to correct" ) self.config_cd = CachedDictionary.CachedDictionary( self.cache_dir, fname) self.config_cd.read() if self.config_cd.error: self.logger.error( f'Config {os.path.join(self.cache_dir, fname)} not found') # Create empty config file path = os.path.join(self.cache_dir, "config.pkl") self.set("gedcom_path", "GEDCOM filename: <empty>") with open(path, 'wb') as file: pickle.dump(self.config_cd.dict, file) return True else: return False
def load_handler(self): """ User pressed LOAD button to load an Ancestry file. Switch app display to the Review Widgets Load in file name and loop through file and find every PLACE entry and verify the entry against the geoname data """ self.w.original_entry.set_text("") self.w.remove_initialization_widgets() # Remove old widgets self.w.create_review_widgets( ) # Switch display from Initial widgets to main review widgets self.load_data() ged_path = self.cfg.get( "gedcom_path") # Get saved config setting for file # Load appropriate handler based on file type if ged_path is not None: if '.ged' in ged_path: self.out_suffix = "import.ged" self.ancestry_file_handler = Gedcom.Gedcom( in_path=ged_path, out_suffix=temp_suffix, cache_d=self.cache_dir, progress=None, geodata=self.geodata ) # Routines to open and parse GEDCOM file elif '.gramps' in ged_path: self.out_suffix = "import.gramps" # self.out_suffix = "csv" self.ancestry_file_handler = GrampsXml.GrampsXml( in_path=ged_path, out_suffix=temp_suffix, cache_d=self.cache_dir, progress=None, geodata=self.geodata ) # Routines to open and parse Gramps file else: self.out_suffix = 'unk.new.ged' messagebox.showwarning( f'UNKNOWN File type. Not .gramps and not .ged. \n\n{ged_path}') self.out_diag_file = open(ged_path + '.output.txt', 'w') self.in_diag_file = open(ged_path + '.input.txt', 'w') if self.ancestry_file_handler.error: TKHelper.fatal_error(f"File {ged_path} not found.") self.w.root.update() self.place: Loc.Loc = Loc.Loc( ) # Create an object to store info for the current Place # Add filename to Title path_parts = os.path.split(ged_path) # Extract filename from full path self.w.title.set_text(f'GEO FINDER - {path_parts[1]}') # Read file, find each place entry and handle it. self.w.user_entry.set_text("Scanning to previous position...") self.handle_place_entry()
def end_of_file_shutdown(self): # End of file reached TKHelper.disable_buttons(button_list=self.w.review_buttons) # self.start_time = time.time() #self.logger.debug(f'COMPLETED time={int((time.time() - self.start_time) / 60)} minutes') self.w.status.set_text("Done. Shutting Down...") self.w.original_entry.set_text(" ") path = self.cfg.get("gedcom_path") self.ancestry_file_handler.close() self.update_statistics() self.w.root.update_idletasks() # Let GUI update if 'ramp' in self.out_suffix: # Gramps file is .csv messagebox.showinfo( "Info", f"Finished. Created file for Import to Ancestry software:\n\n {path}.csv" ) else: messagebox.showinfo( "Info", f"Finished. Created file for Import to Ancestry software:\n\n {path}.{self.out_suffix}" ) self.logger.info('End of file') self.shutdown()
def load_data(self): # Read in Skiplist, Replace list list self.skiplist = CachedDictionary(self.cache_dir, "skiplist.pkl") self.skiplist.read() self.global_replace = CachedDictionary(self.cache_dir, "global_replace.pkl") self.global_replace.read() # self.user_accepted = CachedDictionary(self.cache_dir, "accepted.pkl") # List of items that have been accepted # self.user_accepted.read() # Initialize geodata self.geodata = Geodata.Geodata(directory_name=self.directory, progress_bar=self.w.prog) error = self.geodata.read() if error: TKHelper.fatal_error(MISSING_FILES) # If the list of supported countries is unusually short, display note to user num = self.display_country_note() self.logger.info('{} countries will be loaded'.format(num)) # Read in Geoname Gazeteer file - city names, lat/long, etc. error = self.geodata.read_geonames() if error: TKHelper.fatal_error(MISSING_FILES) self.w.root.update() self.w.prog.update_progress(100, " ")
def display_country_note(self) -> int: """ display warning if only a small number of countries are enabled """ country_list, supported_countries = self.geodata.geo_files.get_supported_countries( ) self.w.root.update() if supported_countries == 0: TKHelper.fatal_error( "No countries enabled.\n\nUse Config Country Tab to change country list\n" ) # if supported_countries < 3: # messagebox.showinfo("Info", f"Loading geocode data for the following ISO country codes:" # f"\n\n{country_list}\n\nUse Config Country Tab to change country list\n") return supported_countries
def filename_handler(self): """ Display file open selector dialog """ fname = filedialog.askopenfilename(initialdir=self.directory, title=f"Select {file_types} file", filetypes=[ ("GEDCOM files", "*.ged"), ("Gramps files", "*.gramps"), ("all files", "*.*") ]) if len(fname) > 1: self.cfg.set("gedcom_path", fname) # Add filename to dict self.cfg.write() # Write out config file self.w.status.set_text(f"Click Open to load {file_types} file") self.w.original_entry.set_text(self.cfg.get("gedcom_path")) TKHelper.set_preferred_button(self.w.load_button, self.w.initialization_buttons, "Preferred.TButton")
def configure_widgets(self, frm): super().configure_widgets(frm) # Add Lable for allow user to Add to list TKHelper.set_grid_position(self.pad, "pad", grd=self.grd) # Add Lable for allow user to Add to list TKHelper.set_grid_position(self.add_label, "add_label", grd=self.grd) # Add Button to allow user to Add to list TKHelper.set_grid_position(self.add_button, "add_button", grd=self.grd) # Create listbox of countries to add with scrollbar TKHelper.set_grid_position(self.listbox_all_countries, "listbox_all_countries", grd=self.grd) self.scrollbar2.config(command=self.listbox_all_countries.yview) TKHelper.set_grid_position(self.scrollbar2, "scrollbar2", grd=self.grd)
def quit_handler(self): """ Set flag for shutdown. Process all global replaces and exit """ self.skip_count += 1 path = self.cfg.get("gedcom_path") if self.w.prog.shutdown_requested: # Already in shutdown and user aborted self.logger.info('Shutdown') self.shutdown() self.w.prog.shutdown_requested = True if messagebox.askyesno( 'Generate Import File?', f'All updates saved.\n\nDo you want to generate a file for import' f' to Gedcom/Gramps?\n\n', default='no'): # Write file for importing back messagebox.showinfo( "Generate Import File", "Reminder - make sure the ancestry export file you are working on is up to date before " "generating a file to import back!\n\nThe file will take about 10 minutes per 1000 places" ) TKHelper.disable_buttons(button_list=self.w.review_buttons) self.w.quit_button.config(state="disabled") self.w.prog.startup = True self.w.statistics_text.configure(style="Good.TLabel") self.w.user_entry.set_text("Creating Import File...") self.start_time = time.time() # Write out the item we are on self.ancestry_file_handler.write_asis( self.w.original_entry.get_text()) # We will still continue to go through file, but only handle global replaces self.handle_place_entry() else: # Immediate exit self.logger.info('Shutdown') self.shutdown()
def __init__(self): print('GeoFinder v{}'.format(__version__.__version__)) print('Python {}.{}'.format(sys.version_info[0], sys.version_info[1])) if sys.version_info < (3, 6, 0): raise Exception("GeoFinder Requires Python 3.6 or higher.") val = '' print(f'GeoFinder Requires Python 3.6 or higher {val}') self.save_enabled = False # Only allow SAVE when we have an item that was matched in geonames self.user_selected_list = False # Indicates whether user selected a list entry or text edit entry self.err_count = 0 self.matched_count = 0 self.review_count = 0 self.skip_count = 0 self.odd = False self.ancestry_file_handler = None self.place = None self.skiplist = None self.global_replace = None self.geodata = None self.out_suffix = 'unknown_suffix' self.out_diag_file = None self.in_diag_file = None # initiate the parser parser = argparse.ArgumentParser() parser.add_argument("--logging", help="Enable quiet logging") parser.add_argument("--diagnostics", help="Create diagnostics files") # read arguments from the command line args = parser.parse_args() # check for --verbose switch if args.logging == 'info': self.logger = self.setup_logging_info('geofinder Init') self.logger.info(f"--logging set to INFO logging {args.logging}") else: self.logger = self.setup_logging('geofinder Init') # check for --diagnostics switch if args.diagnostics: self.logger.info(f"--diagnostics files enabled {args.diagnostics}") self.diagnostics = True else: self.diagnostics = False # Create App window and configure window buttons and widgets self.w: AppLayout.AppLayout = AppLayout.AppLayout(self) self.w.create_initialization_widgets() self.w.config_button.config(state="normal") # Get our base directory path from INI file. Create INI if it doesnt exist home_path = str(Path.home()) self.directory = Path( os.path.join(home_path, GeoKeys.get_directory_name())) self.ini_handler = IniHandler(home_path=home_path, ini_name='geofinder.ini') self.directory = self.ini_handler.get_directory_from_ini() self.cache_dir = GeoKeys.get_cache_directory(self.directory) self.logger.info(f'Cache directory {self.cache_dir}') # Set up configuration class self.cfg = Config.Config(self.directory) self.util = UtilLayout.UtilLayout(root=self.w.root, directory=self.directory, cache_dir=self.cache_dir) if not os.path.exists(self.cache_dir): # Create directories for GeoFinder if messagebox.askyesno( 'Geoname Data Cache Folder not found', f'Create Geoname Cache folder?\n\n{self.cache_dir} '): err = self.cfg.create_directories() if not os.path.exists(self.cache_dir): messagebox.showwarning( 'Geoname Data Cache Folder not found', f'Unable to create folder\n\n{self.cache_dir} ') self.shutdown() else: self.logger.debug(f'Created {self.cache_dir}') messagebox.showinfo( 'Geoname Data Cache Folder created', f'Created folder\n\n{self.cache_dir} ') else: self.shutdown() # Ensure GeoFinder directory structure is valid if self.cfg.valid_directories(): # Directories are valid. See if required Geonames files are present err = self.check_configuration() if err: # Missing files self.logger.warning('Missing files') self.w.status.set_text("Click Config to set up Geo Finder") TKHelper.set_preferred_button(self.w.config_button, self.w.initialization_buttons, "Preferred.TButton") self.w.load_button.config(state="disabled") else: # No config errors # Read config settings (Ancestry file path) err = self.cfg.read() if err: self.logger.warning('error reading {} config.pkl'.format( self.cache_dir)) self.w.original_entry.set_text(self.cfg.get("gedcom_path")) TKHelper.enable_buttons(self.w.initialization_buttons) if os.path.exists(self.cfg.get("gedcom_path")): # file is valid. Prompt user to click Open for file self.w.status.set_text( f"Click Open to load {file_types} file") TKHelper.set_preferred_button( self.w.load_button, self.w.initialization_buttons, "Preferred.TButton") else: # No file. prompt user to select a file - GEDCOM file name isn't valid self.w.status.set_text(f"Choose a {file_types} file") self.w.load_button.config(state="disabled") TKHelper.set_preferred_button( self.w.choose_button, self.w.initialization_buttons, "Preferred.TButton") else: # Missing directories self.logger.warning('Directories not found: {} '.format( self.cache_dir)) self.w.status.set_text("Click Config to set up Geo Finder") self.w.load_button.config(state="disabled") TKHelper.set_preferred_button(self.w.config_button, self.w.initialization_buttons, "Preferred.TButton") # Flag to indicate whether we are in startup or in Window loop. Determines how window idle is called self.startup = False self.w.root.mainloop( ) # ENTER MAIN LOOP and Wait for user to click on load button
def display_result(self, place: Loc.Loc): """ Display result details for an item """ # Enable buttons so user can either click Skip, or edit the item and Click Verify. place.safe_strings() TKHelper.enable_buttons(self.w.review_buttons) # Enable action buttons based on type of result if place.result_type == GeoKeys.Result.MULTIPLE_MATCHES or \ place.result_type == GeoKeys.Result.NO_MATCH or \ place.result_type == GeoKeys.Result.NO_COUNTRY: # Disable the Save & Map button until user clicks Verify and item is found self.set_save_allowed(False) TKHelper.set_preferred_button(self.w.verify_button, self.w.review_buttons, "Preferred.TButton") elif place.result_type == GeoKeys.Result.NOT_SUPPORTED: # Found a match or Not supported - enable save and verify # self.set_save_allowed(True) # Enable save button TKHelper.set_preferred_button(self.w.skip_button, self.w.review_buttons, "Preferred.TButton") else: # Found a match or Not supported - enable save and verify self.set_save_allowed(True) # Enable save button TKHelper.set_preferred_button(self.w.save_button, self.w.review_buttons, "Preferred.TButton") # Display status and color based on success self.set_status_text(place.get_status()) if place.result_type in GeoKeys.successful_match: if place.place_type == Loc.PlaceType.CITY: self.w.status.configure(style="Good.TLabel") else: self.w.status.configure(style="GoodCounty.TLabel") else: self.w.status.configure(style="Error.TLabel") # set Verify as preferred button if len(place.georow_list) > 1: TKHelper.set_preferred_button(self.w.verify_button, self.w.review_buttons, "Preferred.TButton") self.set_save_allowed(False) if len(place.georow_list) > 0: # Display matches in listbox self.w.tree.focus() # Set focus to listbox self.display_georow_list(place) else: # No matches self.w.user_entry.focus() # Set focus to text edit widget self.display_one_georow(place.status_detail, place.geoid, score=9999, feat='') # Display GEDCOM person and event that this location refers to self.w.ged_event_info.set_text( f'{self.ancestry_file_handler.get_name(self.ancestry_file_handler.id)}: ' f'{self.ancestry_file_handler.event_name} {self.ancestry_file_handler.date}' ) self.w.root.update_idletasks()