Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import sys
- import pickle
- import wx
- import wx.aui
- import appdirs
- import broadpy.addrtools as addrtools
- import address_cleaner.const as const
- import address_cleaner.shared as shared
- from address_cleaner.shared import vprint
- from address_cleaner.addrlookup import AddressLookupPanel
- from address_cleaner.tablecleaner import TableCleanerPanel
- def run():
- app = App(redirect=False)
- app.MainLoop()
- class App(wx.App):
- def OnInit(self):
- # Initialize the config system.
- initialize_config()
- # Try to connect to MySQL.
- if not connect_to_database():
- return False
- # Confirm that the cache is loaded.
- load_norway_cache()
- # Create the main frame and show it.
- self.frame = MainFrame(None)
- self.SetTopWindow(self.frame)
- self.frame.Show(True)
- # Call raise on the frame. This helps on Windows, where the window
- # appears below the CMD it was created from.
- self.frame.Raise()
- return True
- def MacOpenFile(self, filename):
- vprint(2, 'MacOpenFile:', filename)
- def MacReopenApp(self):
- vprint(2, 'MacReopenApp')
- self.GetTopWindow().Raise()
- class MainFrame(wx.Frame):
- MIN_SIZE = (400, 300)
- DEFAULT_SIZE = (1024, 768)
- def __init__(self, parent):
- wx.Frame.__init__(self, parent, -1, 'Address cleaner')
- # Initialize the controls.
- self.initialize_ui()
- # Bind accelerators.
- at = wx.AcceleratorTable([
- (wx.ACCEL_CTRL, ord('W'), wx.ID_CLOSE)
- ])
- self.SetAcceleratorTable(at)
- # Set the starting frame size.
- self.initialize_dimensions()
- # Set the initial status bar text.
- self.SetStatusText('Connected to MySQL database at {}.'.format(
- addrtools.good_con_info['mysql_con']['host']
- ))
- # Bind resize event to save the frame size.
- self.Bind(wx.EVT_MOVE, self.on_rect_change)
- self.Bind(wx.EVT_SIZE, self.on_rect_change)
- self.Bind(wx.EVT_CLOSE, self.on_close)
- def initialize_dimensions(self):
- """Loads the cached frame position and size, or uses default values."""
- # Load the frame size.
- rect = shared.config_get('main_frame_rect')
- self.SetMinSize(self.MIN_SIZE)
- if rect:
- self.Rect = rect
- else:
- self.SetSize(self.DEFAULT_SIZE)
- self.CentreOnScreen()
- if shared.config_get('main_frame_maximized', False):
- self.Maximize()
- def initialize_ui(self):
- """Initializes the UI for this Frame."""
- # Create and set the menu bar.
- self.main_menu = self.create_main_menu()
- self.SetMenuBar(self.main_menu)
- # Create the AUI notebook. Also add an address lookup page.
- self.notebook = wx.aui.AuiNotebook(self)
- self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_page_close)
- self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.on_page_changed)
- self.notebook.AddPage(
- AddressLookupPanel(self.notebook),
- 'Address lookup'
- )
- # Add a status bar.
- self.CreateStatusBar()
- def create_main_menu(self):
- """Creates and returns the main menu."""
- main_menu_bar = wx.MenuBar()
- new_al_page_label = 'New &address lookup page\tCTRL+ALT+A'
- file_menu = shared.create_menu([
- (wx.ID_OPEN, '&Open...\tCTRL+O'),
- (const.ID_NEW_ADDRESS_LOOKUP_PAGE, new_al_page_label),
- (),
- (wx.ID_CLOSE, '&Close page'),
- (),
- (wx.ID_EXIT, 'E&xit')
- ])
- help_menu = shared.create_menu([
- (wx.ID_ABOUT, 'About Address Cleaner')
- ])
- # Add menus to menu bar.
- main_menu_bar.Append(file_menu, '&File')
- main_menu_bar.Append(help_menu, '&Help')
- # Event handling.
- self.Bind(wx.EVT_MENU, self.on_main_menu)
- self.Bind(wx.EVT_UPDATE_UI, self.on_main_menu_update_ui)
- return main_menu_bar
- def create_address_lookup_panel(self, parent):
- """Creates and returns an address lookup panel."""
- return
- def add_address_lookup_page(self):
- """Adds an address lookup page."""
- panel = AddressLookupPanel(self.notebook)
- self.notebook.AddPage(panel, 'Address lookup page')
- # Select the new page.
- self.notebook.SetSelection(self.notebook.GetPageCount()-1)
- def add_table_cleaner_page(self, path):
- """Adds a table cleaner page."""
- panel = TableCleanerPanel(self.notebook, path)
- filename = os.path.basename(path)
- # Cap the file name to 30 characters.
- filename = len(filename) > 30 and filename[:30 - 3] + '...' or filename
- # Add the table cleaner panel to a new page.
- self.notebook.AddPage(panel, u'Table cleaner: "{}"'.format(filename))
- # Select the new page.
- self.notebook.SetSelection(self.notebook.GetPageCount()-1)
- def open_table_file(self):
- wildcard = 'Excel 2007 file (*.xlsx)|*.xlsx|' \
- 'CSV file (*.csv)|*.csv'
- # Load the default directory from settings.
- default_dir = shared.config_get('default_dir', '~')
- # Create a file open dialog.
- dialog = wx.FileDialog(self, message='Choose a file', style=wx.OPEN,
- defaultDir=default_dir, wildcard=wildcard)
- if dialog.ShowModal() == wx.ID_OK:
- path = dialog.GetPath()
- # Set the default directory setting to the one just used.
- shared.config_set('default_dir', os.path.dirname(path))
- self.add_table_cleaner_page(path)
- def close_current_page(self):
- """Closes the current focused page."""
- x = self.notebook.GetSelection()
- if x > -1:
- self.notebook.DeletePage(x)
- def show_about(self):
- info = wx.AboutDialogInfo()
- info.Name = address_cleaner.const.APPNAME
- info.Version = address_cleaner.const.VERSION
- info.Copyright = '(C) 2012 Broadnet AS'
- info.Description = address_cleaner.const.DESCRIPTION
- info.Developers = [address_cleaner.const.AUTHOR]
- wx.AboutBox(info)
- def handle_page_switch(self, old_page, new_page):
- is_editor = lambda x: isinstance(x, shared.EditorPanel)
- # If the old and new page is the same page, which can happen when tabs
- # are reorganized, ignore this function call.
- if old_page is new_page:
- return
- if is_editor(old_page):
- old_page.release_main_menu_bar()
- if is_editor(new_page):
- new_page.bind_main_menu_bar(self.main_menu)
- def on_main_menu(self, event):
- event_id = event.GetId()
- if event_id == wx.ID_OPEN:
- self.open_table_file()
- elif event_id == const.ID_NEW_ADDRESS_LOOKUP_PAGE:
- self.add_address_lookup_page()
- elif event_id == wx.ID_CLOSE:
- self.close_current_page()
- elif event_id == wx.ID_EXIT:
- self.Close()
- elif event_id == wx.ID_ABOUT:
- self.show_about()
- else:
- vprint(1, '{}: Unknown menu click ID: {}',
- shared.function_name(), event_id)
- def on_main_menu_update_ui(self, event):
- event_id = event.Id
- # Disable the "Close page" button if there are no pages.
- if event_id == wx.ID_CLOSE:
- if self.notebook.PageCount < 1:
- event.Enable(False)
- else:
- event.Enable(True)
- def on_page_changed(self, event):
- print 'Page changed: {}, {}'.format(event.OldSelection, event.Selection)
- new_page = self.notebook.GetPage(event.Selection)
- # If the old page selection is -1, it means the selection didn't change.
- if event.OldSelection > -1:
- old_page = self.notebook.GetPage(event.OldSelection)
- else:
- old_page = None
- self.handle_page_switch(old_page, new_page)
- event.Skip()
- def on_page_close(self, event):
- print 'Page closed', event
- def on_rect_change(self, event):
- # Save the dialog rect in the config.
- if not self.IsMaximized():
- shared.config_set('main_frame_rect', self.Rect, silent=True)
- # Save the maximized state.
- shared.config_set('main_frame_maximized', self.IsMaximized(),
- silent=True)
- event.Skip()
- def on_maximize(self, event):
- print('Maximized')
- def on_close(self, event):
- # Save the configuration.
- vprint(1, 'Saving the config.')
- shared.config_save()
- event.Skip()
- # Startup routines -------------------------------------------------------------
- def initialize_config():
- """Makes sure the config folder and file is created."""
- config_dir = appdirs.user_data_dir(
- const.APPNAME, const.AUTHOR, version=const.VERSION
- )
- # Create the application data directory if it doesn't exist.
- if not os.path.isdir(config_dir):
- os.makedirs(config_dir)
- # Create the config file if it doesn't exist.
- shared.config_file_path = os.path.join(config_dir, 'config.dat')
- # If the config file doesn't exist, create an empty one.
- if not os.path.isfile(shared.config_file_path):
- shared.config = {}
- with open(shared.config_file_path, 'w') as f:
- pickle.dump(shared.config, f)
- # Otherwise load the file. If the load fails, reset the file.
- else:
- try:
- with open(shared.config_file_path, 'r') as f:
- shared.config = pickle.load(f)
- except Exception as e:
- shared.config = {}
- wx.MessageBox('Config file error',
- 'Config file was corrupted and has been reset',
- style=wx.OK | wx.ICON_ERROR)
- vprint(1, 'Config error: {}', e.message)
- vprint(1, 'Initialized config: "{}"', shared.config_file_path)
- def connect_to_database():
- """Connect to the address database."""
- error_msg = None
- # Display a loading dialog.
- loading = shared.show_loading(None, 'Connecting',
- 'Connecting to address database')
- error, shared.con = addrtools.connect_to_database(return_error=True)
- loading.done()
- if shared.con is None:
- msg = 'Failed to connect to a MySQL address database\n\n{}'
- msg = msg.format(error)
- wx.MessageBox(msg, 'MySQL connection error', wx.OK | wx.ICON_ERROR)
- # The application is useless without the MySQL connection, so just quit.
- return False
- else:
- vprint(1, 'Connected to address database: "{}"',
- addrtools.good_con_info['mysql_con']['host'])
- return True
- def load_norway_cache():
- """Loads the addrtools Norway cache. Displays a progress dialog if the cache
- must be downloaded."""
- loading = None
- # Check if the cache must be updated.
- if not addrtools.check_cache():
- loading = shared.show_loading(None, 'Creating cache',
- 'Creating a cache for quick lookups')
- # Load the cache.
- addrtools.load_cache()
- # Remove the loading dialog.
- if loading:
- loading.done()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement