10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"Dialog to specify or edit the parameters for a user configured help source." 20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os 40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys 50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom Tkinter import * 70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport tkMessageBox 80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport tkFileDialog 90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass GetHelpSourceDialog(Toplevel): 110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self, parent, title, menuItem='', filePath=''): 120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Get menu entry and url/ local file location for Additional Help 130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi User selects a name for the Help resource and provides a web url 150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi or a local file as its source. The user can enter a url or browse 160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for the file. 170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Toplevel.__init__(self, parent) 200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.configure(borderwidth=5) 210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.resizable(height=FALSE, width=FALSE) 220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.title(title) 230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.transient(parent) 240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.grab_set() 250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.protocol("WM_DELETE_WINDOW", self.Cancel) 260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.parent = parent 270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.result = None 280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.CreateWidgets() 290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.menu.set(menuItem) 300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.path.set(filePath) 310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.withdraw() #hide while setting geometry 320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi #needs to be done here so that the winfo_reqwidth is valid 330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.update_idletasks() 340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi #centre dialog over parent: 350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.geometry("+%d+%d" % 360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ((parent.winfo_rootx() + ((parent.winfo_width()/2) 370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi -(self.winfo_reqwidth()/2)), 380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parent.winfo_rooty() + ((parent.winfo_height()/2) 390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi -(self.winfo_reqheight()/2))))) 400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.deiconify() #geometry set, unhide 410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.bind('<Return>', self.Ok) 420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.wait_window() 430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def CreateWidgets(self): 450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.menu = StringVar(self) 460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.path = StringVar(self) 470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.fontSize = StringVar(self) 480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.frameMain = Frame(self, borderwidth=2, relief=GROOVE) 490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) 500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi labelMenu = Label(self.frameMain, anchor=W, justify=LEFT, 510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text='Menu Item:') 520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu = Entry(self.frameMain, textvariable=self.menu, 530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi width=30) 540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu.focus_set() 550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi labelPath = Label(self.frameMain, anchor=W, justify=LEFT, 560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text='Help File Path: Enter URL or browse for file') 570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryPath = Entry(self.frameMain, textvariable=self.path, 580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi width=40) 590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu.focus_set() 600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi labelMenu.pack(anchor=W, padx=5, pady=3) 610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu.pack(anchor=W, padx=5, pady=3) 620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi labelPath.pack(anchor=W, padx=5, pady=3) 630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryPath.pack(anchor=W, padx=5, pady=3) 640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi browseButton = Button(self.frameMain, text='Browse', width=8, 650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi command=self.browseFile) 660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi browseButton.pack(pady=3) 670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi frameButtons = Frame(self) 680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi frameButtons.pack(side=BOTTOM, fill=X) 690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.buttonOk = Button(frameButtons, text='OK', 700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi width=8, default=ACTIVE, command=self.Ok) 710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.buttonOk.grid(row=0, column=0, padx=5,pady=5) 720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.buttonCancel = Button(frameButtons, text='Cancel', 730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi width=8, command=self.Cancel) 740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) 750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def browseFile(self): 770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filetypes = [ 780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("HTML Files", "*.htm *.html", "TEXT"), 790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("PDF Files", "*.pdf", "TEXT"), 800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("Windows Help Files", "*.chm"), 810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("Text Files", "*.txt", "TEXT"), 820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("All Files", "*")] 830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = self.path.get() 840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if path: 850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir, base = os.path.split(path) 860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi base = None 880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if sys.platform[:3] == 'win': 890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir = os.path.join(os.path.dirname(sys.executable), 'Doc') 900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not os.path.isdir(dir): 910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir = os.getcwd() 920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir = os.getcwd() 940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes) 950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi file = opendialog.show(initialdir=dir, initialfile=base) 960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if file: 970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.path.set(file) 980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def MenuOk(self): 1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Simple validity check for a sensible menu item name" 1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi menuOk = True 1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi menu = self.menu.get() 1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi menu.strip() 1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not menu: 1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tkMessageBox.showerror(title='Menu Item Error', 1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi message='No menu item specified', 1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parent=self) 1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu.focus_set() 1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi menuOk = False 1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif len(menu) > 30: 1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tkMessageBox.showerror(title='Menu Item Error', 1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi message='Menu item too long:' 1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\nLimit 30 characters.', 1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parent=self) 1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryMenu.focus_set() 1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi menuOk = False 1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return menuOk 1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def PathOk(self): 1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Simple validity check for menu file path" 1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pathOk = True 1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = self.path.get() 1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path.strip() 1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not path: #no path specified 1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tkMessageBox.showerror(title='File Path Error', 1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi message='No help file path specified.', 1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parent=self) 1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryPath.focus_set() 1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pathOk = False 1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif path.startswith(('www.', 'http')): 1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if path[:5] == 'file:': 1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = path[5:] 1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not os.path.exists(path): 1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tkMessageBox.showerror(title='File Path Error', 1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi message='Help file path does not exist.', 1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parent=self) 1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.entryPath.focus_set() 1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pathOk = False 1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return pathOk 1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def Ok(self, event=None): 1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if self.MenuOk() and self.PathOk(): 1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.result = (self.menu.get().strip(), 1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.path.get().strip()) 1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if sys.platform == 'darwin': 1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = self.result[1] 1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if path.startswith(('www', 'file:', 'http:')): 1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Mac Safari insists on using the URI form for local files 1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.result = list(self.result) 1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.result[1] = "file://" + path 1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.destroy() 1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def Cancel(self, event=None): 1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.result = None 1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.destroy() 1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__': 1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi #test the dialog 1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi root = Tk() 1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def run(): 1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi keySeq = '' 1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dlg = GetHelpSourceDialog(root, 'Get Help Source') 1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print dlg.result 1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Button(root,text='Dialog', command=run).pack() 1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi root.mainloop() 170