Ejemplo n.º 1
0
    def outvarchanged(self):
        local = (
            self.out_bpc.get()
            or self.out_td.get()
            or self.out_csv.get()
            or self.out_ship_eds.get()
            or self.out_ship_coriolis.get()
            or self.out_log_file.get()
        )
        self.outdir_label["state"] = local and tk.NORMAL or tk.DISABLED
        self.outbutton["state"] = local and tk.NORMAL or tk.DISABLED
        self.outdir["state"] = local and "readonly" or tk.DISABLED

        edsm_state = self.out_log_edsm.get() and tk.NORMAL or tk.DISABLED
        self.edsm_autoopen_button["state"] = edsm_state
        self.edsm_label["state"] = edsm_state
        self.edsm_cmdr_label["state"] = edsm_state
        self.edsm_apikey_label["state"] = edsm_state
        self.edsm_cmdr["state"] = edsm_state
        self.edsm_apikey["state"] = edsm_state

        proxyaddr = edproxy.status()
        self.out_log_auto_text["text"] = ""
        self.edsm_log_auto_text["text"] = ""
        if monitor.logdir or proxyaddr:
            log = self.out_log_file.get()
            self.out_log_auto_button["state"] = log and tk.NORMAL or tk.DISABLED

            if log and self.out_log_auto.get():
                if proxyaddr:
                    self.out_log_auto_text["text"] = _("Connected to {EDPROXY} at {ADDR}").format(
                        EDPROXY="edproxy", ADDR=proxyaddr
                    )  # Output settings
                elif not monitor.enable_logging():
                    self.out_log_auto_text[
                        "text"
                    ] = "Can't enable automatic logging!"  # Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.out_log_auto_text["text"] = _(
                        "Re-start Elite: Dangerous to use this feature"
                    )  # Output settings prompt

            self.edsm_log_auto_button["state"] = edsm_state

            if self.out_log_edsm.get() and self.out_log_auto.get():
                if proxyaddr:
                    self.edsm_log_auto_text["text"] = _("Connected to {EDPROXY} at {ADDR}").format(
                        EDPROXY="edproxy", ADDR=proxyaddr
                    )  # Output settings
                elif not monitor.enable_logging():
                    self.edsm_log_auto_text[
                        "text"
                    ] = "Can't enable automatic logging!"  # Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.edsm_log_auto_text["text"] = _(
                        "Re-start Elite: Dangerous to use this feature"
                    )  # Output settings prompt
        else:
            self.out_log_auto_button["state"] = tk.DISABLED
            self.edsm_log_auto_button["state"] = tk.DISABLED
Ejemplo n.º 2
0
    def outvarchanged(self):
        local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get() or self.out_log_file.get()
        self.outdir_label['state'] = local and tk.NORMAL  or tk.DISABLED
        self.outbutton['state']    = local and tk.NORMAL  or tk.DISABLED
        self.outdir['state']       = local and 'readonly' or tk.DISABLED

        edsm_state = self.out_log_edsm.get() and tk.NORMAL or tk.DISABLED
        self.edsm_autoopen_button['state'] = edsm_state
        self.edsm_label['state']        = edsm_state
        self.edsm_cmdr_label['state']   = edsm_state
        self.edsm_apikey_label['state'] = edsm_state
        self.edsm_cmdr['state']         = edsm_state
        self.edsm_apikey['state']       = edsm_state

        if monitor.logdir:
            log = self.out_log_file.get()
            self.out_log_auto_button['state']  = log and tk.NORMAL or tk.DISABLED

            self.out_log_auto_text['text'] = ''
            if log and self.out_log_auto.get():
                if not monitor.enable_logging():
                    self.out_log_auto_text['text'] = "Can't enable automatic logging!"	# Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.out_log_auto_text['text'] = _('Re-start Elite: Dangerous to use this feature')	# Output settings prompt

            self.edsm_log_auto_button['state']  = edsm_state

            self.edsm_log_auto_text['text'] = ''
            if self.out_log_edsm.get() and self.out_log_auto.get():
                if not monitor.enable_logging():
                    self.edsm_log_auto_text['text'] = "Can't enable automatic logging!"	# Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.edsm_log_auto_text['text'] = _('Re-start Elite: Dangerous to use this feature')	# Output settings prompt
Ejemplo n.º 3
0
 def _destroy(self):
     # Re-enable hotkey and log monitoring before exit
     hotkeymgr.register(self.parent, config.getint('hotkey_code'), config.getint('hotkey_mods'))
     if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_AUTO|config.OUT_LOG_EDSM)):
         monitor.enable_logging()
         monitor.start(self.parent)
     else:
         monitor.stop()
     self.destroy()
Ejemplo n.º 4
0
 def _destroy(self):
     # Re-enable hotkey and log monitoring before exit
     hotkeymgr.register(self.parent, config.getint('hotkey_code'), config.getint('hotkey_mods'))
     if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_AUTO|config.OUT_LOG_EDSM)):
         monitor.enable_logging()
         monitor.start(self.parent)
     else:
         monitor.stop()
     self.destroy()
