class TableView(Frame): OPTIONS = {'font': ('bold', 11)} def __init__(self, window, **kwargs): super().__init__(window, **kwargs) self.tree = Treeview(self, selectmode='browse') self.tree.column("#0", width=100, minwidth=75, stretch=NO) self.tree.heading("#0", text='row', anchor='center') self.scroll = Scrollbar(self, command=self.tree.yview) self.tree.config(yscrollcommand=self.scroll.set) self.scroll.pack(side=RIGHT, fill=Y) self.tree.pack(expand=True, side=LEFT, fill=BOTH) def create_columns(self, *columns): for column in columns: self.tree.column(f"{column}", width=150, minwidth=150, stretch=YES) def create_heading(self, *columns): for index, column in enumerate(columns): self.tree.heading(f"#{index+1}", text=f"{column}", anchor='center') def fill_row(self, *args): if args: self.tree.delete(*self.tree.get_children()) for index, contact in enumerate(args): self.tree.insert("", 'end', contact.id, text=f"{index+1}", values=list(contact.informations.values())) else: return
def listVideos(self, chan, target): self.center = target #get chan id chanid = database.get_channel_id(chan) vids = database.get_channel_videos(chanid) tree = Treeview(self.center) tree["columns"] = ("one", "two") tree.column("#0", width=20, minwidth=10, stretch=YES) tree.column("one", width=390, minwidth=250, stretch=YES) tree.column("two", width=200, minwidth=40) tree.heading("#0", text="ID", anchor=W) tree.heading("one", text="Title", anchor=W) tree.heading("two", text="Date", anchor=W) i = 0 tree.tag_configure('oddrow', background='#88DD88') tree.tag_configure('evenrow', background='#FFFFFF') for videodata in vids: foldername = "folder" + str(i) if i % 2 == 0: color = "evenrow" else: color = "oddrow" # tree.insert("", 1, "", text="Folder 1", values=("23-Jun-17 11:05","File folder","")) ts = int(videodata.publish_date) foldername = tree.insert("", "end", text=videodata.yt_videoid, values=(videodata.title, time.ctime(ts)), tags=(color)) #tree.insert(folder1, "end", "", text="photo1.png", values=("23-Jun-17 11:28","PNG file","2.6 KB")) tree.insert(foldername, "end", text="desc", values=(videodata.description, videodata.watched), tags=(color)) i = i + 1 vertscroll = Scrollbar(self.center) vertscroll.config(command=tree.yview) tree.config(yscrollcommand=vertscroll.set) tree.bind("<Button-" + config.mousebuttons + ">", self.video_action_window) tree.grid(row=5, columnspan=3, sticky="NSEW")
def config_table(self, table: ttk.Treeview, **kwds) -> None: """Method for a table configuration.""" height = kwds.get('height', 24) columns = kwds.get('columns', ['']) show = kwds.get('show', 'headings') headwidths = kwds.get('headwidths', [490]) selectmode = kwds.get('selectmode', 'extended') table.config(selectmode=selectmode, columns=columns, height=height, show=show) for heading, headwidth in zip(columns, headwidths): table.heading(heading, text=heading, anchor=CENTER) table.column(heading, width=headwidth, minwidth=headwidth - 8, anchor=W)
def setupTreeView(self): #probably want treeview, not listbox scr_w = 180 scr_h = 10 tabConfig = configRoot.findall('treeview/tab') self.tabLabelList = [] self.headingDict = {} for t in tabConfig: tabName = t.attrib['label'] self.tabLabelList.append(tabName) headingConfig = t.findall('heading') temp = [] for h in headingConfig: temp.append(h.attrib['label']) self.headingDict[tabName] = temp.copy() temp.clear() print(self.headingDict) for tab in self.tabControl.winfo_children(): # listbox = Listbox(tab, width = 120) # listbox.grid(column = 0, row = 0, padx = 20, pady = 10) tabText = self.tabControl.tab(tab)['text'] treeview = Treeview(tab) #treeview['columns'] = ('Title', 'Author', 'Platform') treeview['columns'] = self.headingDict[tabText] treeview.heading("#0", text="ID") treeview.column('#0', minwidth=50, width=50, stretch=False) for h in treeview['columns']: print(h) treeview.heading(h, text=h) treeview.grid( column=0, row=0, sticky="NSEW", ) treeview.bind("<Double-1>", self.itemSelected) treeview.config(height=25) scrollbar = Scrollbar(tab) scrollbar.grid(column=1, row=0, sticky="NS") treeview.config(yscrollcommand=scrollbar.set) scrollbar.config(command=treeview.yview)
def show_feed(self, body, value): center = body tree = Treeview(center) tree["columns"] = ("one", "two") tree.column("#0", width=20, minwidth=10, stretch=YES) tree.column("one", width=390, minwidth=250, stretch=YES) tree.column("two", width=200, minwidth=40) tree.heading("#0", text="ID", anchor=W) tree.heading("one", text="Title", anchor=W) tree.heading("two", text="Date", anchor=W) i = 0 tree.tag_configure('oddrow', background='#88DD88') tree.tag_configure('evenrow', background='#FFFFFF') vids = self.get_feed(value) for videodata in vids: foldername = "folder" + str(i) if i % 2 == 0: color = "evenrow" else: color = "oddrow" ts = int(videodata.publish_date) foldername = tree.insert("", "end", text=i, values=(videodata.title, time.ctime(ts)), tags=(color)) tree.insert(foldername, "end", text="desc", values=(videodata.description, ""), tags=(color)) i = i + 1 vertscroll = Scrollbar(center) vertscroll.config(command=tree.yview) tree.config(yscrollcommand=vertscroll.set) tree.grid(row=5, columnspan=3, sticky="NSEW") vertscroll.grid(column=3, row=5, sticky='NSE')
def consultar(buscartabla): name = buscartabla # fetch(buscartabla) filewin = Toplevel(root) frame_router = Frame(filewin) frame_router.grid(row=4, column=0, columnspan=4, rowspan=6, pady=20, padx=20) buscarColumnas = """PRAGMA table_info({});""".format(buscartabla) infoTabla = CursorSql.execute(buscarColumnas) buscartabla = [] for campo in infoTabla: buscartabla.append(campo[1]) #end for query = f"select * from '{name}'" dataTable = CursorSql.execute(query).fetchall() # print(dataTable[0][0]) columns = buscartabla router_tree_view = Treeview(frame_router, columns=columns, show="headings") router_tree_view.column(buscartabla[0], width=100) for col in columns[0:]: router_tree_view.column(col, width=120) router_tree_view.heading(col, text=col) #end for if type(dataTable) is list: for data in dataTable: i = 0 router_tree_view.insert('', i, values=dinamyFill(name, data)) i = i + 1 #end for router_tree_view.pack(side="left", fill="y") scrollbar = Scrollbar(frame_router, orient='vertical') scrollbar.configure(command=router_tree_view.yview) scrollbar.pack(side="right", fill="y") router_tree_view.config(yscrollcommand=scrollbar.set) filewin.geometry("400x300") filewin.mainloop()
class DialogOpenArchive(Toplevel): def __init__(self, parent, openType, filesource, filenames, title, colHeader, showAltViewButton=False, multiselect=False): if isinstance(parent, Cntlr): cntlr = parent parent = parent.parent # parent is cntlrWinMain else: # parent is a Toplevel dialog cntlr = parent.cntlr super(DialogOpenArchive, self).__init__(parent) self.parent = parent self.showAltViewButton = showAltViewButton parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.accepted = False self.transient(self.parent) frame = Frame(self) treeFrame = Frame(frame, width=500) vScrollbar = Scrollbar(treeFrame, orient=VERTICAL) hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL) self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set) self.treeView.grid(row=0, column=0, sticky=(N, S, E, W)) self.treeView.config( selectmode="extended" if multiselect else "browse") hScrollbar["command"] = self.treeView.xview hScrollbar.grid(row=1, column=0, sticky=(E, W)) vScrollbar["command"] = self.treeView.yview vScrollbar.grid(row=0, column=1, sticky=(N, S)) treeFrame.columnconfigure(0, weight=1) treeFrame.rowconfigure(0, weight=1) treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.treeView.focus_set() if openType not in (PLUGIN, PACKAGE): cntlr.showStatus(_("loading archive {0}").format(filesource.url)) self.filesource = filesource self.filenames = filenames self.selection = filesource.selection self.hasToolTip = False self.multiselect = multiselect selectedNode = None if openType == ENTRY_POINTS: try: metadataFiles = filesource.taxonomyPackageMetadataFiles ''' take first for now if len(metadataFiles) != 1: raise IOError(_("Taxonomy package contained more than one metadata file: {0}.") .format(', '.join(metadataFiles))) ''' metadataFile = metadataFiles[0] metadata = filesource.url + os.sep + metadataFile self.metadataFilePrefix = os.sep.join( os.path.split(metadataFile)[:-1]) if self.metadataFilePrefix: self.metadataFilePrefix += "/" # zip contents have /, never \ file seps self.taxonomyPkgMetaInf = '{}/META-INF/'.format( os.path.splitext(os.path.basename(filesource.url))[0]) self.taxonomyPackage = parsePackage( cntlr, filesource, metadata, os.sep.join(os.path.split(metadata)[:-1]) + os.sep) if self.taxonomyPackage["entryPoints"]: # may have instance documents too self.packageContainedInstances = [] self.packageContainedIXDSes = defaultdict(list) packageContentInstanceCounts = {} packageContentTypeCounts = {} for suffix in ( ".xhtml", ".htm", ".html" ): # try for suffixes in order of likelihood to have instance for potentialInstance in filesource.dir: if potentialInstance.endswith(suffix): m = reportIxdsPattern.match( potentialInstance) # IXDS if multiselect and m: # only in ixds multiselect mode _type = "Inline Doc Set" self.packageContainedIXDSes[m.group( 1)].append(potentialInstance) potentialInstance = m.group( 1) # use package name only else: _type = "Inline Instance" if not self.packageContainedInstances or self.packageContainedInstances[ -1][0] != potentialInstance: self.packageContainedInstances.append( [potentialInstance, _type]) packageContentInstanceCounts[ potentialInstance] = packageContentInstanceCounts.get( potentialInstance, 0) + 1 packageContentTypeCounts[ _type] = packageContentTypeCounts.get( _type, 0) + 1 if self.packageContainedInstances: break if self.packageContainedInstances: # add sequences to any duplicated entry types for _type, count in packageContentTypeCounts.items(): if count > 1: _dupNo = 0 for i in range( len(self.packageContainedInstances)): if self.packageContainedInstances[i][ 1] == _type: _dupNo += 1 self.packageContainedInstances[i][ 1] = "{} {}".format(_type, _dupNo) for _instance, count in packageContentInstanceCounts.items( ): if count > 1: _dupNo = 0 for i in range( len(self.packageContainedInstances)): if self.packageContainedInstances[i][ 0] == _instance: _dupNo += 1 self.packageContainedInstances[i][ 0] = "{} {}".format( _instance, _dupNo) else: # may be a catalog file with no entry oint names openType = ARCHIVE # no entry points to show, just archive self.showAltViewButton = False except Exception as e: self.close() err = _( "Failed to parse metadata; the underlying error was: {0}" ).format(e) messagebox.showerror(_("Malformed taxonomy package"), err) cntlr.addToLog(err) return if openType not in (PLUGIN, PACKAGE): cntlr.showStatus(None) if openType in (DISCLOSURE_SYSTEM, PLUGIN, PACKAGE): y = 3 else: y = 1 okButton = Button(frame, text=_("OK"), command=self.ok) cancelButton = Button(frame, text=_("Cancel"), command=self.close) okButton.grid(row=y, column=2, sticky=(S, E, W), pady=3) cancelButton.grid(row=y, column=3, sticky=(S, E, W), pady=3, padx=3) if self.showAltViewButton: self.altViewButton = Button(frame, command=self.showAltView) self.altViewButton.grid(row=y, column=0, sticky=(S, W), pady=3, padx=3) self.loadTreeView(openType, colHeader, title) self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100)) frame.grid(row=0, column=0, sticky=(N, S, E, W)) frame.columnconfigure(0, weight=1) frame.rowconfigure(0, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) window.rowconfigure(0, weight=1) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.toolTipText = StringVar() if self.hasToolTip: self.treeView.bind("<Motion>", self.motion, '+') self.treeView.bind("<Leave>", self.leave, '+') self.toolTipText = StringVar() self.toolTip = ToolTip(self.treeView, textvariable=self.toolTipText, wraplength=640, follow_mouse=True, state="disabled") self.toolTipRowId = None self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeView(self, openType, title, colHeader): self.title(title) self.openType = openType selectedNode = None # clear previous treeview entries for previousNode in self.treeView.get_children(""): self.treeView.delete(previousNode) # set up treeView widget and tabbed pane if openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE): if openType in (PLUGIN, PACKAGE): width = 770 else: width = 500 self.treeView.column("#0", width=width, anchor="w") self.treeView.heading("#0", text=colHeader) self.isRss = getattr(self.filesource, "isRss", False) if self.isRss: self.treeView.column("#0", width=350, anchor="w") self.treeView["columns"] = ("descr", "date", "instDoc") self.treeView.column("descr", width=50, anchor="center", stretch=False) self.treeView.heading("descr", text="Form") self.treeView.column("date", width=170, anchor="w", stretch=False) self.treeView.heading("date", text="Pub Date") self.treeView.column("instDoc", width=200, anchor="w", stretch=False) self.treeView.heading("instDoc", text="Instance Document") elif openType == PLUGIN: self.treeView.column("#0", width=150, anchor="w") self.treeView["columns"] = ("name", "vers", "descr", "license") self.treeView.column("name", width=150, anchor="w", stretch=False) self.treeView.heading("name", text="Name") self.treeView.column("vers", width=60, anchor="w", stretch=False) self.treeView.heading("vers", text="Version") self.treeView.column("descr", width=300, anchor="w", stretch=False) self.treeView.heading("descr", text="Description") self.treeView.column("license", width=60, anchor="w", stretch=False) self.treeView.heading("license", text="License") elif openType == PACKAGE: self.treeView.column("#0", width=200, anchor="w") self.treeView["columns"] = ("vers", "descr", "license") self.treeView.column("vers", width=100, anchor="w", stretch=False) self.treeView.heading("vers", text="Version") self.treeView.column("descr", width=400, anchor="w", stretch=False) self.treeView.heading("descr", text="Description") self.treeView.column("license", width=70, anchor="w", stretch=False) self.treeView.heading("license", text="License") else: self.treeView["columns"] = tuple() loadedPaths = [] for i, filename in enumerate(self.filenames): if isinstance(filename, tuple): if self.isRss: form, date, instDoc = filename[2:5] elif openType == PLUGIN: name, vers, descr, license = filename[3:7] elif openType == PACKAGE: vers, descr, license = filename[3:6] filename = filename[0] # ignore tooltip self.hasToolTip = True if filename.endswith("/"): filename = filename[:-1] path = filename.split("/") if not self.isRss and len( path) > 1 and path[:-1] in loadedPaths: parent = "file{0}".format(loadedPaths.index(path[:-1])) else: parent = "" node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1]) if self.isRss: self.treeView.set(node, "descr", form) self.treeView.set(node, "date", date) self.treeView.set(node, "instDoc", os.path.basename(instDoc)) elif openType == PLUGIN: self.treeView.set(node, "name", name) self.treeView.set(node, "vers", vers) self.treeView.set(node, "descr", descr) self.treeView.set(node, "license", license) elif openType == PACKAGE: self.treeView.set(node, "vers", vers) self.treeView.set(node, "descr", descr) self.treeView.set(node, "license", license) if self.selection == filename: selectedNode = node loadedPaths.append(path) elif openType == ENTRY_POINTS: self.treeView.column("#0", width=200, anchor="w") self.treeView.heading("#0", text="Name") self.treeView["columns"] = ("url", ) self.treeView.column("url", width=300, anchor="w") self.treeView.heading("url", text="URL") for fileType, fileUrl in getattr(self, "packageContainedInstances", ()): self.treeView.insert("", "end", fileUrl, values=fileType, text=fileUrl or urls[0][2]) for name, urls in sorted( self.taxonomyPackage["entryPoints"].items(), key=lambda i: i[0][2]): self.treeView.insert("", "end", name, values="\n".join(url[1] for url in urls), text=name or urls[0][2]) self.hasToolTip = True else: # unknown openType return None if selectedNode: self.treeView.see(selectedNode) self.treeView.selection_set(selectedNode) if self.showAltViewButton: self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries")) def ok(self, event=None): selection = self.treeView.selection() if len(selection) > 0: filename = None if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM): if self.multiselect: filenames = [] for _selection in selection: filename = self.filenames[int(_selection[4:])] if isinstance(filename, tuple): if self.isRss: filename = filename[4] else: filename = filename[0] if self.multiselect: filenames.append(filename) else: break if self.multiselect and filenames: self.filesource.select(filenames) # array of file names self.accepted = True self.close() elif self.openType == ENTRY_POINTS: epName = selection[0] #index 0 is the remapped Url, as opposed to the canonical one used for display # Greg Acsone reports [0] does not work for Corep 1.6 pkgs, need [1], old style packages filenames = [] for _url, _type in self.packageContainedInstances: # check if selection was an inline instance if _type in selection: if _url in self.packageContainedIXDSes: # taxonomy package filenames.extend(self.packageContainedIXDSes[_url]) else: # single instance filenames.append(_url) if not filenames: # else if it's a named taxonomy entry point for url in self.taxonomyPackage["entryPoints"][epName]: filename = url[0] if not filename.endswith("/"): # check if it's an absolute URL rather than a path into the archive if not isHttpUrl( filename ) and self.metadataFilePrefix != self.taxonomyPkgMetaInf: # assume it's a path inside the archive: filename = self.metadataFilePrefix + filename filenames.append(filename) if filenames: self.filesource.select(filenames) self.accepted = True self.close() return elif self.openType in (PLUGIN, PACKAGE): filename = self.filenames[int(selection[0][4:])][2] if filename is not None and not self.multiselect and not filename.endswith( "/"): if hasattr(self, "taxonomyPackage"): # attempt to unmap the filename to original file # will be mapped again in loading, but this allows schemaLocation to be unmapped for prefix, remapping in self.taxonomyPackage[ "remappings"].items(): if isHttpUrl(remapping): remapStart = remapping else: remapStart = self.metadataFilePrefix + remapping if filename.startswith(remapStart): # set unmmapped file filename = prefix + filename[len(remapStart):] break if self.openType in (PLUGIN, PACKAGE): self.filesource.selection = filename else: self.filesource.select(filename) self.accepted = True self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def showAltView(self, event=None): if self.openType == ENTRY_POINTS: self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File")) else: self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File")) def leave(self, *args): self.toolTipRowId = None def motion(self, *args): tvRowId = self.treeView.identify_row(args[0].y) if tvRowId != self.toolTipRowId: text = None if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE): self.toolTipRowId = tvRowId if tvRowId and len(tvRowId) > 4: try: text = self.filenames[int(tvRowId[4:])] if isinstance(text, tuple): text = (text[1] or "").replace("\\n", "\n") except (KeyError, ValueError): pass elif self.openType == ENTRY_POINTS: try: text = "{0}\n{1}".format( tvRowId, "\n".join( url[1] for url in self.taxonomyPackage["entryPoints"][tvRowId])) except KeyError: pass self.setToolTip(text) def setToolTip(self, text): self.toolTip._hide() if text: self.toolTipText.set(text) self.toolTip.configure(state="normal") self.toolTip._schedule() else: self.toolTipText.set("") self.toolTip.configure(state="disabled")
class Gui(tk.Frame): """Main program graphical user interface""" def __init__(self, master=None, *args, **kwargs): super().__init__(master, *args, **kwargs) self.build_menu(), self.build() def build_menu(self): """Initializes and builds program menu bar""" self.top = tk.Menu(self) # create file menu self.file = tk.Menu(self.top, tearoff=False) self.file.add_command(label='Search', accelerator='Ctrl+S', command=self.search, compound=tk.LEFT, underline=0) self.file.add_separator() self.file.add_command(label='Exit', command=self.quit_program, underline=0) self.top.add_cascade(label='File', menu=self.file, underline=0) # commands: view help, about self.info = tk.Menu(self.top, tearoff=False) self.info.add_command(label='About ...', command=self.view_credits, compound=tk.LEFT, underline=0) self.top.add_cascade(label='?', menu=self.info, underline=0) def build(self): """Builds main program interface""" # search frame f1 = tk.Frame() f1.grid(row=0, column=0) group = tk.LabelFrame(f1, text="Search", padx=5, pady=5, fg='brown') group.pack(side="top", expand='yes', fill='x', padx=2, pady=2, anchor='n') self.entry_main = tk.Entry(group, width=73) self.entry_main.grid(sticky='ne') # results frame f2 = tk.Frame() f2.grid(row=1, column=0) group_2 = tk.LabelFrame(f2, text="Results", padx=5, pady=5, fg='brown') group_2.pack(side="top", expand='yes', fill='both', padx=2, pady=2) self.status = tk.Label(f2, text='ready', font=('verdana', 6, 'normal')) self.status.pack(anchor='se') self.treeview = Treeview(group_2, column=('A', 'B'), selectmode='extended', height=5) self.treeview.grid(row=0, column=0, sticky='w') self.treeview.column("#0", stretch=tk.NO, width=200) self.treeview.heading("#0", text='target') self.treeview.column("A", width=150, anchor='center') self.treeview.heading("A", text='technology') self.treeview.column("B", width=70) self.treeview.heading("B", text="version") self.sbar = tk.Scrollbar(group_2) self.treeview.config(yscrollcommand=self.sbar.set) self.sbar.config(command=self.treeview.yview) self.sbar.grid(column=1, row=0, rowspan=1, pady=0, sticky='ens') # key shortcut bindings self.entry_main.bind('<Return>', self.search) self.entry_main.bind('<Double-1>', self.search) self.bind_all('<Control-S>', self.search) self.bind_all('<Control-s>', self.search) def search(self, event=None): """Triggers a threaded technology detection scan""" url = self.entry_main.get() self.status['text'] = 'scanning...' Thread(target=self.scan_target, args=(url, )).start() def scan_target(self, url): """Function to detect technologies running on target and list them in gui treeview""" _id = None try: d = Detector().detect(url=url, timeout=5) for result in d: if d[result]: ext = tldextract.extract(url) _id = self.treeview.insert('', 'end', text='.'.join(ext[:3])) tech_type, software = d[result][0].get('type'), \ d[result][0].get('app') version = d[result][0].get('ver') # assign to gui treeview if not version: version = 'None' self.treeview.insert(_id, 'end', text=tech_type, values=(software, version)) self.status['text'] = 'done' else: self.status['text'] = 'No results found' except ValueError: self.status['text'] = "Invalid! Please input a full url" finally: del _id def view_credits(self): """ Opens a new window providing credits information.""" # launch window and configure window settings self.win_credits = CreditsTool(self) self.win_credits.title('') self.win_credits.iconbitmap('wad/data/magnifier.ico') self.win_credits.geometry('+%d+%d' % (root.winfo_x() + 20, root.winfo_y() + 20)) self.win_credits.resizable(width=False, height=False) # set focus on window self.win_credits.grab_set() self.win_credits.focus() # start mainloop self.win_credits.mainloop() @staticmethod def quit_program(): """Quits main program window""" root.destroy()
class RefBook(Frame): ######## # Opens database from provided arguments and creates and populates widgets. def __init__(self, master, *args, **kwargs): super().__init__(master) self._dbm = DatabaseManager(*args, **kwargs) self._openItems = {} self._openStores = {} self._openAttacks = {} self._openCreatures = {} self._openLocations = {} self._create_widgets() self._populate_items() self._populate_stores() self._populate_attacks() self._populate_creatures() self._populate_locations() ######## # Initializes and places all GUI elements. def _create_widgets(self): self._nb = Notebook(self) # items self._itemTab = Frame(self._nb) self._itemTree = Treeview(self._itemTab, columns=["type", "value"], selectmode="browse", height=25) self._itemTree.heading("#0", text="Item", anchor=N + W) self._itemTree.column("#0", width=300, anchor=N + W, stretch=True) self._itemTree.heading("type", text="Type", anchor=N + W) self._itemTree.column("type", width=100, anchor=N + W) self._itemTree.heading("value", text="Value", anchor=N + W) self._itemTree.column("value", width=60, anchor=N + W) self._itemScroll = Scrollbar(self._itemTab, command=self._itemTree.yview) self._itemTree.config(yscrollcommand=self._itemScroll.set) self._itemTree.grid(row=0, column=0, sticky=N + W + S + E) self._itemScroll.grid(row=0, column=1, sticky=N + S) self._nb.add(self._itemTab, text="Items") # stores self._storeTab = Frame(self._nb) self._storeTree = Treeview(self._storeTab, columns=["location"], selectmode="browse", height=25) self._storeTree.heading("#0", text="Store", anchor=N + W) self._storeTree.column("#0", width=330, anchor=N + W, stretch=True) self._storeTree.heading("location", text="Location", anchor=N + W) self._storeTree.column("location", width=130, anchor=N + W) self._storeScroll = Scrollbar(self._storeTab, command=self._storeTree.yview) self._storeTree.config(yscrollcommand=self._storeScroll.set) self._storeTree.grid(row=0, column=0, sticky=N + W + S + E) self._storeScroll.grid(row=0, column=1, sticky=N + S) self._nb.add(self._storeTab, text="Stores") # attacks self._attackTab = Frame(self._nb) self._attackTree = Treeview(self._attackTab, columns=["id", "spell"], selectmode="browse", height=25) self._attackTree.heading("#0", text="Attacks", anchor=N + W) self._attackTree.column("#0", width=370, anchor=N + W, stretch=True) self._attackTree.heading("id", text="ID", anchor=N + W) self._attackTree.column("id", width=40, anchor=N + E) self._attackTree.heading("spell", text="Spell", anchor=N + W) self._attackTree.column("spell", width=50, anchor=CENTER) self._attackScroll = Scrollbar(self._attackTab, command=self._attackTree.yview) self._attackTree.config(yscrollcommand=self._attackScroll.set) self._attackTree.grid(row=0, column=0, sticky=N + W + S + E) self._attackScroll.grid(row=0, column=1, sticky=N + S) self._nb.add(self._attackTab, text="Attacks") # creatures self._creatureTab = Frame(self._nb) self._creatureTree = Treeview(self._creatureTab, columns=["hd"], selectmode="browse", height=25) self._creatureTree.heading("#0", text="Creatures", anchor=N + W) self._creatureTree.column("#0", width=420, anchor=N + W, stretch=True) self._creatureTree.heading("hd", text="HD", anchor=N + W) self._creatureTree.column("hd", width=40, anchor=N + E) self._creatureScroll = Scrollbar(self._creatureTab, command=self._creatureTree.yview) self._creatureTree.config(yscrollcommand=self._creatureScroll.set) self._creatureTree.grid(row=0, column=0, sticky=N + W + S + E) self._creatureScroll.grid(row=0, column=1, sticky=N + S) self._nb.add(self._creatureTab, text="Creatures") # locations self._locationTab = Frame(self._nb) self._locationTree = Treeview(self._locationTab, selectmode="browse", height=25) self._locationTree.heading("#0", text="Locations", anchor=N + W) self._locationTree.column("#0", width=460, anchor=N + W, stretch=True) self._locationScroll = Scrollbar(self._locationTab, command=self._locationTree.yview) self._locationTree.config(yscrollcommand=self._locationScroll.set) self._locationTree.grid(row=0, column=0, sticky=N + W + S + E) self._locationScroll.grid(row=0, column=1, sticky=N + S) self._nb.add(self._locationTab, text="Locations") self._nb.grid(row=0, column=0, sticky=N + W + S + E) # bindings self._itemTree.bind("<Double-Button-1>", self._item_on_double_click) self._storeTree.bind("<Double-Button-1>", self._store_on_double_click) self._attackTree.bind("<Double-Button-1>", self._attack_on_double_click) self._creatureTree.bind("<Double-Button-1>", self._creature_on_double_click) self._locationTree.bind("<Double-Button-1>", self._location_on_double_click) ######## # Populates item list. def _populate_items(self): self._itemList = self._dbm.get_item_list() allItems = self._itemTree.get_children() for item in allItems: self._itemTree.delete(item) self._itemImgs = [] if self._dbm == None: return for entry in self._itemList: img = entry["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["name"] fields = [BaseView.TYPE_MAP[entry["type"]], entry["value"]] for i in range(len(fields)): if fields[i] == None: fields[i] = BaseView.EMPTY_STR self._itemImgs.append(img) self._itemTree.insert("", END, image=img, text=name, values=fields) ######## # Populates store list. def _populate_stores(self): self._storeList = self._dbm.get_store_list() allStores = self._storeTree.get_children() for store in allStores: self._storeTree.delete(store) self._storeImgs = [] if self._dbm == None: return for entry in self._storeList: img = entry["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["name"] fields = [entry["location"]] for i in range(len(fields)): if fields[i] == None: fields[i] = BaseView.EMPTY_STR self._storeImgs.append(img) self._storeTree.insert("", END, image=img, text=name, values=fields) ######## # Populates attack list. def _populate_attacks(self): self._attackList = self._dbm.get_attack_list() allAttacks = self._attackTree.get_children() for attack in allAttacks: self._attackTree.delete(attack) self._attackImgs = [] if self._dbm == None: return for entry in self._attackList: img = entry["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["name"] fields = [entry["id"], "✔" if entry["isSpell"] else ""] for i in range(len(fields)): if fields[i] == None: fields[i] = BaseView.EMPTY_STR self._attackImgs.append(img) self._attackTree.insert("", END, image=img, text=name, values=fields) ######## # Populates creature list. def _populate_creatures(self): self._creatureList = self._dbm.get_creature_list() allCreatures = self._creatureTree.get_children() for creature in allCreatures: self._creatureTree.delete(creature) self._creatureImgs = [] if self._dbm == None: return for entry in self._creatureList: img = entry["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["name"] fields = [str(entry["hd"])] for i in range(len(fields)): if fields[i] == None: fields[i] = BaseView.EMPTY_STR self._creatureImgs.append(img) self._creatureTree.insert("", END, image=img, text=name, values=fields) ######## # Populates location list. def _populate_locations(self): self._locationList = self._dbm.get_location_list() allLocations = self._locationTree.get_children() for location in allLocations: self._locationTree.delete(location) self._locationImgs = [] if self._dbm == None: return for entry in self._locationList: img = entry["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["name"] self._locationImgs.append(img) self._locationTree.insert("", END, image=img, text=name) ######## # Callback for double clicking in item treeview. def _item_on_double_click(self, *args, **kwargs): if len(self._itemTree.selection()) == 0: return self.show_item(self._itemList[self._itemTree.index( self._itemTree.selection())]["name"]) ######## # Callback for double clicking in store treeview. def _store_on_double_click(self, *args, **kwargs): if len(self._storeTree.selection()) == 0: return curr = self._storeList[self._storeTree.index( self._storeTree.selection())] self.show_store(curr["name"], curr["location"]) ######## # Callback for double clicking in attack treeview. def _attack_on_double_click(self, *args, **kwargs): if len(self._attackTree.selection()) == 0: return self.show_attack(self._attackList[self._attackTree.index( self._attackTree.selection())]["id"]) ######## # Callback for double clicking in creature treeview. def _creature_on_double_click(self, *args, **kwargs): if len(self._creatureTree.selection()) == 0: return self.show_creature(self._creatureList[self._creatureTree.index( self._creatureTree.selection())]["name"]) ######## # Callback for double clicking in location treeview. def _location_on_double_click(self, *args, **kwargs): if len(self._locationTree.selection()) == 0: return self.show_location(self._locationList[self._locationTree.index( self._locationTree.selection())]["name"]) ######## # Shows a full item in a new window. def show_item(self, name): if name in self._openItems.keys(): # TODO: make this cleaner try: self._openItems[name].lift() self._openItems[name].focus_set() return except TclError: pass # fallthrough to make new window newWindow = Toplevel(self) itemView = ItemView(newWindow, self._dbm.get_item(name), refBook=self) itemView.grid(row=0, column=0, sticky=N + W + E + S) newWindow.title(name) newWindow.lift() newWindow.focus_set() self._openItems[name] = newWindow ######## # Shows a full store in a new window. def show_store(self, name, location): key = (name, location) if key in self._openStores.keys(): # TODO: make this cleaner try: self._openStores[key].lift() self._openStores[key].focus_set() return except TclError: pass # fallthrough to make new window newWindow = Toplevel(self) storeView = StoreView(newWindow, self._dbm.get_store(name, location), refBook=self) storeView.grid(row=0, column=0, sticky=N + W + E + S) newWindow.title(name) newWindow.lift() newWindow.focus_set() self._openStores[key] = newWindow ######## # Shows a full attack in a new window. def show_attack(self, attackId): if attackId in self._openAttacks.keys(): # TODO: make this cleaner try: self._openAttacks[attackId].lift() self._openAttacks[attackId].focus_set() return except TclError: pass # fallthrough to make new window attack = self._dbm.get_attack(attackId) newWindow = Toplevel(self) attackView = AttackView(newWindow, self._dbm.get_attack(attackId), refBook=self) attackView.grid(row=0, column=0, sticky=N + W + E + S) newWindow.title("{} ({})".format(attack["name"], attack["id"])) newWindow.lift() newWindow.focus_set() self._openAttacks[attackId] = newWindow ######## # Shows a full creature in a new window. def show_creature(self, name): if name in self._openCreatures.keys(): # TODO: make this cleaner try: self._openCreatures[name].lift() self._openCreatures[name].focus_set() return except TclError: pass # fallthrough to make new window newWindow = Toplevel(self) creatureView = CreatureView(newWindow, self._dbm.get_creature(name), refBook=self) creatureView.grid(row=0, column=0, sticky=N + W + E + S) newWindow.title(name) newWindow.lift() newWindow.focus_set() self._openCreatures[name] = newWindow ######## # Shows a full location in a new window. def show_location(self, name): if name in self._openLocations.keys(): # TODO: make this cleaner try: self._openLocations[name].lift() self._openLocations[name].focus_set() return except TclError: pass # fallthrough to make new window newWindow = Toplevel(self) locationView = LocationView(newWindow, self._dbm.get_location(name), refBook=self) locationView.grid(row=0, column=0, sticky=N + W + E + S) newWindow.title(name) newWindow.lift() newWindow.focus_set() self._openLocations[name] = newWindow
update_btn.grid(row=0, column=2) clear_btn = Button(frame_btns, text='Clear', width=12, command=clear_text) clear_btn.grid(row=0, column=3) #frame 3 contact list frame_router = Frame(app) frame_router.grid(row=2, column=0, columnspan=4, rowspan=6, pady=20, padx=20) columns = ['id', 'Name'] router_tree_view = Treeview(frame_router, columns=columns, show="headings") router_tree_view.column("id", width=30) for col in columns[1:]: router_tree_view.column(col, width=450) router_tree_view.heading(col, text=col) router_tree_view.bind('<<TreeviewSelect>>', select_contact) router_tree_view.pack(side="left", fill="y") scrollbar = Scrollbar(frame_router, orient='vertical') scrollbar.configure(command=router_tree_view.yview) scrollbar.pack(side="right", fill="y") router_tree_view.config(yscrollcommand=scrollbar.set) app.title('Contacts') app.geometry('525x575') # Populate data populate_list() # Start program app.mainloop()
class Gui(Frame): __slots__ = ('selectedbox','desiredbox','logger','clidisp','ls','tgtbox',\ 'thread','dir','running','startb','cliententry','commandlist','clientnum', 'scale'\ ) def __init__(self, master): Frame.__init__(self, master) xpos = 0.05 self.running = 0 #not listening self.debug = BooleanVar() self.debug.set(False) self.frame = Frame(colormap='new') self.frame.place(relx=xpos, rely=0.67) self.startb = Button(self.frame, text = "Start Server", command = self.startc,height=2, width=20,\ bg='#90ee90') self.startb.pack(side=LEFT, anchor=S) self.connectionl = Label(self.frame, text="OFF.", height=2, bg='#ff5f5f') self.connectionl.pack(side=LEFT, anchor=E, expand=YES) self.expertmode = BooleanVar() self.expertmode.set(False) self.showexpert = Checkbutton(text='Expert Mode', variable=self.expertmode, command=self.placeframe) self.showexpert.place(relx=xpos, rely=0.74) self.framecommand = Frame() self.commandlabel = Label(self.framecommand, text='Command to Client: ') self.commandtext = Entry(self.framecommand, width=15) self.cliententry = Entry(self.framecommand, width=10) self.addrlabel = Label(self.framecommand, text='Client Box ID: ') self.sendbutton=Button(self.framecommand,text='Send Command\nto Client', width=12,height=4\ ,command=self.send_command) self.tgtbox = None self.logoframe = Frame() self.logoframe.place(relx=xpos, rely=0.04) self.logo = PhotoImage(file=os.path.join('images', 'logo2.png')) self.logolabel = Label(self.logoframe, image=self.logo) self.logolabel.pack() self.cliframe = Frame(colormap='new') self.cliframe.place(relx=0.4, rely=0.1) # self.condisp=Listbox (self.cliframe,width=80,height=12) self.scrollbartop = Scrollbar(self.cliframe) self.clidisp = Treeview(self.cliframe, height=12) self.clidisp['show'] = 'headings' self.clidisp['columns'] = ('boxid', 'ip') self.clidisp.heading('ip', text='IP') self.clidisp.heading('boxid', text='Box ID') self.clidisp.column('boxid', width=152) self.clidisp.column('ip', width=490) self.clidisp.pack(side=LEFT, fill=Y) # self.condisp.pack(side=LEFT,fill=Y) self.scrollbartop.pack(side=RIGHT, fill=Y) self.scrollbartop.config(command=self.clidisp.yview) self.clidisp.config(yscrollcommand=self.scrollbartop.set) self.conntitle = Label(text='Connected Clients↓ ') self.conntitle.place(relx=0.4, rely=0.05) self.cdframe = Frame(colormap='new') self.cdframe.place(relx=0.7, rely=0.05) self.numtitle=Label(self.cdframe,text='Total Connected Clients: ',\ bg='#ff5f5f') self.clientnum=Label(self.cdframe,text=str(len(self.clidisp.get_children())),\ bg='#ff5f5f',font=("", 16)) self.numtitle.pack(side=LEFT) self.clientnum.pack(side=LEFT) self.checkdebug = Checkbutton(text='Debug Mode', variable=self.debug) self.checkdebug.place(relx=0.6, rely=0.5) self.logtitile = Label(text='Logs↓ ') self.logtitile.place(relx=0.4, rely=0.5) self.scrolltext = Frame(colormap='new') self.scrolltext.place(relx=0.4, rely=0.55) if sys.platform.startswith('win'): self.logger = Text(self.scrolltext, state=DISABLED, height=16, width=71) else: self.logger = Text(self.scrolltext, state=DISABLED, height=15, width=64) self.scrollbar = Scrollbar(self.scrolltext) self.logger.pack(side=LEFT, fill=Y) self.scrollbar.pack(fill=BOTH, expand=True) self.scrollbar.config(command=self.logger.yview) self.logger.config(yscrollcommand=self.scrollbar.set) self.logger.tag_configure(0, background="#27d827", foreground='#d82780') self.logger.tag_configure(1, background="#58a758") self.logger.tag_configure(2, background="#4bb543") self.logger.tag_configure(3, background="#000000", foreground='#00aecd') self.logger.tag_configure(4, background="#ffd8ff") self.logger.tag_configure(5, background="#ffc4ff") self.logger.tag_configure(6, background="#ff89ff") self.logger.tag_configure(7, background="#ff9d9d") self.logger.tag_configure(8, background="#ff6262") self.logger.tag_configure(9, background="#d80000", foreground='#00d8d8') self.framehp = Frame() self.framehp.place(relx=xpos, rely=0.17) self.framehost = Frame(self.framehp) self.frameport = Frame(self.framehp) self.invalidtext = Label(self.framehost, text=' ✘ Please Enter a number \nfrom 0-254', foreground='#c40000') self.invalidtextport = Label( self.frameport, text=' ✘ Please Enter a number \nfrom 1-65535', foreground='#c40000') self.framehost.pack(side=TOP, anchor=W) self.frameport.pack(side=TOP, anchor=W) self.hostnum1 = intEnt(self.framehost, width=3, label=self.invalidtext) self.hostnum1.insert(INSERT, '0') self.hostnum2 = intEnt(self.framehost, width=3, label=self.invalidtext) self.hostnum2.insert(INSERT, '0') self.hostnum3 = intEnt(self.framehost, width=3, label=self.invalidtext) self.hostnum3.insert(INSERT, '0') self.hostnum4 = intEnt(self.framehost, width=3, label=self.invalidtext) self.hostnum4.insert(INSERT, '0') self.dot1 = Label(self.framehost, text='.') self.dot2 = Label(self.framehost, text='.') self.dot3 = Label(self.framehost, text='.') self.hostlabel = Label(self.framehost, text='Host :') self.portnum=intEnt(self.frameport,width=6,\ maxlen=5,minval=0,maxval=65536,label=self.invalidtextport) self.portlabel = Label(self.frameport, text='Port :') self.portnum.insert(INSERT, '10086') self.hostlabel.pack(side=LEFT, pady=3) self.hostnum1.pack(side=LEFT, pady=3) self.dot1.pack(side=LEFT, pady=3) self.hostnum2.pack(side=LEFT, pady=3) self.dot2.pack(side=LEFT, pady=3) self.hostnum3.pack(side=LEFT, pady=3) self.dot3.pack(side=LEFT, pady=3) self.hostnum4.pack(side=LEFT, pady=3) self.portlabel.pack(side=LEFT, pady=3) self.portnum.pack(side=LEFT, pady=3) self.errhost = Label(text='Number must between 0 and 255') self.errport = Label(text='Number must between 1 and 65535') self.framets = Frame(colormap='new') self.framets.place(relx=xpos, rely=0.27) self.timespan = IntVar() self.scale=Scale(self.framets,variable=self.timespan, orient=HORIZONTAL, \ from_=10, to=60,bg='#dcdcdc', length=230) self.scale.set(60) self.tslabel = Label(self.framets, text='Time per File (seconds):') self.tslabel.pack(side=TOP, anchor=W) self.scale.pack(side=LEFT) self.frame2 = Frame(colormap='new') self.frame2.place(relx=xpos, rely=0.5) self.outbtn = Button(text='Select Directory', command=self.Folder, bg='#cfcfcf', width=20) self.dir = os.path.join('data', '') self.outbtn.place(relx=xpos, rely=0.4) self.dirlabel = Label(self.frame2, text='↓ Curret Directory ') self.dirtext = Label(self.frame2, text=self.dir, wraplength=400, justify=LEFT) self.dirlabel.pack(side=TOP, anchor=W, pady=5) self.dirtext.pack(side=LEFT) self.radioframe = Frame(colormap='new') self.v = BooleanVar() explain = Label(self.radioframe, text='Save File As: ').pack(side=LEFT, anchor=W) self.rb1 = Radiobutton(self.radioframe, text=".mseed", variable=self.v, value=False) self.rb1.pack(side=LEFT, anchor=W) self.rb2 = Radiobutton(self.radioframe, text=".dat", variable=self.v, value=True) self.rb2.pack(side=LEFT, anchor=W) self.radioframe.place(relx=xpos, rely=0.45) self.sendbutton.pack(side=RIGHT, anchor=SE, padx=20, pady=10, expand=YES) self.addrlabel.pack(side=TOP, anchor=NW) self.cliententry.pack(side=TOP, anchor=NW) self.commandlabel.pack(side=TOP, anchor=NW) self.commandtext.pack(side=TOP, anchor=NW) self.bytestosend = bytearray(b'') self.selectedbox = None self.desiredbox = None self.headlen = 24 self.commandlist = { 'command1': b'\x55\xaa\x55', 'command2': b'\xaa\x55\xaa' } return def send_command(self): box = self.cliententry.get() self.tgtbox = box self.showtext( '{} Command send to Box# {}'.format(self.commandtext.get(), box), 2) return def check_entval(self): self.hostcheck=all((self.hostnum1.check(),self.hostnum2.check(),\ self.hostnum3.check(),self.hostnum4.check())) self.portcheck = self.portnum.check() if self.hostcheck: self.errhost.place(relx=0.4, rely=0.4) else: self.errhost.place_forget() if self.portcheck: self.errport.place(relx=0.4, rely=0.4) else: self.errport.place_forget() return def socket_thread(self): host = self.check_ip() port = self.check_port() if (host and port): self.showtext("thread started.. ", 0) self.ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.ls.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.ls.bind((host, port)) except OSError as err: self.enableedit() self.showtext("OS error: {0} ".format(err), 9) self.showtext( 'Please Close Application using Port: %s ' % port, 9) self.showtext('Server Stopped ', 7) self.connectionl.configure(text="OFF.", bg='#ff5f5f') raise OSError('Port Being Used') return self.running = 1 sleep(0.2) try: self.showtext("Server listening on port %s " % port, 1) while self.running != 0: self.ls.listen(5) self.ls.setblocking(1) self.connectionl.configure(text="RUNNING!", bg='#4bb543') (conn, addr) = self.ls.accept() self.showtext("client is at "+ str(addr[0])+ \ " on port "+str(addr[1]),2) newthread = Thread(target=self.run_server, args=(conn, addr)) newthread.start() newthread.join(1) except (Exception) as e: self.enableedit() self.showtext("Connect exception: " + str(e) + '', 9) self.connectionl.configure(text="OFF.", bg='#ff5f5f') self.forcestop() return return def run_server(self, conn, addr): head = b'\x34\x37\x36\x35' NotInserted = True i = 0 counter = 0 data_saved = bytearray(b'') seed_data = [] recv_data = bytearray(b'') data_recv = bytearray(b'') timeNotpresent = True SendClientInfo = False st = Stream([]) self.showtext("connected to {}, {}".format(conn, addr), 3) self.showtext('Data From: {}'.format(addr), 3) try: while self.running != 0: recv_data = bytearray(conn.recv(524288)) Permission = False data_recv += recv_data if len(data_recv) >= 15000: start = data_recv.find(b'\x32\x34\x56\x67') end = data_recv.rfind(b'\x32\x34\x56\x67') check = (len(data_recv[start:end]) - self.headlen) % 4 if start == end: data_recv = data_recv[start:] elif end > start and (check) % 4 == 0: data_buffer = data_recv[start:end] data_recv = data_recv[end:] Permission = True elif end > start: data_buffer = data_recv[start:end - check] data_recv = data_recv[end:] Permission = True if (Permission and len(data_buffer) > 12): connect_start = time() # reset timeout time if i == 0: i += 1 data_buffer.clear() Permission = False continue ID = str(data_buffer[4:7].decode()) if (ID == 'SEL'): children = self.clidisp.get_children() # self.values=b'\xff\xfe\xfd\xfc\xfb' self.values = bytearray(b'') for child in children: a = list(self.clidisp.item(child).values()) a = a[2][0] if isinstance(a, int): thing = struct.pack('>H', a) self.values += thing conn.sendall(self.bytestosend + head + self.values) # self.bytestosend.clear() self.bytestosend = bytearray(b'') if NotInserted: address = ('{}:{}'.format(addr[0], addr[1])) self.clidisp.insert('', 'end', 'box' + ID, values=(ID, address)) # self.clientnum.config(text=str(len(self.clidisp.get_children()))) NotInserted = False if (data_buffer[7:9] != b'\x99\x99'): self.desiredbox = struct.unpack( '>H', data_buffer[7:9])[0] else: # conn.settimeout(120) conn.sendall(data_buffer[0:7]) # print(data_buffer[0:7]) if int(ID) == self.desiredbox: self.bytestosend.clear() self.bytestosend += data_buffer if (self.tgtbox == ID): command = self.commandtext.get() commandtosend = self.commandlist[command] conn.sendall(commandtosend) counter += 1 if counter >= 5: self.tgtbox = None continue if counter > 10: self.tgtbox = None break if NotInserted: address = ('{}:{}'.format(addr[0], addr[1])) try: self.clidisp.insert('', 'end', 'box{}'.format(ID), values=(ID, address)) except: pass # self.clientnum.config(text=str(len(self.clidisp.get_children()))) NotInserted = False self.showtext('Hello, I am Box# {}'.format(ID), 2) self.checkcolor() if timeNotpresent: try: year = struct.unpack('>1H', data_buffer[7:9]) year = int(year[0]) month = int( struct.unpack('>1B', data_buffer[9:10])[0]) day = int( struct.unpack('>1B', data_buffer[10:11])[0]) hour = int( struct.unpack('>1B', data_buffer[11:12])[0]) minute = int( struct.unpack('>1B', data_buffer[12:13])[0]) second = int( struct.unpack('>1B', data_buffer[13:14])[0]) starttime = datetime(year, month, day, hour, minute, second) except: self.showtext( 'Invalid Time in box# {}.. Using Computer UTC\ time instead'.format(ID), 7) starttime = datetime.utcnow() timeNotpresent = False data_buffer = bytearray(data_buffer[self.headlen:]) if self.v.get(): if timeNotpresent: fn = starttime.strftime("%Y%m%d%H%M%Ss") timeNotpresent = False data_saved += data_buffer if len(data_saved) >= 12000 * self.timespan.get(): # self.showtext('Time Check--> '+str(starttime),2,self.debug.get()) self.showtext( '{} Writing Original Files'.format(addr), 2, self.debug.get()) with open( os.path.join(self.dir, str(ID), fn + '.dat'), 'wb') as f: f.write(data_saved) data_saved.clear() timeNotpresent = True else: unpacked_display_data = np.array( unpack(data_buffer)) if max(unpacked_display_data) > 10e10: data_buffer.clear() Permission = False self.showtext( 'Box {} Have corrupted Data'.format(ID), 7) seed_data.extend( np.zeros(len(unpacked_display_data))) continue # seed_data.extend(unpacked_display_data) # if len(seed_data) >=3000*self.timespan.get(): # self.showtext('{} Writing miniseed Files'.format(addr),2,self.debug.get()) # writeseed(np.array(seed_data[:3000*self.timespan.get()]),\ # starttime,ID,self.dir) # seed_data=seed_data[3000*self.timespan.get():] # timeNotpresent=True tempst=trace_gen(unpacked_display_data,\ starttime,ID) st += tempst if (len(st) >= int(3 * self.timespan.get())): self.showtext( '{} Writing mini-seed Files'.format(addr), 2, self.debug.get()) st.merge(method=1, fill_value='interpolate') # st.merge(method=-1) writestream(st, ID, self.dir) st = Stream([]) data_buffer.clear() Permission = False if (self.running == 0) or (time() - connect_start > 60): self.showtext("No Data! Closing Connections!", 9) # self.clidisp.delete('box'+str(ID)) break except (Exception) as e: # we can wait on the line if desired self.showtext("socket error: " + repr(e), 9) finally: self.showtext("Client at {} disconnected...".format(addr), 3) SendClientInfo = False try: self.clidisp.delete('box{}'.format(ID)) conn.shutdown(socket.SHUT_RDWR) except: pass self.showtext("closing connection on Box# {}".format(ID), 5) conn.close() self.showtext("connection closed on Box# {}".format(ID), 4) self.tgtbox = None counter = 0 self.checkcolor() return def close_sequence(self, conn, addr, ID=None): try: self.clidisp.delete('box{}'.format(ID)) self.forcestop() except: pass self.checkcolor() return def startc(self): if self.running == 0: self.disableedit() self.connectionl.configure(text="INITIALIZING!", bg='#ffffaa') self.size = 1000 * 3 * int(self.timespan.get()) self.scale.config(state='disabled', bg='#3f3f3f', fg='#fafafa') self.showtext("Starting Server ", 0) self.thread = Thread(target=self.socket_thread) self.thread.start() self.startb.configure(bg='#ff276f', text="Stop Server", command=self.stopc) else: self.showtext("Server already started. ", 8) return return def stopc(self): self.enableedit() self.scale.config(state='active', bg='#dcdcdc', fg='#000000') if self.running: self.forcestop(Close=True) self.showtext("stopping thread... ", 7) sleep(1) self.clidisp.delete(*self.clidisp.get_children()) self.checkcolor() self.connectionl.configure(text="OFF.", bg='#ff5f5f') self.running = 0 self.thread.join(1) try: raise KeyboardInterrupt('Server Terminated Due to user Action') except KeyboardInterrupt: self.showtext('Server Terminated Due to user Action', 7) return else: self.showtext("Server not running", 7) return def check_ip(self): try: if int(self.hostnum1.get()) > 255: showerror( "Error", "First number in your Host Section is greather than 255 ") self.showtext('Server Stopped ', 7) return 0 elif int(self.hostnum2.get()) > 255: showerror( "Error", "Second number in your Host Section is greather than 255 ") self.showtext('Server Stopped ', 7) return 0 elif int(self.hostnum3.get()) > 255: showerror( "Error", "Third number in your Host Section is greather than 255 ") self.showtext('Server Stopped ', 7) return 0 elif int(self.hostnum4.get()) > 255: showerror( "Error", "Forth number in your Host Section is greather than 255 ") self.showtext('Server Stopped ', 7) return 0 else: return '{}.{}.{}.{}'.format (self.hostnum1.get(),self.hostnum2.get(),\ self.hostnum3.get(),self.hostnum4.get()) except: showerror( "Error", "Please make sure whole numbers are entered in host section") self.showtext('Server Stopped ', 7) return 0 def check_port(self): try: if 65536 < int(self.portnum.get()): showerror( "Error", "Please enter a whole number between 1 and 65535 in Port section" ) self.showtext('Server Stopped ', 7) else: return int(self.portnum.get()) except: showerror( "Error", "Please make sure whole numbers are entered in port section") self.showtext('Server Stopped ', 7) return 0 def Folder(self): targetdir = askdirectory() if targetdir: self.dirtext.config(text=targetdir) self.dir = targetdir return def checkcolor(self): if len(self.clidisp.get_children()) > 0: self.numtitle.config(text='Total Connected Clients: ',\ bg='#afffbf') self.clientnum.config(text=str(len(self.clidisp.get_children())),\ bg='#afffbf',font=("", 16)) else: self.numtitle.config(text='Total Connected Clients: ',\ bg='#ff5f5f') self.clientnum.config(text=str(len(self.clidisp.get_children())),\ bg='#ff5f5f',font=("", 16)) return def placeframe(self): if self.expertmode.get(): showwarning("Warning","Command in Expert Mode can permnantly " \ 'shutdown selected device(s)') self.framecommand.place(relx=0.05, rely=0.79) else: self.framecommand.place_forget() return def showtext(self, text, colorcheck, DEBUG=True): with open('logs.txt', 'a+') as f: f.write(gettime() + text + '\n') if DEBUG: self.logger.config(state=NORMAL) self.logger.insert(END, gettime() + text + '\n', colorcheck) self.logger.see('end') self.logger.config(state=DISABLED) return return def forcestop(self, Close=False): self.startb.configure(bg='#90ee90', text="Start Server", command=self.startc) try: self.ls.shutdown(socket.SHUT_RDWR) except: pass if Close: try: self.ls.close() except: pass return def enableedit(self): self.portnum.configure(state='normal') self.hostnum1.configure(state='normal') self.hostnum2.configure(state='normal') self.hostnum3.configure(state='normal') self.hostnum4.configure(state='normal') self.rb1.configure(state='normal') self.rb2.configure(state='normal') self.outbtn.configure(state='normal') return def disableedit(self): self.portnum.configure(state='disable') self.hostnum1.configure(state='disable') self.hostnum2.configure(state='disable') self.hostnum3.configure(state='disable') self.hostnum4.configure(state='disable') self.rb1.configure(state='disable') self.rb2.configure(state='disable') self.outbtn.configure(state='disable') return
class TestprogramPane(Labelframe): ''' classdocs ''' def __init__(self, master, tp=None, name='No TP Loaded'): ''' Constructor ''' Labelframe.__init__(self, master) self.name = name self.tp = tp self.tree = Treeview(self) self.tree.pack(fill=BOTH, expand=True) self.config(width=200, height=200, relief=RIDGE, text='Test Program', padding=10) self.tree.bind('<<TreeviewSelect>>', self.show_params) self.param_view = Labelframe(self) self.pins_view = Labelframe(self) self.params = {} self.pins = {} self.load() def load(self): self.tree.delete(*self.tree.get_children()) if (self.tp == None): self.tree.insert("", 'end', 'Default', text=self.name) else: self.populate(self.tp.testtree) def show_params(self, event): self.param_view.destroy() if (self.params.get(self.tree.selection()[0], None) != None): self.param_view = Labelframe(self) self.load_params(self.param_view, self.tree.selection()[0]) self.param_view.config(text='Test Parameters') self.param_view.pack(fill=BOTH, expand=True) def populate(self, tp): for element in tp.iter(): if (element.tag == 'TestRef'): self.tree.insert("", 'end', element.get("name"), text=element.get("name"), open=True) else: self.tree.insert(element.getparent().get("name"), 'end', element.get("name"), text=element.get("name"), open=True) if (element.tag == 'Test'): self.params[element.get("name")] = { 'delay': element.get('delay'), 'force': element.get('force'), 'lolim': element.get('lolim'), 'hilim': element.get('hilim'), 'pinref': element.get('pinref'), 'testtype': element.get('testtype') } def fetch_pins(self, tp, pinref): for element in tp.iter(): if (element.get("name") == pinref): self.pins[element.get("name")] = { 'pintype': element.get("pintype"), 'pins': [] } else: if (element.tag == 'Pin' and element.getparent().get("name") == pinref): self.pins[pinref].get('pins').append(element.get("name")) # def load_params(self, master, test): master.config(text=test) self.param_tree = Treeview(master) self.param_tree.pack(fill=BOTH, expand=True) self.param_tree.heading('#0', text='Parameter') self.param_tree.config(columns=('value')) self.param_tree.column('value', width=100) self.param_tree.heading('value', text='Value') self.param_tree.insert('', 'end', 'delay', text='DELAY', values=self.params.get(test).get('delay')) self.param_tree.insert('', 'end', 'force', text='FORCE', values=self.params.get(test).get('force')) self.param_tree.insert('', 'end', 'lolim', text='LOLIM', values=self.params.get(test).get('lolim')) self.param_tree.insert('', 'end', 'hilim', text='HILIM', values=self.params.get(test).get('hilim')) self.param_tree.insert('', 'end', 'pinref', text='PINREF', values=self.params.get(test).get('pinref')) self.param_tree.insert('', 'end', 'testtype', text='TESTTYPE', values=self.params.get(test).get('testtype')) if self.pins_view: self.pins_view.destroy() self.pins_view = Labelframe(self) self.param_tree.bind('<<TreeviewSelect>>', self.show_pins) def show_pins(self, event): self.pins_view.destroy() self.pins_view = Labelframe(self) pinref = self.param_tree.item(self.param_tree.selection()[0], "value")[0] self.fetch_pins(self.tp.pintree, pinref) if (self.pins.get(pinref, None) != None): self.pins_view = Labelframe(self) self.load_pins(self.pins_view, pinref) self.pins_view.config(text='Pin Parameters') self.pins_view.pack(fill=BOTH, expand=True) def load_pins(self, master, pinref): pins_tree = Treeview(master) pins_tree.pack(fill=BOTH, expand=True) pins_tree.heading('#0', text=(next(iter(self.pins)), ' PinType: ', self.pins.get(pinref).get('pintype'))) for p in self.pins.get(pinref).get('pins'): pins_tree.insert('', 'end', p, text=p)
class Windview: def __init__(self,root): self.root = root self.root.config(bg="#2c2f33") self.root.title("Portal") self.root.geometry("1220x720") self.root.iconbitmap('Medical-Management/icone.ico') self.root.resizable(0, 0) #============================================================================================================= self.frame_left = Frame(self.root, width=260, height=720, bg="#23272a") self.frame_left.place(x=0,y=0) self.clck = Label(self.root,text="",font='Helvetica 14',fg="white",bg="#1e2124") self.clck.place(x=0, y=20,width=260,height=30) self.update_clock() self.label3 = Label(root, text='All work by mr-p-oliveira (⌐■_■), 2021',font='Helvetica 7', fg="#D0D3D4",bg="#1e2124") self.label3.place(x=0 ,y=700, width=260, height=22) self.label2 = Label(root,font='Helvetica 7', fg="#D0D3D4",bg="#1e2124") self.label2.place(x=260 ,y=700, width=960, height=22) self.label = Label(root, text='Selected',font='Helvetica 8', fg="#D0D3D4",bg="#1e2124") self.label.place(x=0,y=87,width=260,height=13) self.lf_lbl = Label(root,text="View",font='Helvetica 12',fg="white", bg="#005042").place(x=0,y=100,width=260,height=55) #====================================================================================================================== self.but_ex = Button(root,text="Exit",font='Helvetica 7',width=10,fg="white", bg="#2c2f33",relief='flat',command=self.ExitApp).place(x=1150,y=700) self.bck_btn = Button(root,text="Back",font='Helvetica 12',width=12,fg="white", bg="#005042",command=self.back_win).place(x=1050,y=650) self.see_btn = Button(root,text="See all",font='Helvetica 12',width=12,fg="white", bg="#005042",command=self.allreg_win).place(x=925,y=650) #====================================================================================================================== i = 0 db.connect() self.tree = Treeview(root, columns=("NHS","Social", "Gender", "Blood", "Allergies","Phone", "Doctor"),show='headings', selectmode="extended") headings=('NHS','Social','Gender','Blood', 'Allergies','Phone','Doctor') sq2l = ("SELECT * FROM pat_reg") db_cursor.execute(sq2l) for j in range(len(headings)): self.tree.column(j, width=10, anchor=CENTER) self.tree.heading(j, text=headings[j]) for ro in db_cursor: self.tree.insert('', i, text="",values=(ro[11], ro[10], ro[3], ro[12], ro[16],ro[8] ,ro[17])) i+=1 self.tree.place(x=295,y=70,height=400,width=900) db.close() self.vscroll = Scrollbar(root,orient=VERTICAL,command=self.tree.yview) self.vscroll.place(x=1195,y=70,height=400) self.tree.config(yscrollcommand=self.vscroll.set) #======================================================================================================================= def ExitApp(self): self.ExitApp = tkinter.messagebox.askquestion ('Exit Portal','Are you sure you want to exit the application. ( Your data is automatically saved )',icon = 'warning') if self.ExitApp == 'yes': root.destroy() else: messagebox.showinfo('Return','You will now return to the application screen') def update_clock(self): now = time.strftime("%d %b %Y ,%H:%M:%S") self.clck.configure(text=now) self.clck.after(1000, self.update_clock) def back_win(self): self.root.withdraw() self.newWindow = Toplevel(self.root) self.app = Window1(self.newWindow) def allreg_win(self): self.root.withdraw() self.newWindow = Toplevel(self.root) self.app = Windallreg(self.newWindow)
class ManagerWindow: """ 主管理界面入口类,直接无参数创建对象即可。 """ # 窗口宽高 WIN_WIDTH = 800 WIN_HEIGHT = 600 def __init__(self): # 界面根节点 self.root = Tk() # 主窗口标题 self.root.title(MANAGER_TITLE) # 读取config self.config_dict = ConfigOperation.get_dir_from_file() # 主窗口分辨率 self.root.geometry("%sx%s+%s+%s" % ( self.WIN_WIDTH, self.WIN_HEIGHT, int((self.root.winfo_screenwidth() - self.WIN_WIDTH) / 2), int((self.root.winfo_screenheight() - self.WIN_HEIGHT) / 2) )) self.root.minsize(self.WIN_WIDTH, self.WIN_HEIGHT) # 选项卡 self.tab_main = Notebook(self.root) self.tab_main.pack(expand=True, fill=BOTH) # 登录选项卡 self.frame_login = Frame(self.tab_main, bg=BG_COLOR) self.frame_login.pack(side=TOP) self.tab_main.add(self.frame_login, text=TAB_NAME_LIST["login"]["text"]) # 管理选项卡 self.frame_manage = Frame(self.tab_main, bg=BG_COLOR) self.tab_main.add(self.frame_manage, text=TAB_NAME_LIST["manage"]["text"]) # 好友选项卡 self.frame_friend = Frame(self.tab_main, bg=BG_COLOR) self.frame_friend.pack(side=TOP) self.tab_main.add(self.frame_friend, text=TAB_NAME_LIST["friends"]["text"]) # 群选项卡 self.frame_group = Frame(self.tab_main, bg=BG_COLOR) self.frame_group.pack(side=TOP) self.tab_main.add(self.frame_group, text=TAB_NAME_LIST["groups"]["text"]) # 插件选项卡 self.frame_plugin = Frame(self.tab_main, bg=BG_COLOR) self.frame_plugin.pack(side=TOP) self.tab_main.add(self.frame_plugin, text=TAB_NAME_LIST["plugins"]["text"]) # 初始化登录选项卡 self.__init_login_tab() # 初始化好友选项卡 self.__init_friend_tab() # 初始化群选项卡 self.__init_group_tab() # 初始化管理选项卡 self.__init_manage_tab() # 初始化插件选项卡 self.__init_plugin_tab() # 关闭窗口自动释放Session self.root.protocol("WM_DELETE_WINDOW", lambda: self.__on_close_root()) # 刷新显示 self.__refresh() # 运行相关线程 fetch_message_thread = FetchMessageThread() fetch_message_thread.daemon = True fetch_message_thread.start() # 运行插件初始化方法 PluginHandler.call_init() # 执行自动连接一次 self.__auto_connect() # 显示 self.root.mainloop() def __init_login_tab(self): """ 初始化登录选项卡界面 :return: 无 """ # 左边列表的frame frame_login_list = Frame(self.frame_login, bg=BG_COLOR) frame_login_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 列表,用于保存连接记录 self.treeview_login_list = Treeview( frame_login_list, columns=[ LOGIN_GUIDE["host"], LOGIN_GUIDE["port"], LOGIN_GUIDE["authkey"], LOGIN_GUIDE["qq"] ], show="headings", selectmode=BROWSE ) self.treeview_login_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_login_list.column( LOGIN_GUIDE["host"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["host"], text=LOGIN_GUIDE["host"] ) self.treeview_login_list.column( LOGIN_GUIDE["port"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["port"], text=LOGIN_GUIDE["port"] ) self.treeview_login_list.column( LOGIN_GUIDE["authkey"], width=40 ) self.treeview_login_list.heading( LOGIN_GUIDE["authkey"], text=LOGIN_GUIDE["authkey"] ) self.treeview_login_list.column( LOGIN_GUIDE["qq"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["qq"], text=LOGIN_GUIDE["qq"] ) # 设定双击事件 self.treeview_login_list.bind( "<Double-Button-1>", lambda event: self.__on_double_click_login_list_content() ) # 设定登录列表的滚动条 scrollbar_login_list = Scrollbar(frame_login_list) scrollbar_login_list.pack(fill="y", expand=True) self.treeview_login_list.config(yscrollcommand=scrollbar_login_list.set) scrollbar_login_list.config(command=self.treeview_login_list.yview) # 设置列表右键菜单 self.treeview_login_list.bind("<Button-3>", self.__show_login_list_pop_up_menu) # 登录界面显示的那一坨 frame_login_menu = Frame(self.frame_login, bg=BG_COLOR) frame_login_menu.pack(side=LEFT, padx=5, pady=5) # mirai端地址 Label(frame_login_menu, text=LOGIN_GUIDE["host"], bg=BG_COLOR).grid(row=0, sticky=E, padx=5, pady=5) self.entry_host = Entry(frame_login_menu) self.entry_host.grid(row=0, column=1, sticky=W, padx=5, pady=5) # mirai端端口号 Label(frame_login_menu, text=LOGIN_GUIDE["port"], bg=BG_COLOR).grid(row=1, sticky=E, padx=5, pady=5) self.entry_port = Entry(frame_login_menu) self.entry_port.grid(row=1, column=1, sticky=W, padx=5, pady=5) # mirai端http授权码 Label(frame_login_menu, text=LOGIN_GUIDE["authkey"], bg=BG_COLOR).grid( row=2, sticky=E, padx=5, pady=5 ) self.entry_authkey = Entry(frame_login_menu, show=PWD_CHAR_CIRCLE) self.entry_authkey.grid(row=2, column=1, sticky=W, padx=5, pady=5) # 用于激活sessioKey的qq号码 Label(frame_login_menu, text=LOGIN_GUIDE["qq"], bg=BG_COLOR).grid( row=3, sticky=E, padx=5, pady=5 ) self.entry_qq = Entry(frame_login_menu) self.entry_qq.grid(row=3, column=1, sticky=W, padx=5, pady=5) # 自动连接复选框 self.auto_connect_var = BooleanVar() self.checkbutton_auto_connect = Checkbutton( frame_login_menu, text=AUTO_CONNECT_GUIDE, onvalue=True, offvalue=False, variable=self.auto_connect_var, bg=BG_COLOR ) self.checkbutton_auto_connect.grid(row=4, column=0, padx=5, pady=5, columnspan=2) # 连接按钮 self.btn_connect = Button( frame_login_menu, text=BTN_TEXT_CONN["connect"], width=15, command=lambda: self.__on_click_connect_event(), ) self.btn_connect.grid(row=5, columnspan=2, padx=5, pady=5) # 添加到登录列表按钮 self.btn_save_login = Button( frame_login_menu, width=15, text=BTN_TEXT_ADD_LOGIN, command=lambda: self.__on_click_add_to_login_list() ) self.btn_save_login.grid(row=6, columnspan=2, padx=5, pady=5) # 状态栏 self.label_login_status_bar = Label( self.root, text=LOGIN_STATUS_BAR_TEXT["notConnect"], fg=STATUS_BAR_COLOR["normal"] ) self.label_login_status_bar.pack(side=LEFT) # 下面开始从config中将内容填充进文本框中 self.entry_host.delete(0, END) self.entry_host.insert(END, self.config_dict["lastConnection"]["host"]) self.entry_port.delete(0, END) self.entry_port.insert(END, self.config_dict["lastConnection"]["port"]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, self.config_dict["lastConnection"]["authkey"]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, self.config_dict["lastConnection"]["qq"]) # 自动连接复选框内容 self.auto_connect_var.set(self.config_dict["autoConnect"]) def __init_friend_tab(self): """ 初始化好友选项卡内容 :return: 无 """ # 创建好友列表框架 frame_friend_list = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_friend_send = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_friend_list = Treeview( frame_friend_list, columns=[ FRIEND_GUIDE["qq"], FRIEND_GUIDE["nickname"], FRIEND_GUIDE["remark"] ], show="headings", selectmode=BROWSE ) self.treeview_friend_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_friend_list.column( FRIEND_GUIDE["qq"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["qq"], text=FRIEND_GUIDE["qq"] ) self.treeview_friend_list.column( FRIEND_GUIDE["nickname"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["nickname"], text=FRIEND_GUIDE["nickname"] ) self.treeview_friend_list.column( FRIEND_GUIDE["remark"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["remark"], text=FRIEND_GUIDE["remark"] ) # 设定好友列表的滚动条 scrollbar_friend_list = Scrollbar(frame_friend_list) scrollbar_friend_list.pack(fill="y", expand=True) self.treeview_friend_list.config(yscrollcommand=scrollbar_friend_list.set) scrollbar_friend_list.config(command=self.treeview_friend_list.yview) # 刷新列表按钮 Button( frame_friend_send, text=BTN_FRIEND_REFRESH, command=lambda: self.__on_click_refresh_friend_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_friend_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_friend_send = Text(frame_friend_send, width=30, height=5) self.text_friend_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_friend_send, text=BTN_SEND, command=lambda: self.__on_click_send_friend_message() ).grid(row=3, padx=5, pady=5) def __init_group_tab(self): """ 初始化群选项卡内容 :return: 无 """ # 创建好友列表框架 frame_group_list = Frame(self.frame_group, bg=BG_COLOR) frame_group_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_group_send = Frame(self.frame_group, bg=BG_COLOR) frame_group_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_group_list = Treeview( frame_group_list, columns=[ GROUP_GUIDE["group"], GROUP_GUIDE["name"], GROUP_GUIDE["permission"] ], show="headings", selectmode=BROWSE ) self.treeview_group_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_group_list.column( GROUP_GUIDE["group"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["group"], text=GROUP_GUIDE["group"] ) self.treeview_group_list.column( GROUP_GUIDE["name"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["name"], text=GROUP_GUIDE["name"] ) self.treeview_group_list.column( GROUP_GUIDE["permission"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["permission"], text=GROUP_GUIDE["permission"] ) # 设定群列表的滚动条 scrollbar_group_list = Scrollbar(frame_group_list) scrollbar_group_list.pack(fill="y", expand=True) self.treeview_group_list.config(yscrollcommand=scrollbar_group_list.set) scrollbar_group_list.config(command=self.treeview_group_list.yview) # 刷新列表按钮 Button( frame_group_send, text=BTN_GROUP_REFRESH, command=lambda: self.__on_click_refresh_group_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_group_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_group_send = Text(frame_group_send, width=30, height=5) self.text_group_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_group_send, text=BTN_SEND, command=lambda: self.__on_click_send_group_message() ).grid(row=3, padx=5, pady=5) def __init_manage_tab(self): """ 初始化管理选项卡 :return: 无 """ f_manage = Frame(self.frame_manage, bg=BG_COLOR) f_manage.pack(padx=5, pady=5, expand=True) # 指定头指示 Label(f_manage, text=MANAGE_GUIDE["commandHead"], bg=BG_COLOR).grid( row=0, column=0, padx=5, pady=5, sticky=E ) # 指令头文本框 self.entry_command_head = Entry(f_manage) self.entry_command_head.grid(row=0, column=1, padx=5, pady=5, sticky=EW) # 调试复选框 self.debug_var = BooleanVar() checkbutton_debug = Checkbutton( f_manage, text=MANAGE_GUIDE["debug"], onvalue=True, offvalue=False, variable=self.debug_var, bg=BG_COLOR ) checkbutton_debug.grid(row=1, column=0, columnspan=3, padx=5, pady=5) # 启用机器人 self.enable_var = BooleanVar() checkbutton_enable = Checkbutton( f_manage, text=MANAGE_GUIDE["enable"], onvalue=True, offvalue=False, variable=self.enable_var, bg=BG_COLOR ) checkbutton_enable.grid(row=2, column=0, columnspan=3, padx=5, pady=5) # 配置保存 Button( f_manage, text=MANAGE_GUIDE["saveConfig"], command=self.__on_click_save_config ).grid( row=3, column=1, padx=5, pady=5, sticky=EW ) # bot管理qq列表 self.treeview_op_list = Treeview( f_manage, columns=[ MANAGE_GUIDE["botOpQQ"] ], show="headings", selectmode=BROWSE ) self.treeview_op_list.column(MANAGE_GUIDE["botOpQQ"], width=200) self.treeview_op_list.heading(MANAGE_GUIDE["botOpQQ"], text=MANAGE_GUIDE["botOpQQ"]) self.treeview_op_list.grid( row=4, column=0, columnspan=3, rowspan=10, sticky=EW ) # 列表右键 self.treeview_op_list.bind("<Button-3>", self.__show_op_list_pop_up_menu) # 添加管理标签 Label(f_manage, text=MANAGE_GUIDE["addOpQQ"], bg=BG_COLOR).grid(row=14, column=0, padx=5, pady=5) # 添加管理文本框 self.entry_add_op = Entry(f_manage) self.entry_add_op.grid(row=14, column=1, padx=5, pady=5) # 添加添加按钮 Button( f_manage, text=MANAGE_GUIDE["btnAddOpQQ"], command=lambda: self.__on_click_add_op() ).grid(row=14, column=2, padx=5, pady=5, sticky=EW) def __init_plugin_tab(self): """ 初始化插件选项卡 :return: 无 """ # 指示标签 Label(self.frame_plugin, text=PLUGIN_LABEL_TEXT, bg=BG_COLOR).pack(side=TOP) # 插件列表frame frame_plugin_list = Frame(self.frame_plugin, bg=BG_COLOR) frame_plugin_list.pack( side=TOP, expand=True, fill=BOTH, padx=5, pady=5 ) # 插件列表 self.treeview_plugin_list = Treeview( frame_plugin_list, columns=[ PLUGIN_GUIDE["pluginName"] ], show="headings", selectmode=BROWSE ) self.treeview_plugin_list.pack(fill=BOTH, expand=True, side=LEFT) self.treeview_plugin_list.column(PLUGIN_GUIDE["pluginName"]) self.treeview_plugin_list.heading(PLUGIN_GUIDE["pluginName"], text=PLUGIN_GUIDE["pluginName"]) # 设定插件列表滚动条 scrollbar_plugin_list = Scrollbar(frame_plugin_list) scrollbar_plugin_list.pack(fill="y", expand=True) self.treeview_plugin_list.config(yscrollcommand=scrollbar_plugin_list.set) scrollbar_plugin_list.config(command=self.treeview_plugin_list.yview) def __on_click_connect_event(self): """ 点击连接按钮事件 :return: 无 """ if not GlobalValues.is_connected: # 如果是要连接 # 存到全局使用变量 GlobalValues.conn_host = self.entry_host.get() GlobalValues.conn_port = self.entry_port.get() GlobalValues.conn_authkey = self.entry_authkey.get() try: # 转换为整型后保存 GlobalValues.conn_qq = int(self.entry_qq.get()) except ValueError: self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["wrongQQ"], fg=STATUS_BAR_COLOR["failed"]) return # 修改界面上的一些内容为不可修改 self.__set_login_tools_active(False) # 修改按钮内容 self.btn_connect.config(text=BTN_TEXT_CONN["disconnect"]) # 修改状态栏内容 self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["connecting"], fg=STATUS_BAR_COLOR["normal"]) # 调用连接 try: Conn.new_session_key() except ( requests.exceptions.InvalidURL, requests.exceptions.ConnectionError, ): # 连接错误 # 错误信息显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connectFailed"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except WrongAuthkeyException: # 授权码错误 # 显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["wrongAuthkey"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except BotNotExistException: # bot不存在错误 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["qqNotExist"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connected"], fg=STATUS_BAR_COLOR["passed"] ) # 修改连接状态值 GlobalValues.is_connected = True # 修改上次连接键值对 ConfigOperation.modify_dict("lastConnection", { "host": GlobalValues.conn_host, "port": GlobalValues.conn_port, "authkey": GlobalValues.conn_authkey, "qq": GlobalValues.conn_qq }) # 修改文件中自动连接开关 ConfigOperation.modify_dict("autoConnect", self.auto_connect_var.get()) else: # 如果要断开连接 # 修改文本框为可修改 self.__set_login_tools_active(True) # 修改按钮名称 self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) # 修改属性值 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["disconnectSuccess"], fg=STATUS_BAR_COLOR["normal"] ) # 释放session Conn.release_session_key() # 修改连接状态值 GlobalValues.is_connected = False def __set_login_tools_active(self, active: bool): """ 修改界面上的一些内容为不可修改 :param active: bool,如果为False则禁用掉文本框,否则启用 :return: 无 """ if active: self.entry_host.config(state=ACTIVE) self.entry_port.config(state=ACTIVE) self.entry_authkey.config(state=ACTIVE) self.entry_qq.config(state=ACTIVE) self.checkbutton_auto_connect.config(state=ACTIVE) else: self.entry_host.config(state=DISABLED) self.entry_port.config(state=DISABLED) self.entry_authkey.config(state=DISABLED) self.entry_qq.config(state=DISABLED) self.checkbutton_auto_connect.config(state=DISABLED) def __on_close_root(self): """ 关闭窗口的事件 :return: 无 """ # 如果正在连接则释放连接 if GlobalValues.is_connected: Conn.release_session_key() # 杀掉root self.root.destroy() def __refresh(self): """ 用于刷新界面,在必要时调用 :return: 无 """ def refresh_login_list(): """ 刷新登录列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_login_list.delete(*self.treeview_login_list.get_children()) # 把登录列表内容添加到显示中 for one_record in LoginListOperation.get_list_from_file(): self.treeview_login_list.insert("", index=END, values=( one_record["host"], one_record["port"], one_record["authkey"], one_record["qq"] )) def refresh_op_list(): """ 刷新bot管理员qq列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_op_list.delete(*self.treeview_op_list.get_children()) # 把内容添加到显示中 for one_record in OpListOperation.get_list(): self.treeview_op_list.insert("", index=END, values=( one_record )) def refresh_config(): """ 刷新配置 :return: 无 """ # 重新获取config self.config_dict = ConfigOperation.get_dir_from_file() # 将文件中的内容显示到界面中 self.entry_command_head.delete(0, END) self.entry_command_head.insert(END, self.config_dict["commandHead"]) # 设置复选框默认勾选 self.debug_var.set(self.config_dict["debug"]) self.enable_var.set(self.config_dict["enable"]) # 将内容设置到全局变量 GlobalValues.command_head = self.config_dict["commandHead"] GlobalValues.debug_var = self.debug_var GlobalValues.enable_var = self.enable_var def refresh_plugin_list(): # 获取插件名称 plugin_names = PluginHandler.get_plugin_name_list() # 显示 self.treeview_plugin_list.delete(*self.treeview_plugin_list.get_children()) for name in plugin_names: self.treeview_plugin_list.insert("", index=END, values=( name )) # 调用刷新登录列表 refresh_login_list() # 调用刷新op列表 refresh_op_list() # 刷新config显示 refresh_config() # 刷新插件列表显示 refresh_plugin_list() def __on_click_add_to_login_list(self): """ 将填写内容添加到列表中 :return: 无 """ # 非空检测 if [ self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ] == [""] * 4: return # 调用添加登录项方法 LoginListOperation.add_to_list( self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ) # 刷新显示 self.__refresh() def __on_double_click_login_list_content(self): """ 双击登录列表项目时,自动填充到右侧 :return: 无 """ # 获取item的值 item_list = self.treeview_login_list.item(self.treeview_login_list.focus(), "values") # 获取需要的项目并设置 self.entry_host.delete(0, END) self.entry_host.insert(END, item_list[0]) self.entry_port.delete(0, END) self.entry_port.insert(END, item_list[1]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, item_list[2]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, item_list[3]) def __show_login_list_pop_up_menu(self, event): """ 显示右键菜单 :param event: 事件 :return: 无 """ def on_delete_event(item_id): """ 删除选项的事件 :return: 无 """ # 删除该项 LoginListOperation.remove_from_list(*self.treeview_login_list.item(item_id, "values")) self.treeview_login_list.delete(item_id) self.__refresh() # 获取选择对象 iid = self.treeview_login_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if iid: self.treeview_login_list.selection_set(iid) menu_pop_up = Menu(self.treeview_login_list, tearoff=False) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event(iid) ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_refresh_friend_list_event(self): """ 点击刷新好友列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 friend_list = Conn.get_friend_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_friend_list.delete(*self.treeview_friend_list.get_children()) # 解析friend_list for friend_block in friend_list: self.treeview_friend_list.insert("", index=END, values=( friend_block["id"], friend_block["nickname"], friend_block["remark"] )) def __on_click_refresh_group_list_event(self): """ 点击刷新群列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 group_list = Conn.get_group_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_group_list.delete(*self.treeview_group_list.get_children()) # 解析group_list for group_block in group_list: self.treeview_group_list.insert("", index=END, values=( group_block["id"], group_block["name"], group_block["permission"] )) def __on_click_send_friend_message(self): """ 点击发送消息给好友按钮 :return: 无 """ # 获取到选中好友的值列表 value_list = self.treeview_friend_list.item(self.treeview_friend_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_friend_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_friend_message(qq, message_chain) self.text_friend_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_send_group_message(self): """ 点击发送消息给群按钮 :return: 无 """ # 获取到选中群的值列表 value_list = self.treeview_group_list.item(self.treeview_group_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_group_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_group_message(qq, message_chain) self.text_group_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_add_op(self): """ 点击添加op按钮事件 :return: 无 """ content = self.entry_add_op.get() # 如果添加op的文本框中没有东西,则不添加 if content == "": return # 如果转换数字出错则不添加 try: op_qq = int(content) except ValueError: return # 添加到op列表中 OpListOperation.add_to_list(op_qq) # 刷新显示 self.__refresh() def __show_op_list_pop_up_menu(self, event): """ op列表右键菜单 :return: 无 """ def on_delete_event(): """ 删除选项的事件 :return: 无 """ # 删除该项 # 注意此处的强转,由于能够保证显示出来的内容一定只含有数字,故可以直接转换 OpListOperation.remove_from_list(int(self.treeview_op_list.item(op_qq, "values")[0])) self.treeview_op_list.delete(op_qq) self.__refresh() # 获取选择对象 op_qq = self.treeview_op_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if op_qq: menu_pop_up = Menu(self.treeview_op_list, tearoff=False) self.treeview_op_list.selection_set(op_qq) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event() ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_save_config(self): """ 点击保存配置事件 :return: 无 """ content = self.entry_command_head.get() # 如果为空,则不存入,但是刷新 # 这样是为了保证点击后会显示原来的设置 if content == "": self.__refresh() return ConfigOperation.modify_dict("commandHead", content) ConfigOperation.modify_dict("debug", self.debug_var.get()) ConfigOperation.modify_dict("enable", self.enable_var.get()) # 刷新 self.__refresh() # 弹出对话框 messagebox.showinfo(message=MANAGE_GUIDE["successSaveCommandHeadMsg"]) def __auto_connect(self): if self.config_dict["autoConnect"]: self.__on_click_connect_event()
def listchans(self, index=None, tagsearch="", archived=0, ob=Channel.displayname, so=asc): self.center = Frame(root, bg=config.bgcolor, width=50, height=40, padx=3, pady=3) # layout all of the main containers root.grid_rowconfigure(1, weight=1) root.grid_columnconfigure(0, weight=1) self.center.grid(row=1, sticky="nsew") channels = database.get_channels(archived, ob, so) if so == desc: so = asc else: so = desc tree = Treeview(self.center) sstring = Entry(self.center, width=config.textBoxWidth) sstring.bind( "<KeyRelease-Return>", lambda e: self.listchans(None, sstring.get(), archived, ob, so)) sstring.grid(column=0, row=0) if len(tagsearch) >= 1: sstring.focus() sstring.insert(0, tagsearch) searchbutton = Button(self.center, text="Search", command=lambda: self.listchans( None, sstring.get(), archived, ob, so)) searchbutton.grid(column=1, row=0) clearbutton = Button(self.center, text="Clear Search") clearbutton.configure(command=lambda: self.listchans(archived)) clearbutton.grid(column=3, row=0) tree["columns"] = ("one", "two") tree.column("#0", width=210, minwidth=10, stretch=YES) tree.column("one", width=350, minwidth=250, stretch=YES) tree.column("two", width=210, minwidth=10, stretch=YES) tree.heading("#0", text="Last Check", anchor=W, command=lambda: self.listchans(None, sstring.get( ), archived, Channel.lastcheck, so)) tree.heading("one", text="Channel Name", anchor=E, command=lambda: self.listchans(None, sstring.get( ), archived, Channel.displayname, so)) tree.heading("two", text="Last Published", command=lambda: self.listchans(None, sstring.get( ), archived, Channel.lastpub, so)) i = 0 tree.tag_configure('oddrow', background='#88DD88') tree.tag_configure('evenrow', background='#FFFFFF') tree.tag_configure('archivedodd', background="#88DD88", foreground="#aaaaaa") tree.tag_configure('archivedeven', background='#FFFFFF', foreground="#cccccc") for item in channels: foldername = "folder" + str(i) if i % 2 == 0: color = "evenrow" else: color = "oddrow" if item.archive == True: if i % 2 == 0: color = "archivedeven" else: color = "archivedodd" if tagsearch.lower() in str( item.displayname).lower() or tagsearch.lower() in str( item.dldir).lower() or tagsearch.lower() in str( item.yt_channelid).lower(): if item.lastpub == None: lastpub = "N/A" else: lastpub = time.ctime(item.lastpub) foldername = tree.insert("", "end", text=time.ctime(item.lastcheck), values=(item.displayname, lastpub), tags=(color, item.displayname, item.dldir, item.yt_channelid)) tree.insert(foldername, "end", text="Directory", values=(item.dldir, ), tags=(color)) tree.insert(foldername, "end", text="Last Published", values=(lastpub, ), tags=(color)) i = i + 1 vertscroll = Scrollbar(self.center) vertscroll.config(command=tree.yview) tree.config(yscrollcommand=vertscroll.set, height=20) vertscroll.grid(column=4, row=1, sticky='NSE') tree.bind("<Double-1>", self.item_selected) tree.grid(row=1, columnspan=4, sticky="NSEW") tree.focus(index) tree.selection_set(index) tree.see(index)
class CsvFrame: """ Display csv data in a tkinter TreeView """ def __init__(self, parent, manager): """ CsvFrame constructor """ top = self.top = tkinter.Toplevel(parent) self.__parent = parent self.__manager = manager top_frame = tkinter.Frame(top, borderwidth=2, relief=tkinter.GROOVE) top_frame.pack(side=tkinter.TOP, fill=tkinter.X, padx=5, pady=5) label_data = Label(top_frame, text="Data: ") label_data.grid(row=1, column=1, padx=5, pady=5) data_select_combo3 = tkinter.StringVar() self.combo_data = Combobox(top_frame, textvariable=data_select_combo3, values=manager.get_field_names(), state='readonly', postcommand=lambda: self.combo_data.configure(values=manager.get_field_names())) self.combo_data.grid(row=1, column=2, padx=5, pady=5) edit_button = Button(top_frame, text="Edit header", command=self.edit_header, width=20) edit_button.grid(row=1, column=3, columnspan=1, rowspan=1, padx=5, pady=5) # TODO change values for combobox transform_select_combo4 = tkinter.StringVar() self.combo_transform = Combobox(top_frame, textvariable=transform_select_combo4, values=["rad_to_deg", "deg_to_rad"], state='readonly') self.combo_transform.grid(row=1, column=4, padx=5, pady=5) transform_button = Button(top_frame, text="Transform data", command=self.transform_data, width=20) transform_button.grid(row=1, column=5, columnspan=1, rowspan=1, padx=5, pady=5) table_frame = Frame(top) table_frame.pack(side=tkinter.BOTTOM, expand=True, fill=tkinter.BOTH) scrollbar_x = Scrollbar(table_frame, orient=tkinter.HORIZONTAL) scrollbar_y = Scrollbar(table_frame, orient=tkinter.VERTICAL) self.tree = Treeview(table_frame, columns=manager.get_field_names(), show="headings", selectmode="extended", yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set) scrollbar_y.config(command=self.tree.yview) scrollbar_y.pack(side=tkinter.RIGHT, fill=tkinter.Y) scrollbar_x.config(command=self.tree.xview) scrollbar_x.pack(side=tkinter.BOTTOM, fill=tkinter.X) self.fill_data() self.tree.pack(expand=True, fill=tkinter.BOTH) self.top.protocol("WM_DELETE_WINDOW", self.quit) def edit_header(self): """ Edit the header a data column """ if self.combo_data.get() != "": answer = simpledialog.askstring("Input", "What is the new header?", parent=self.top) if answer is not None: self.__manager.edit_header(answer, self.combo_data.get()) self.fill_data() self.combo_data.set('') else: logger.log(logging.INFO, "[CsvFrame] No new header entered") else: logger.log(logging.ERROR, "[CsvFrame] No data field selected") def clear_data(self): """ Clear data in Treeview """ logger.log(logging.INFO, "[CsvFrame] Clear data in TreeView") for i in self.tree.get_children(): self.tree.delete(i) def fill_data(self): """ Fill data in Treeview """ logger.log(logging.INFO, "[CsvFrame] Fill data in TreeView") self.clear_data() self.tree.config(columns=self.__manager.get_field_names()) for field_name in self.__manager.get_field_names(): self.tree.heading(field_name, text=field_name, anchor=tkinter.W) self.tree.column(field_name, stretch=tkinter.YES) for entry in self.__manager.get_data_tuple(): self.tree.insert("", 'end', values=entry) def transform_data(self): """ Transform data and add in Treeview """ # TODO to be completed data_field_name = self.combo_data.get() if data_field_name != "": if self.combo_transform.get() != "": data = self.__manager.get_data_from_field_name(data_field_name) transformed_data = transform_data(self.combo_transform.get(), self.combo_data.get(), data) if transformed_data[0] != "": self.__manager.add_data(transformed_data[0], transformed_data[1], transformed_data[2]) self.fill_data() else: logger.log(logging.ERROR, "[CsvFrame] Data has not been transformed") else: logger.log(logging.ERROR, "[CsvFrame] No transform operation selected") else: logger.log(logging.ERROR, "[CsvFrame] No data field selected") def quit(self): """ Destroy the frame """ self.__parent.reset_csvframe() self.top.destroy()
class LDAPConsole(Frame): def __init__(self): super().__init__() self.initConsole() self.addMenuBar() self.createSections() def initConsole(self): self.master.title("LDAP Management Console") self.style = Style() self.style.theme_use("alt") ## Frame principal. self.pack(fill=BOTH, expand=1) def addMenuBar(self): ## Creacion de barra de menus. menubar = Menu(self.master) self.master.config(menu=menubar) ## Seccion File del menu. fileMenu = Menu(menubar, tearoff=0) fileMenu.add_command(label="Connect", command=self.OpenConnection) fileMenu.add_command(label="Disconnect", command=self.CloseConnection) fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self.ExitOption) menubar.add_cascade(label="File", menu=fileMenu) ## Seccion Advanced del menu. AdvancedMenu = Menu(menubar, tearoff=0) AdvancedMenu.add_command(label="Display Options") AdvancedMenu.add_command(label="Verify") AdvancedMenu.add_command(label="Configure") menubar.add_cascade(label="Advanced", menu=AdvancedMenu) ## Seccion Help del menu. HelpMenu = Menu(menubar, tearoff=0) HelpMenu.add_command(label="Show Help") HelpMenu.add_command(label="About LDAP GUI") menubar.add_cascade(label="Help", menu=HelpMenu) def createSections(self): ## Definicion de frames secundarios anidados en el principal. ## Nuevo Frame para contener la representacion del arbol de ## directorio incluyendo las barras de desplazamiento. self.treeNavFrame = Frame(self) self.treeNavFrame.config(relief=RAISED, borderwidth=2) self.treeNavView = Treeview(self.treeNavFrame, show="tree", selectmode="browse") ## Definicion de barras de desplazamiento. ## La barra de desplazamiento tiene como padre el Frame pero controla ## el widget treeview. ### Barra de desplazamiento horizontal. self.HorScrollBar = Scrollbar(self.treeNavFrame, activerelief=RAISED, orient=HORIZONTAL) self.HorScrollBar.config(command=self.treeNavView.xview) self.HorScrollBar.pack(fill=X, side=BOTTOM) ### Barra de desplazamiento vertical. self.VerScrollBar = Scrollbar(self.treeNavFrame, activerelief=RAISED, orient=VERTICAL) self.VerScrollBar.config(command=self.treeNavView.yview) self.VerScrollBar.pack(fill=Y, side=RIGHT) self.treeNavFrame.pack(fill=BOTH, side=LEFT) self.treeNavView.pack(fill=BOTH, side=LEFT) self.treeNavView.config(xscrollcommand=self.HorScrollBar.set, yscrollcommand=self.VerScrollBar.set) ## Nuevo frame para contener la informacion de objetos seleccionados. self.infoFrame = Frame(self) self.infoFrame.config(relief=RAISED, borderwidth=2) self.infoFrameCanvas = Canvas(self.infoFrame, bg="white", width=500, height=400) self.infoFrameCanvas.pack(fill=X, anchor=NE) self.infoFrame.pack(fill=X, anchor=NE) def updateInfoSection(self, dntoSearch, infoToDisplay): try: self.infoFrameCanvas.delete("all") self.infoFrameCanvas.create_text(20, 20, font=("Liberation Serif Bold", 30, "bold"), anchor=W, text="{}".format(dntoSearch[0])) row = 50 self.infoFrameCanvas.create_text(20, row, font=("Liberation Serif Bold", 20), anchor=W, text="objectClass: ") for objclass in infoToDisplay[0]["attributes"]["objectClass"]: self.infoFrameCanvas.create_text(160, row, font=("Liberation Serif Bold", 10), anchor=W, text="{}".format(objclass)) row += 20 print(objclass) except: print("Error en updateInfoSection") def contextOperations(self, cadena, elLDAPObject, operationType): try: if (operationType == "REFRESH"): print("Refresh sobre {}.".format(cadena)) if (operationType == "ADD"): print("Nueva entrada sobre {}.".format(cadena)) if (operationType == "DELETE"): print("Borrar entrada sobre {}.".format(cadena)) if (operationType == "MOVE"): print("Mover entrada sobre {}.".format(cadena)) except: print("Error en contextOperations") def __oneRightClick(self, event, ldapconnectionobject): print("Right clicked mouse on line {}".format( event.widget.selection())) self.operationsMenu = Menu(self, tearoff=0, borderwidth=2, relief=RAISED) self.operationsMenu.add_command( label="Refresh tree", command=lambda: self.contextOperations(event.widget.selection( ), ldapconnectionobject, "REFRESH")) self.operationsMenu.add_separator() self.operationsMenu.add_command( label="Add Entry", command=lambda: self.contextOperations(event.widget.selection( ), ldapconnectionobject, "ADD")) self.operationsMenu.add_command( label="Delete Entry", command=lambda: self.contextOperations(event.widget.selection( ), ldapconnectionobject, "DELETE")) self.operationsMenu.add_command( label="Move Entry", command=lambda: self.contextOperations(event.widget.selection( ), ldapconnectionobject, "MOVE")) self.operationsMenu.tk_popup(self.treeNavView.winfo_pointerx(), self.treeNavView.winfo_pointery()) def __oneLeftClick(self, event, ldapconnectionobject): ## Por defecto, click sobre cualquier entrada provoca una busqueda de la misma. print("Left clicked mouse on line {}".format(event.widget.selection())) dntoSearch = event.widget.selection() print(dntoSearch[0]) ldapoperations.SearchLdap(ldapconnectionobject, rootSearch=dntoSearch[0], scopeSearch="BASE") self.updateInfoSection(dntoSearch, ldapconnectionobject.response) def DisplayAndBind(self, parentID, lineIDX, entryIID, textString, ldapconnectionobject, isOpen): self.treeNavView.insert(parentID, lineIDX, entryIID, open=isOpen, text=textString) def lefclickhandler(event, self=self, parameters=ldapconnectionobject): return self.__oneLeftClick(event, ldapconnectionobject) self.treeNavView.bind('<<TreeviewSelect>>', lefclickhandler) def rightclickhandler(event, self=self, parameters=ldapconnectionobject): return self.__oneRightClick(event, ldapconnectionobject) self.treeNavView.bind('<Button-3>', rightclickhandler) def ExitOption(self): self.quit() def OpenConnection(self): self.quit() def CloseConnection(self): self.quit()
class SearchBox(Frame): '''A Treeview widget on top, Entry on bottom, using queues for interaction with outside functions''' def __init__(self, parent=None, db=DB, fdict={}): Frame.__init__(self, parent) self.Tests = Tests self.db = db self.fdict = dbm.open(self.db, 'c') #self.fdict['**']='' self.db_update = False #will hold the query to be processed self.query = None self.drives = self.get_drives() self.start_func = StartFunc( ) #platform dependent double-click response self.results = iter( ()) #initiating query results as an empty generator self.total_width = self.winfo_screenwidth( ) #to adjust column widths relative to screen size #Remember scorch mode self.scorch = False self.encoding = ENCODING #for scorch mode #self.keylist=self.fdict.keys() self.keylist_index = 0 self.keylist_counter = 0 #keystroke indicator self.counter = 0 #queues for passing search queries and results self.query_queue = Queue() self.result_queue = Queue() #for usage by db generating function self.dbinit_queue = Queue() #--Search Results panel at top self.panel = Treeview(columns=('Path', 'Size', 'Date')) self.panel.pack(expand=True, fill='both') self.panel.heading('#0', text='Name') self.panel.heading(0, text='Path') self.panel.heading(1, text='Size') self.panel.heading(2, text='Date Modified') #--Starting geometry of the search panel try: #start maximized self.panel.master.attributes('-zoomed', 1) except: self.panel.master.state('zoomed') self.panel_width = self.panel.winfo_width() #Name - 2/5-----Path - 2/5-----Size -1/25-----Date -4/25 # '#0' is the 'Name' column self.panel.column('#0', width=int(self.total_width * 0.4)) self.panel.column('Path', width=int(self.total_width * 0.4)) self.panel.column('Size', width=int(self.total_width * 0.06)) self.panel.column('Date', width=int(self.total_width * 0.14)) #--Panel font, style self.font = Font(family='Helvetica', size=11) '''TkDefaultFont - {'family': 'Segoe UI', 'overstrike': 0, 'size': 9, 'slant': 'roman', 'underline': 0, 'weight': normal'}''' self.style = Style() #linespace - adjust the row height to the font, doesn't happen on its own in tkinter self.style.configure('SearchBox.Treeview', font=self.font, rowheight=self.font.metrics('linespace')) self.panel.config(style='SearchBox.Treeview') #alternating background colors self.panel.tag_configure('color1', background='gray85') #, foreground='white') self.panel.tag_configure('color2', background='gray90') #, foreground='white') #'dark sea green', 'wheat3', 'black' #--App title and icon, currently transparent self.panel.master.title('Jiffy') self.icon = PhotoImage(height=16, width=16) self.icon.blank() #transparent icon, works on all but Py35/Win #loading the transparent icon. black on Py35/Win try: self.master.wm_iconphoto('True', self.icon) except: #For some reason this jammed Python 3.5 with Tk 8.6 on Windows self.tk.call('wm', 'iconphoto', self.master._w, self.icon) #--A string variable to monitor input to the Entry box self.entry_var = StringVar() #self.entry_var.set('Type to search. [F5 - Refresh Database]. [F12 - Scorch Mode]') # [Ctrl-O - Options]. [Ctrl-I - Info] self.entry_var.trace('w', self.update_query) #--Entry line on the bottom self.entry_box = Entry(textvariable=self.entry_var) #keep it as a single line on all window sizes self.entry_box.pack(side='bottom', fill='x') #--Widget Bindings #self.master.bind('<Ctrl-Z>', self.quit) #alternative to Alt-F4 self.master.bind('<Control-equal>', self.scaleup) self.master.bind('<Control-Button-4>', self.scaleup) self.master.bind('<Control-minus>', self.scaledown) self.master.bind('<Control-Button-5>', self.scaledown) self.master.bind('<Control-MouseWheel>', self.scale_mouse) self.panel.bind('<Double-1>', self.doubleclick) self.panel.bind('<Return>', self.doubleclick) #allow scrolling and typing without switching focus self.entry_box.bind('<MouseWheel>', self.scroll_from_entry) self.entry_box.bind('<Button-4>', self.scroll_from_entry) self.entry_box.bind('<Button-5>', self.scroll_from_entry) self.master.bind('<F5>', self.make_database) #self.master.bind('<F12>', self.scorch_mode) #--Starting up with entry box active self.entry_box.focus_set() #--Generating a starting message based on existence of a database if not self.fdict: self.panel.insert('', 'end', text='No cache database found', values=('Hit F5 to generate database', )) else: self.panel.insert( '', 'end', text='Type to search. [F5 - Refresh Database]', values=('[Ctrl - +/-/MouseWheel - Adjust font size]', )) # [Ctrl-O - Options]. [Ctrl-I - Info] #self.panel.insert('', 'end', text='Scorch Mode is faster but uses more memory', values=('Loads the entire database into RAM',)) self.update_searchbox() #Initializing the query managing function in a separate thread (upgrade to pool?) thread.start_new_thread( TMakeSearch, (self.fdict, self.query_queue, self.result_queue)) ##GUI functionality-------------------------------------------------------- #O change to initiation from parameter to SearchBox for more modularity def get_drives(event): return GetDrives() def scroll_from_entry(self, event): '''Scroll results without deactivating entry box, called from entry_box''' self.panel.yview_scroll(1, 'units') def scaleup(self, event): '''The Treeview widget won't auto-adjust the row height, so requires manual resetting upon font changing''' self.font['size'] += 1 self.style.configure('SearchBox.Treeview', rowheight=self.font.metrics('linespace') + 1) def scaledown(self, event): self.font['size'] -= 1 self.style.configure('SearchBox.Treeview', rowheight=self.font.metrics('linespace') + 1) def scale_mouse(self, event): self.scaleup(event) if event.delta > 0 else self.scaledown(event) def doubleclick(self, event): '''Invoke default app on double-click or Enter''' #getting file/folder name and removing '[' and ']' for folders selection = self.panel.item(self.panel.focus()) filename = selection['text'] #remove folder indicating square brackets if filename[0] == '[': filename = filename[1:-2] #SPLIT_TOKEN='\\' if 'win' in sys.platform else '/' full_path = selection['values'][0] + SPLIT_TOKEN + filename self.start_func(full_path) def quit(self, event): '''Currently Alt-F4 exits program, in case I want to add more shortcuts. Also add thread closing management here''' self.master.destroy() ##Cheese: update_database()->is_sb_generated(), trace_results(), update_query() def make_database(self, event): '''Using a thread to generate the dictionary to prevent GUI freezing''' #* dbm might not be thread safe - best might be to restart TMakeSearch self.gtime = time() # for testing self.entry_var.set('Updating Database') self.entry_box.icursor('end') #Resulting dicitionay will be passed via dbinint_queue thread.start_new_thread(RecursiveCreateDict, (self.drives, self.dbinit_queue, self.fdict)) #Wait for the dictionary to be generated self.is_db_generated() def is_db_generated(self): '''Update database if available or sleep and try again''' if not self.dbinit_queue.empty(): #A new dictionary was passed #retrieving new dict self.newdict, self.unsearched = self.dbinit_queue.get() #Messaging TMakeSearch to stop querying the dictionary self.db_update = True self.query_queue.put(None) sleep(0.11) #TMakeSearch takes 0.1s naps. Check further ''' if whichdb(self.db) == ('dbhash'): '''For dumbdbm, this jams the app, as does manual updating. it's not dumb, it's just not worthy''' self.fdict.update(self.newdict) else: for key in self.newdict: self.fdict[key] = self.newdict[key] print('fdict is created') self.db_update = False #save new database self.fdict.sync() print('fdict synced') #Open a new TMakeSearch with the updated database #thread.start_new_thread(TMakeSearch, (self.fdict, self.query_queue, self.result_queue)) #Cleaning up self.newdict.clear() self.newdict = None self.gtime = time() - self.gtime #to read about {}.format #also, a label may be simpler self.entry_var.set('Database generation time- ' + str(self.gtime) + 's. Type to search. [F5 - Refresh Database]') #Pass a signal to close TMakeSearch, then reopen it self.query_queue.put(True) thread.start_new_thread( TMakeSearch, (self.fdict, self.query_queue, self.result_queue)) self.entry_box.icursor(0) #self.loading.destroy() self.panel.delete(*self.panel.get_children()) self.panel.insert( '', 0, text='Scorch Mode is faster but uses more memory', values=('Loads database into RAM', )) #self.keylist=fdict.keys() #for scorch mode self.counter = 0 #self.IS_1ST_PRESS=True #for testing #print time()-self.start #print self.dict_size() else: self.after(100, self.is_db_generated) def update_searchbox(self): '''Update GUI with new result batches ''' self.even = True #for splitting size and date from the keys self.separator = ' * '.encode(self.encoding) while not self.result_queue.empty(): qresult = self.result_queue.get() #print ('is_batch_recieved:', qresult) #if qcounter==self.counter: #currently assuming results will arrive by querying order #break try: #if nothing in queue this will raise an error, saves a preemptive if clause self.results, self.is_new = qresult if Tests.is_batch_recieved: print('is_batch_recieved:', self.results) except: pass #no new results if Tests.is_batch_recieved: print('is_batch_recieved: no new results') else: #if self.panel.get_children()!=(): #results for a newer query, erase old results if self.is_new: self.panel.delete(*self.panel.get_children()) for key in self.results: try: name, size, date = key.decode(self.encoding).split(u'*') #name, size, date=key.split(self.separator) if Tests.is_result_parsed: print(name) except: if Tests.is_result_parsed: print('parsing issue with', key) else: path = self.fdict[key].decode(self.encoding) '''if 'win' in sys.platform and top[0] is u'/': top=u'C:\\'+top[1:] ''' color = 'color1' if self.even else 'color2' self.even = not self.even self.panel.insert('', 'end', text=name, values=(path, size, date), tags=(color, )) self.after(60, self.update_searchbox) def update_query(self, x=None, y=None, z=None): '''Invoked by StringVar().trace() method, which passes 3 arguments that are honorably ditched ''' #Deactivate while switching dictionaries if self.db_update: pass #Cleaning up for 1st keystroke or after a message in the Entry box if not self.counter: '''Entry box needs to be cleaned, the new char put in and the cursor placed after it''' #get&set the 1st search char. user may've changed cursor location b4 typing self.entry_var.set( self.entry_var.get()[self.entry_box.index(INSERT) - 1]) #move cursor after the first char self.entry_box.icursor(1) #counter goes up either way self.counter += 1 self.query = self.entry_var.get() self.query_queue.put(self.query) if Tests.is_query_sent: print(self.query) print(self.counter) ##Not in use ---------------------------------------------------------------- def trace_query(self): '''If I opt for periodically checking the StringVar''' if self.counter: #when counter=0 there's a message/notification in the entry box if self.query != self.entry_var.get(): self.query = self.entry_var.get() self.query_queue.put(self.query) self.after(100, self.trace_query) def trace_and_update(self): ''' In-GUI implementation of query searching, uses a list for iterating over the keys''' '''works smoother when results are generated quickly, but with sparse results GUI becomes unresponsive for short whiles. Relevant only if results are guaranteed to be generated swiftly''' #print self.query #if new query, resetting search parameters and GUI if self.query != self.entry_var.get(): self.keylist_counter = 0 self.query = self.entry_var.get() self.search_list = self.query.lower().split() self.panel.delete(*self.panel.get_children()) self.insertion_counter = 0 self.keylist_index = self.keylist_counter for key in self.keylist[self.keylist_index:]: filename = key.split('*')[0].lower() #If a match, parse and add to the Treeview if self.all(token in filename for token in self.search_list): name, size, date = key.split('*') self.panel.insert('', 'end', text=name, values=(self.fdict[key], size, date)) self.insertion_counter += 1 self.keylist_counter += 1 if self.insertion_counter >= self.INSERTIONS_PER_CYCLE: #50 ##or not dict_counter: break #nap time self.after(60, self.trace_and_update)
class MyProgram: def __init__(self, master): self._database = Data() self._materias = self._database.consultar('MATERIA') self._estudiantes = self._database.consultar('ESTUDIANTE') self._carrera = self._database.consultar('CARRERA') self._provincia = self._database.consultar('PROVINCIA') self._imgfile = 'profileIcon.png' self._master = master master.title("Sistema de Estudiantes") self.menubar = Menu(master) self.router_tree_view = ttk.Treeview(self._master) #menu 1 self.estudiantesmenu = Menu(self.menubar, tearoff=0) self.estudiantesmenu.add_command( label="Consultar", command=lambda: self.consultar("ESTUDIANTE")) self.estudiantesmenu.add_command( label="Modificar", command=lambda: self.estudianteControl()) self.menubar.add_cascade(label="Estudiantes", menu=self.estudiantesmenu) #menu 2 self.materiasmenu = Menu(self.menubar, tearoff=0) self.materiasmenu.add_command( label="Consultar", command=lambda: self.consultar("MATERIA")) self.materiasmenu.add_command(label="Modificar", command=lambda: self.materiaControl()) self.menubar.add_cascade(label="Materias", menu=self.materiasmenu) #menu 3 self.calificacionesmenu = Menu(self.menubar, tearoff=0) self.calificacionesmenu.add_command( label="Consultar", command=lambda: self.consultar("CALIFICACIONES")) self.calificacionesmenu.add_command( label="Modificar", command=lambda: self.calificacionControl()) self.menubar.add_cascade(label="Calificaciones", menu=self.calificacionesmenu) #menu 4 self.reportesmenu = Menu(self.menubar, tearoff=0) self.reportesmenu.add_command(label="Reporte html", command=lambda: self.reporteControl()) self.reportesmenu.add_command(label="Reporte mapa", command=lambda: self.reporteControlM()) self.reportesmenu.add_command(label="Reporte grafico", command=lambda: self.reporteControlG()) self.menubar.add_cascade(label="Reportes", menu=self.reportesmenu) master.config(menu=self.menubar) master.geometry("400x300") #end _init def reporteControl(self): idEstudiante = StringVar() filewin = Toplevel(self._master) Label(filewin, text="Estudiante").place(x=10, y=30) CbBoxEstudiante = ttk.Combobox( filewin, state='readonly', textvariable=idEstudiante, values=self.get_dataCombo('ESTUDIANTE')).place(x=100, y=30) botonReportee = Button( filewin, text="Reporte html", width=14, command=lambda: self.reporteH(idEstudiante.get())).place(x=100, y=80) filewin.geometry("250x200") filewin.mainloop() #end method def reporteControlM(self): idMateria = StringVar() idProvincia = StringVar() idLitereal = StringVar() filewin = Toplevel(self._master) Label(filewin, text="Materia").place(x=10, y=30) Label(filewin, text="Provincia").place(x=10, y=60) Label(filewin, text="Literal").place(x=10, y=90) CbBoxEstudiante = ttk.Combobox( filewin, state='readonly', textvariable=idMateria, values=self.get_dataCombo('MATERIA')).place(x=100, y=30) CbBoxProvincia = ttk.Combobox( filewin, state='readonly', textvariable=idProvincia, values=self.get_dataCombo('PROVINCIA')).place(x=100, y=60) CbBoxLiteral = ttk.Combobox(filewin, state='readonly', textvariable=idLitereal, values=['A', 'B', 'C', 'D', 'F', 'TODOS']).place(x=100, y=90) botonReporte = Button( filewin, text="Reporte mapa", width=14, command=lambda: self.reportM( [idMateria.get(), idProvincia.get(), idLitereal.get()])).place(x=100, y=130) filewin.geometry("250x200") filewin.mainloop() #end method def reporteControlG(self): filewin = Toplevel(self._master) idprovinciaBarra = StringVar() idprovinciaComp1 = StringVar() idprovinciaComp2 = StringVar() ttk.Combobox(filewin, state='readonly', textvariable=idprovinciaBarra, values=self.get_dataCombo('PROVINCIA')).place(x=170, y=71) ttk.Combobox(filewin, state='readonly', textvariable=idprovinciaComp1, values=self.get_dataCombo('PROVINCIA')).place(x=10, y=190) ttk.Combobox(filewin, state='readonly', textvariable=idprovinciaComp2, values=self.get_dataCombo('PROVINCIA')).place(x=230, y=190) Label(filewin, text="Notas por literales").place(x=10, y=30) Label(filewin, text="Literal por provincia").place(x=10, y=70) Label(filewin, text="Estudiantes por carrera").place(x=10, y=110) Label(filewin, text="Comparativo por provincia").place(x=10, y=150) photoLabel = Label(filewin) photoLabel.place(x=10, y=230) def setPhotoLabel(imagen): img = ImageTk.PhotoImage(Image.open(imagen)) photoLabel.config(image=img) photoLabel.photo = img # Label(filewin, text="Literal").place(x=10,y=90) # CbBoxEstudiante = ttk.Combobox(filewin, state='readonly', textvariable=idMateria, values=self.get_dataCombo('MATERIA')).place(x=100,y=30) # CbBoxProvincia = ttk.Combobox(filewin, state='readonly', textvariable=idProvincia, values=self.get_dataCombo('PROVINCIA')).place(x=100,y=60) # CbBoxLiteral = ttk.Combobox(filewin,state='readonly', textvariable=idLitereal, values=['A','B','C','D','F','TODOS']).place(x=100,y=90) botonReporteL = Button( filewin, text="Generar", width=14, command=lambda: self.reportG1(setPhotoLabel)).place(x=170, y=30) botonReporteP = Button( filewin, text="Generar", width=10, command=lambda: self.reportG2(idprovinciaBarra.get(), setPhotoLabel )).place(x=330, y=67) botonReporteP3d = Button( filewin, text="Generar en 3D", width=10, command=lambda: self.reportG5(idprovinciaBarra.get(), setPhotoLabel )).place(x=420, y=67) botonReporteC = Button( filewin, text="Generar", width=14, command=lambda: self.reportG3(setPhotoLabel)).place(x=170, y=110) botonReporteComp = Button( filewin, text="Generar", width=10, command=lambda: self.reportG4(idprovinciaComp1.get( ), idprovinciaComp2.get(), setPhotoLabel)).place(x=440, y=186) filewin.geometry("600x550") filewin.mainloop() #end method def materiaControl(self, id=0): codigo = StringVar() nombre = StringVar() filewin = Toplevel(self._master) Label(filewin, text="Codigo").place(x=10, y=30) Label(filewin, text="Nombre").place(x=10, y=60) TxtBoxCodigo = Entry(filewin, width=20, textvariable=codigo).place(x=100, y=30) TxtBoxNombre = Entry(filewin, width=20, textvariable=nombre).place(x=100, y=60) botonInsertar = Button(filewin, text="Insertar", width=14, command=lambda: self.insert_materia( [codigo.get(), nombre.get()])).place(x=10, y=120) # botonModificar=Button(filewin, text = "Modificar", width= 14).place(x=120, y=120) # botonBorrar=Button(filewin, text = "Borrar", width= 14,command=lambda:self.greet()).place(x=60, y=160) if id != 0: data = self._database.consultarById("MATERIA", "CODIGO", id) print(data[0]) codigo.set(data[0]) nombre.set(data[1]) #end condition filewin.geometry("250x200") filewin.mainloop() #end method def estudianteControl(self, id=0): mat = StringVar() cedula = StringVar() nom = StringVar() apellido = StringVar() self._imgfile = "profileIcon.png" sex = StringVar() idcarrera = StringVar() idprovincia = StringVar() filewin = Toplevel(self._master) Label(filewin, text="Cecula").place(x=10, y=30) Label(filewin, text="Nombre").place(x=10, y=60) Label(filewin, text="Apellido").place(x=10, y=90) Label(filewin, text="Sexo").place(x=10, y=120) Label(filewin, text="Matricula").place(x=10, y=150) Label(filewin, text="Carrera").place(x=10, y=180) Label(filewin, text="Provincia").place(x=10, y=210) canvas = Canvas(filewin, width=300, height=300).place(x=310, y=60) img = ImageTk.PhotoImage(Image.open(self._imgfile)) photoLabel = Label(filewin, image=img) photoLabel.place(x=320, y=60) TxtBoxCedula = Entry(filewin, width=20, textvariable=cedula).place(x=100, y=30) TxtBoxNombre = Entry(filewin, width=20, textvariable=nom).place(x=100, y=60) TxtBoxApellido = Entry(filewin, width=20, textvariable=apellido).place(x=100, y=90) TxtBoxSexo = Entry(filewin, width=20, textvariable=sex).place(x=100, y=120) TxtBoxMatricula = Entry(filewin, width=20, textvariable=mat).place(x=100, y=150) CbBoxCarrera = ttk.Combobox( filewin, state='readonly', textvariable=idcarrera, values=self.get_dataCombo('CARRERA')).place(x=100, y=180) CbBoxProvincia = ttk.Combobox( filewin, state='readonly', textvariable=idprovincia, values=self.get_dataCombo('PROVINCIA')).place(x=100, y=210) botonInsertar = Button(filewin, text="Insertar", width=14, command=lambda: self.insert_estudiante([ mat.get(), nom.get(), apellido.get(), cedula.get(), self._imgfile, sex.get(), idprovincia.get(), idcarrera.get() ])).place(x=10, y=240) botonConsultar = Button( filewin, text="Consultar", width=10, command=lambda: self.estudianteDesdeApi(cedula.get( ), [nom, apellido, sex], photoLabel)).place(x=300, y=30) #botonModificar=Button(filewin, text = "Modificar", width= 14,).place(x=120, y=120) #botonBorrar=Button(filewin, text = "Borrar", width= 14, command= lambda:self.greet()).place(x=60, y=160) if id != 0: data = self._database.consultarById("ESTUDIANTE", "ID_ESTUDIANTE", id) print(data[0]) mat.set(data[1]) nom.set(data[2]) apellido.set(data[3]) cedula.set(data[4]) self._imgfile = data[5] raw_data = urllib.request.urlopen(self._imgfile).read() img = Image.open(io.BytesIO(raw_data)) photo = ImageTk.PhotoImage(img) photoLabel.config(image=photo) photoLabel.photo = photo sex.set(data[6]) idprovincia.set(data[7]) idcarrera.set(data[8]) #end condition filewin.geometry("450x280") filewin.mainloop() #end method def calificacionControl(self, id=0): idEstudiante = StringVar() idMateria = StringVar() practica1 = StringVar() practica2 = StringVar() foro1 = StringVar() foro2 = StringVar() primerParcial = StringVar() segundoParcial = StringVar() examenFinal = StringVar() filewin = Toplevel(self._master) Label(filewin, text="Estudiante").place(x=10, y=10) Label(filewin, text="Materia").place(x=260, y=10) Label(filewin, text="Practica1").place(x=10, y=30) Label(filewin, text="Practica2").place(x=10, y=50) Label(filewin, text="Foro1").place(x=260, y=30) Label(filewin, text="Foro2").place(x=260, y=50) Label(filewin, text="Primer Parcial").place(x=10, y=70) Label(filewin, text="Segundo Parcial").place(x=10, y=90) Label(filewin, text="Examen Final").place(x=260, y=70) # TxtBoxEstudiante=Entry(filewin, width=20, textvariable=idEstudiante).place(x=100,y=10) CbBoxEstudiante = ttk.Combobox( filewin, state='readonly', textvariable=idEstudiante, values=self.get_dataCombo('ESTUDIANTE')).place(x=100, y=10) CbBoxMateria = ttk.Combobox( filewin, state='readonly', textvariable=idMateria, values=self.get_dataCombo('MATERIA')).place(x=350, y=10) # TxtBoxMateria1=Entry(filewin, width=20, textvariable=idMateria).place(x=350,y=10) TxtBoxPractica1 = Entry(filewin, width=20, textvariable=practica1).place(x=100, y=30) TxtBoxPractica2 = Entry(filewin, width=20, textvariable=practica2).place(x=100, y=50) TxtBoxForo1 = Entry(filewin, width=20, textvariable=foro1).place(x=350, y=30) TxtBoxForo2 = Entry(filewin, width=20, textvariable=foro2).place(x=350, y=50) TxtBoxPrimerParcial = Entry(filewin, width=20, textvariable=primerParcial).place(x=100, y=70) TxtBoxSegundoParcial = Entry(filewin, width=20, textvariable=segundoParcial).place(x=100, y=90) TxtBoxExamenfinal = Entry(filewin, width=20, textvariable=examenFinal).place(x=350, y=70) botonInsertar = Button( filewin, text="Insertar", width=14, command=lambda: self.insert_calificaciones(id if ( id != 0) else 0, [idEstudiante.get(), idMateria.get()], [ practica1.get(), practica2.get(), foro1.get(), foro2.get(), primerParcial.get(), segundoParcial.get(), examenFinal.get() ])).place(x=100, y=120) # botonModificar=Button(filewin, text = "Modificar", width= 14,).place(x=260, y=120) # botonBorrar=Button(filewin, text = "Borrar", width= 14,command= lambda:self.greet()).place(x=180, y=160) if id != 0: data = self._database.consultarById("CALIFICACIONES", "ID_CALIFICACION", id) print(data) idEstudiante.set(data[1]) idMateria.set(data[2]) practica1.set(data[3]) practica2.set(data[4]) foro1.set(data[5]) foro2.set(data[6]) primerParcial.set(data[7]) segundoParcial.set(data[8]) examenFinal.set(data[9]) #end condition filewin.geometry("500x200") filewin.mainloop() #end method def consultar(self, tabla): print(tabla) filewin = Toplevel(self._master) frame_router = Frame(filewin) frame_router.grid(row=4, column=0, columnspan=4, rowspan=6, pady=20, padx=20) infoTabla = self._database.infotabla(tabla) buscartabla = [] for campo in infoTabla: buscartabla.append(campo[1]) #end for dataTable = self._database.consultar(tabla) # print(dataTable[0][0]) columns = buscartabla self.router_tree_view = Treeview(frame_router, columns=columns, show="headings") self.router_tree_view.bind("<Double-1>", self.itemEvent) self.router_tree_view.column(buscartabla[0], width=100) for col in columns[0:]: self.router_tree_view.column(col, width=120) self.router_tree_view.heading(col, text=col) #end for print(dataTable) if type(dataTable) is list: i = 0 for data in dataTable: self.router_tree_view.insert(parent='', index='end', iid=self.dinamyFill(tabla, data)[0], values=self.dinamyFill( tabla, data)) i = i + 1 #end for self.router_tree_view.pack(side="left", fill="y") scrollbar = Scrollbar(frame_router, orient='vertical') scrollbar.configure(command=self.router_tree_view.yview) scrollbar.pack(side="right", fill="y") self.router_tree_view.config(yscrollcommand=scrollbar.set) botonEliminar = Button( filewin, text="Eliminar", width=14, command=lambda: self.tableItemDelete(tabla, filewin)).place(x=20, y=250) botonEditar = Button( filewin, text="Editar", width=14, command=lambda: self.tableItemEdit(tabla, filewin)).place(x=150, y=250) filewin.geometry(self.set_dimension(tabla)) filewin.mainloop() #end method def dinamyFill(self, tabla, data): if tabla == "ESTUDIANTE": return (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]) elif tabla == "MATERIA": return (data[0], data[1]) elif tabla == "CALIFICACIONES": return (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]) #end method def set_dimension(self, tabla): dimension = "700x300" if tabla == "MATERIA": dimension = "400x300" elif tabla == "CALIFICACIONES": dimension = "800x300" return dimension #end method def itemEvent(self): item = self.router_tree_view.selection( ) #[0] # now you got the item on that tree print("you clicked on id", item[0]) #end method def tableItemDelete(self, tabla, f): item = self.router_tree_view.selection( ) #[0] # now you got the item on that tree if len(item) > 0: print("you clicked on id", item[0]) if tabla == "ESTUDIANTE": data = self._database.delete(item[0], tabla, 'ID_ESTUDIANTE') messagebox.showinfo(title='Informacion', message=data) f.destroy() elif tabla == 'MATERIA': data = self._database.delete(item[0], tabla, 'CODIGO') messagebox.showinfo(title='Informacion', message=data) f.destroy() else: data = self._database.delete(item[0], tabla, 'ID_CALIFICACION') messagebox.showinfo(title='Informacion', message=data) f.destroy() else: messagebox.showinfo(title='Informacion', message='Seleccione algo') #end method def tableItemEdit(self, tabla, f): item = self.router_tree_view.selection( ) #[0] # now you got the item on that tree if len(item) > 0: print("you clicked on id", item[0]) if tabla == "ESTUDIANTE": f.destroy() self.estudianteControl(item[0]) #print(self._database.delete(item[0], tabla, 'ID_ESTUDIANTE')) elif tabla == 'MATERIA': f.destroy() self.materiaControl(item[0]) # print(self._database.delete(item[0], tabla, 'CODIGO')) else: f.destroy() self.calificacionControl(item[0]) # print(self._database.delete(item[0], tabla, 'ID_CALIFICACION')) else: messagebox.showinfo(title='Informacion', message='Seleccione algo') #end method def insert_estudiante(self, values): dic = {'data': values, 'notas': [0, 0, 0, 0, 0, 0, 0]} alumno = Alumno(dic) print('data antes', dic['data']) if alumno.is_valid(): data = self._database.insert( [(dic['data'][0], dic['data'][0], dic['data'][1], dic['data'][2], dic['data'][3], dic['data'][4], dic['data'][5], dic['data'][6], dic['data'][7])], 'ESTUDIANTE', 9) messagebox.showinfo(title='Informacion', message=data) self._estudiantes = self._database.consultar('ESTUDIANTE') else: messagebox.showinfo(title='Informacion', message='Datos no validos') #end method def insert_materia(self, values): if values[0] != "" and values[0] != "": data = self._database.insert([(values[0], values[1])], 'MATERIA', 2) messagebox.showinfo(title='Informacion', message=data) self._materias = self._database.consultar('MATERIA') else: messagebox.showinfo(title='Informacion', message='Datos no validos') #end method def insert_calificaciones(self, editing, info, values): # dic = {'data':['','',''],'notas':values} ncalif = self._database.calificacionByEstudiante(info[0]) print(len(ncalif)) nota = Notas(values) print(info) print(values) now = datetime.now() timestamp = datetime.timestamp(now) id = str(timestamp) if nota.is_valid( ) and info[0] != "" and info[1] != '' and len(ncalif) < 4: data = self._database.insert( [(editing if (editing != 0) else id[11:17], info[0], info[1], values[0], values[1], values[2], values[3], values[4], values[5], values[6])], "CALIFICACIONES", 10) messagebox.showinfo(title='Informacion', message=data) else: messagebox.showinfo(title='Informacion', message='Ya tiene 3 materias.' if (len(ncalif) == 3) else 'Datos no validos') #end method def estudianteDesdeApi(self, cedula, inputsFields, photoLabel): if (cedula != ""): respuestaServicio = Services(cedula).get_datos() #manejo de service fail print('aqui', respuestaServicio) if respuestaServicio['ok'] != False: if "Cedula" in respuestaServicio: print(respuestaServicio) inputsFields[0].set(respuestaServicio['Nombres']) inputsFields[1].set( f"{respuestaServicio['Apellido1']} {respuestaServicio['Apellido2']}" ) inputsFields[2].set(respuestaServicio['IdSexo']) print(respuestaServicio["foto"]) self._imgfile = respuestaServicio["foto"] raw_data = urllib.request.urlopen(self._imgfile).read() img = Image.open(io.BytesIO(raw_data)) photo = ImageTk.PhotoImage(img) photoLabel.config(image=photo) photoLabel.photo = photo print(photo) #image = ImageTk.PhotoImage(im) # else: # messagebox.showinfo(title='Informacion', message='Cedula no encontrada') else: messagebox.showinfo( title='Informacion', message='Ha ocurrido un error, intente otra cedula.') else: messagebox.showinfo(title='Informacion', message='Cedula no valida.') #end method def greet(self): messagebox.showinfo(title='Informacion', message='Greetings!') #end methhod def get_dataCombo(self, tabla): data = [] values = self._estudiantes if tabla == 'MATERIA': values = self._materias elif tabla == 'CARRERA': values = self._carrera elif tabla == 'PROVINCIA': values = self._provincia i = 0 for v in values: data.append(v[1] if ( tabla == 'PROVINCIA' or tabla == 'CARRERA') else v[0]) i = i + 1 return data #end method def reporteH(self, m): print(m) report = Reporte(m) report.get_report() #end method def reportM(self, values): #0 materi 1 provincia 2 literal if values[0] != "" and values[1] != "" and values[2] != "": report = Reporte('20202020') report.get_reportM(values) else: messagebox.showinfo(title='Informacion', message='Seleccione los campos.') #end method def reportG3(self, setPhotoLabel): values = self._database.estudianteByCarrera() # values=[(1, 'Ingeniería de software'), (2, 'Ingeniería industrial')] value = [] legend = [] for i in values: value.append(i[0]) legend.append(i[1]) report = Reporte('20202020') # values=['tipo',[0,2,4],['juan','pedro'],'title','colum','values'] data = ['pastel', value, legend, 'Estudiantes por carreras'] report.get_reportG(data) setPhotoLabel("pastel.png") #end method def reportG1(self, setPhotoLabel): n = self._database.consultar('CALIFICACIONES') letras = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'F': 0} for i in n: nota = Notas([i[3], i[4], i[5], i[6], i[7], i[8], i[9]]) cal = Calculo(nota) for f in letras: if f == cal.get_literal(): letras[f] = letras[f] + 1 print(letras) report = Reporte('20202020') # values=['tipo',[0,2,4],['juan','pedro'],'title','colum','values'] value = [i for i in letras] legend = [letras[i] for i in letras] data = [ 'barra', value, legend, 'Notas por literal', 'Literal', 'Cantidad' ] report.get_reportG(data) setPhotoLabel("barra.png") #end method def reportG5(self, idProvincia, setPhotoLabel): if (idProvincia): n = self._database.literalesByProvincia() graphData = self.filterLiteralsByProvince(idProvincia, n) report = Reporte('20202020') data = [ 'barra3D', graphData[0], graphData[1], f'Notas en {idProvincia}', 'Literal', 'Cantidad' ] report.get_reportG(data) setPhotoLabel("barra3D.png") else: messagebox.showinfo(title='Informacion', message='Seleccione una provincia') #end method def reportG2(self, idProvincia, setPhotoLabel): if (idProvincia): n = self._database.literalesByProvincia() graphData = self.filterLiteralsByProvince(idProvincia, n) report = Reporte('20202020') data = [ 'barra', graphData[0], graphData[1], f'Notas en {idProvincia}', 'Literal', 'Cantidad' ] report.get_reportG(data) setPhotoLabel("barra.png") else: messagebox.showinfo(title='Informacion', message='Seleccione una provincia') #end method def filterLiteralsByProvince(self, idProvincia, grade): letras = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'F': 0} for i in grade: if (i[10] == idProvincia): nota = Notas([i[3], i[4], i[5], i[6], i[7], i[8], i[9]]) cal = Calculo(nota) for f in letras: if f == cal.get_literal(): letras[f] = letras[f] + 1 value = [i for i in letras] legend = [letras[i] for i in letras] return [value, legend] def reportG4(self, idProvincia1, idProvincia2, setPhotoLabel): if (idProvincia1 and idProvincia2): values = self._database.literalesByProvincia() graphData1 = self.filterLiteralsByProvince(idProvincia1, values) graphData2 = self.filterLiteralsByProvince(idProvincia2, values) provincias = [idProvincia1, idProvincia2] report = Reporte('20202020') data = [ 'Comparativo', graphData1, graphData2, 'Grafico Comparativo', provincias ] report.get_reportG(data) setPhotoLabel("Comparativo.png") else: messagebox.showinfo(title='Informacion', message='Seleccione las provincias')
class Report(Frame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.root = self.winfo_toplevel() self.root.title(" ".join((APPNAME, VERSION, "| Report"))) self.root.resizable(0, 0) self.items = None headers = ('Page', 'Rank', 'PageRank Value', 'Incoming') self.t = Scale(self, from_=0, to=1, label='n-th iteration', bd=1, width=7, orient='horizontal', command=self.__set_t) self.t.pack(fill='x') self.label = Label(self, anchor='e') self.label.pack(fill='x') self.tree = Treeview(self, columns=headers, show="headings", height=REPORT_HEIGHT) self.tree.column(0, anchor='center', width=55) self.tree.column(1, anchor='center', width=55) self.tree.column(2, width=175) self.tree.column(3, anchor='center', width=55) self.scroll = Scrollbar(self, command=self.tree.yview) self.scroll.pack(side='right', fill='y') self.tree.config(yscrollcommand=self.scroll.set) for col in headers: self.tree.heading(col, text=col.title()) self.root.master.focus_force() self.root.bind('<Key>', self.__keys) def __keys(self, event): if event.char == 'i': self.t.set(self.t.get() - 1) elif event.char == 'I': self.t.set(0) elif event.char == 'o': self.t.set(self.t.get() + 1) elif event.char == 'O': self.t.set(self.pagerank[1]) def __set_t(self, t=None): self.render(self.pagerank, self.edge_counts, self.d, self.e, t=int(t)) def render(self, pagerank, edge_counts, d, e, t=None): self.d, self.e = d, e self.edge_counts = edge_counts self.pagerank = pagerank if t is not None: pr = pagerank[0][t] else: self.t.config(command=None) self.t.config(to=self.pagerank[1]) self.t.set(self.pagerank[1]) self.t.config(command=self.__set_t) pr = pagerank[0][-1] label_text = '# of ranks:{0:>3} # of iterations:{1:>3}'.format( len(set(pr.values())), self.pagerank[1]) self.label.config(text=label_text) in_map = {k: 0 for k in pr.keys()} # incoming edges by nodes for (tail, head), n in edge_counts.items(): if tail is not head: in_map[head] += n get_rank = lambda k: sorted(pr.values())[::-1].index(pr[k]) + 1 data = tuple( (k, get_rank(k), pr[k], in_map[k]) for k in sorted(pr.keys())) if self.items: self.tree.delete(*self.items) self.items = [ self.tree.insert('', 'end', values=line) for line in data ] self.tree.pack(side='left', fill='y') #self.root.master.focus_force() def destroy(self): super().destroy() self.root.master.r_win = False self.root.master.windowsmenu.entryconfig(0, label='[ ] Report window') self.root.destroy()
class Configurator(tk.Tk): """ The main Tk window representing the main app. Attributes ---------- treeview : :py:class:`~tkinter.Treeview` The treeview widget. treeview_popup_target_id : `int` The pop target id relating to the id of the selected element. treeview_popup : :py:class:`~tkinter.Widget` The treeview popup widget. cfg_file_name : `str` The file name of the current configuration. element_dict : `dict` The dictionary of elements. Keys are the element ids. root_element : :py:class:`~enrich2.base.storemanager.StoreManager` An instance inheriting from storemanager that acts as a root object. force_recalculate :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. component_outliers :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. tsv_requested : :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. treeview_buttons : `list` The ``new``, ``edit`` and ``delete`` buttons. go_button : :py:class`~tkinter.ttk.Button` The button that begins the analysis scorer_widget : :py:class:`~enrich2.gui.options_frame.ScorerScriptsDropDown` The ScorerScriptsDropDown instance associated with this app. scorer : :py:class:`~enrich2.plugins.scoring.BaseScorerPlugin` The scorer class loaded from a plugin scorer_attrs : `dict` The scoring attributes for the plugin. scorer_path : `str` The path to the currently selected scoring plugin. analysis_thread : :py:class:`~threading.Thread` The thread object that runs the computation method to prevent GUI blocking. Methods ------- create_main_frame create_menubar create_treeview_context_menu create_new_element menu_open menu_save menu_saveas menu_selectall refresh_treeview treeview_context_menu set_treeview_properties populate_tree go_button_press new_button_press edit_button_press delete_button_press delete_element apply_seqlib_fastq get_element get_focused_element get_selected_elements get_selected_scorer_class get_selected_scorer_attrs get_selected_scorer_path run_analysis set_gui_state configure_analysis refresh_plugins show_plugin_source_window See Also -------- :py:class:`~tkinter.Tk` """ def __init__(self): tk.Tk.__init__(self) self.title("Enrich 2") # Main app variables self.cfg_file_name = tk.StringVar() self.element_dict = dict() self.root_element = None self.analysis_thread = None self.plugin_source_window = None self.queue = queue.Queue() # Treeview variables self.treeview = None self.treeview_popup_target_id = None self.treeview_popup = None # analysis options self.force_recalculate = tk.BooleanVar() self.component_outliers = tk.BooleanVar() self.tsv_requested = tk.BooleanVar() # allow resizing self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) # create UI elements self.treeview_buttons = [] self.go_button = None self.scorer_widget = None self.scorer = None self.scorer_attrs = None self.scorer_path = None self.create_main_frame() self.create_menubar() self.create_treeview_context_menu() self.after(10, self.poll_logging_queue) self.plugin_source_window = SourceWindow(master=self) self.plugin_source_window.hide() self.refresh_plugins() # ---------------------------------------------------------------------- # # Creation Methods # ---------------------------------------------------------------------- # def create_treeview_context_menu(self): """ This creates the tree-like view rendering the experiment heirachy. """ self.treeview_popup = tk.Menu(self, tearoff=0) self.treeview_popup.add_command(label="Apply FASTQ...", command=self.apply_seqlib_fastq) def create_main_frame(self): """ Large function creating all the basic elements of the main app frame. Creates the treeview and associated buttons, the scoring plugin frame and the go button. """ # Frame for the Treeview and New/Edit/Delete buttons main = Frame(self, padding=(3, 3, 12, 12)) main.rowconfigure(0, weight=1) main.columnconfigure(0, weight=1) main.columnconfigure(1, weight=0) main.grid(row=0, column=0, sticky="nsew") # ------------------------------------------------------- # # Frame for the Treeview and its scrollbars tree_frame = Frame(main, padding=(3, 3, 12, 12)) tree_frame.rowconfigure(0, weight=1) tree_frame.rowconfigure(1, weight=0) tree_frame.columnconfigure(0, weight=1) tree_frame.columnconfigure(1, weight=0) tree_frame.grid(row=0, column=0, sticky="nsew") # ------------------------------------------------------- # # Treeview with column headings self.treeview = Treeview(tree_frame) self.treeview["columns"] = ("class", "barcodes", "variants") self.treeview.column("class", width=120) self.treeview.heading("class", text="Type") self.treeview.column("barcodes", width=25, stretch=tk.NO, anchor=tk.CENTER) self.treeview.heading("barcodes", text="BC") self.treeview.column("variants", width=25, stretch=tk.NO, anchor=tk.CENTER) self.treeview.heading("variants", text="V") self.treeview.grid(row=0, column=0, sticky="nsew") # Treeview context menu bindings self.treeview.bind("<Button-2>", self.treeview_context_menu) # Treeview scrollbars tree_ysb = tk.Scrollbar(tree_frame, orient="vertical", command=self.treeview.yview) tree_xsb = tk.Scrollbar(tree_frame, orient="horizontal", command=self.treeview.xview) tree_ysb.grid(row=0, column=1, sticky="nsw") tree_xsb.grid(row=1, column=0, sticky="ewn") self.treeview.config(yscroll=tree_ysb.set, xscroll=tree_xsb.set) # ------------------------------------------------------- # # Frame for New/Edit/Delete buttons button_frame = Frame(main, padding=(3, 3, 12, 12)) button_frame.grid(row=1, column=0) new_button = Button(button_frame, text="New...", command=self.new_button_press) new_button.grid(row=0, column=0) edit_button = Button(button_frame, text="Edit...", command=self.edit_button_press) edit_button.grid(row=0, column=1) delete_button = Button(button_frame, text="Delete", command=self.delete_button_press) delete_button.grid(row=0, column=2) self.treeview_buttons = [new_button, delete_button, edit_button] # ------------------------------------------------------- # # Frame for Plugin and Analysis Options right_frame = Frame(main, padding=(3, 3, 12, 12)) right_frame.rowconfigure(0, weight=1) right_frame.rowconfigure(1, weight=0) right_frame.columnconfigure(0, weight=1) right_frame.columnconfigure(1, weight=0) right_frame.grid(row=0, column=1, sticky="new") # ------------------------------------------------------- # # LabelFrame for plugin and options scoring_plugin = ScorerScriptsDropDown(right_frame, text="Scoring Options", padding=(3, 3, 12, 12)) scoring_plugin.grid(row=0, column=0, sticky="new") self.scorer_widget = scoring_plugin # ------------------------------------------------------- # # LabelFrame for Analysis Options row = 0 options_frame = LabelFrame(right_frame, text="Analysis Options", padding=(3, 3, 12, 12)) options_frame.grid(row=1, column=0, sticky="new", pady=4) # force recalculate force_recalculate = Checkbutton(options_frame, text="Force Recalculation", variable=self.force_recalculate) force_recalculate.grid(column=0, row=row, sticky="w") row += 1 # component outliers component_outliers = Checkbutton( options_frame, text="Component Outlier Statistics", variable=self.component_outliers, ) component_outliers.grid(column=0, row=row, sticky="w") row += 1 # write tsv tsv_requested = Checkbutton(options_frame, text="Write TSV Files", variable=self.tsv_requested) tsv_requested.grid(column=0, row=row, sticky="w") tsv_requested.invoke() row += 1 # ------------------------------------------------------- # # Run Analysis button frame go_button_frame = Frame(main, padding=(3, 3, 12, 12)) go_button_frame.grid(row=1, column=1) go_button = Button(go_button_frame, text="Run Analysis", command=self.go_button_press) go_button.grid(column=0, row=0) self.go_button = go_button def create_new_element(self): """ Create and return a new element based on the current selection. This element is not added to the treeview. """ element = None parent_element = self.get_focused_element() if isinstance(parent_element, Experiment): element = Condition() element.parent = parent_element elif isinstance(parent_element, Condition): element = Selection() element.parent = parent_element elif isinstance(parent_element, Selection): element = CreateSeqLibDialog(self).element_type() element.parent = parent_element elif isinstance(parent_element, SeqLib): # special case: creates a copy of the selected SeqLib as a sibling element = type(parent_element)() element.configure(parent_element.serialize()) element.parent = parent_element.parent # clear out the seqlib-specific values element.name = None element.timepoint = None element.counts_file = None element.reads = None else: raise ValueError("Unrecognized parent object " "type '{}'".format(type(parent_element))) return element def create_menubar(self): """ Creates the menubar for the main app, with associated drop down menus. """ # make platform-specific keybinds if platform.system() == "Darwin": accel_string = "Command+" accel_bind = "Command-" else: accel_string = "Ctrl+" accel_bind = "Control-" # create the menubar menubar = tk.Menu(self) # file menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Open...", accelerator="{}O".format(accel_string), command=self.menu_open, ) filemenu.add_command(label="Save", accelerator="{}S".format(accel_string), command=self.menu_save) filemenu.add_command( label="Save As...", accelerator="{}Shift+S".format(accel_string), command=self.menu_saveas, ) menubar.add_cascade(label="File", menu=filemenu) # edit menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Select All", accelerator="{}A".format(accel_string), command=self.menu_selectall, ) menubar.add_cascade(label="Edit", menu=filemenu) # tools menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Show Log", accelerator="{}L".format(accel_string), command=show_log_window, ) filemenu.add_command( label="Plugin Sources", accelerator="{}P".format(accel_string), command=self.show_plugin_source_window, ) filemenu.add_command( label="Refresh Plugins", accelerator="{}R".format(accel_string), command=self.refresh_plugins, ) menubar.add_cascade(label="Tools", menu=filemenu) # add the menubar self.config(menu=menubar) # add file menu keybinds self.bind("<{}o>".format(accel_bind), lambda event: self.menu_open()) self.bind("<{}s>".format(accel_bind), lambda event: self.menu_save()) self.bind("<{}Shift-s>".format(accel_bind), lambda event: self.menu_saveas()) # add edit menu keybinds self.bind("<{}a>".format(accel_bind), lambda event: self.menu_selectall()) # add show log menu keybinds # add edit menu keybinds self.bind("<{}l>".format(accel_bind), lambda event: show_log_window()) self.bind("<{}p>".format(accel_bind), lambda event: self.show_plugin_source_window()) self.bind("<{}r>".format(accel_bind), lambda event: self.refresh_plugins()) # ---------------------------------------------------------------------- # # Treeview Methods # ---------------------------------------------------------------------- # def treeview_context_menu(self, click): """ Sets the currently selected treeview object id in the variable ``treeview_popup_target_id``. Parameters ---------- click : tkinter click event """ target = self.treeview.identify_row(click.y) if target != "": self.treeview_popup_target_id = target self.treeview_popup.post(click.x_root, click.y_root) self.treeview_popup_target_id = None def apply_seqlib_fastq(self): """ Applies settings to the seqlib object by running the configuration method. """ SeqLibApplyDialog(self, self, self.treeview_popup_target_id) def new_button_press(self): """ Spawns a dialog box depending on the currently selected treeview item to create a new element. """ if self.treeview.focus() == "" and self.root_element is not None: tkinter.messagebox.showwarning(None, "No parent element selected.") else: if self.treeview.focus() == "" and self.root_element is None: element = CreateRootDialog(self).element if isinstance(element, SeqLib): EditDialog(self, self, element) self.root_element = element else: element = self.create_new_element() EditDialog(self, self, element) # refresh the treeview and re-assign treeview id's self.refresh_treeview() # select the newly added element if it was successfully added if element.treeview_id in list(self.element_dict.keys()): self.treeview.focus(element.treeview_id) self.treeview.selection_set(element.treeview_id) else: if element.parent is not None: self.treeview.focus(element.parent.treeview_id) self.treeview.selection_set(element.parent.treeview_id) del element def edit_button_press(self): """ Spawns a dialog box depending on the currently selected treeview item to edit the selected element. """ if self.treeview.focus() == "": tkinter.messagebox.showwarning(None, "No element selected.") else: EditDialog(self, self, self.get_focused_element()) def delete_button_press(self): """ Deletes the selected treeview element and it's children. """ if self.treeview.focus() == "": tkinter.messagebox.showwarning(None, "No element selected.") else: DeleteDialog(self, self) def delete_element(self, tree_id): """ Delete element with Treeview id *tree_id* from the tree, from the element dictionary, and from the associated data structure. Recursively deletes all children of *tree_id*. The tree should be refreshed using :py:meth:`refresh_tree` after each deletion. This is the responsibility of the caller. Parameters ---------- tree_id : `int` The id of the currently selected treeview element. """ if tree_id in self.element_dict: # recursively delete children if self.element_dict[tree_id].children is not None: for child in self.element_dict[tree_id].children: self.delete_element(child.treeview_id) # check if deleting the root element if self.root_element.treeview_id == tree_id: # clear the root element print("None {}".format(tree_id)) self.root_element = None else: try: # remove the element from its parent's list of children self.element_dict[tree_id].parent.remove_child_id(tree_id) except AttributeError: raise AttributeError( "Non-root element lacks proper parent") # delete the element from the dictionary del self.element_dict[tree_id] def refresh_treeview(self): """ Clears the Treeview and repopulates it with the current contents of the tree. """ # clear the entries in the Treeview for x in self.treeview.get_children(): self.treeview.delete(x) # clear the id-element dictionary # elements may be given new id's after repopulation self.element_dict.clear() # repopulate if self.root_element is not None: self.populate_tree(self.root_element) def set_treeview_properties(self, element): """ Set the information text for the Treeview *element*. Parameters ---------- element : :py:class:`~enrich2.base.storemanager.StoreManager` The storemanager object to configure. """ # set class property self.treeview.set(element.treeview_id, "class", element.treeview_class_name) # add the check marks for barcodes/variants if "variants" in element.labels: self.treeview.set(element.treeview_id, "variants", u"\u2713") else: self.treeview.set(element.treeview_id, "variants", "") if "barcodes" in element.labels: self.treeview.set(element.treeview_id, "barcodes", u"\u2713") else: self.treeview.set(element.treeview_id, "barcodes", "") self.treeview.set(element.treeview_id, "class", element.treeview_class_name) def populate_tree(self, element, parent_id=""): """ Recursively populate the Treeview. Also populates the *id_cfgstrings*. Parameters ---------- element : :py:class:`~enrich2.base.storemanager.StoreManager` The storemanager object to configure. parent_id : `int` ``treeview_id`` of element's parent. """ # insert into the Treeview element.treeview_id = self.treeview.insert(parent_id, "end", text=element.name, open=True) # add id-element pair to dictionary self.element_dict[element.treeview_id] = element # set information fields self.set_treeview_properties(element) # populate for children if element.children is not None: for child in element.children: self.populate_tree(child, parent_id=element.treeview_id) # ---------------------------------------------------------------------- # # Getter Methods # ---------------------------------------------------------------------- # def get_selected_scorer_class(self): """ Returns the currently selected scoring class object. """ return self.scorer def get_selected_scorer_attrs(self): """ Returns the currently selected scoring class attribute `dict`. """ return self.scorer_attrs def get_selected_scorer_path(self): """ Returns the currently selected scoring path. """ return self.scorer_path def get_element(self, treeview_id): """ Returns the element with *treeview_id*. Parameters ---------- treeview_id : `int` ``treeview_id`` attribute of element to get. Returns ------- :py:class:`~enrich2.base.storemanager.StoreManager` The instance with matching ``treeview_id`` """ return self.element_dict[treeview_id] def get_focused_element(self): """ Gets the focused element in the treeview. Returns ------- :py:class:`~enrich2.base.storemanager.StoreManager` Returns the element that is currently being focused in the Treeview. ``None`` if nothing is focused. """ if self.treeview.focus() != "": return self.get_element(self.treeview.focus()) else: return None def get_selected_elements(self): """ Returns a list of currently selected elements in the treeview. Returns ------- `list` Returns a list of elements that are currently selected in the Treeview. If no elements are selected, it returns an empty list. """ return [self.get_element(x) for x in self.treeview.selection()] # ---------------------------------------------------------------------- # # Menubar Methods # ---------------------------------------------------------------------- # def menu_open(self): """ Spawns an `askopenfilename` dialog to open a configuration file. """ message_title = "Open Configuration" fname = tkinter.filedialog.askopenfilename() if len(fname) > 0: # file was selected try: with open(fname, "rU") as handle: cfg = json.load(handle) except ValueError: tkinter.messagebox.showerror(message_title, "Failed to parse config file.") except IOError: tkinter.messagebox.showerror(message_title, "Could not read config file.") else: if is_experiment(cfg): obj = Experiment() elif is_selection(cfg): obj = Selection() elif is_seqlib(cfg): sltype = seqlib_type(cfg) obj = globals()[sltype]() else: tkinter.messagebox.showerror( message_title, "Unrecognized config format.") return obj.output_dir_override = False try: if isinstance(obj, Experiment) or isinstance( obj, Selection): obj.configure(cfg, init_from_gui=True) else: obj.configure(cfg) # Try load the scorer into the GUI scorer_path = cfg.get(SCORER, {}).get(SCORER_PATH, "") scorer_attrs = cfg.get(SCORER, {}).get(SCORER_OPTIONS, {}) if scorer_path: self.scorer_widget.load_from_cfg_file( scorer_path, scorer_attrs) else: log_message( logging_callback=logging.warning, msg="No plugin could be loaded from configuration.", extra={"oname": self.__class__.__name__}, ) except Exception as e: tkinter.messagebox.showerror( message_title, "Failed to load config file:\n\n{}".format(e)) else: self.root_element = obj self.cfg_file_name.set(fname) self.refresh_treeview() def menu_save(self): """ Asks the user where to save the current configuration. """ if len(self.cfg_file_name.get()) == 0: self.menu_saveas() elif self.root_element is None: tkinter.messagebox.showwarning("Save Configuration", "Cannot save empty configuration.") else: save = askyesno("Save Configuration", "Overwrite existing configuration?") if not save: return try: with open(self.cfg_file_name.get(), "w") as handle: cfg = self.root_element.serialize() # Get the currently selected scorer if not isinstance(self.root_element, SeqLib) and not isinstance( self.root_element, Condition): ( _, attrs, scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path() cfg[SCORER] = { SCORER_PATH: scorer_path, SCORER_OPTIONS: attrs } write_json(cfg, handle) except IOError: tkinter.messagebox.showerror("Save Configuration", "Failed to save config file.") else: tkinter.messagebox.showinfo( "Save Configuration", "Saved file at location:\n\n{}".format( self.cfg_file_name.get()), ) def menu_saveas(self): """ Asks the user where to save the current configuration. """ if self.root_element is None: tkinter.messagebox.showwarning("Save Configuration", "Cannot save empty configuration.") else: fname = tkinter.filedialog.asksaveasfilename() if len(fname) > 0: # file was selected try: with open(fname, "w") as handle: cfg = self.root_element.serialize() # Get the currently selected scorer if not isinstance(self.root_element, SeqLib) and not isinstance( self.root_element, Condition): ( _, attrs, scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path( ) cfg[SCORER] = { SCORER_PATH: scorer_path, SCORER_OPTIONS: attrs, } write_json(cfg, handle) except IOError: tkinter.messagebox.showerror( "Save Configuration", "Failed to save config file.") else: self.cfg_file_name.set(fname) tkinter.messagebox.showinfo( "Save Configuration", "Saved file at location:\n\n{}".format( self.cfg_file_name.get()), ) def menu_selectall(self): """ Add all elements in the Treeview to the selection. """ for k in self.element_dict.keys(): self.treeview.selection_add(k) def show_plugin_source_window(self): """ Show the pop-up window to modify plugin sources """ if not self.plugin_source_window: self.plugin_source_window = SourceWindow(master=self) else: self.plugin_source_window.toggle_show() # ---------------------------------------------------------------------- # # Run Analysis Methods # ---------------------------------------------------------------------- # def go_button_press(self): """ Starts the analysis if all elements have been properly configured. This will run the analysis in a new thread and block out GUI editing to prevent the analysis breaking. """ ( self.scorer, self.scorer_attrs, self.scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path() if self.scorer is None or self.scorer_attrs is None: tkinter.messagebox.showwarning("Incomplete Configuration", "No scoring plugin selected.") elif self.root_element is None: tkinter.messagebox.showwarning( "Incomplete Configuration", "No experimental design specified.") else: plugin, *_ = self.scorer_widget.get_selected_plugin() if plugin.md5_has_changed(): proceed = askokcancel( "Selected plugin has been modified.", "The selected plugin has been modified on disk. Do you " "want to proceed with the current version? To see changes " "click 'Cancel' and refresh plugins before proceeding.", ) if not proceed: return if askyesno( "Save Configuration?", "Would you like to save the confiugration " "file before proceeding?", ): self.menu_save() run = askyesno( "Begin Analysis?", "Click Yes when you are ready to start.\n\nThis could " "take some time so grab a cup of tea, or a beer if that's " "your thing, and enjoy the show.", ) if run: self.configure_analysis() self.set_gui_state(tk.DISABLED) thread = threading.Thread(target=self.run_analysis) thread.setDaemon(True) self.analysis_thread = thread self.analysis_thread.start() self.after(100, self.poll_analysis_thread) def poll_logging_queue(self): """ Polls the logging queue for messages to log. """ try: log = get_logging_queue(init=True).get(0) log[CALLBACK](log[MESSAGE], **log[KWARGS]) self.after(10, self.poll_logging_queue) except queue.Empty: self.after(10, self.poll_logging_queue) def poll_analysis_thread(self): """ Polls the thread to check it's state. When it is finished, all stores are closed. """ try: analysis_result = self.queue.get(0) self.handle_analysis_result(analysis_result) except queue.Empty: self.after(100, self.poll_analysis_thread) def handle_analysis_result(self, success): """ Shows the appropriate messagebox and logs exceptions upon analysis completing. Parameters ---------- success : `bool` Exception object if an error occured during analysis, otherwise None to indicate successful computation. """ log_message( logging_callback=logging.info, msg="Closing stores...", extra={"oname": self.root_element.name}, ) self.root_element.store_close(children=True) log_message( logging_callback=logging.info, msg="Stores closed.", extra={"oname": self.root_element.name}, ) if success: showinfo("Analysis completed.", "Analysis has completed successfully!") log_message( logging_callback=logging.info, msg="Completed successfully!", extra={"oname": self.root_element.name}, ) else: showwarning( "Error during analysis.", "An error occurred during the analysis. See log for details", ) log_message( logging_callback=logging.info, msg="Completed, but with errors!", extra={"oname": self.root_element.name}, ) self.set_gui_state(tk.NORMAL) def run_analysis(self): """ Runs the storemanager compute method. """ try: self.root_element.validate() self.root_element.store_open(children=True) self.root_element.calculate() if self.root_element.tsv_requested: self.root_element.write_tsv() self.queue.put(True, block=False) except Exception as exception: log_message( logging_callback=logging.exception, msg=exception, extra={"oname": self.root_element.name}, ) self.queue.put(False, block=False) finally: return def configure_analysis(self): """ Configures the attributes of the root_element by querying the GUI options. """ try: self.root_element.force_recalculate = self.force_recalculate.get() self.root_element.component_outliers = self.component_outliers.get( ) self.root_element.tsv_requested = self.tsv_requested.get() scorer_class = self.get_selected_scorer_class() scorer_class_attrs = self.get_selected_scorer_attrs() scorer_path = self.get_selected_scorer_path() self.root_element.scorer_class = scorer_class self.root_element.scorer_class_attrs = scorer_class_attrs self.root_element.scorer_path = scorer_path except Exception as e: log_message( logging_callback=logging.info, msg="An error occurred when trying to configure the " "root element.", extra={"oname": self.root_element.name}, ) log_message( logging_callback=logging.exception, msg=e, extra={"oname": self.root_element.name}, ) # ---------------------------------------------------------------------- # # GUI Modifications # ---------------------------------------------------------------------- # def set_gui_state(self, state): """ Sets the state of the `go_button`, `treeview` and `treeview_buttons`. Parameters ---------- state : `str` State to set, usually ``'normal'`` or ``'disabled'`` """ for btn in self.treeview_buttons: btn.config(state=state) self.go_button.config(state=state) if state == "normal": self.treeview.bind("<Button-2>", self.treeview_context_menu) else: self.treeview.bind("<Button-2>", lambda event: event) def refresh_plugins(self): """ Refresh the plugins by re-checking the sources file. """ if self.plugin_source_window: sources = self.plugin_source_window.sources self.scorer_widget.refresh_sources(sources)
class Search: def __init__(self): self.window = Tk() self.window.title( "Search | All Record | National Textile University Faisalabad") self.window.iconbitmap('blood1.ico') can = Canvas(self.window, width=800, height=400, bg="white") can.pack(expand=YES, fill=BOTH) width = self.window.winfo_screenwidth() height = self.window.winfo_screenheight() # print("Width:",width,"\n","Height:",height) x = int(width / 2 - 800 / 2) y = int(height / 2 - 400 / 2) str1 = "980x450+" + str(x) + "+" + str(y) self.window.geometry(str1) self.window.maxsize(980, 450) self.window.minsize(980, 450) def add_fram_search(self): self.frame = Frame(self.window, width=850, height=385, bg="#ef5151") self.frame.place(x=77, y=20) self.l1 = Label(self.frame, text="Enter Reg_N/Blood_G:", font="Times 16 bold") self.l1.place(x=50, y=43) self.Entry_reg = Entry(self.frame, font="courior 14 bold") self.Entry_reg.place(x=280, y=43, height=30) # search-Button self.b1 = Button(self.frame, text="Search-RN", font="Times 12 bold") self.b1.place(x=510, y=40, height=37) self.b1.bind('<Button-1>', self.regno) self.b1 = Button(self.frame, text="Search-BG", font="Times 12 bold") self.b1.place(x=599, y=40, height=37) self.b1.bind('<Button-1>', self.bg) # Back-Buton self.b1 = Button(self.frame, text="Back", font="Times 12 bold") self.b1.place(x=690, y=40, height=37) self.b1.bind('<Button-1>', self.back) # for Styling Table style = Style() style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=('Calibri 11')) # Modify the font of the body style.configure( "mystyle.Treeview.Heading", font=('Calibri 13 bold')) # Modify the font of the headings style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', { 'sticky': 'nswe' })]) # Remove the borders # import TreeViewe self.tr = Treeview(self.frame, columns=('A', 'B', 'C', 'D', 'E', 'F'), selectmode="extended", style="mystyle.Treeview") # heading key+text self.tr.heading("#0", text="Sr_No") self.tr.column("#0", minwidth=0, width=100, stretch=NO) self.tr.heading("#1", text="Name") self.tr.column("#1", minwidth=0, width=100, stretch=NO) self.tr.heading("#2", text="Reg_No") self.tr.column("#2", minwidth=0, width=100, stretch=NO) self.tr.heading("#3", text="Blood_Group") self.tr.column("#3", minwidth=0, width=100, stretch=NO) self.tr.heading("#4", text="Phone_No") self.tr.column("#4", minwidth=0, width=100, stretch=NO) self.tr.heading("#5", text="update") self.tr.column("#5", minwidth=0, width=100, stretch=NO) self.tr.heading("#6", text="delete") self.tr.column("#6", minwidth=0, width=100, stretch=NO) self.sb = Scrollbar(self.tr) self.sb.place(x=673, y=2, height=223, width=20, bordermode=OUTSIDE) self.sb.config(command=self.tr.yview) self.tr.config(yscrollcommand=self.sb.set) self.tr.place(x=50, y=100, width=691) # Remove All ROW self.Entry_reg.bind('<KeyRelease>', self.remove) self.tr.bind('<Double-Button-1>', self.action) self.window.mainloop() def regno(self, event): try: data = (self.Entry_reg.get(), ) if self.Entry_reg.get() == "": msg.showwarning("Message!", "insert Reg No!") else: j = 1 D = Database_Insert.search_details(data) if D: self.Entry_reg.delete(0, END) for i in D: self.tr.insert('', index=j, text=j, values=(i[0], i[1], i[2], i[3], "update", "delete")) j += 1 else: msg.showwarning("Message!", "No result Found!") except: msg.showwarning("Error!", "ERORR!") def bg(self, event): try: data = (self.Entry_reg.get(), ) if self.Entry_reg.get() == "": msg.showwarning("Message!", "insert Blood_Group!") else: j = 1 D = Database_Insert.search_details_bg(data) if D: self.Entry_reg.delete(0, END) for i in D: self.tr.insert('', index=j, text=j, values=(i[0], i[1], i[2], i[3], "update", "delete")) j += 1 else: msg.showwarning("Message!", "No result Found!") except: msg.showwarning("Error!", "ERORR!") def remove(self, event): x = self.tr.get_children() if x != '()': for child in x: self.tr.delete(child) def action(self, event): fcs = self.tr.focus() col = self.tr.identify_column(event.x) x = self.tr.item(fcs).get('values') text = x[1] data = (text, ) if col == "#6": res = msg.askyesno("Message!", "Do you want to delete?") if res: d = Database_Insert.delete_details(data) if d: msg.showinfo("Deleted", "Successfully") self.window.destroy() x = Search() x.add_fram_search() else: self.window.destroy() x = Search() x.add_fram_search() elif col == "#5": # self.window.destroy() x = Home.data(self.tr.item(fcs)) x.add_frame() def back(self, event): self.window.destroy() x = Home.data() x.add_frame()
class TestcaseSelector: def start(self): # Create TK window self.root = Tk() # Create Style object for TK window self.root.style = Style() # Set default frame size to 800x640 self.root.geometry('800x640') # Set Treeview row height to 40 so there's no overlap self.root.style.configure('Treeview',rowheight=40) # Set title and window size self.root.wm_title("Select Testcases to Run") # Create a frame for the treeview self.testcase_frame = Frame(self.root) # Create scrollbar for treeview scrollbar = Scrollbar(self.root) scrollbar.pack(side=RIGHT,fill=Y) # Create Treeview self.treeView = Treeview(self.testcase_frame) self.treeView.pack(expand=1,fill=BOTH) # Attach scrollbar to Treeview self.treeView.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.treeView.yview) # Get testcase name dictionary to use for filling out treeview testcase_dictionary = get_testcase_name_dictonary() self.testcase_data = {} self.testcase_run_data = {} for key in testcase_dictionary.keys(): subsection = testcase_dictionary[key] self.testcase_data[key] = subsection s_p = self.treeView.insert('', END, text=key) for test in subsection: testcase_name = test._testMethodName testcase_name = testcase_name self.treeView.insert(s_p, END, text=testcase_name) self.testcase_run_data[testcase_name] = test self.webData = self.testcase_run_data # Create buttons for cancel and run tests run_button = Button(self.testcase_frame, text="Run", fg="green",command=self._save_selection,width=25,height=5) run_button.pack(side=LEFT,expand=1,fill=BOTH) quit_button = Button(self.testcase_frame, text="Cancel", fg="red", command=self.treeView.quit,width=25,height=5) quit_button.pack(side=RIGHT,expand=1,fill=BOTH) # Pack the rest of the frame and tell it to scale on both x and y axis self.testcase_frame.pack(expand=1,fill=BOTH) def get_tests_from_selected_names(self,names): ret_tests = {} for name in names: ret_tests[name] = self.webData[name] return ret_tests def _save_selection(self): selected_tests = self.treeView.selection() output=[] for selection in selected_tests: item_text = self.treeView.item(selection,'text') if 'test_' in item_text: if item_text not in output: output.append(item_text) else: pass elif 'Tests' in item_text: for test in self.testcase_data[item_text]: output.append(test._testMethodName) # output = output + self.testSectionData[item_text] self.testcases = self.get_tests_from_selected_names(output) self.root.quit() def get_testcases(self): self.start() self.root.mainloop() self.root.destroy() # Try/Except to fail gracefully try: return self.testcases except: exit(0)
class XRDApp(Toplevel): def __init__(self, *args, **kwargs): Toplevel.__init__(self, *args, **kwargs) Toplevel.wm_title(self, "XRDApp") Toplevel.config(self, background="white") self.wm_geometry("650x650") center(self) self.initUI() def initUI(self): global refsamplenameslist, Patternsamplenameslist self.master.withdraw() self.protocol("WM_DELETE_WINDOW", self.on_closing) self.canvas0 = tk.Canvas(self, borderwidth=0, background="#ffffff") self.superframe = Frame(self.canvas0, background="#ffffff") self.canvas0.pack(side="left", fill="both", expand=True) label = tk.Label(self.canvas0, text="XRD DATA Analyzer", font=LARGE_FONT, bg="black", fg="white") label.pack(fill=tk.X, expand=0) frame1 = Frame(self.canvas0, borderwidth=0, bg="white") frame1.pack(fill=tk.BOTH, expand=1) frame1.bind("<Configure>", self.onFrameConfigure) self.fig1 = plt.figure(figsize=(1, 3)) canvas = FigureCanvasTkAgg(self.fig1, frame1) canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1) self.XRDgraph = plt.subplot2grid((1, 1), (0, 0), colspan=3) self.toolbar = NavigationToolbar2Tk(canvas, frame1) self.toolbar.update() canvas._tkcanvas.pack(fill=tk.BOTH, expand=1) frame2 = Frame(self.canvas0, borderwidth=0, bg="white") frame2.pack(fill=tk.BOTH, expand=0) frame21 = Frame(frame2, borderwidth=0, bg="lightgrey") frame21.pack(side=tk.LEFT, fill=tk.BOTH, expand=1) frame211 = Frame(frame21, borderwidth=0, bg="lightgrey") frame211.pack(fill=tk.BOTH, expand=1) self.shift = tk.DoubleVar() Entry(frame211, textvariable=self.shift, width=3).pack(side=tk.LEFT, fill=tk.X, expand=1) self.shiftBut = Button(frame211, text="X Shift", command=self.shiftX).pack(side=tk.LEFT, expand=1) self.shift.set(0) self.shiftYval = tk.DoubleVar() Entry(frame211, textvariable=self.shiftYval, width=3).pack(side=tk.LEFT, fill=tk.X, expand=1) self.shiftYBut = Button(frame211, text="Y Shift", command=self.shiftY).pack(side=tk.LEFT, expand=1) self.shiftYval.set(0) self.CheckBkgRemoval = Button(frame211, text="BkgRemoval", command=self.backgroundremoval).pack( side=tk.LEFT, expand=1) # frame212=Frame(frame21,borderwidth=0, bg="lightgrey") # frame212.pack(fill=tk.BOTH,expand=1) # refpattern=StringVar() # refpatternlist=['Original','Si','ITO']#to be replace by actual files in a specific folder # cbbox = ttk.Combobox(frame212, textvariable=refpattern, values=refpatternlist) # cbbox.pack(side=tk.LEFT,expand=0) # refpattern.set(refpatternlist[0]) # self.refbut = Button(frame212, text="ShiftToRef",command = self.shifttoRef).pack(side=tk.LEFT,expand=1) frame213 = Frame(frame21, borderwidth=0, bg="lightgrey") frame213.pack(fill=tk.BOTH, expand=1) self.rescale = tk.DoubleVar() Entry(frame213, textvariable=self.rescale, width=3).pack(side=tk.LEFT, fill=tk.X, expand=1) self.rescale.set(1000) self.rescaleBut = Button(frame213, text="Rescale to ref", command=self.scaleYtoRef).pack(side=tk.LEFT, expand=1) self.backtoOriginalBut = Button(frame213, text="BackToOriginal", command=self.backtoOriginal).pack( side=tk.LEFT, expand=1) frame22 = Frame(frame2, borderwidth=0, bg="white") frame22.pack(side=tk.LEFT, fill=tk.BOTH, expand=1) frame221 = Frame(frame22, borderwidth=0, bg="white") frame221.pack(fill=tk.BOTH, expand=1) self.importBut = Button(frame221, text="Import", command=self.importDATA).pack(side=tk.LEFT, expand=1) self.importRefBut = Button(frame221, text="ImportRef", command=self.importRefDATA).pack( side=tk.LEFT, expand=1) self.UpdateBut = Button(frame221, text="Update", command=lambda: self.updateXRDgraph(0)).pack( side=tk.LEFT, expand=1) frame222 = Frame(frame22, borderwidth=0, bg="grey") frame222.pack(fill=tk.BOTH, expand=1) self.ShowPeakDetectionBut = Button(frame222, text="Peak Detection", command=self.PeakDetection).pack( side="left", expand=1) self.ChangePeakNameBut = Button(frame222, text="Change Peak Names", command=self.ChangePeakNames).pack( side="left", expand=1) self.CheckPeakNames = IntVar() Checkbutton(frame222, text="ShowNames", variable=self.CheckPeakNames, onvalue=1, offvalue=0, height=1, width=10, command=lambda: self.updateXRDgraph(0), fg='black', background='grey').pack(side=tk.LEFT, expand=1) frame223 = Frame(frame22, borderwidth=0, bg="grey") frame223.pack(fill=tk.BOTH, expand=1) self.thresholdPeakDet = tk.DoubleVar() Entry(frame223, textvariable=self.thresholdPeakDet, width=5).pack(side=tk.LEFT, expand=1) self.thresholdPeakDet.set(0.05) tk.Label(frame223, text="Threshold", bg="grey").pack(side=tk.LEFT, expand=1) self.MinDistPeakDet = tk.DoubleVar() Entry(frame223, textvariable=self.MinDistPeakDet, width=3).pack(side=tk.LEFT, expand=1) self.MinDistPeakDet.set(40) tk.Label(frame223, text="MinDist", bg="grey").pack(side=tk.LEFT, expand=1) self.CheckPeakDetec = IntVar() Checkbutton(frame223, text="Show", variable=self.CheckPeakDetec, onvalue=1, offvalue=0, height=1, width=3, command=lambda: self.updateXRDgraph(0), fg='black', background='grey').pack(side=tk.LEFT, expand=1) # frame23=Frame(frame2,borderwidth=0, bg="lightgrey") # frame23.pack(fill=tk.BOTH,expand=1) # frame231=Frame(frame23,borderwidth=0, bg="lightgrey") # frame231.pack(fill=tk.BOTH,expand=1) self.ExportBut = Button(frame221, text="Export", command=self.Export).pack(side="left", expand=1) self.ExportRefFileBut = Button(frame221, text="ExportasRefFile", command=self.ExportasRef).pack( side="left", expand=1) # self.GraphCheck = IntVar() # legend=Checkbutton(frame23,text='Graph',variable=self.GraphCheck, # onvalue=1,offvalue=0,height=1, width=10, command = (), bg="lightgrey") # legend.pack(expand=1) # self.PeakData = IntVar() # legend=Checkbutton(frame23,text='PeakData',variable=self.PeakData, # onvalue=1,offvalue=0,height=1, width=10, command = (), bg="lightgrey") # legend.pack(expand=1) frame5 = Frame(self.canvas0, borderwidth=0, bg="white") frame5.pack(fill=tk.BOTH, expand=1) frame3 = Frame(frame5, borderwidth=0, bg="white") frame3.pack(side="left", fill=tk.BOTH, expand=1) frame32 = Frame(frame3, borderwidth=0, bg="white") frame32.pack(fill=tk.BOTH, expand=1) #listbox for imported samples self.frame322 = Frame(frame32, borderwidth=0, bg="white") self.frame322.pack(fill=tk.BOTH, expand=1) self.frame3221 = Frame(self.frame322, borderwidth=0, bg="white") self.frame3221.pack(fill=tk.BOTH, expand=1) importedsamplenames = StringVar() self.listboxsamples = Listbox(self.frame3221, listvariable=importedsamplenames, selectmode=tk.MULTIPLE, width=15, height=3, exportselection=0) self.listboxsamples.bind('<<ListboxSelect>>', self.updateXRDgraph) self.listboxsamples.pack(side="left", fill=tk.BOTH, expand=1) scrollbar = tk.Scrollbar(self.frame3221, orient="vertical") scrollbar.config(command=self.listboxsamples.yview) scrollbar.pack(side="right", fill="y") self.listboxsamples.config(yscrollcommand=scrollbar.set) for item in Patternsamplenameslist: self.listboxsamples.insert(tk.END, item) #lisbox for ref pattern self.frame323 = Frame(frame32, borderwidth=0, bg="white") self.frame323.pack(fill=tk.BOTH, expand=1) self.frame3231 = Frame(self.frame323, borderwidth=0, bg="white") self.frame3231.pack(fill=tk.BOTH, expand=1) refsamplenames = StringVar() self.listboxref = Listbox(self.frame3231, listvariable=refsamplenames, selectmode=tk.MULTIPLE, width=15, height=3, exportselection=0) self.listboxref.bind('<<ListboxSelect>>', self.updateXRDgraph) self.listboxref.pack(side="left", fill=tk.BOTH, expand=1) scrollbar = tk.Scrollbar(self.frame3231, orient="vertical") scrollbar.config(command=self.listboxref.yview) scrollbar.pack(side="right", fill="y") self.listboxref.config(yscrollcommand=scrollbar.set) for item in refsamplenameslist: self.listboxref.insert(tk.END, item) # frame321=Frame(frame32,borderwidth=0, bg="white") # frame321.pack(fill=tk.X,expand=0) # self.addtolistBut = Button(frame321, text="Add to list",command = ()).pack(side=tk.LEFT,expand=1) # self.RemoveFromListBut = Button(frame321, text="Remove from list",command = ()).pack(side=tk.LEFT,expand=1) self.frame4 = Frame(frame5, borderwidth=0, bg="white") self.frame4.pack(side="right", fill=tk.BOTH, expand=1) self.frame41 = Frame(self.frame4, borderwidth=0, bg="white") self.frame41.pack(side="right", fill=tk.BOTH, expand=1) # self.addtolistBut = Button(self.frame4, text="Add to list",command = ()).pack(side=tk.LEFT,expand=1) # self.TableBuilder(self.frame4) self.CreateTable() #%%############# def on_closing(self): global DATA, RefPattDATA, Patternsamplenameslist, colorstylelist if messagebox.askokcancel("Quit", "Do you want to quit?"): DATA = {} RefPattDATA = {} Patternsamplenameslist = [] colorstylelist = [ 'black', 'red', 'blue', 'brown', 'green', 'cyan', 'magenta', 'olive', 'navy', 'orange', 'gray', 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'greenyellow', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgreen', 'lightgray', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen' ] plt.close() self.destroy() self.master.deiconify() def onFrameConfigure(self, event): #self.canvas0.configure(scrollregion=self.canvas0.bbox("all")) self.canvas0.configure(scrollregion=(0, 0, 500, 500)) #%% def updateXRDgraph(self, a): global DATA, RefPattDATA, colorstylelist, samplestakenforplot self.XRDgraph.clear() coloridx = 0 #plot patterns from DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: minX = min(DATA[samplestakenforplot[0]][2]) maxX = max(DATA[samplestakenforplot[0]][2]) minY = min(DATA[samplestakenforplot[0]][3]) maxY = max(DATA[samplestakenforplot[0]][3]) for item in samplestakenforplot: x = DATA[item][2] y = DATA[item][3] if min(x) < minX: minX = min(x) if max(x) > maxX: maxX = max(x) if min(y) < minY: minY = min(y) if max(y) > maxY: maxY = max(y) self.XRDgraph.plot(x, y, color=colorstylelist[coloridx], label=item) coloridx += 1 #add text for Peak Names if self.CheckPeakNames.get(): for item in range(len(peaknamesforplot)): plt.text(peaknamesforplot[item][0], peaknamesforplot[item][1], peaknamesforplot[item][2], rotation=90, verticalalignment='bottom', horizontalalignment='left', multialignment='center') #plot from RefPattDATA reftakenforplot = [ self.listboxref.get(idx) for idx in self.listboxref.curselection() ] for item in reftakenforplot: x = RefPattDATA[item][0] y = RefPattDATA[item][1] lines = [] for i in range(len(x)): pair = [(x[i], 0), (x[i], y[i])] lines.append(pair) linecoll = matcoll.LineCollection(lines, color='black', linestyle='dashed') # linecoll = matcoll.LineCollection(lines) self.XRDgraph.add_collection(linecoll) self.XRDgraph.scatter(x, y, label=item, color=colorstylelist[coloridx]) coloridx += 1 if self.CheckPeakNames.get(): for item1 in range(len(RefPattDATA[item][0])): if samplestakenforplot != []: if RefPattDATA[item][0][item1] > minX and RefPattDATA[ item][0][item1] < maxX: plt.text(RefPattDATA[item][0][item1], RefPattDATA[item][1][item1], RefPattDATA[item][2][item1], rotation=90, verticalalignment='bottom', horizontalalignment='left', multialignment='center') else: plt.text(RefPattDATA[item][0][item1], RefPattDATA[item][1][item1], RefPattDATA[item][2][item1], rotation=90, verticalalignment='bottom', horizontalalignment='left', multialignment='center') coloridx += 1 if self.CheckPeakDetec.get(): if samplestakenforplot != []: for item in samplestakenforplot: for item1 in range(len(DATA[item][5])): self.XRDgraph.plot(DATA[item][5][item1][0], DATA[item][5][item1][1], color=colorstylelist[coloridx]) for item1 in range(len(DATA[item][6])): self.XRDgraph.plot( [DATA[item][6][item1][0], DATA[item][6][item1][1]], [DATA[item][6][item1][2], DATA[item][6][item1][3]], color=colorstylelist[coloridx + 1]) for item1 in range(len(DATA[item][7])): self.XRDgraph.plot( [DATA[item][7][item1][0], DATA[item][7][item1][1]], [DATA[item][7][item1][2], DATA[item][7][item1][3]], color=colorstylelist[coloridx + 1]) #legends and graph styles if samplestakenforplot != [] or reftakenforplot != []: self.XRDgraph.legend() self.XRDgraph.set_ylabel("Intensity (a.u.)") self.XRDgraph.set_xlabel("2\u0398 (degree)") if samplestakenforplot != []: self.XRDgraph.axis([minX, maxX, minY, 1.1 * maxY]) plt.gcf().canvas.draw() self.CreateTable() class PopulateListofPeakNames(tk.Frame): def __init__(self, root): tk.Frame.__init__(self, root) self.canvas0 = tk.Canvas(root, borderwidth=0, background="#ffffff") self.frame = tk.Frame(self.canvas0, background="#ffffff") self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas0.yview) self.canvas0.configure(yscrollcommand=self.vsb.set) self.vsb.pack(side="right", fill="y") self.canvas0.pack(side="left", fill="both", expand=True) self.canvas0.create_window((4, 4), window=self.frame, anchor="nw", tags="self.frame") self.frame.bind("<Configure>", self.onFrameConfigure) self.populate() def populate(self): global DATA, listofanswer, samplestakenforplot rowpos = 1 if samplestakenforplot != []: for item in samplestakenforplot: for item1 in range(len(DATA[item][4])): label = tk.Label(self.frame, text=item, fg='black', background='white') label.grid(row=rowpos, column=0, columnspan=1) label = tk.Label(self.frame, text="%.2f" % DATA[item][4][item1]["Position"], fg='black', background='white') label.grid(row=rowpos, column=1, columnspan=1) textinit = tk.StringVar() listofanswer[str( DATA[item][4][item1]["Position"])] = Entry( self.frame, textvariable=textinit) listofanswer[str( DATA[item][4][item1]["Position"])].grid( row=rowpos, column=2, columnspan=2) textinit.set(DATA[item][4][item1]["PeakName"]) rowpos = rowpos + 1 def onFrameConfigure(self, event): '''Reset the scroll region to encompass the inner frame''' self.canvas0.configure(scrollregion=self.canvas0.bbox("all")) def ChangePeakNames(self): global DATA self.window = tk.Toplevel() self.window.wm_title("Change Peak Names") center(self.window) self.window.geometry("400x300") Button(self.window, text="Update", command=self.UpdatePeakNames).pack() self.PopulateListofPeakNames(self.window).pack(side="top", fill="both", expand=True) def UpdatePeakNames(self): global DATA, listofanswer, samplestakenforplot, peaknamesforplot peaknamesforplot = [] for item in samplestakenforplot: for item1 in range(len(DATA[item][4])): DATA[item][4][item1]["PeakName"] = listofanswer[str( DATA[item][4][item1]["Position"])].get() peaknamesforplot.append([ DATA[item][4][item1]["Position"], DATA[item][4][item1]["Intensity"], DATA[item][4][item1]["PeakName"] ]) self.window.destroy() self.updateXRDgraph(0) #%% def backgroundremoval(self): global DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: y = DATA[item][3] y = np.array(y) base = peakutils.baseline(y, 3) DATA[item][3] = list(y - base) self.updateXRDgraph(0) def shiftX(self): global DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: x = DATA[item][2] DATA[item][2] = [item1 + self.shift.get() for item1 in x] self.updateXRDgraph(0) def shiftY(self): global DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: print(self.shiftYval.get()) y = DATA[item][3] DATA[item][3] = [item1 + self.shiftYval.get() for item1 in y] self.updateXRDgraph(0) def shifttoRef(self): global DATA # still to be done # automatic detection of peaks and comparison to the selected RefPattern # then shifts the data to match the ref peak self.updateXRDgraph(0) def scaleYtoRef(self): global DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: y = DATA[item][3] maxy = max(y) miny = min(y) DATA[item][3] = [ ((item1 - miny) / (maxy - miny)) * self.rescale.get() for item1 in y ] self.updateXRDgraph(0) def backtoOriginal(self): global DATA samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: DATA[item][2] = DATA[item][0] DATA[item][3] = DATA[item][1] self.updateXRDgraph(0) #%% def PeakDetection(self): global DATA, peaknamesforplot peaknamesforplot = [] samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for item in samplestakenforplot: #reinitialize list of dict DATA[item][4] = [] #list of dictionaries DATA[item][5] = [] #list of points taken for the peak analysis DATA[item][6] = [] #baselines DATA[item][7] = [] #FWHM lines x = np.array(DATA[item][2]) y = np.array(DATA[item][3]) #get peak position indexes = peakutils.indexes(y, thres=self.thresholdPeakDet.get(), min_dist=self.MinDistPeakDet.get()) for item1 in range(len(indexes)): tempdat = {} nbofpoints = 80 #on each side of max position appendcheck = 0 while (1): try: x0 = x[indexes[item1] - nbofpoints:indexes[item1] + nbofpoints] y0 = y[indexes[item1] - nbofpoints:indexes[item1] + nbofpoints] #baseline height bhleft = np.mean(y0[:20]) bhright = np.mean(y0[-20:]) baselineheightatmaxpeak = (bhleft + bhright) / 2 if abs(bhleft - bhright ) < 50: #arbitrary choice of criteria... #find FWHM d = y0 - ((max(y0) - bhright) / 2) ind = np.where(d > bhright)[0] hl = (x0[ind[0] - 1] * y0[ind[0]] - y0[ind[0] - 1] * x0[ind[0]]) / ( x0[ind[0] - 1] - x0[ind[0]]) ml = (y0[ind[0] - 1] - hl) / x0[ind[0] - 1] yfwhm = ((max(y0) - baselineheightatmaxpeak) / 2) + baselineheightatmaxpeak xleftfwhm = (yfwhm - hl) / ml hr = (x0[ind[-1]] * y0[ind[-1] + 1] - y0[ind[-1]] * x0[ind[-1] + 1]) / ( x0[ind[-1]] - x0[ind[-1] + 1]) mr = (y0[ind[-1]] - hr) / x0[ind[-1]] xrightfwhm = (yfwhm - hr) / mr FWHM = abs(xrightfwhm - xleftfwhm) Peakheight = max(y0) - baselineheightatmaxpeak center = x[indexes[item1]] tempdat["Position"] = center tempdat["FWHM"] = FWHM tempdat["Intensity"] = Peakheight tempdat["PeakName"] = '' DATA[item][5].append([x0, y0]) DATA[item][6].append( [x0[0], x0[-1], bhleft, bhright]) DATA[item][7].append( [xleftfwhm, xrightfwhm, yfwhm, yfwhm]) appendcheck = 1 break else: if nbofpoints >= 15: nbofpoints -= 10 else: print("indexerror unsolvable") break except IndexError: if nbofpoints >= 15: nbofpoints -= 10 else: print("indexerror unsolvable") break if appendcheck: DATA[item][4].append(tempdat) for item in samplestakenforplot: for item1 in range(len(DATA[item][4])): peaknamesforplot.append([ DATA[item][4][item1]["Position"], DATA[item][4][item1]["Intensity"], DATA[item][4][item1]["PeakName"] ]) self.CreateTable() self.updateXRDgraph(0) #%% def importRefDATA(self): global DATA, RefPattDATA, refsamplenameslist #ask for the files file_path = filedialog.askopenfilenames( title="Please select the reference XRD pattern") #read the files and fill the RefPattDATA dictionary for filename in file_path: filetoread = open(filename, "r") filerawdata = filetoread.readlines() samplename = os.path.splitext(os.path.basename(filename))[0] refsamplenameslist.append(samplename) RefPattDATA[samplename] = [[], [], []] for row in filerawdata: RefPattDATA[samplename][0].append(float(row.split("\t")[0])) RefPattDATA[samplename][1].append(float(row.split("\t")[1])) try: RefPattDATA[samplename][2].append( str(row.split("\t")[2])[:-1]) except: RefPattDATA[samplename][2].append("") #update the listbox self.frame3231.destroy() self.frame3231 = Frame(self.frame323, borderwidth=0, bg="white") self.frame3231.pack(fill=tk.BOTH, expand=1) refsamplenames = StringVar() self.listboxref = Listbox(self.frame3231, listvariable=refsamplenames, selectmode=tk.MULTIPLE, width=15, height=3, exportselection=0) self.listboxref.bind('<<ListboxSelect>>', self.updateXRDgraph) self.listboxref.pack(side="left", fill=tk.BOTH, expand=1) scrollbar = tk.Scrollbar(self.frame3231, orient="vertical") scrollbar.config(command=self.listboxref.yview) scrollbar.pack(side="right", fill="y") self.listboxref.config(yscrollcommand=scrollbar.set) for item in refsamplenameslist: self.listboxref.insert(tk.END, item) def importDATA(self): global DATA, Patternsamplenameslist #ask for the files file_path = filedialog.askopenfilenames( title="Please select the XRD files") #self.WhichXRD() DataSource = messagebox.askquestion( title='Data Source', message= 'Which XRD machine gave you your precious data? \n yes = EPFL, no = CSEM' ) #read the files and fill the DATA dictionary for filename in file_path: tempdat = [] filetoread = open(filename, "r") samplename = os.path.splitext(os.path.basename(filename))[0] filerawdata = filetoread.readlines() x = [] y = [] if DataSource == "yes": for item in filerawdata: x.append(float(item.split(' ')[0])) y.append(float(item.split(' ')[1])) elif DataSource == "no": for line in filerawdata[30:]: x.append(float(line.split(',')[0])) y.append(float(line.split(',')[1])) tempdat.append(x) #original x data tempdat.append(y) #original y data tempdat.append( x) #corrected x, set as the original on first importation tempdat.append( y) #corrected y, set as the original on first importation tempdat.append([]) #4 peak data, list of dictionaries tempdat.append([]) #5 tempdat.append([]) #6 tempdat.append([]) #7 DATA[samplename] = tempdat Patternsamplenameslist.append(samplename) #update the listbox self.frame3221.destroy() self.frame3221 = Frame(self.frame322, borderwidth=0, bg="white") self.frame3221.pack(fill=tk.BOTH, expand=1) importedsamplenames = StringVar() self.listboxsamples = Listbox(self.frame3221, listvariable=importedsamplenames, selectmode=tk.MULTIPLE, width=15, height=3, exportselection=0) self.listboxsamples.bind('<<ListboxSelect>>', self.updateXRDgraph) self.listboxsamples.pack(side="left", fill=tk.BOTH, expand=1) scrollbar = tk.Scrollbar(self.frame3221, orient="vertical") scrollbar.config(command=self.listboxsamples.yview) scrollbar.pack(side="right", fill="y") self.listboxsamples.config(yscrollcommand=scrollbar.set) for item in Patternsamplenameslist: self.listboxsamples.insert(tk.END, item) # def WhichXRD(self): # win = Toplevel() # win.title('Data Source') # message = 'Which XRD machine gave you your precious data?' # Label(Toplevel(), text='123').pack() # Button(win, text='EPFL') # Button(win, text='CSEM') #%% def Export(self): global DATA f = filedialog.asksaveasfilename(defaultextension=".png", filetypes=(("graph file", "*.png"), ("All Files", "*.*"))) self.fig1.savefig(f, dpi=300) testdata = ['name\tPeakName\tPosition\tIntensity\tFWHM\n'] dattotxt = [] samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for key in samplestakenforplot: for item in DATA[key][4]: testdata.append(key + '\t' + item["PeakName"] + '\t' + str("%.2f" % item["Position"]) + '\t' + str("%.2f" % item["Intensity"]) + '\t' + str("%.2f" % item["FWHM"]) + '\n') x = ["2theta", "degree", ""] y = ["XRD intensity", "a.u.", key] for item in range(len(DATA[key][2])): x.append(DATA[key][2][item]) y.append(DATA[key][3][item]) dattotxt.append(x) dattotxt.append(y) file = open(f[:-4] + "PeakDat.txt", 'w') file.writelines("%s" % item for item in testdata) file.close() dattotxt = map(list, six.moves.zip_longest(*dattotxt, fillvalue=' ')) dattotxt1 = [] for item in dattotxt: line = "" for item1 in item: line = line + str(item1) + "\t" line = line[:-1] + "\n" dattotxt1.append(line) file = open(str(f[:-4] + "_dat.txt"), 'w') file.writelines("%s" % item for item in dattotxt1) file.close() def ExportasRef(self): global DATA, RefPattDATA f = filedialog.asksaveasfilename(defaultextension=".txt") samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for key in samplestakenforplot: datforref = [] for item in range(len(DATA[key][2])): datforref.append( str(DATA[key][2][item]) + '\t' + str(DATA[key][3][item]) + '\n') file = open(str(f[:-4] + "_" + key + ".txt"), 'w') file.writelines("%s" % item for item in datforref) file.close() #%% def CreateTable(self): global DATA global testdata testdata = [] #self.parent.grid_rowconfigure(0,weight=1) #self.parent.grid_columnconfigure(0,weight=1) # self.parent.config(background="white") self.frame41.destroy() self.frame41 = Frame(self.frame4, borderwidth=0, bg="white") self.frame41.pack(side="right", fill=tk.BOTH, expand=1) samplestakenforplot = [ self.listboxsamples.get(idx) for idx in self.listboxsamples.curselection() ] if samplestakenforplot != []: for key in samplestakenforplot: for item in DATA[key][4]: testdata.append([ key, item["PeakName"], "%.2f" % item["Position"], "%.2f" % item["Intensity"], "%.2f" % item["FWHM"] ]) self.tableheaders = ('name', 'PeakName', 'Position', 'Intensity', 'FWHM') # Set the treeview self.tree = Treeview(self.frame41, columns=self.tableheaders, show="headings") for col in self.tableheaders: self.tree.heading( col, text=col.title(), command=lambda c=col: self.sortby(self.tree, c, 0)) self.tree.column( col, width=int(round(1.1 * tkFont.Font().measure(col.title()))), anchor='n') scrollbar = tk.Scrollbar(self.frame41, orient="vertical") scrollbar.config(command=self.tree.yview) scrollbar.pack(side="right", fill="y") self.tree.config(yscrollcommand=scrollbar.set) self.tree.pack(side="left", fill=tk.BOTH, expand=1) self.treeview = self.tree self.insert_data(testdata) def insert_data(self, testdata): for item in testdata: self.treeview.insert('', 'end', values=item) def sortby(self, tree, col, descending): data = [(tree.set(child, col), child) for child in tree.get_children('')] try: data.sort(key=lambda t: float(t[0]), reverse=descending) except ValueError: data.sort(reverse=descending) for ix, item in enumerate(data): tree.move(item[1], '', ix) # switch the heading so it will sort in the opposite direction tree.heading(col, text=col.capitalize(), command=lambda _col_=col: self.sortby( tree, _col_, int(not descending)))
class StoreView(BaseView): ######## # Initializes and places all GUI elements. def _create_widgets(self): # left frame self._leftFrame = Frame(self) self._imgLabel = Label(self._leftFrame) self._locLabel = Label(self._leftFrame, text="Location:", font=BaseView.NORMAL_FONT) self._locPreview = SimpleLocationView(self._leftFrame) # right frame self._rightFrame = Frame(self) self._nameLabel = Label(self._rightFrame, compound=LEFT, text="Name", font=BaseView.LARGE_FONT) self._descLabel = Label(self._rightFrame, text="Description:", font=BaseView.NORMAL_FONT) self._descFrame = Frame(self._rightFrame) self._descText = Text(self._descFrame, width=50, height=4, state=DISABLED, wrap=WORD, font=BaseView.NORMAL_FONT) self._descScroll = Scrollbar(self._descFrame, command=self._descText.yview) self._descText.config(yscrollcommand=self._descScroll.set) self._notesLabel = Label(self._rightFrame, text="Notes:", font=BaseView.NORMAL_FONT) self._notesFrame = Frame(self._rightFrame) self._notesText = Text(self._notesFrame, width=50, height=4, state=DISABLED, wrap=WORD, font=BaseView.NORMAL_FONT) self._notesScroll = Scrollbar(self._notesFrame, command=self._notesText.yview) self._notesText.config(yscrollcommand=self._notesScroll.set) # bottom self._sep1 = Separator(self, orient="horizontal") self._invLabel = Label(self, text="Inventory:", font=BaseView.NORMAL_FONT) self._invFrame = Frame(self) self._inventory = Treeview( self._invFrame, columns=["type", "price", "qty", "stockDays"], selectmode="browse", height=15) self._inventory.heading("#0", text="Item", anchor=N + W) self._inventory.column("#0", width=300, anchor=N + W, stretch=True) self._inventory.heading("type", text="Type", anchor=N + W) self._inventory.column("type", width=100, anchor=N + W) self._inventory.heading("price", text="Price", anchor=N + W) self._inventory.column("price", width=60, anchor=N + W) self._inventory.heading("qty", text="Qty", anchor=N + W) self._inventory.column("qty", width=40, anchor=N + W) self._inventory.heading("stockDays", text="Stock Days", anchor=N + W) self._inventory.column("stockDays", width=200, anchor=N + W, stretch=True) self._invScroll = Scrollbar(self._invFrame, command=self._inventory.yview) self._inventory.config(yscrollcommand=self._invScroll.set) # placement: scrollbars self._descText.grid(row=0, column=0, sticky=N + W + E + S) self._descScroll.grid(row=0, column=1, sticky=N + S) self._notesText.grid(row=0, column=0, sticky=N + W + E + S) self._notesScroll.grid(row=0, column=1, sticky=N + S) self._inventory.grid(row=0, column=0, sticky=N + W + E + S) self._invScroll.grid(row=0, column=1, sticky=N + S) # placement: left frame self._imgLabel.grid(row=0, column=0, sticky=N + W + E + S) self._locLabel.grid(row=1, column=0, sticky=N + W) self._locPreview.grid(row=2, column=0, sticky=W + E) # placement: right frame self._nameLabel.grid(row=0, column=0, sticky=W) self._descLabel.grid(row=1, column=0, sticky=W) self._descFrame.grid(row=2, column=0, sticky=W) self._notesLabel.grid(row=3, column=0, sticky=W) self._notesFrame.grid(row=4, column=0, sticky=W) # bottom self._sep1.grid(row=1, column=0, columnspan=2, sticky=W + E) self._invLabel.grid(row=2, column=0, columnspan=2, sticky=N + W) self._invFrame.grid(row=3, column=0, columnspan=2, sticky=W + E) self._leftFrame.grid(row=0, column=0, sticky=N + W) self._rightFrame.grid(row=0, column=1, sticky=N + W) ######## # Add callbacks for all GUI element events and Tkinter variables. def _bind_widgets(self): self._locPreview.bind("<Double-Button-1>", self._open_loc) self._inventory.bind("<Double-Button-1>", self._inventory_on_double_click) ######## # Populates all GUI elements with new data. def populate(self, data): self._data = data if data == None: # null check self.set_defaults() return for k, v in data.items(): if k == "name": # non-null self._nameLabel.config(text=v) elif k == "img": if v == None: # null check v = BaseView.DEFAULT_IMG utility.update_img(self._imgLabel, v, maxSize=300) elif k == "location": # non-null self._locPreview.populate(v) elif k == "description": if v == None: # null check v = BaseView.EMPTY_STR utility.update_text(self._descText, v) elif k == "notes": if v == None: # null check v = BaseView.EMPTY_STR utility.update_text(self._notesText, v) elif k == "sells": self._update_inventory() ######## # Resets GUI elements to default values. def set_defaults(self): utility.update_img(self._imgLabel, BaseView.DEFAULT_IMG, maxSize=300) utility.update_text(self._descText, BaseView.EMPTY_STR) utility.update_text(self._notesText, BaseView.EMPTY_STR) ######## # Populates inventory with correct values def _update_inventory(self): allItems = self._inventory.get_children() for item in allItems: self._inventory.delete(item) self._imgs = [] if self._data == None: return for entry in self._data["sells"]: img = entry["item"]["img"] if img == None: img = BaseView.DEFAULT_IMG img = utility.get_img(img, maxSize=20) name = entry["item"]["name"] fields = [ BaseView.TYPE_MAP[entry["item"]["type"]], entry["price"], entry["qty"], entry["stockDays"] ] for i in range(len(fields)): if fields[i] == None: fields[i] = BaseView.EMPTY_STR self._imgs.append(img) self._inventory.insert("", END, image=img, text=name, values=fields) ######## # Opens location view through refBook. def _open_loc(self, *args, **kwargs): if self._refBook == None or self._data == None: return self._refBook.show_location(self._data["location"]["name"]) ######## # Callback for double clicking in inventory treeview. def _inventory_on_double_click(self, *args, **kwargs): if self._refBook == None or self._data == None or len( self._inventory.selection()) == 0: return self._refBook.show_item(self._data["sells"][self._inventory.index( self._inventory.selection())]["item"]["name"])
tv['columns'] = ('temperature', 'light', 'soil', 'rainfall', 'land') #tv['columns'] = ('starttime', 'endtime', 'status') tv.heading("#0", text='Crop', anchor="center") tv.column("#0", anchor=W, width=60) tv.heading('temperature', text='Temperature') tv.column('temperature', anchor='center', width=95) tv.heading('light', text='Light') tv.column('light', anchor='center', width=65) tv.heading('soil', text='Soil') tv.column('soil', anchor='center', width=50) tv.heading('rainfall', text='Rainfall') tv.column('rainfall', anchor='center', width=75) tv.heading('land', text='Land', anchor=W) tv.column('land', anchor=W, width=75) #tv.grid(row=10,column=0,sticky = (N,S,W,E)) tv.config(height=1) #tv.tag_configure('test',background='red') tv.grid(row=10, columnspan=3) tv.grid_rowconfigure(10, weight=1) label2.grid(row=13, column=1) """ lb.grid(row=15,column=1) lb.config(height=10) for i in range(100): lb.insert(END, i) lb.config(yscrollcommand=scrollbar.set) scrollbar.config(command=lb.yview) """
class show: def __init__(self): self.window=Tk() self.window.title("Show | Sales Products") self.window.iconbitmap('shop.ico') self.window.geometry("1365x670+0+0") self.window.maxsize(1365,670) self.window.minsize(1365,670) # self.window.resizable(width=False,height=False) def add_background(self): self.image = Image.open("images/back.jpg") self.image = self.image.resize((1365, 700), Image.ANTIALIAS) self.img = ImageTk.PhotoImage(self.image) self.li = Label(image = self.img, text="TALHA") self.li.image = self.img self.li.pack() self.Menubar() def Menubar(self): self.menubar = Menu() self.menuitems_add = Menu(self.menubar, tearoff=0,bg="blue",fg="white") self.menuitems_add.add_command(label="Add Products", command=self.add_products) # self.menuitems.add_separator() self.menuitems_sales = Menu(self.menubar, tearoff=0,bg="blue",fg="white") self.menuitems_sales.add_command(label="Sale Products", command=self.sales_products) self.menuitems_customer = Menu(self.menubar, tearoff=0, bg="blue", fg="white") self.menuitems_customer.add_command(label="Add Customer", command=self.add_customer) self.menuitems_customer.add_command(label="Show Customer Records", command=self.customer_record) self.menuitems_reports = Menu(self.menubar, tearoff=0, bg="blue", fg="white") self.menuitems_reports.add_command(label="Check Products Quantity", command=self.check_products_quantity) self.menuitems_reports.add_command(label="Check Profit/Loss", command=self.check_profit_loss) self.menuitems_reports.add_command(label="Check Sales Products", command=self.check_products_sales) self.menuitems_reports.add_command(label="Check Sent Amount Details", command=self.check_amount) self.menubar.add_cascade(label="Add Products", menu=self.menuitems_add) self.menubar.add_cascade(label="Sales Products", menu=self.menuitems_sales) self.menubar.add_cascade(label="Customer", menu=self.menuitems_customer) self.menubar.add_cascade(label="Reports", menu=self.menuitems_reports) self.menubar.add_cascade(label="Exit", command=quit) self.window.config(menu=self.menubar) def add_table(self): self.l1=Label(self.window,text="**Sales Details**",font="Courier 25 bold",bg="black",fg="white",width=61) self.l1.place(x=82,y=20) self.l1 = Label(self.window, text="Developed by : Muhammad Talha | NTU", font="Courier 10 bold") self.l1.place(x=470, y=610) self.l1 = Label(self.window, text="Enter Product Name:", font="courier 16 bold",bg="blue",fg="white") self.l1.place(x=280, y=90) self.Entry_reg = Entry(self.window, font="courior 14 bold") self.Entry_reg.place(x=550, y=90, height=30) self.b1 = Button(self.window, text="Search", font="Times 13 bold",fg="white",bg="blue",width=10) self.b1.place(x=790, y=90) self.b1.bind('<Button-1>', self.search_product) # for Style Table style = Style() style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=('courier 12 bold'),rowheight=43) # Modify the font of the body style.configure("mystyle.Treeview.Heading", font=('Times 15 bold'),foreground="black") # Modify the font of the headings # style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})]) # Remove the borders # import TreeViewe self.tr=Treeview(self.window,columns=('A','B','C','D','E'),selectmode="extended",style='mystyle.Treeview') # heading key+text self.tr.heading("#0", text="Sr.No") self.tr.column("#0", minwidth=0, width=85, stretch=NO) self.tr.heading("#1",text="Product Name") self.tr.column("#1",minwidth=0,width=160,stretch=NO) self.tr.heading("#2", text="Product Catagory") self.tr.column("#2", minwidth=0, width=200, stretch=NO) self.tr.heading("#3", text="Quantity") self.tr.column("#3", minwidth=0, width=175, stretch=NO) self.tr.heading("#4", text="Price Per Product") self.tr.column("#4", minwidth=0, width=175, stretch=NO) self.tr.heading("#5", text="Sales Price") self.tr.column("#5", minwidth=0, width=160, stretch=NO) j=1 for i in Database.show_sales_details(): self.tr.insert('',index=j,text=j,values=(i[1],i[2],i[3],i[4],i[5])) j+=1 self.Entry_reg.bind('<KeyRelease>', self.remove) self.sb = Scrollbar(self.tr) self.sb.place(x=935,y=2,height=452,width=22,bordermode=OUTSIDE) self.sb.config(command=self.tr.yview) self.tr.config(yscrollcommand=self.sb.set) self.tr.place(x=170,y=150) # to excel file self.b1 = Button(self.window, text="Save to Excel", font="Times 12 bold",bg="blue",fg="white",width=20, ) self.b1.place(x=938, y=610) self.b1.bind('<Button-1>', self.excel) self.window.mainloop() def remove(self,event): for row in self.tr.get_children(): self.tr.delete(row) j = 1 for i in Database.show_sales_details(): self.tr.insert('', index=j, text=j, values=(i[1], i[2], i[3], i[4], i[5])) j += 1 def search_product(self,event): try: data = (self.Entry_reg.get(),) if self.Entry_reg.get() == "": msg.showwarning("Message ! ", "please insert product name !") else: j = 1 D = Database.search_details_sales_table(data) if D: for row in self.tr.get_children(): self.tr.delete(row) self.Entry_reg.delete(0, END) for i in D: self.tr.insert('', index=j, text=j, values=(i[1],i[2],i[3],i[4],i[5])) j += 1 else: msg.showwarning("Message!", "No result Found!") except: msg.showwarning("Error!", "Something went wrong! please contact with developer !!!") def excel(self,event): try: x=Database.show_sales_details() p_name=[] p_catagory=[] p_quantity=[] price=[] p_sales_price=[] for i in range(len(x)): z=x.__getitem__(i) p_name.append(z[1]) p_catagory.append(z[2]) p_quantity.append(z[3]) price.append(z[4]) p_sales_price.append(z[5]) products = pd.DataFrame({ "Product Name": p_name, "Product Catagory":p_catagory, "Quantity":p_quantity, "Price Per Product":price, "Sales Price":p_sales_price }) with pd.ExcelWriter("Excel Files/Sales_Products_Records.xlsx") as writer: products.to_excel(writer, sheet_name="Sales_Products", index=False) msg.showinfo("Message ! ", "Your data has been inserted Susccessfully !") except: msg.showwarning("Message!","Something Went Wrong!please contact with developer!!!") def add_products(self): self.window.destroy() home = Home.data() home.add_background() home.add_frame() def sales_products(self): self.window.destroy() showP = Showing_Records.show() showP.add_background() showP.add_table() def check_products_quantity(self): self.window.destroy() showP = Check_Products_Quantity.show() showP.add_background() showP.add_table() def check_products_sales(self): pass def check_amount(self): self.window.destroy() showP = Check_Amount_Details.show() showP.add_background() showP.add_table() def check_profit_loss(self): self.window.destroy() showP = Check_Profit_Loss_GUI.show() showP.add_background() showP.add_table() def add_customer(self): self.window.destroy() home = Add_Customer.data() home.add_background() home.add_frame() def customer_record(self): self.window.destroy() showP = Customer_Records.show() showP.add_background() showP.add_table()
class GUI: """ Graphical User Interface, makes the communication easier for the bus driver in order to reduce the time the driver has to put into communicating with the system. designed in a 3 color scheme, black, green, and white has a background glow thats used to show the bus driver important updates, that need his attention default color is green, changes the color to red when there's a passenger that needs to be picked up and changes the color to gray when the bus is offline. has a welcome window that his purpose is to acquire some information regarding the bus from the driver. 3 entries that get the Bus ID, the line number and the starting station of the bus. And a Finish Button that saves the information and starts the bus system with the given information After the finish is clicked, the window will close and a loading screen is displayed while the main window is loading. the main window holds on top a display that shows the locations of all the relevant buses and passengers. Next Station button that moves the bus to the next station. a square with the purpose to make sure that the bus will stop at the station if there's a passengers. server broadcasts section that shows all the messages recieved from the server place to send messages to the server that consists of a send button and an entry to type the text into. also displays some statistics. and a big red exit button. """ __BLACK = "#000000" __GREEN = "#105e29" __GREEN1 = "#1DB954" def __init__(self): """ creates a GUI class instance :return: GUI """ self.__line, self.__id, self.__station = None, None, None self.__bus = None self.__font_name = "Bahnschrift SemiBold SemiConden" self.__headlines = None self.asking_to_reconnect = False self.__passengers_count_stringvar = None self.__buses_count_stringvar = None self.__session_time_stringvar = None self.__window = None self.__finished_window = None self.__lost_connection_window = None self.__kicked_window = None self.__server_broadbast_stringvars_dict = dict() #those dictionaries store the location regarding plament widget groups on the screen self.__statistics_coords = {"x": 540, "y": 408} self.__updating_statistics_coords ={"x": 680, "y": 331} self.__next_btn_coords = {"x": 29, "y": 177} self.__exit_btn_coords = {"x": 29, "y": 490} self.__broadcast_section_coords = {"x": 44, "y": 427} self.__server_messages_coords = {"x": 66, "y": 322, "jump": 34} self.__table_coords = {"x": 26, "y": 74, "width" : 744, "height":59} def start(self): """ starts the gui starts by asking for starting information for the bus, after that creates a bus instance with the given information after that starts the loading process for the rest of the program components. :return: None """ self.config_first_data() if self.__line == None: sys.exit("Ended by user") self.__window = Tk() self.__window.iconbitmap(f'images bus\\icon.ico') # put stuff to icon self.__window.title("Bus Client") self.__window.resizable(OFF, OFF) self.__start_loading_screen() self.__window.mainloop() self.stop() def stop(self): """ stops the run of the gui and tells the bus to stop as well. at the end closes the code :return: None """ self.__bus.stop = True if self.__finished_window != None and self.__finished_window.state() == "normal": self.__finished_window.destroy() if self.__window != None and self.__window.state() == "normal": self.__window.destroy() if self.__lost_connection_window != None and self.__lost_connection_window.state() == "normal": self.__lost_connection_window.destory() if self.__kicked_window != None and self.__kicked_window.state() == "normal": self.__kicked_window.destroy() sys.exit("closed by user") def __start_loading_screen(self): """ Starts the loading proccess. At first shows the loading image, waits for 10ms and then starts loading all the widgets and the properties of the program. :return: None """ loading_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\loading screen.png")) self.__window.geometry(f"{loading_img.width()}x{loading_img.height()}") self.__bg_label = Label(self.__window, image=loading_img, bg="#192b3d") self.__bg_label.place(x=0, y=0) self.__window.after(10, self.__finish_loading_screen) self.__window.mainloop() def __finish_loading_screen(self, launch_bus=True): """ starts the bus object, places all the labels, buttons, data tables, entries and initializes all the values needed for the rest of the run :return: False """ if launch_bus: self.__bus = Bus(self, self.__id, self.__line, self.__station) self.__bus.start() self.__headlines = [str(x) for x in range(1, self.__bus.max_number_of_stations + 1)] self.__passengers_count_stringvar = StringVar() self.__buses_count_stringvar = StringVar() self.__server_broadbast_stringvar1 = StringVar() self.__server_broadbast_stringvar2 = StringVar() self.__session_time_stringvar = StringVar() #init all the images self.__bg_nobody_is_waiting_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\nobody is waiting.png")) self.__bg_lost_connection_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\lost connection.png")) self.__bg_stop_at_the_next_station_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\stop at the next station.png")) self.__next_btn_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\next station.png")) self.__exit_btn_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\exit btn.png")) self.__send_btn_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\send btn.png")) #place the widgets on the window self.__create_table() self.__update_table() self.__place_buttons() self.__place_labels() self.__place_free_text_section() self.__window.geometry(f"{self.__bg_nobody_is_waiting_img.width()}x{self.__bg_nobody_is_waiting_img.height()}") self.__update_bg() #start the updates loop that will keep the widgets updated self.__loop() def __create_table(self): """ creates and places the table that display the locations of the buses and the passengers for the line. uses the ttk. widgets Treeview combined with a scrollbar. and the ThemedStyle lib in order to give the dark themed look to the widget. :return: None """ base_x = self.__table_coords["x"] base_y = self.__table_coords["y"] base_width = self.__table_coords["width"] base_height = self.__table_coords["height"] self.__tree_style = ThemedStyle(self.__window) self.__tree_style.set_theme("black") self.__tree_style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=(self.__font_name, 11)) # Modify the font of the body self.__tree_style.configure("mystyle.Treeview", background="black", fieldbackground="black", foreground=GUI.__GREEN1) self.__tree_style.configure("mystyle.Treeview.Heading", font=(self.__font_name, 13, 'bold'), foreground=GUI.__GREEN1) # Modify the font of the headings scrollX = ttk.Scrollbar(self.__window, orient=HORIZONTAL) self.__tree = Treeview(self.__window, show="headings", columns=self.__headlines, xscrollcommand=scrollX.set, style = "mystyle.Treeview") self.__tree.place(x=base_x, y=base_y, width=base_width, height=base_height) scrollX.config(command=self.__tree.xview) scrollX.place(x=base_x, y=base_y+base_height, width=base_width) def __place_buttons(self): """ Places the main buttons on the screen. next_button - tells the bus to move onto the next station and tell the server that he moved exit_button - closes the gui and the server :return: None """ self.__next_button = tkinter.Button(self.__window, image=self.__next_btn_img, command=self.__bus.next_station, borderwidth=0, background = "#000000", activebackground = "#083417") self.__next_button.place(x=self.__next_btn_coords["x"], y=self.__next_btn_coords["y"]) self.__exit_button = tkinter.Button(self.__window, command=self.stop, image=self.__exit_btn_img, borderwidth=0, background=GUI.__BLACK, activebackground=GUI.__BLACK, fg="red") self.__exit_button.place(x=self.__exit_btn_coords["x"], y=self.__exit_btn_coords["y"]) def __update_labels(self): """ updates all the labels in the program passenger count - shows how many passengers are waiting for the bus buses count - shows how many buses are active in the line session time - displays the session time of the driver server messages - shows the messages received from the server updates the StringVars instead of recreating the label. the messages label is actually more than just 1 label, but all the labels and the StringVars are stored in the same dict the reason is that breaking down the messages into a couple layers allows more flexible formatting :return: None """ #statistics self.__passengers_count_stringvar.set(str(self.__bus.count_people())) self.__buses_count_stringvar.set(str(self.__bus.count_buses())) self.__session_time_stringvar.set(f"{self.__bus.session_time}") #server messages messages = [] for message in self.__bus.server_free_text_messages: if time.time() - message["time"] > Bus.MESSAGE_TTL: #Removes old messages self.__bus.server_free_text_messages.remove(message) messages.append(f"{time.strftime('%H:%M:%S', time.localtime(message['time']))}: {message['text']} \n") #makes sure that all the labels will be addressed, if there's not enough information for them fills with "" while len(messages) <Bus.MAX_MESSAGE_COUNT: messages.append("") #updates the StringVars for i in range(0,Bus.MAX_MESSAGE_COUNT): self.__server_broadbast_stringvars_dict[i].set(messages[i]) def __loop(self): """ the main GUI loop, run in the main thread and updates data on the screen (labels, table and background) runs twice per second but can be easily changes if needed will stop looping only when the self.__bus.stop is equal to True :return: None """ if self.__bus.stop: return try: self.__update_table() self.__update_bg() self.__update_labels() self.__after_job = self.__window.after(500, self.__loop) except Exception as e: print(f"Done looping because: {e}") def __place_labels(self): """ creates labels, configures them and places them at the places they're supposed to be. labels that are placed - passengers_count shows the passengers count in the line - buses_count shows the bus count of the buses in the line - server_messages shows the messages received from the server - line_label shows the line number - id_label shows the bus id - session_time_label shows the session time :return: None """ # statistics labels self.__passengers_count_stringvar.set(str(self.__bus.count_people())) self.__buses_count_stringvar.set(str(self.__bus.count_buses())) #changing statistics base_x = self.__updating_statistics_coords["x"] base_y = self.__updating_statistics_coords["y"] passengers_count_label = Label(self.__window, textvariable=self.__passengers_count_stringvar, fg=GUI.__GREEN, bg=GUI.__BLACK, font=(self.__font_name, 13, "bold")) buses_count_label = Label(self.__window, textvariable=self.__buses_count_stringvar, fg=GUI.__GREEN, bg=GUI.__BLACK, font=(self.__font_name, 13, "bold")) passengers_count_label.place(x=base_x, y=base_y) buses_count_label.place(x=base_x + 42, y=base_y + 28) #broadcasts base_x =self.__server_messages_coords["x"] base_y = self.__server_messages_coords["y"] jump = self.__server_messages_coords["jump"] for i in range(0,Bus.MAX_MESSAGE_COUNT): self.__server_broadbast_stringvars_dict[i] = StringVar() Label(self.__window, fg=GUI.__GREEN, bg = GUI.__BLACK, font=(self.__font_name, 15, "bold"), textvariable=self.__server_broadbast_stringvars_dict[i]).place(x=base_x, y=base_y+jump*i) # statistics base_x = self.__statistics_coords["x"] base_y = self.__statistics_coords["y"] Label(self.__window, text=str(self.__line), fg=GUI.__GREEN, bg = GUI.__BLACK, font=(self.__font_name, 12, "bold")).place(x=base_x, y=base_y) Label(self.__window, text=str(self.__id), fg=GUI.__GREEN, bg = GUI.__BLACK, font=(self.__font_name, 12, "bold")).place(x=base_x-14, y=base_y+20) Label(self.__window, textvariable=self.__session_time_stringvar, fg=GUI.__GREEN, bg=GUI.__BLACK, font=(self.__font_name, 12, "bold")).place(x=base_x+37, y=base_y+39) def __place_free_text_section(self): """ places the free text section has a button and an entry that will send messages to the server if needed upon a button click the data in the entry will be sent to the server as a message from the bus. :return: None """ self.__message_entry = Entry(self.__window, width = 30, borderwidth=0, background = "black", insertbackground ="#1DB954", foreground="#1DB954",font = (self.__font_name, 14)) self.__send_broadcast_button = Button(self.__window, image=self.__send_btn_img, borderwidth=0, background = "#000000", activebackground = "#083417", command=self.__send_free_text_to_server) base_x =self.__broadcast_section_coords["x"] base_y =self.__broadcast_section_coords["y"] self.__message_entry.place(x=base_x, y=base_y) self.__send_broadcast_button.place(x=base_x-3, y=base_y +29) def __send_free_text_to_server(self): """ harvests the data from the self.__message_entry, clears the entry then tells the bus to send the message to the server :return: None """ if self.__bus.connected: data = self.__message_entry.get() print(f"broad casting data: {data}") if not self.__bus.send_free_text(data): print("failed to send") else: self.__message_entry.delete(0, 'end') else: print("failed to send") def __update_table(self): """ recalculates the way the display table is supposed to look and places all the widgets into the table. :return: None """ self.__headlines = [str(x) for x in range(1, self.__bus.max_number_of_stations + 1)] self.__tree.config(columns=self.__headlines) for headline in self.__headlines: self.__tree.heading(headline, text=headline) self.__tree.column(headline, anchor="center", stretch=False, width=47) data = self.__bus.display_passengers() for i in self.__tree.get_children(): self.__tree.delete(i) self.__tree.insert("", END, values=data) def __update_bg(self): """ changes the background according to the state of the bus currently has only 3 states but more states can be easily added nobody is waiting - will display a greenish background with the message "nobody is waiting" when there are no passengers waiting stop at the next station - will display a red background with the message "somebody is waiting" when there's a passenger at the next station lost connection - will display a gray background with the message "lost connection" when the bus loses connection or gets kicked. :return: None """ if self.__bus.connected and not self.__bus.kicked: if self.__bus.next_station_people_count==0: self.__bg_label["image"] = self.__bg_nobody_is_waiting_img elif self.__bus.next_station_people_count > 0: self.__bg_label["image"] = self.__bg_stop_at_the_next_station_img else: self.__bg_label["image"] = self.__bg_lost_connection_img def display_lost_connection(self): """ creates a window saying that the bus has lost connection to the server has a button that says "Reconnect" and will try to reconnect to the server. if failed to reconnect a new message will show saying "failed to reestablish connection to the server" :return: None """ if self.__bus.stop == True: return self.__lost_connection_window = Tk() self.__lost_connection_popup_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\Lost connection popup.png"),master=self.__lost_connection_window) self.__lost_connection_window.geometry(f"{self.__lost_connection_popup_img.width()}x{self.__lost_connection_popup_img.height()}") self.__lost_connection_window.iconbitmap(r'Images bus\icon.ico') # put stuff to icon self.__lost_connection_window.title("Lost Connection to the server") self.__lost_connection_window.resizable(OFF, OFF) self.__bg_label_lost_connection = Label(self.__lost_connection_window, image=self.__lost_connection_popup_img, bg="white") self.__bg_label_lost_connection.place(x=0, y=0) self.__reconnect_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\reconnect.png"), master=self.__lost_connection_window) self.__reconnect_button = tkinter.Button(self.__lost_connection_window, command=lambda: self.__try_to_reconnect("PostLogin"), image=self.__reconnect_img, borderwidth =0, activebackground="white") self.__reconnect_button.place(x=152, y=101) self.__lost_connection_window.mainloop() if not self.__bus.connected: sys.exit("closed by user") def failed_to_connect(self, firstattempt = True): """ creates a window saying that the bus has failed to establish the first connection to the server. has a button that says "Reconnect" and will try to reconnect to the server. if failed to reconnect a new message will show saying "failed to reestablish connection to the server" :return: None """ if self.__bus.stop == True: return if not firstattempt: self.__failed_to_reconnect_img = ImageTk.PhotoImage( PIL.Image.open(r"Images bus\failed to reestablish.png"), master=self.__failed_to_connect_window) self.__bg_label_failed_to_connect["image"] = self.__failed_to_reconnect_img return self.__failed_to_connect_window = Tk() self.__failed_to_connect_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\failed to establish.png"), master=self.__failed_to_connect_window) self.__failed_to_connect_window.geometry( f"{self.__failed_to_connect_img.width()}x{self.__failed_to_connect_img.height()}") self.__failed_to_connect_window.iconbitmap(r'Images bus\icon.ico') # put stuff to icon self.__failed_to_connect_window.title("Failed To Connect") self.__failed_to_connect_window.resizable(OFF, OFF) self.__bg_label_failed_to_connect = Label(self.__failed_to_connect_window, image=self.__failed_to_connect_img, bg="white") self.__bg_label_failed_to_connect.place(x=0, y=0) self.__reconnect_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\reconnect.png"), master=self.__failed_to_connect_window) self.__reconnect_button = tkinter.Button(self.__failed_to_connect_window, command=lambda: self.__try_to_reconnect("PreLogin"), image=self.__reconnect_img, borderwidth=0, activebackground="white") self.__reconnect_button.place(x=152, y=101) self.__failed_to_connect_window.mainloop() if not self.__bus.connected: sys.exit("closed by user") def display_kicked(self, reason: str): """ creates a window saying that the bus has been kicked from the server has a button that says "Reconnect" and will try to reconnect to the server. if failed to reconnect a new message will show saying "failed to reestablish connection to the server". takes the reason that the bus had been kicked as a parameter, currently has no use, but here to make future development easier. :param reason: str :return: None """ if self.__bus.stop == True: return self.__kicked_window = Tk() self.__kicked_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\kicked.png"),master=self.__kicked_window) self.__kicked_window.geometry(f"{self.__kicked_img.width()}x{self.__kicked_img.height()}") self.__kicked_window.iconbitmap(r'Images bus\icon.ico') # put stuff to icon self.__kicked_window.title("kicked") self.__kicked_window.resizable(OFF, OFF) self.__bg_label_kicked = Label(self.__kicked_window, image=self.__kicked_img, bg="white") self.__bg_label_kicked.place(x=0, y=0) self.__reconnect_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\reconnect.png"), master=self.__kicked_window) self.__reconnect_button = tkinter.Button(self.__kicked_window, command=lambda: self.__try_to_reconnect("Kicked"), image=self.__reconnect_img, borderwidth =0, activebackground="white") self.__reconnect_button.place(x=152, y=101) self.__kicked_window.mainloop() if not self.__bus.connected: sys.exit("closed by user") def display_finished(self): """ opens a window that shows the finished image and all the statistics that come with it. shows the session time, and how many people the bus picked up during his ride. has an exit button that closes the program and ends the session. used as the last window in the program, nothing will open after this window is closed. return: None """ self.__window.after_cancel(self.__after_job) self.__window.destroy() finished_font = ("Bauhaus 93", 30) self.__finished_window = Tk() self.__finished_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\finished.png")) self.__finished_exit_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\exit finished.png")) self.__finished_window.geometry(f"{self.__finished_img.width()}x{self.__finished_img.height()}") self.__finished_window.iconbitmap(r'Images bus\icon.ico') # put stuff to icon self.__finished_window.title("Finished") self.__finished_window.resizable(OFF, OFF) bg_label = Label(self.__finished_window, image=self.__finished_img, bg="#1DB954") bg_label.place(x=0, y=0) self.__people_count_label = Label(self.__finished_window, text=str(self.__bus.total_people_count), bg="#1DB954", fg="#000000", font=finished_font) self.__session_time_label = Label(self.__finished_window, text=str(self.__bus.session_time), fg="#1DB954", bg="#000000", font=finished_font) self.__finish_button = tkinter.Button(self.__finished_window, image=self.__finished_exit_img, command=self.stop, borderwidth=0, activebackground="gray", fg="red") self.__finish_button.place(x=276, y=462) self.__people_count_label.place(x=494, y=190) self.__session_time_label.place(x=560, y=320) self.__finished_window.mainloop() if not self.__bus.connected: sys.exit("closed by user") def __try_to_reconnect(self, status): """ tries to reconnect the bus back to the server takes the status of the program when the command was called, can be "PreLogin"\"PostLogin"\"Kicked" used in case if failed to reconnect, it makes sure that the correct window will be updated. :param status: str return: Bool """ if status == "PreLogin": if self.__bus.start(first_attempt = False): self.__finish_loading_screen(launch_bus=False) self.__failed_to_connect_window.destroy() elif self.__bus.reconnect(): if status =="PostLogin": self.__lost_connection_window.destroy() elif status == "Kicked": self.__kicked_window.destroy() else: print(f"ughh..... i dunno what to do, status: {status} unrecognized") self.__bus.asking_user_to_reconnect = False else: if status == "PostLogin": self.__failed_to_reconnect_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\failed to reestablish.png"), master=self.__lost_connection_window) self.__bg_label_lost_connection["image"]=self.__failed_to_reconnect_img elif status == "Kicked": self.__failed_to_reconnect_img = ImageTk.PhotoImage( PIL.Image.open(r"Images bus\failed to reestablish.png"), master=self.__kicked_window) self.__bg_label_kicked["image"] = self.__failed_to_reconnect_img else: print(f"ughh..... i dunno what to do, status: {status} unrecognized") def config_first_data(self): """ the first thing that the uses sees when he runs the client. opens a window asking the user to give some information about the bus he's driving and the line he's working for has 3 entries and a finish button - id_entry the bus id - line_entry the line that the bus works for - station_entry the station number that the driver starts from - finish_button passes the entries to the __set_up_data method that takes the data, saves it and closes the window :return: None """ window = Tk() back_ground_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\opening screen.png")) finish_img = ImageTk.PhotoImage(PIL.Image.open(r"Images bus\finish btn.png")) window.geometry(f"{back_ground_img.width()}x{back_ground_img.height()}") window.iconbitmap(f'images bus\\icon.ico') # put stuff to icon window.title("User Setup") window.resizable(OFF, OFF) back_ground_label = Label(window, image=back_ground_img, bg=GUI.__BLACK) back_ground_label.place(x=0, y=0) station_entry = Entry(window, width=8, borderwidth=0, background = "black", foreground="#1DB954", insertbackground ="#1DB954", font = (self.__font_name, 22)) station_entry.insert(END, "1") station_entry.place(x=570, y=397) id_entry = Entry(window, width=20, borderwidth=0, background = "black", foreground="#1DB954", insertbackground ="#1DB954", font = (self.__font_name, 22)) id_entry.insert(END, str(random.randint(1, 11111111))) id_entry.place(x=295, y=247) line_entry = Entry(window, width=14, borderwidth=0, background = "black", foreground="#1DB954", insertbackground ="#1DB954", font = (self.__font_name, 22)) line_entry.insert(END, "14") line_entry.place(x=484, y=323) finish_button = tkinter.Button(window, image =finish_img, activebackground=GUI.__GREEN, borderwidth=0, background = GUI.__GREEN, command=lambda: self.__set_up_data(id_entry, station_entry, line_entry, window)) finish_button.place(x=299, y=478) window.mainloop() def __set_up_data(self, id_entry, station_entry, line_entry, window): """ checks that all the values given match the expected (all of them are numbers) after that stores them as part of the class variables and and closes the given window in case if the given values don't match the expectation then a new window will be shown saying that the values must be numbers. :param id_entry: Entry :param station_entry: Entry :param line_entry: Entry :param window: Tk :return: None """ try: self.__id = int(id_entry.get()) self.__line = int(line_entry.get()) self.__station = int(station_entry.get()) window.destroy() except: error_window = Tk() error_window.geometry("200x80") error_window.iconbitmap(r'Images bus\icon.ico') # put stuff to icon error_window.title("Error") error_window.resizable(OFF, OFF) error_window.configure(bg="red") error_label = Label(error_window, text="Error\n\nValues must be numbers") error_label.configure(bg="red") error_label.place(x=20, y=20)