Ejemplo n.º 5
0
 def _destroy(self):
     # Re-enable hotkey and log monitoring before exit
     hotkeymgr.register(self.parent, config.getint('hotkey_code'), config.getint('hotkey_mods'))
     if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_FILE|config.OUT_LOG_EDSM)):
         monitor.enable_logging()
         monitor.start(self.parent)
         edproxy.start(self.parent)
     else:
         monitor.stop()
         edproxy.stop()
     self.parent.wm_attributes('-topmost', config.getint('always_ontop') and 1 or 0)
     self.destroy()
Ejemplo n.º 6
0
    def outvarchanged(self):
        local = self.out_bpc.get(
        ) or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get(
        ) or self.out_ship_coriolis.get() or self.out_log_file.get()
        self.outdir_label['state'] = local and tk.NORMAL or tk.DISABLED
        self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
        self.outdir['state'] = local and 'readonly' or tk.DISABLED

        edsm_state = self.out_log_edsm.get() and tk.NORMAL or tk.DISABLED
        self.edsm_autoopen_button['state'] = edsm_state
        self.edsm_label['state'] = edsm_state
        self.edsm_cmdr_label['state'] = edsm_state
        self.edsm_apikey_label['state'] = edsm_state
        self.edsm_cmdr['state'] = edsm_state
        self.edsm_apikey['state'] = edsm_state

        if monitor.logdir:
            log = self.out_log_file.get()
            self.out_log_auto_button[
                'state'] = log and tk.NORMAL or tk.DISABLED

            self.out_log_auto_text['text'] = ''
            if log and self.out_log_auto.get():
                if not monitor.enable_logging():
                    self.out_log_auto_text[
                        'text'] = "Can't enable automatic logging!"  # Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.out_log_auto_text['text'] = _(
                        'Re-start Elite: Dangerous to use this feature'
                    )  # Output settings prompt

            self.edsm_log_auto_button['state'] = edsm_state

            self.edsm_log_auto_text['text'] = ''
            if self.out_log_edsm.get() and self.out_log_auto.get():
                if not monitor.enable_logging():
                    self.edsm_log_auto_text[
                        'text'] = "Can't enable automatic logging!"  # Shouldn't happen - don't translate
                elif monitor.restart_required():
                    self.edsm_log_auto_text['text'] = _(
                        'Re-start Elite: Dangerous to use this feature'
                    )  # Output settings prompt
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        if platform == 'win32':
            self.w.wm_iconbitmap(default='EDMarketConnector.ico')
        elif platform == 'linux2':
            from PIL import Image, ImageTk
            icon = ImageTk.PhotoImage(Image.open("EDMarketConnector.png"))
            self.w.tk.call('wm', 'iconphoto', self.w, '-default', icon)
            style = ttk.Style()
            style.theme_use('clam')
        elif platform == 'darwin':
            # Default ttk font choice looks bad on El Capitan
            font = tkFont.Font(family='TkDefaultFont',
                               size=13,
                               weight=tkFont.NORMAL)
            style = ttk.Style()
            style.configure('TLabel', font=font)
            style.configure('TButton', font=font)
            style.configure('TLabelframe.Label', font=font)
            style.configure('TCheckbutton', font=font)
            style.configure('TRadiobutton', font=font)
            style.configure('TEntry', font=font)

        frame = ttk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(4, weight=1)

        ttk.Label(frame, text=_('Cmdr') + ':').grid(row=0,
                                                    column=0,
                                                    sticky=tk.W)  # Main window
        ttk.Label(frame,
                  text=_('System') + ':').grid(row=1, column=0,
                                               sticky=tk.W)  # Main window
        ttk.Label(frame,
                  text=_('Station') + ':').grid(row=2, column=0,
                                                sticky=tk.W)  # Main window

        self.cmdr = ttk.Label(frame, width=-21)
        self.system = HyperlinkLabel(frame,
                                     compound=tk.RIGHT,
                                     url=self.system_url,
                                     popup_copy=True)
        self.station = HyperlinkLabel(
            frame,
            url=self.station_url,
            popup_copy=lambda x: x != self.STATION_UNDOCKED)
        self.button = ttk.Button(
            frame,
            name='update',
            text=_('Update'),
            command=self.getandsend,
            default=tk.ACTIVE,
            state=tk.DISABLED)  # Update button in main window
        self.status = ttk.Label(frame, name='status', width=-25)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        self.cmdr.grid(row=0, column=1, sticky=tk.EW)
        self.system.grid(row=1, column=1, sticky=tk.EW)
        self.station.grid(row=2, column=1, sticky=tk.EW)
        self.button.grid(row=3, column=0, columnspan=2, sticky=tk.NSEW)
        self.status.grid(row=4, column=0, columnspan=2, sticky=tk.EW)

        for child in frame.winfo_children():
            child.grid_configure(padx=5,
                                 pady=(platform == 'darwin' and 3 or 2))

        menubar = tk.Menu()
        if platform == 'darwin':
            from Foundation import NSBundle
            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            apple_menu = tk.Menu(menubar, name='apple')
            apple_menu.add_command(
                label=_("About {APP}").format(APP=applongname),
                command=lambda: self.w.call('tk::mac::standardAboutPanel'
                                            ))  # App menu entry on OSX
            apple_menu.add_command(
                label=_("Check for Updates..."),
                command=lambda: self.updater.checkForUpdates())
            menubar.add_cascade(menu=apple_menu)
            self.edit_menu = tk.Menu(menubar, name='edit')
            self.edit_menu.add_command(
                label=_('Copy'),
                accelerator='Command-c',
                state=tk.DISABLED,
                command=self.copy)  # As in Copy and Paste
            menubar.add_cascade(label=_('Edit'),
                                menu=self.edit_menu)  # Menu title
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(menubar, name='view')
            self.view_menu.add_command(label=_('Status'),
                                       state=tk.DISABLED,
                                       command=lambda: stats.StatsDialog(
                                           self.w, self.session))  # Menu item
            menubar.add_cascade(label=_('View'),
                                menu=self.view_menu)  # Menu title on OSX
            window_menu = tk.Menu(menubar, name='window')
            menubar.add_cascade(label=_('Window'),
                                menu=window_menu)  # Menu title on OSX
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand(
                'tkAboutDialog',
                lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand(
                "::tk::mac::ShowPreferences",
                lambda: prefs.PreferencesDialog(self.w, self.login))
            self.w.createcommand(
                "::tk::mac::ReopenApplication",
                self.w.deiconify)  # click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW",
                            self.w.withdraw)  # close button shouldn't quit app
        else:
            file_menu = self.view_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            file_menu.add_command(label=_('Status'),
                                  state=tk.DISABLED,
                                  command=lambda: stats.StatsDialog(
                                      self.w, self.session))  # Menu item
            file_menu.add_command(
                label=_("Check for Updates..."),
                command=lambda: self.updater.checkForUpdates())
            file_menu.add_command(
                label=_("Settings"),
                command=lambda: prefs.PreferencesDialog(
                    self.w, self.login))  # Item in the File menu on Windows
            file_menu.add_separator()
            file_menu.add_command(
                label=_("Exit"),
                command=self.onexit)  # Item in the File menu on Windows
            menubar.add_cascade(label=_("File"),
                                menu=file_menu)  # Menu title on Windows
            self.edit_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(
                label=_('Copy'),
                accelerator='Ctrl+C',
                state=tk.DISABLED,
                command=self.copy)  # As in Copy and Paste
            menubar.add_cascade(label=_('Edit'),
                                menu=self.edit_menu)  # Menu title
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
        if platform == 'linux2':
            # Fix up menu to use same styling as everything else
            (fg, bg, afg, abg) = (style.lookup('TLabel.label', 'foreground'),
                                  style.lookup('TLabel.label', 'background'),
                                  style.lookup('TButton.label', 'foreground',
                                               ['active']),
                                  style.lookup('TButton.label', 'background',
                                               ['active']))
            menubar.configure(fg=fg,
                              bg=bg,
                              activeforeground=afg,
                              activebackground=abg)
            file_menu.configure(fg=fg,
                                bg=bg,
                                activeforeground=afg,
                                activebackground=abg)
            self.edit_menu.configure(fg=fg,
                                     bg=bg,
                                     activeforeground=afg,
                                     activebackground=abg)
        self.w['menu'] = menubar

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match and (
                    platform != 'darwin' or int(match.group(2)) > 0
            ):  # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                self.w.geometry(config.get('geometry'))
        self.w.update_idletasks()
        self.w.wait_visibility()
        (w, h) = (self.w.winfo_width(), self.w.winfo_height())
        self.w.minsize(w, h)  # Minimum size = initial size
        if platform != 'linux2':  # update_idletasks() doesn't allow for the menubar on Linux
            self.w.maxsize(-1, h)  # Maximum height = initial height

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)  # user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)  # user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'),
                           config.getint('hotkey_mods'))

        # Install log monitoring
        self.w.bind_all('<<Jump>>', self.system_change)  # user-generated
        if (config.getint('output') & config.OUT_LOG_AUTO) and (
                config.getint('output') &
            (config.OUT_LOG_AUTO | config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.login)
        else:
            self.login()
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        if platform == 'win32':
            self.w.wm_iconbitmap(default='EDMarketConnector.ico')
        elif platform == 'linux2':
            from PIL import Image, ImageTk
            icon = ImageTk.PhotoImage(Image.open("EDMarketConnector.png"))
            self.w.tk.call('wm', 'iconphoto', self.w, '-default', icon)
            style = ttk.Style()
            style.theme_use('clam')
        elif platform=='darwin':
            # Default ttk font choice looks bad on El Capitan
            font = tkFont.Font(family='TkDefaultFont', size=13, weight=tkFont.NORMAL)
            style = ttk.Style()
            style.configure('TLabel', font=font)
            style.configure('TButton', font=font)
            style.configure('TLabelframe.Label', font=font)
            style.configure('TCheckbutton', font=font)
            style.configure('TRadiobutton', font=font)
            style.configure('TEntry', font=font)

        frame = ttk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(4, weight=1)

        ttk.Label(frame, text=_('Cmdr')+':').grid(row=0, column=0, sticky=tk.W)	# Main window
        ttk.Label(frame, text=_('System')+':').grid(row=1, column=0, sticky=tk.W)	# Main window
        ttk.Label(frame, text=_('Station')+':').grid(row=2, column=0, sticky=tk.W)	# Main window

        self.cmdr = ttk.Label(frame, width=-21)
        self.system =  HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True)
        self.station = HyperlinkLabel(frame, url = self.station_url, popup_copy = lambda x: x!=self.STATION_UNDOCKED)
        self.button = ttk.Button(frame, name='update', text=_('Update'), command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED)	# Update button in main window
        self.status = ttk.Label(frame, name='status', width=-25)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        self.cmdr.grid(row=0, column=1, sticky=tk.EW)
        self.system.grid(row=1, column=1, sticky=tk.EW)
        self.station.grid(row=2, column=1, sticky=tk.EW)
        self.button.grid(row=3, column=0, columnspan=2, sticky=tk.NSEW)
        self.status.grid(row=4, column=0, columnspan=2, sticky=tk.EW)

        for child in frame.winfo_children():
            child.grid_configure(padx=5, pady=(platform=='darwin' and 3 or 2))

        menubar = tk.Menu()
        if platform=='darwin':
            from Foundation import NSBundle
            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            apple_menu = tk.Menu(menubar, name='apple')
            apple_menu.add_command(label=_("About {APP}").format(APP=applongname), command=lambda:self.w.call('tk::mac::standardAboutPanel'))	# App menu entry on OSX
            apple_menu.add_command(label=_("Check for Updates..."), command=lambda:self.updater.checkForUpdates())
            menubar.add_cascade(menu=apple_menu)
            self.edit_menu = tk.Menu(menubar, name='edit')
            self.edit_menu.add_command(label=_('Copy'), accelerator='Command-c', state=tk.DISABLED, command=self.copy)	# As in Copy and Paste
            menubar.add_cascade(label=_('Edit'), menu=self.edit_menu)	# Menu title
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(menubar, name='view')
            self.view_menu.add_command(label=_('Status'), state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))	# Menu item
            menubar.add_cascade(label=_('View'), menu=self.view_menu)	# Menu title on OSX
            window_menu = tk.Menu(menubar, name='window')
            menubar.add_cascade(label=_('Window'), menu=window_menu)	# Menu title on OSX
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand('tkAboutDialog', lambda:self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand("::tk::mac::ShowPreferences", lambda:prefs.PreferencesDialog(self.w, self.login))
            self.w.createcommand("::tk::mac::ReopenApplication", self.w.deiconify)	# click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW", self.w.withdraw)	# close button shouldn't quit app
        else:
            file_menu = self.view_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            file_menu.add_command(label=_('Status'), state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))	# Menu item
            file_menu.add_command(label=_("Check for Updates..."), command=lambda:self.updater.checkForUpdates())
            file_menu.add_command(label=_("Settings"), command=lambda:prefs.PreferencesDialog(self.w, self.login))	# Item in the File menu on Windows
            file_menu.add_separator()
            file_menu.add_command(label=_("Exit"), command=self.onexit)	# Item in the File menu on Windows
            menubar.add_cascade(label=_("File"), menu=file_menu)	# Menu title on Windows
            self.edit_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(label=_('Copy'), accelerator='Ctrl+C', state=tk.DISABLED, command=self.copy)	# As in Copy and Paste
            menubar.add_cascade(label=_('Edit'), menu=self.edit_menu)	# Menu title
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
        if platform == 'linux2':
            # Fix up menu to use same styling as everything else
            (fg, bg, afg, abg) = (style.lookup('TLabel.label', 'foreground'),
                                  style.lookup('TLabel.label', 'background'),
                                  style.lookup('TButton.label', 'foreground', ['active']),
                                  style.lookup('TButton.label', 'background', ['active']))
            menubar.configure(  fg = fg, bg = bg, activeforeground = afg, activebackground = abg)
            file_menu.configure(fg = fg, bg = bg, activeforeground = afg, activebackground = abg)
            self.edit_menu.configure(fg = fg, bg = bg, activeforeground = afg, activebackground = abg)
        self.w['menu'] = menubar

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match and (platform!='darwin' or int(match.group(2))>0):	# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                self.w.geometry(config.get('geometry'))
        self.w.update_idletasks()
        self.w.wait_visibility()
        (w, h) = (self.w.winfo_width(), self.w.winfo_height())
        self.w.minsize(w, h)		# Minimum size = initial size
        if platform != 'linux2':	# update_idletasks() doesn't allow for the menubar on Linux
            self.w.maxsize(-1, h)	# Maximum height = initial height

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)	# user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)	# user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'), config.getint('hotkey_mods'))

        # Install log monitoring
        self.w.bind_all('<<Jump>>', self.system_change)	# user-generated
        if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_AUTO|config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.login)
        else:
            self.login()
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        # Special handling for overrideredict
        self.w.bind("<Map>", self.onmap)

        plug.load_plugins()

        if platform != 'darwin':
            if platform == 'win32':
                self.w.wm_iconbitmap(default='EDMarketConnector.ico')
            else:
                from PIL import Image, ImageTk
                self.w.tk.call('wm', 'iconphoto', self.w, '-default', ImageTk.PhotoImage(Image.open("EDMarketConnector.png")))
            self.theme_icon = tk.PhotoImage(data = 'R0lGODlhEAAQAMYAAAAAAAEAAAEBAQICAgQEAwYFBAsHBAoIBgwIBAwIBQ0IBA8JBBAJBBAKBRMMBRkPBhoQBykWCSoWCCoXCTsfCzwfCkAhDEIjDD8kC0AlDEEmC0EmDEcoDk4oDU8pDU4qEFMrD1ktDlotD1ouD1g0EWAyEWU0EV03EmA4EWo2EW03EWQ6Emw4EWo9FGo+E3Y8FH5AFH1IFoBJFo1RGo1SGY1SGpBTGZFTGZJTGZhYG6piHa1kHa5kHbBkHr9uIMt0IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEKAEAALAAAAAAQABAAAAd7gACCg4SFhoeHGCiIhRs5JwMCkpKGGTIFODaaNjc/D4QaMQMAk5MuEIQOO6OFAiscCIQNPQk8NTO4NDofLwayPi0mIMPDLAcqvoIBDiQWkaUCAykKhAsXAoYCHRKEDDAjIyIiIyEEHhHYhAPr7BQlE+mMABXo8oTx9oWBADs=')
            self.theme_minimize = tk.BitmapImage(data = '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f,\n   0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n')
            self.theme_close    = tk.BitmapImage(data = '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x1c, 0x38, 0x38, 0x1c, 0x70, 0x0e,\n   0xe0, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x07, 0x70, 0x0e, 0x38, 0x1c,\n   0x1c, 0x38, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00 };\n')

        frame = tk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)

        self.cmdr_label = tk.Label(frame)
        self.system_label = tk.Label(frame)
        self.station_label = tk.Label(frame)

        self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
        self.system_label.grid(row=2, column=0, sticky=tk.W)
        self.station_label.grid(row=3, column=0, sticky=tk.W)

        self.cmdr = tk.Label(frame, anchor=tk.W)
        self.system =  HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True)
        self.station = HyperlinkLabel(frame, url = self.station_url, popup_copy = lambda x: x!=self.STATION_UNDOCKED)

        self.cmdr.grid(row=1, column=1, sticky=tk.EW)
        self.system.grid(row=2, column=1, sticky=tk.EW)
        self.station.grid(row=3, column=1, sticky=tk.EW)

        for plugname in plug.PLUGINS:
            appitem = plug.get_plugin_app(plugname, frame)
            if appitem:
                appitem.grid(columnspan=2, sticky=tk.W)

        self.button = ttk.Button(frame, text=_('Update'), width=28, command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED)	# Update button in main window
        self.theme_button = tk.Label(frame, width = platform == 'darwin' and 32 or 28, state=tk.DISABLED)
        self.status = tk.Label(frame, name='status', anchor=tk.W)

        row = frame.grid_size()[1]
        self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        theme.register_alternate((self.button, self.theme_button), {'row':row, 'columnspan':2, 'sticky':tk.NSEW})
        self.status.grid(columnspan=2, sticky=tk.EW)

        theme.button_bind(self.theme_button, self.getandsend)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        for child in frame.winfo_children():
            child.grid_configure(padx=5, pady=(platform=='win32' and 1 or 3))

        self.menubar = tk.Menu()
        if platform=='darwin':
            # Can't handle (de)iconify if topmost is set, so suppress iconify button
            # http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
            root.call('tk::unsupported::MacWindowStyle', 'style', root, 'document', 'closeBox horizontalZoom resizable')

            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            self.file_menu = tk.Menu(self.menubar, name='apple')
            self.file_menu.add_command(command=lambda:self.w.call('tk::mac::standardAboutPanel'))
            self.file_menu.add_command(command=lambda:self.updater.checkForUpdates())
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, name='edit')
            self.edit_menu.add_command(accelerator='Command-c', state=tk.DISABLED, command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(self.menubar, name='view')
            self.view_menu.add_command(state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))
            self.menubar.add_cascade(menu=self.view_menu)
            window_menu = tk.Menu(self.menubar, name='window')
            self.menubar.add_cascade(menu=window_menu)
            self.w['menu'] = self.menubar
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand('tkAboutDialog', lambda:self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand("::tk::mac::ShowPreferences", lambda:prefs.PreferencesDialog(self.w, self.postprefs))
            self.w.createcommand("::tk::mac::ReopenApplication", self.w.deiconify)	# click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW", self.w.withdraw)	# close button shouldn't quit app
        else:
            self.file_menu = self.view_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
            self.file_menu.add_command(state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))
            self.file_menu.add_command(command=lambda:self.updater.checkForUpdates())
            self.file_menu.add_command(command=lambda:prefs.PreferencesDialog(self.w, self.postprefs))
            self.file_menu.add_separator()
            self.file_menu.add_command(command=self.onexit)
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(accelerator='Ctrl+C', state=tk.DISABLED, command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            if platform == 'win32':
                # Must be added after at least one "real" menu entry
                self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop'))
                system_menu = tk.Menu(self.menubar, name='system', tearoff=tk.FALSE)
                system_menu.add_separator()
                system_menu.add_checkbutton(label=_('Always on top'), variable = self.always_ontop, command=self.ontop_changed)	# Appearance setting
                self.menubar.add_cascade(menu=system_menu)	# Gets index 0
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
            theme.register(self.menubar)	# menus and children aren't automatically registered
            theme.register(self.file_menu)
            theme.register(self.edit_menu)

            # Alternate title bar and menu for dark theme
            self.theme_menubar = tk.Frame(frame)
            self.theme_menubar.columnconfigure(2, weight=1)
            theme_titlebar = tk.Label(self.theme_menubar, text=applongname, image=self.theme_icon, anchor=tk.W, compound=tk.LEFT)
            theme_titlebar.grid(columnspan=3, sticky=tk.NSEW)
            self.drag_offset = None
            theme_titlebar.bind('<Button-1>', self.drag_start)
            theme_titlebar.bind('<B1-Motion>', self.drag_continue)
            theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
            if platform == 'win32':	# Can't work out how to deiconify on Linux
                theme_minimize = tk.Label(self.theme_menubar, image=self.theme_minimize)
                theme_minimize.grid(row=0, column=3)
                theme.button_bind(theme_minimize, self.oniconify, image=self.theme_minimize)
            theme_close = tk.Label(self.theme_menubar, image=self.theme_close)
            theme_close.grid(row=0, column=4)
            theme.button_bind(theme_close, self.onexit, image=self.theme_close)
            self.theme_file_menu = tk.Label(self.theme_menubar, anchor=tk.W)
            self.theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W)
            theme.button_bind(self.theme_file_menu, lambda e: self.file_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height()))
            self.theme_edit_menu = tk.Label(self.theme_menubar, anchor=tk.W)	# Menu title
            self.theme_edit_menu.grid(row=1, column=1, sticky=tk.W)
            theme.button_bind(self.theme_edit_menu, lambda e: self.edit_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height()))
            theme.register_highlight(theme_titlebar)
            theme.register(self.theme_minimize)	# images aren't automatically registered
            theme.register(self.theme_close)
            theme.register_alternate((self.menubar, self.theme_menubar), {'row':0, 'columnspan':2, 'sticky':tk.NSEW})

        self.set_labels()

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match:
                if platform == 'darwin':
                    if int(match.group(2)) >= 0:	# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                        self.w.geometry(config.get('geometry'))
                elif platform == 'win32':
                    # Check that the titlebar will be at least partly on screen
                    import ctypes
                    from ctypes.wintypes import POINT
                    # https://msdn.microsoft.com/en-us/library/dd145064
                    MONITOR_DEFAULTTONULL = 0
                    if ctypes.windll.user32.MonitorFromPoint(POINT(int(match.group(1)) + 16, int(match.group(2)) + 16), MONITOR_DEFAULTTONULL):

                        self.w.geometry(config.get('geometry'))
                else:
                    self.w.geometry(config.get('geometry'))
        self.w.attributes('-topmost', config.getint('always_ontop') and 1 or 0)
        self.w.resizable(tk.TRUE, tk.FALSE)

        theme.register(frame)
        theme.register_highlight(self.system)
        theme.register_highlight(self.station)
        theme.apply(self.w)

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)	# user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)	# user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'), config.getint('hotkey_mods'))

        # Install log monitoring
        monitor.set_callback(self.system_change)
        edproxy.set_callback(self.system_change)
        if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_FILE|config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)
            edproxy.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.postprefs)
        else:
            self.login()
Ejemplo n.º 10
0
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        # Special handling for overrideredict
        self.w.bind("<Map>", self.onmap)

        plug.load_plugins()

        if platform != 'darwin':
            if platform == 'win32':
                self.w.wm_iconbitmap(default='EDMarketConnector.ico')
            else:
                from PIL import Image, ImageTk
                self.w.tk.call(
                    'wm', 'iconphoto', self.w, '-default',
                    ImageTk.PhotoImage(Image.open("EDMarketConnector.png")))
            self.theme_icon = tk.PhotoImage(
                data=
                'R0lGODlhEAAQAMYAAAAAAAEAAAEBAQICAgQEAwYFBAsHBAoIBgwIBAwIBQ0IBA8JBBAJBBAKBRMMBRkPBhoQBykWCSoWCCoXCTsfCzwfCkAhDEIjDD8kC0AlDEEmC0EmDEcoDk4oDU8pDU4qEFMrD1ktDlotD1ouD1g0EWAyEWU0EV03EmA4EWo2EW03EWQ6Emw4EWo9FGo+E3Y8FH5AFH1IFoBJFo1RGo1SGY1SGpBTGZFTGZJTGZhYG6piHa1kHa5kHbBkHr9uIMt0IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEKAEAALAAAAAAQABAAAAd7gACCg4SFhoeHGCiIhRs5JwMCkpKGGTIFODaaNjc/D4QaMQMAk5MuEIQOO6OFAiscCIQNPQk8NTO4NDofLwayPi0mIMPDLAcqvoIBDiQWkaUCAykKhAsXAoYCHRKEDDAjIyIiIyEEHhHYhAPr7BQlE+mMABXo8oTx9oWBADs='
            )
            self.theme_minimize = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f,\n   0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n'
            )
            self.theme_close = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x1c, 0x38, 0x38, 0x1c, 0x70, 0x0e,\n   0xe0, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x07, 0x70, 0x0e, 0x38, 0x1c,\n   0x1c, 0x38, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00 };\n'
            )

        frame = tk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)

        self.cmdr_label = tk.Label(frame)
        self.system_label = tk.Label(frame)
        self.station_label = tk.Label(frame)

        self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
        self.system_label.grid(row=2, column=0, sticky=tk.W)
        self.station_label.grid(row=3, column=0, sticky=tk.W)

        self.cmdr = tk.Label(frame, anchor=tk.W)
        self.system = HyperlinkLabel(frame,
                                     compound=tk.RIGHT,
                                     url=self.system_url,
                                     popup_copy=True)
        self.station = HyperlinkLabel(
            frame,
            url=self.station_url,
            popup_copy=lambda x: x != self.STATION_UNDOCKED)

        self.cmdr.grid(row=1, column=1, sticky=tk.EW)
        self.system.grid(row=2, column=1, sticky=tk.EW)
        self.station.grid(row=3, column=1, sticky=tk.EW)

        for plugname in plug.PLUGINS:
            appitem = plug.get_plugin_app(plugname, frame)
            if appitem:
                appitem.grid(columnspan=2, sticky=tk.W)

        self.button = ttk.Button(
            frame,
            text=_('Update'),
            width=28,
            command=self.getandsend,
            default=tk.ACTIVE,
            state=tk.DISABLED)  # Update button in main window
        self.theme_button = tk.Label(frame,
                                     width=platform == 'darwin' and 32 or 28,
                                     state=tk.DISABLED)
        self.status = tk.Label(frame, name='status', anchor=tk.W)

        row = frame.grid_size()[1]
        self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        theme.register_alternate((self.button, self.theme_button), {
            'row': row,
            'columnspan': 2,
            'sticky': tk.NSEW
        })
        self.status.grid(columnspan=2, sticky=tk.EW)

        theme.button_bind(self.theme_button, self.getandsend)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        for child in frame.winfo_children():
            child.grid_configure(padx=5, pady=(platform == 'win32' and 1 or 3))

        self.menubar = tk.Menu()
        if platform == 'darwin':
            # Can't handle (de)iconify if topmost is set, so suppress iconify button
            # http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
            root.call('tk::unsupported::MacWindowStyle', 'style', root,
                      'document', 'closeBox horizontalZoom resizable')

            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            self.file_menu = tk.Menu(self.menubar, name='apple')
            self.file_menu.add_command(
                command=lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.file_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, name='edit')
            self.edit_menu.add_command(accelerator='Command-c',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(self.menubar, name='view')
            self.view_menu.add_command(
                state=tk.DISABLED,
                command=lambda: stats.StatsDialog(self.w, self.session))
            self.menubar.add_cascade(menu=self.view_menu)
            window_menu = tk.Menu(self.menubar, name='window')
            self.menubar.add_cascade(menu=window_menu)
            self.w['menu'] = self.menubar
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand(
                'tkAboutDialog',
                lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand(
                "::tk::mac::ShowPreferences",
                lambda: prefs.PreferencesDialog(self.w, self.postprefs))
            self.w.createcommand(
                "::tk::mac::ReopenApplication",
                self.w.deiconify)  # click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW",
                            self.w.withdraw)  # close button shouldn't quit app
        else:
            self.file_menu = self.view_menu = tk.Menu(self.menubar,
                                                      tearoff=tk.FALSE)
            self.file_menu.add_command(
                state=tk.DISABLED,
                command=lambda: stats.StatsDialog(self.w, self.session))
            self.file_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.file_menu.add_command(command=lambda: prefs.PreferencesDialog(
                self.w, self.postprefs))
            self.file_menu.add_separator()
            self.file_menu.add_command(command=self.onexit)
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(accelerator='Ctrl+C',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            if platform == 'win32':
                # Must be added after at least one "real" menu entry
                self.always_ontop = tk.BooleanVar(
                    value=config.getint('always_ontop'))
                system_menu = tk.Menu(self.menubar,
                                      name='system',
                                      tearoff=tk.FALSE)
                system_menu.add_separator()
                system_menu.add_checkbutton(
                    label=_('Always on top'),
                    variable=self.always_ontop,
                    command=self.ontop_changed)  # Appearance setting
                self.menubar.add_cascade(menu=system_menu)  # Gets index 0
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
            theme.register(
                self.menubar
            )  # menus and children aren't automatically registered
            theme.register(self.file_menu)
            theme.register(self.edit_menu)

            # Alternate title bar and menu for dark theme
            self.theme_menubar = tk.Frame(frame)
            self.theme_menubar.columnconfigure(2, weight=1)
            theme_titlebar = tk.Label(self.theme_menubar,
                                      text=applongname,
                                      image=self.theme_icon,
                                      anchor=tk.W,
                                      compound=tk.LEFT)
            theme_titlebar.grid(columnspan=3, sticky=tk.NSEW)
            self.drag_offset = None
            theme_titlebar.bind('<Button-1>', self.drag_start)
            theme_titlebar.bind('<B1-Motion>', self.drag_continue)
            theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
            if platform == 'win32':  # Can't work out how to deiconify on Linux
                theme_minimize = tk.Label(self.theme_menubar,
                                          image=self.theme_minimize)
                theme_minimize.grid(row=0, column=3)
                theme.button_bind(theme_minimize,
                                  self.oniconify,
                                  image=self.theme_minimize)
            theme_close = tk.Label(self.theme_menubar, image=self.theme_close)
            theme_close.grid(row=0, column=4)
            theme.button_bind(theme_close, self.onexit, image=self.theme_close)
            self.theme_file_menu = tk.Label(self.theme_menubar, anchor=tk.W)
            self.theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W)
            theme.button_bind(
                self.theme_file_menu, lambda e: self.file_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            self.theme_edit_menu = tk.Label(self.theme_menubar,
                                            anchor=tk.W)  # Menu title
            self.theme_edit_menu.grid(row=1, column=1, sticky=tk.W)
            theme.button_bind(
                self.theme_edit_menu, lambda e: self.edit_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            theme.register_highlight(theme_titlebar)
            theme.register(
                self.theme_minimize)  # images aren't automatically registered
            theme.register(self.theme_close)
            theme.register_alternate((self.menubar, self.theme_menubar), {
                'row': 0,
                'columnspan': 2,
                'sticky': tk.NSEW
            })

        self.set_labels()

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match:
                if platform == 'darwin':
                    if int(
                            match.group(2)
                    ) >= 0:  # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                        self.w.geometry(config.get('geometry'))
                elif platform == 'win32':
                    # Check that the titlebar will be at least partly on screen
                    import ctypes
                    from ctypes.wintypes import POINT
                    # https://msdn.microsoft.com/en-us/library/dd145064
                    MONITOR_DEFAULTTONULL = 0
                    if ctypes.windll.user32.MonitorFromPoint(
                            POINT(
                                int(match.group(1)) + 16,
                                int(match.group(2)) + 16),
                            MONITOR_DEFAULTTONULL):

                        self.w.geometry(config.get('geometry'))
                else:
                    self.w.geometry(config.get('geometry'))
        self.w.attributes('-topmost', config.getint('always_ontop') and 1 or 0)
        self.w.resizable(tk.TRUE, tk.FALSE)

        theme.register(frame)
        theme.register_highlight(self.system)
        theme.register_highlight(self.station)
        theme.apply(self.w)

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)  # user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)  # user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'),
                           config.getint('hotkey_mods'))

        # Install log monitoring
        monitor.set_callback(self.system_change)
        edproxy.set_callback(self.system_change)
        if (config.getint('output') & config.OUT_LOG_AUTO) and (
                config.getint('output') &
            (config.OUT_LOG_FILE | config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)
            edproxy.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.postprefs)
        else:
            self.login()