class GUI: runModeMenuItems = { RUN_MODE_MONITOR: 'Monitor', } def __init__(self, master, sample): self.master = master self.sample = sample self.master.title('Sample positioner') self.createWidgets(self.master) self.blank_parameters() self.putBanner() def callback(self, cb): self._callback = cb def do_callback(self, context, *args): if hasattr(self, '_callback'): self._callback(context, *args) def close(self): for (w, r, c) in (self.wMCStatusDisplay, ): w.close() def createWidgets(self, master): master.grid_columnconfigure(0, weight=0, minsize=200) master.grid_columnconfigure(1, weight=1, minsize=700) master.grid_rowconfigure(0, weight=1, minsize=575) master.grid_rowconfigure(1, weight=0, minsize=25) self.populateMenu(master) row = 0 col = 0 w = XScroll(master) w.grid(row=row, column=col, sticky=NSEW) self.populateDisplayPanel(w.interior) col += 1 w = Frame(master) w.grid(row=row, column=col, sticky=NSEW) self.populatePlotPanel(w) row += 1 col = 0 w = Frame(master) w.grid(row=row, column=col, columnspan=2, sticky=NSEW) self.populateStatusFrame(w) def populateMenu(self, master): ### Main Menu self.mainmenu = Menu(master) self.mainmenu.config(borderwidth=1) master.config(menu=self.mainmenu) self.filemenu = Menu(self.mainmenu) self.filemenu.config(tearoff=0) self.mainmenu.add_cascade(label='File', menu=self.filemenu, underline=0) #self.settingsmenu = Menu (self.mainmenu) #self.settingsmenu.config (tearoff = 0) #self.mainmenu.add_cascade ( #label = 'Settings', menu = self.settingsmenu, underline = 0) self.toolsmenu = Menu(self.mainmenu) self.toolsmenu.config(tearoff=0) self.mainmenu.add_cascade(label='Tools', menu=self.toolsmenu, underline=0) # ++++ Populating file menu ++++ menu_items = [ \ ('Connect' , self.wConnectDeviceCB), ('Hide' , self.wHideCB) \ ] for (l, c) in menu_items: self.filemenu.add_command(label=l, command=c) # ++++ Populating settings menu ++++ #menu_items = [ \ #('Pitch' , self.wPitchSettingCB) \ #] #for (l, c) in menu_items: #self.settingsmenu.add_command (label = l, command = c) # ++++ Populating tools menu ++++ menu_items = [ \ ('Reset' , self.wResetDeviceCB ), ('Move absolute' , self.wMoveAbsoluteCB), ('Move relative' , self.wMoveRelativeCB), ('Stop' , self.wStopDeviceCB ) \ ] for (l, c) in menu_items: self.toolsmenu.add_command(label=l, command=c) def populateDisplayPanel(self, master): master.grid_columnconfigure(0, weight=1, minsize=230) row = 0 col = 0 w = Frame(master) w.grid(row=row, column=col, sticky=NSEW) self.wMCStatusDisplay = (GUI_MCStatusDisplay(w), row, col) row += 1 w = Frame(master) w.grid(row=row, column=col, sticky=NSEW) self.populateControlFrame(w) def populateControlFrame(self, master): master.grid_columnconfigure(0, weight=1) row = 0 col = 0 w = LabelFrame(master, text='Control') w.grid(row=row, column=col, sticky=NSEW, padx=5, pady=5) self.populateControlFrameWidgets(w) def populateControlFrameWidgets(self, master): master.grid_columnconfigure(0, weight=1) master.grid_columnconfigure(1, weight=1) row = 0 col = 0 w = Label(master, text="Control mode: ") w.grid(row=row, column=col, sticky=NSEW) col += 1 var = self.runMode = StringVar() options = self.runModeMenuItems.values() w = self.wRunMode = OptionMenu(master, var, *options, command=self.wRunModeCB) w.config(anchor=W) w.grid(row=row, column=col, sticky=NSEW) row += 1 col = 0 w = self.wStart = Button(master, text='Start', command=self.wStartCB) w.grid(row=row, column=col, sticky=NSEW) col += 1 w = self.wFinish = Button(master, text='Finish', state=DISABLED, command=self.wFinishCB) w.grid(row=row, column=col, sticky=NSEW) # ++++++++++++++++++++++++++++++++++++++++++++++++++ def populatePlotPanel(self, master): master.grid_rowconfigure(0, weight=1) master.grid_columnconfigure(0, weight=1) w = self.wPlots = XTab(master) w.grid(row=0, column=0, sticky=NSEW) def newPlot(self, name): return Plot2D.Plot2D(self.wPlots.add(name)) def clearPlot(self): self.wPlots.clear() self.putBanner() # ++++++++++++++++++++++++++++++++++++++++++++++++++ def populateStatusFrame(self, master): master.grid_columnconfigure(0, weight=1) #master.grid_rowconfigure (0, weight = 1) row = 0 col = 0 w = self.wStatus = Label(master, text='...', anchor=W, width=10) w.grid(row=row, column=col, sticky=NSEW) def set_status(self, text): lt = localtime(systime()) time_stamp = (str('%02d' % lt.tm_hour) + ':' + str('%02d' % lt.tm_min) + ':' + str('%02d' % lt.tm_sec)) text = '<' + time_stamp + ':XMC> ' + text print text old_text = self.wStatus['text'] new_text = text + ' . ' + old_text new_text = new_text[:1024] self.wStatus['text'] = new_text # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def setConnectionStatus(self, status): if status == DEVICE_CONNECTING: self.filemenu.entryconfig(0, label='Connecting', state=DISABLED, command=None) elif status == DEVICE_CONNECTED: self.filemenu.entryconfig(0, label='Disconnect', state=NORMAL, command=self.wDisconnctDeviceCB) self.set_status('Sample positioner connected') elif status == DEVICE_DISCONNECTING: self.filemenu.entryconfig(0, label='Disconnecting', state=DISABLED, command=None) elif status == DEVICE_DISCONNECTED: self.filemenu.entryconfig(0, label='Connect', state=NORMAL, command=self.wConnectDeviceCB) self.wMCStatusDisplay[0].blank_parameters() self.set_status('Sample positioner disconnected') elif status == DEVICE_NOT_FOUND: self.filemenu.entryconfig(0, label='Connect', state=NORMAL, command=self.wConnectDeviceCB) self.wMCStatusDisplay[0].blank_parameters() self.set_status('Sample positioner not found') else: raise ValueError(status) def wHideCB(self): self.master.withdraw() def wConnectDeviceCB(self): self.do_callback(CONNECT_DEVICE) def wDisconnctDeviceCB(self): self.do_callback(DISCONNECT_DEVICE) # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def wStartCB(self): self.do_callback(START_RUN, self.getRunMode()) def wFinishCB(self): self.do_callback(FINISH_RUN) def setRunControlStatus(self, status): if status == RUN_STARTING: self.wRunMode.config(state=DISABLED) self.wStart.config(text='Starting', state=DISABLED) self.wFinish.config(text='Finish', state=DISABLED) elif status == RUN_STARTED: self.wRunMode.config(state=DISABLED) self.wStart.config(text='Started', state=DISABLED) self.wFinish.config(text='Finish', state=NORMAL) elif status == RUN_FINISHING: self.wRunMode.config(state=DISABLED) self.wStart.config(text='Started', state=DISABLED) self.wFinish.config(text='Finishing', state=DISABLED) elif status == RUN_FINISHED: self.wRunMode.config(state=NORMAL) self.wStart.config(text='Start', state=NORMAL) self.wFinish.config(text='Finish', state=DISABLED) def wRunModeCB(self, *args): self.do_callback(RUN_MODE, self.getRunMode()) def getRunMode(self): runModes = {v: k for (k, v) in self.runModeMenuItems.items()} return runModes.get(self.runMode.get()) def setRunMode(self, mode): self.runMode.set(self.runModeMenuItems.get(mode)) if mode == RUN_MODE_MONITOR: pass else: raise ValueError(mode) def wPitchSettingCB(self): self.do_callback(OPEN_DIALOG, PITCH_SETTING_DIALOG) def wResetDeviceCB(self): self.do_callback(RESET_DEVICE) def wMoveAbsoluteCB(self): self.do_callback(OPEN_DIALOG, MOVE_ABSOLUTE_DIALOG) def wMoveRelativeCB(self): self.do_callback(OPEN_DIALOG, MOVE_RELATIVE_DIALOG) def wStopDeviceCB(self): self.do_callback(STOP_DEVICE) def setMCStatusDisplay(self, state, position, remainingDistance): (w, row, col) = self.wMCStatusDisplay w.setValues(state, position, remainingDistance) def setMCProgressBarDisplay(self, position): (w, row, col) = self.wMCStatusDisplay w.setBar(position) def setStatusJammed(self): (w, row, col) = self.wMCStatusDisplay w.setStatusJammed() def setMCProgressBarMin(self, position): (w, row, col) = self.wMCStatusDisplay w.setBarMin(position) def setMCProgressBarMax(self, position): (w, row, col) = self.wMCStatusDisplay w.setBarMax(position) def blank_parameters(self): self.wMCStatusDisplay[0].blank_parameters() def putBanner(self): w = GUI_Banner(self.wPlots.add('Welcome')) w.grid(row=0, column=0, sticky=NSEW)
class MainApp(object): """ The MainApp based on TKinter Attributes ---------- root : Tk The Tk object dbfdata : dictionary The current dbf data menubar : Menu The menu bar attibmenu : Menu The attribute menu """ def __init__(self): self.root = Tk() self.root.geometry("300x250") self.root.title("Shape file Reader") self.createMenu() self.root.mainloop() def createMenu(self): """ Creates GUI components and register events """ self.menubar = Menu(self.root) self.dbfdata = None filemenu = Menu(self.menubar, tearoff=0) filemenu.add_command(label="Open", command=self.__openShpfile) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.root.quit) self.menubar.add_cascade(label="File", menu=filemenu) self.attibmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Attibutes", menu=self.attibmenu,state='disabled') #Sagar Jha self.menubar.add_cascade(label="Simulator",command=self.__simulate) #Added Simulator self.root.config(menu=self.menubar) def __simulate(self): """ This function will create object of SimulatorExperimence """ self.Sim = SimulatorExperimence() ## Test to check object type ## print(type(self.Sim)) self.Sim.doTest() def __openShpfile(self): """ Open a shapefile and read in the contents, pop up the attribute menu with the attributes of the shapefile """ print "open shape file!" directory="C:/Users/sjha1/Documents/GitHub/Simulator_GUI/Python-Sample/data/states/48States.shp" #tkFileDialog.askopenfilename(filetypes=[("SHAPE_FILE","*.shp")]) print directory if directory == "": return self.shapes, self.shp_type, self.bbox = shp_reader.read_shp(directory) #read corresponding dbf data dbfFile = dbf.DbfLoader(directory[:-3] + "dbf") t = dbfFile.table2list() varNames = dbfFile.get_field_names() variables = {} for variable in varNames: variables[variable] = [record[varNames.index(variable)] for record in t] if self.dbfdata!=None: self.attibmenu.delete(0, len(self.dbfdata)-1) #add attributes into menu for key in variables.keys(): self.__addAttribute(key) self.dbfdata = variables self.menubar.entryconfig(2, state=Tkconstants.NORMAL) self.__updateCanvas("STATE_NAME") def __addAttribute(self,attributeName): """ Add an attribute to the menu """ self.attibmenu.add_command(label=attributeName, command=lambda i=attributeName:self.__updateCanvas(i)) def __updateCanvas(self, attributeName): """ Updates the canvas and showing statistical information """ print "update Canvas "+attributeName data_list=self.dbfdata[attributeName] print "attribute values: ", data_list try: n, min_max, mean, var, skew, kurt = stats.describe(data_list) print "============================" print "attribute statistics\n" print("Number of units: {0:d}".format(n)) print("Minimum: {0:8.6f} Maximum: {1:8.6f}".format(min_max[0], min_max[1])) print("Mean: {0:8.6f}".format(mean)) print("Standard deviation: {0:8.6f}".format(math.sqrt(var))) print("Skew : {0:8.6f}".format(skew)) print("Kurtosis: {0:8.6f}".format(kurt)) print "\n============================" high=max(data_list) low=min(data_list) dif=float(high-low) for i in range(len(data_list)): #map colors to 0-200, 0-200, 0-200 (avoid pure white for display purpose) index=float(data_list[i]-low)/dif*200 index=str(hex(200-int(index)).split('x')[1]) color="#"+index+index+index self.shapes[i].color=color except: print "non-numeric attribute" self.canvas=MainCanvas(self.shapes,self.bbox,self.shp_type,self.root,attributeName,data_list)
class SerialTerm(Tk): def __init__(self, serial_queue, serial_thread): Tk.__init__(self) self.title("Foss SerialTerminal for Multi") self.serial_queue = serial_queue self.serial_thread = serial_thread menu_bar = Menu(self) file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="Save as...") file_menu.add_command(label="Exit", command=self.quit) menu_bar.add_cascade(label="File", menu=file_menu) self.parser_menu = Menu(menu_bar, tearoff=0) self.serial_parser_enabled = IntVar() self.serial_parser_enabled.set(1) self.parser_menu.add_checkbutton( label="Serial parser enabled", variable=self.serial_parser_enabled ) self.parser_menu.add_command(label="Edit parser rules", command=self.open_conditionals_editor) menu_bar.add_cascade(label="Parser", menu=self.parser_menu) self.config(menu=menu_bar) main_frame = Frame(self) output_frame = Frame(main_frame) input_frame = Frame(main_frame) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) main_frame.grid(column=0, row=0, padx=3, pady=3, sticky=(N, W, E, S)) main_frame.grid_columnconfigure(0, weight=1) main_frame.grid_rowconfigure(0, weight=1) output_text_vertical_scrollbar = Scrollbar(output_frame, orient=VERTICAL) output_text_horizontal_scrollbar = Scrollbar(output_frame, orient=HORIZONTAL) self.output_text = Text( output_frame, wrap=NONE, xscrollcommand=output_text_horizontal_scrollbar.set, yscrollcommand=output_text_vertical_scrollbar.set ) self.output_text.configure(bg="white", state="disabled") self.output_text.grid(column=0, row=0, sticky=(N, S, E, W)) output_text_vertical_scrollbar.grid(column=1, row=0, sticky=(N, S)) output_text_vertical_scrollbar.config(command=self.output_text.yview) output_text_horizontal_scrollbar.grid(column=0, row=1, sticky=(E, W)) output_text_horizontal_scrollbar.config(command=self.output_text.xview) output_frame.grid(column=0, row=0, sticky=(N, S, E, W)) output_frame.grid_columnconfigure(0, weight=1) output_frame.grid_rowconfigure(0, weight=1) self.input_string = StringVar() input_entry = Entry(input_frame, textvariable=self.input_string) input_entry.grid(column=0, row=0, sticky=(E, W)) line_end_selection_items = ["CR&NL", "NL", "CR", "None"] self.line_end_selection = Combobox( input_frame, values=line_end_selection_items, state="readonly", width=len(max(line_end_selection_items, key=len)) ) self.line_end_selection.current(newindex=0) self.line_end_selection.grid(column=1, row=0) serial_port_names = ["Port"] serial_port_names.extend([s.name for s in serial.tools.list_ports.comports()]) self.port_name_selection = Combobox( input_frame, values = serial_port_names, state="readonly", width=len(max(serial_port_names, key=len)) ) self.port_name_selection.current(newindex=0) self.port_name_selection_index = 0 self.port_name_selection.grid(column=2, row=0) baudrates = [ "300 baud", "1200 baud", "2400 baud", "4800 baud", "9600 baud", "19200 baud", "38400 baud", "57600 baud", "74880 baud", "115200 baud", "230400 baud", "250000 baud" ] self.baudrate_selection = Combobox( input_frame, values = baudrates, state="readonly", width=len(max(baudrates, key=len)) ) self.baudrate_selection.current(newindex=9) self.baudrate_selection.grid(column=3, row=0) input_frame.grid(column=0, row=1, sticky=(E, W)) input_frame.grid_columnconfigure(0, weight=1) self.port_name_selection.bind("<<ComboboxSelected>>", self.port_name_selected) self.baudrate_selection.bind("<<ComboboxSelected>>", self.baudrate_selected) self.after(100, self.serial_tick) # TODO Load from pickle file. self.conditionals = [ ["Enabled", "line.startswith(\"Hello\")", "Python", "print 'Fooobaaaaar. Jibb.'"], ["Enabled", "line.startswith(\"Foo\")", "Debugger", "halt\nreset"], ] self.counter = 0 def open_conditionals_editor(self): self.conditionals_editor = Toplevel(master=self) self.parser_menu.entryconfig("Edit parser rules", state="disabled") ConditionalsEditor(self.conditionals_editor, self.conditionals, self.closing_conditionals_editor) def closing_conditionals_editor(self): self.parser_menu.entryconfig("Edit parser rules", state="normal") def update_output_text(self, line): self.output_text.configure(state="normal") self.output_text.insert(END, line) self.output_text.configure(state="disabled") self.output_text.see(END) def evaluate_conditionals(self, line): if self.serial_parser_enabled.get() == 1: for condition in self.conditionals: if condition[0] == "Enabled": if eval(condition[1]): if condition[2] == "Python": exec(condition[3], locals()) elif condition[2] == "Debugger": print "Send to debugger: %s"%condition[3] def serial_tick(self): while True: try: line = self.serial_queue.get_nowait() self.update_output_text(line) self.evaluate_conditionals(line) except Queue.Empty: break self.after(100, self.serial_tick) def port_name_selected(self, event): port_name = event.widget.selection_get() if port_name == "Port": event.widget.current(newindex=self.port_name_selection_index) return self.port_name_selection_index = event.widget.current() self.serial_thread.set_port(port_name) def baudrate_selected(self, event): self.serial_thread.set_baudrate(event.widget.selection_get())
class App(Frame): def __init__(self, master=None): self.master = master Frame.__init__(self, master, relief=SUNKEN, bd=2) self.gcode = [] self.slicing = False self.printing = False self.connected = False self.monitorTemp = False self.paused = False self.sdpresent = False self.sdlisting = False self.sdchecking = False self.sdprinting = False self.sdpaused = False self.sduploading = False self.sdbytes = 0 self.sdmaxbytes = 0 self.insidelisting = False self.readingFirmware = False self.sdfiles = [] self.bedtemp = float(0) self.bedtarget = float(0) self.exttemp = float(0) self.exttarget = float(0) self.acceleration = 0 self.m114count = 0 self.speedcount = 0 self.location = [0, 0, 0, 0] self.pausePoint = [0, 0, 0, 0] self.percent = 0.0 self.ets = "??" self.gcodeInfo = None self.GCodeFile = None self.StlFile = None self.Profile = None self.printStartLine = 0 self.startTime = 0 self.endTime = 0 self.elapsedTime = 0 self.FanSpeed = 0 self.FeedMultiply = 100 self.ExtrudeMultiply = 100 self.timingReport = None self.filamentReport = None self.measurementsReport = None self.macroButtons = None self.rpt1re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *B:([0-9\.]+)") self.rpt2re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *W:.*") self.locrptre = re.compile("^X:([0-9\.\-]+)Y:([0-9\.\-]+)Z:([0-9\.\-]+)E:([0-9\.\-]+) *Count") self.speedrptre = re.compile("Fan speed:([0-9]+) Feed Multiply:([0-9]+) Extrude Multiply:([0-9]+)") self.sdre = re.compile("SD printing byte *([0-9]+) *\/ *([0-9]+)") self.printer = printcore() self.settings = Settings() self.settings.cmdFolder = cmd_folder self.logger = Logger(self) if self.settings.speedcommand is not None: allow_while_printing.append(self.settings.speedcommand) self.acceleration = self.settings.acceleration self.dataLoggers = {} for d in DLLIST: self.dataLoggers[d] = DataLogger(self, d) self.skeinforge = Skeinforge(self.settings) self.slic3r = Slic3r(self.settings) self.httpServer = RepRapServer(self, self.printer, self.settings, self.logger, self.settings.port) self.menubar = Menu(self) self.filemenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="File", menu=self.filemenu) self.filemenu.add_command(label="Slice", command=self.openSTLFile) self.filemenu.add_command(label="Load GCode", command=self.openGCodeFile) self.slicemenuindex = self.filemenu.index("Slice") self.loadgcodemenuindex = self.filemenu.index("Load GCode") self.filemenu.add_separator() self.filemenu.add_command(label="Exit", command=self.quitApp) self.editmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Edit", menu=self.editmenu) self.editmenu.add_command(label="Settings", command=self.editSettings) self.editmenu.add_command(label="Firmware Settings", command=self.FirmwareSettings) self.editmenu.add_separator() self.editmenu.add_command(label=GCODE_MENU_TEXT, command=self.doGEdit, state=DISABLED) self.slicermenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Slicer", menu=self.slicermenu) self.rbSlicer = StringVar() self.slicermenu.add_radiobutton( label="Skeinforge", command=self.selSlicer, value=SKEINFORGE, variable=self.rbSlicer ) self.slicermenu.add_command(label="Settings", command=self.skeinforgeSettings) self.slicermenu.add_command(label="Choose Profile", command=self.chooseSFProfile) self.SFprofileindex = self.slicermenu.index("Choose Profile") self.setSFProfileMenuText() self.slicermenu.add_command(label="Alterations", command=self.doEditAlterations) self.slicermenu.add_separator() self.slicermenu.add_radiobutton(label="Slic3r", command=self.selSlicer, value=SLIC3R, variable=self.rbSlicer) self.slicermenu.add_command(label="Settings", command=self.slic3rSettings) self.slicermenu.add_command(label="Choose Profile", command=self.chooseS3Profile) self.S3profileindex = self.slicermenu.index("Choose Profile") self.setS3ProfileMenuText() self.rbSlicer.set(self.settings.slicer) self.macromenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Macros", menu=self.macromenu) self.macromenu.add_command(label="New", command=self.doNewMacro) self.macromenu.add_command(label="Edit", command=self.doEditMacro) self.macromenu.add_command(label="Delete", command=self.doDelMacro) self.macromenu.add_separator() self.cbShowMacroButtons = BooleanVar() self.cbShowMacroButtons.set(self.settings.showmacrobuttons) self.macromenu.add_checkbutton( label="Show Macro Buttons", command=self.doShowButtons, onvalue=True, offvalue=False, variable=self.cbShowMacroButtons, ) self.macromenu.add_separator() self.runmacromenu = Menu(self.macromenu, tearoff=0) self.loadMacros() self.macromenu.add_cascade(label="Run", menu=self.runmacromenu) self.reportmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="View", menu=self.reportmenu) self.cbShowPrevious = BooleanVar() self.cbShowPrevious.set(self.settings.showprevious) self.reportmenu.add_checkbutton( label="Show Previous Layer", command=self.toggleShowPrevious, onvalue=True, offvalue=False, variable=self.cbShowPrevious, ) self.cbShowMoves = BooleanVar() self.cbShowMoves.set(self.settings.showmoves) self.reportmenu.add_checkbutton( label="Show Non-extrusion Moves", command=self.toggleShowMoves, onvalue=True, offvalue=False, variable=self.cbShowMoves, ) self.reportmenu.add_separator() self.reportmenu.add_command(label="Show Hours of Usage", command=self.doDataLogReport) self.reportmenu.add_command(label="Reset Hours of Usage", command=self.doDataLogReset) self.reportmenu.add_separator() self.reportmenu.add_command(label="Layer by Layer Timing", command=self.doTimingReport) self.reportmenu.add_command(label="Layer by Layer Filament Usage", command=self.doFilamentReport) self.reportmenu.add_command(label="GCode Measurements", command=self.doMeasurementsReport) self.toolsmenu = Menu(self.menubar, tearoff=0) n = 0 if self.settings.platercmd is not None: n += 1 self.toolsmenu.add_command(label="Plater", command=self.doPlater) if self.settings.gcodeviewcmd is not None: n += 1 self.toolsmenu.add_command(label="GCode Viewer", command=self.doGCodeView) if self.settings.stlviewcmd is not None: n += 1 self.toolsmenu.add_command(label="STL Viewer", command=self.doSTLView) if self.settings.openscadcmd is not None: n += 1 self.toolsmenu.add_command(label="OpenSCAD", command=self.doOpenSCAD) if n > 0: self.menubar.add_cascade(label="Tools", menu=self.toolsmenu) try: self.master.config(menu=self.menubar) except AttributeError: self.master.tk.call(master, "config", "-menu", self.menubar) self.toolbar = ToolBar(self, self.printer, self.settings, self.logger) self.toolbar.grid(row=1, column=1, columnspan=4, sticky=W) self.ctl = MoveControl(self, self.printer, self.settings, self.logger) self.ctl.grid(row=2, column=1, rowspan=3, sticky=N) self.extr = Extruder(self, self.printer, self.settings, self.logger) self.extr.grid(row=2, column=2, rowspan=1, sticky=N + E + W) self.temps = Temperatures(self, self.printer, self.settings, self.logger) self.temps.grid(row=3, column=2, rowspan=2, sticky=N + E + W) self.gc = GcFrame(self, None, [], self.settings, self.logger) self.gc.grid(row=2, column=3, rowspan=3, sticky=N) self.statline = Status(self, self.printer, self.settings, self.logger) self.statline.grid(row=5, column=1, columnspan=4, sticky=E + W) self.logger.grid(row=2, column=4, rowspan=2, sticky=N + E + W) self.sendgcode = SendGCode(self, self.printer, self.settings, self.logger) self.sendgcode.grid(row=4, column=4, sticky=N + E + W) self.printer.errorcb = self.errorcb self.printer.sendcb = self.sendcb self.printer.recvcb = self.recvcb self.sd = SDCard(self, self.printer, self.settings, self.logger) self.firmware = FirmwareParms(self, self.printer, self.settings, self.logger) self.bind(MWM_FIRMWARECOMPLETE, self.firmwareReportComplete) self.bind(MWM_SLICERCOMPLETE, self.sliceComplete) self.bind(MWM_GCODELOADCOMPLETE, self.loadgcodeFinished) self.bind(MWM_GEDITMEASURECOMPLETE, self.geditMeasureComplete) self.bind(MWM_REQUESTPOSITIONREPORT, self.requestPosition) self.doShowButtons() def doStopAll(self): self.toolbar.doPause() self.temps.doOffBed() self.temps.doOffExt() def requestPosition(self, *arg): self.m114count += 1 self.printer.send_now("M400") # finish all moves self.printer.send_now("M114") def doShowButtons(self): self.settings.showmacrobuttons = self.cbShowMacroButtons.get() == 1 self.settings.setModified() if self.settings.showmacrobuttons: self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger) else: if self.macroButtons: self.macroButtons.close() self.macroButtons = None def toggleShowPrevious(self): self.settings.showprevious = self.cbShowPrevious.get() == 1 self.settings.setModified() self.gc.drawCanvas() def toggleShowMoves(self): self.settings.showmoves = self.cbShowMoves.get() == 1 self.settings.setModified() self.gc.drawCanvas() def selSlicer(self): self.settings.slicer = self.rbSlicer.get() self.settings.setModified() self.toolbar.setSliceText() def macroButtonClose(self): self.settings.showmacrobuttons = False self.settings.setModified() self.cbShowMacroButtons.set(False) def firmwareReportComplete(self, *arg): p = self.firmware.reportComplete() if p is not None: self.acceleration = p["m204_s"].getFlash() print "Retrieved acc value of ", self.acceleration def openSTLFile(self): if self.printing: self.logger.logMsg("Cannot open a new file while printing") return if self.StlFile is None: fn = askopenfilename( filetypes=[("STL files", "*.stl"), ("G Code files", "*.gcode")], initialdir=self.settings.lastdirectory ) else: fn = askopenfilename( filetypes=[("STL files", "*.stl"), ("G Code files", "*.gcode")], initialdir=self.settings.lastdirectory, initialfile=os.path.basename(self.StlFile), ) if fn: self.settings.lastdirectory = os.path.dirname(os.path.abspath(fn)) self.settings.setModified() if fn.lower().endswith(".gcode"): self.StlFile = None self.loadgcode(fn) elif fn.lower().endswith(".stl"): self.StlFile = fn self.doSlice(fn) else: self.logger.logMsg("Invalid file type") def openGCodeFile(self): if self.printing: self.logger.logMsg("Cannot open a new file while printing") return fn = askopenfilename(filetypes=[("G Code files", "*.gcode")], initialdir=self.settings.lastdirectory) if fn: self.settings.lastdirectory = os.path.dirname(os.path.abspath(fn)) self.settings.setModified() if fn.lower().endswith(".gcode"): self.StlFile = None self.loadgcode(fn) else: self.logger.logMsg("Invalid file type") else: self.toolbar.clearCancelMode() def loadgcode(self, fn): self.GCodeFile = fn self.gcodeloadSuccess = True self.toolbar.setLoading(True) self.loader = threading.Thread(target=self.loadgcodeThread) self.loader.daemon = True self.loader.start() def loadgcodeFinished(self, *arg): self.toolbar.setLoading(False) if self.gcodeloadSuccess: self.showMetrics() def loadgcodeThread(self): try: self.gcode = [] l = list(open(self.GCodeFile)) for s in l: self.gcode.append(s.rstrip()) self.logger.logMsg("read %d lines from %s" % (len(self.gcode), os.path.basename(self.GCodeFile))) except: self.logger.logMsg("Problem reading gcode from %s" % self.GCodeFile) self.gcode = [] self.GCodeFile = None if len(self.gcode) != 0: self.logger.logMsg("Processing...") self.gc.loadFile(self.GCodeFile, self.gcode) self.printStartLine = self.gc.getPrintStartLine() self.gcodeInfo = GCode(self.gcode) self.logger.logMsg("Measuring...") self.gcodeInfo.measure(self.acceleration) self.estEta = self.gcodeInfo.totalduration self.timeLayers = self.gcodeInfo.layerdurations else: self.gcodeloadSuccess = False self.event_generate(MWM_GCODELOADCOMPLETE) def replace(self, s, slicer): if slicer == SLIC3R: d = os.path.expandvars(os.path.expanduser(self.settings.s3profiledir)) profile = os.path.join(d, self.slic3r.getProfile() + ".ini") else: profile = self.skeinforge.getProfile() d = {} d["%starttime%"] = time.strftime("%H:%M:%S", time.localtime(self.startTime)) d["%endtime%"] = time.strftime("%H:%M:%S", time.localtime(self.endTime)) d["%elapsed%"] = formatElapsed(self.elapsedTime) d["%profile%"] = profile d["%slicer%"] = self.settings.slicer if self.StlFile is not None: d["%stlbase%"] = os.path.basename(self.StlFile) d["%stl%"] = self.StlFile else: d["%stlbase%"] = "" d["%stl%"] = "" if self.GCodeFile is not None: d["%gcodebase%"] = os.path.basename(self.GCodeFile) d["%gcode%"] = self.GCodeFile else: d["%gcodebase%"] = "" d["%gcode%"] = "" for t in d.keys(): if d[t] is not None: s = s.replace(t, d[t]) s = s.replace('""', "") return s def showMetrics(self): if len(self.gcode) != 0: self.paused = False self.toolbar.initializeToolbar() self.toolbar.checkAllowPrint() self.allowGEdit() self.logger.logMsg( "Width: %f mm (%f -> %f)" % (self.gcodeInfo.width, self.gcodeInfo.xmin, self.gcodeInfo.xmax) ) self.logger.logMsg( "Depth: %f mm (%f -> %f)" % (self.gcodeInfo.depth, self.gcodeInfo.ymin, self.gcodeInfo.ymax) ) self.logger.logMsg( "Height: is %f mm (%f -> %f)" % (self.gcodeInfo.height, self.gcodeInfo.zmin, self.gcodeInfo.zmax) ) self.logger.logMsg("Total extrusion length: %f mm" % self.gcodeInfo.filament_length()) self.logger.logMsg("Estimated print time: %s" % formatElapsed(self.estEta)) def calcEta(self, line, timeThusFar): foundLayer = False for i in range(len(self.timeLayers)): if self.timeLayers[i][0] > line: foundLayer = True break if not foundLayer: return 0 currentLayer = i - 1 if currentLayer < 0: return 0 totalInLayer = self.timeLayers[i][0] - self.timeLayers[currentLayer][0] printedInLayer = line - self.timeLayers[currentLayer][0] pct = printedInLayer / float(totalInLayer) thisLayerTime = (self.timeLayers[currentLayer][1]) * pct ratio = (self.timeLayers[currentLayer][2] - self.timeLayers[currentLayer][1] + thisLayerTime) / float( timeThusFar ) ne = self.estEta / float(ratio) return ne - timeThusFar def doTimingReport(self): if not self.printing: self.logger.logMsg("Only available while printing") return self.timingReport = TimingReport(self, self.printer, self.settings, self.logger) def closeTimingReport(self): if self.timingReport is not None: self.timingReport.cleanup() self.timingReport.destroy() self.timingReport = None def doMeasurementsReport(self): if not self.gcodeInfo: self.logger.logMsg("Only available when GCode loaded") return self.measurementsReport = MeasurementsReport(self, self.printer, self.settings, self.logger) def closeMeasurementsReport(self): if self.measurementsReport is not None: self.measurementsReport.destroy() self.measurementsReport = None def doFilamentReport(self): if not self.gcodeInfo: self.logger.logMsg("Only available when GCode loaded") return if len(self.gcodeInfo.filLayers) == 0: self.logger.logMsg("No filament usage in this gcode") return self.filamentReport = FilamentReport(self, self.printer, self.settings, self.logger) def closeFilamentReport(self): if self.filamentReport is not None: self.filamentReport.destroy() self.filamentReport = None def closeAllReports(self): self.closeTimingReport() self.closeFilamentReport() self.closeMeasurementsReport() def doPlater(self): s = self.replace(self.settings.platercmd, self.settings.slicer) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def doGCodeView(self): s = self.replace(self.settings.gcodeviewcmd, self.settings.slicer) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def doSTLView(self): s = self.replace(self.settings.stlviewcmd, self.settings.slicer) self.logger.logMsg(s) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def doOpenSCAD(self): s = self.replace(self.settings.openscadcmd, self.settings.slicer) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def doSlice(self, fn): self.paused = False self.toolbar.initializeToolbar() self.slicerfn = fn self.slicing = True self.slicerCancel = False self.toolbar.setCancelMode() if self.settings.slicer == SLIC3R: self.GCodeFile = fn.replace(".stl", ".gcode") cmd = self.replace(os.path.expandvars(os.path.expanduser(self.settings.s3cmd)), SLIC3R) else: self.GCodeFile = fn.replace(".stl", "_export.gcode") cmd = self.replace(os.path.expandvars(os.path.expanduser(self.settings.sfcmd)), SKEINFORGE) self.slicer = threading.Thread(target=self.slicerThread, args=(cmd,)) self.slicer.daemon = True self.slicer.start() def slicerThread(self, cmd): args = shlex.split(cmd) p = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) obuf = "" while not self.slicerCancel: o = p.stdout.read(1) if o == "": break if o == "\r" or o == "\n": self.logger.logMsg(obuf) obuf = "" elif ord(o) < 32: pass else: obuf += o if self.slicerCancel: p.kill() p.wait() self.event_generate(MWM_SLICERCOMPLETE) def sliceComplete(self, *arg): self.slicing = False self.toolbar.clearCancelMode() if self.slicerCancel: self.slicerCancel = False self.logger.logMsg("Slicing was cancelled") return self.logger.logMsg("Slicing has completed successfully") if os.path.exists(self.GCodeFile): self.loadgcode(self.GCodeFile) else: self.logger.logMsg("Unable to find slicer output file: %s" % self.GCodeFile) def allowGEdit(self): self.editmenu.entryconfig(self.editmenu.index(GCODE_MENU_TEXT), state=NORMAL) def allowSliceMenu(self, flag=True): s = NORMAL if not flag: s = DISABLED self.filemenu.entryconfig(self.slicemenuindex, state=s) def allowLoadGCodeMenu(self, flag=True): s = NORMAL if not flag: s = DISABLED self.filemenu.entryconfig(self.loadgcodemenuindex, state=s) def doGEdit(self): GEditor(self, self.gcode, None) def geditMeasureComplete(self, *arg): self.showMetrics() def gEditSave(self, newgcode, fn, editwindow): if fn == None: self.gcode = newgcode self.meas = threading.Thread(target=self.geditMeasureThread) self.meas.daemon = True self.meas.start() return False else: try: f = open(fn, "w") for l in newgcode: f.write(l + "\n") f.close() self.logger.logMsg("Alterations %s successfully saved" % fn) return True except: self.logger.logMsg("Unable to open %s for output" % fn) return False def geditMeasureThread(self): self.logger.logMsg("Processing...") self.gcodeInfo = GCode(self.gcode) self.logger.logMsg("Measuring...") self.gcodeInfo.measure(self.acceleration) self.estEta = self.gcodeInfo.totalduration self.timeLayers = self.gcodeInfo.layerdurations self.event_generate(MWM_GEDITMEASURECOMPLETE) def doSD(self): if not self.sd.isActive(): self.sd.start() def setToolbarSDPrint(self): self.toolbar.setSDPrint() def startUpload(self): self.sduploading = True self.toolbar.doPrint() def printerAvailable(self, silent=False, cmd="xx"): if not self.connected: if not silent: self.logger.logMsg("Unable to comply - printer not on-line") return False if (self.printing or self.sdprinting) and cmd.upper() not in allow_while_printing: if not silent: self.logger.logMsg("Unable to comply - currently printing") return False return True def printerConnected(self, flag): self.sendgcode.activate(flag) self.connected = flag if flag: self.firmware.start(True) def updateScreen(self): if self.printing: self.gc.updatePrintProgress(self.printer.queueindex) def errorcb(self, s): self.logger.logMsg(s.rstrip()) def sendcb(self, s): # self.logger.logMsg("Sent: %s" % s) pass def recvcb(self, s): if self.readingFirmware: if "M92" in s: X = self.parseG(s, "X") Y = self.parseG(s, "Y") Z = self.parseG(s, "Z") E = self.parseG(s, "E") self.firmware.m92(X, Y, Z, E) return elif "M201" in s: X = self.parseG(s, "X") Y = self.parseG(s, "Y") Z = self.parseG(s, "Z") E = self.parseG(s, "E") self.firmware.m201(X, Y, Z, E) return elif "M203" in s: X = self.parseG(s, "X") Y = self.parseG(s, "Y") Z = self.parseG(s, "Z") E = self.parseG(s, "E") self.firmware.m203(X, Y, Z, E) return elif "M204" in s: S = self.parseG(s, "S") T = self.parseG(s, "T") self.firmware.m204(S, T) return elif "M205" in s: S = self.parseG(s, "S") T = self.parseG(s, "T") B = self.parseG(s, "B") X = self.parseG(s, "X") Z = self.parseG(s, "Z") E = self.parseG(s, "E") self.firmware.m205(S, T, B, X, Z, E) return elif "M206" in s: X = self.parseG(s, "X") Y = self.parseG(s, "Y") Z = self.parseG(s, "Z") self.firmware.m206(X, Y, Z) return elif "M301" in s: P = self.parseG(s, "P") I = self.parseG(s, "I") D = self.parseG(s, "D") self.firmware.m301(P, I, D) return elif ( ("Steps per unit" in s) or ("Acceleration:" in s) or ("Maximum Acceleration" in s) or ("Maximum feedrates" in s) or ("Advanced variables" in s) or ("Home offset" in s) or ("PID settings" in s) or ("Stored settings retreived" in s) ): return if self.sdchecking: if "SD card ok" in s: self.sdchecking = False self.sdpresent = True self.sd.sdCheckComplete(True) return elif "SD init fail" in s: self.sdchecking = False self.sdpresent = False self.sd.sdCheckComplete(False) return if self.sdlisting: if "Begin file list" in s: self.insidelisting = True self.sdfiles = [] return elif "End file list" in s: self.sdlisting = False self.insidelisting = False self.sd.sdListComplete(self.sdfiles) return else: if self.insidelisting: self.sdfiles.append(s.strip()) return if "SD printing byte" in s: m = self.sdre.search(s) t = m.groups() if len(t) != 2: return self.sdbytes = int(t[0]) self.sdmaxbytes = int(t[1]) return elif "Done printing file" in s: if self.sdprinting: self.sdprinting = False self.toolbar.clearSDPrint() m = self.speedrptre.search(s) if m: t = m.groups() if len(t) >= 3: if self.settings.forcefanspeed: ns = int(t[0]) if ns != self.FanSpeed: self.logger.logMsg("Asserting fan speed of %d" % self.FanSpeed) self.toolbar.forceFanSpeed(self.FanSpeed) else: self.FanSpeed = int(t[0]) self.FeedMultiply = int(t[1]) self.ExtrudeMultiply = int(t[2]) self.toolbar.syncSpeeds() if self.speedcount > 0: self.speedcount -= 1 return m = self.locrptre.search(s) if m: t = m.groups() if len(t) >= 4: self.location[XAxis] = float(t[0]) self.location[YAxis] = float(t[1]) self.location[ZAxis] = float(t[2]) self.location[EAxis] = float(t[3]) if self.m114count != 0: self.m114count -= 1 if self.m114count < 0: self.m114count = 0 return if s.startswith("ok"): return if s.startswith("echo:"): s = s[5:] m = self.rpt1re.search(s) if m: t = m.groups() if len(t) >= 1: self.exttemp = float(t[0]) if len(t) >= 2: self.bedtemp = float(t[1]) self.temps.updateTempDisplay(self.bedtemp, self.exttemp) m = self.rpt2re.search(s) if m: t = m.groups() if len(t) >= 1: self.exttemp = float(t[0]) self.temps.updateTempDisplay(self.bedtemp, self.exttemp) self.logger.logMsg(s.rstrip()) def parseG(self, s, v): l = s.split() for p in l: if p.startswith(v): try: return float(p[1:]) except: return None return None def editSettings(self): # TO DO pass def slic3rSettings(self): s = self.replace(self.settings.s3config, SLIC3R) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def skeinforgeSettings(self): s = self.replace(self.settings.sfconfig, SKEINFORGE) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) def chooseS3Profile(self): pl = self.slic3r.getProfileOptions() if len(pl) > 0: l = ListBoxChoice( clist=pl.keys(), master=self, title="Choose Slic3r Profile", message="Choose Slic3r profile" ) pn = l.returnValue() if pn: self.slic3r.setProfile(pn) self.setS3ProfileMenuText() self.toolbar.setSliceText() else: self.logger.logMsg("Unable to retrieve available slic3r profiles") def chooseSFProfile(self): pl = self.skeinforge.getProfileOptions() if len(pl) > 0: l = ListBoxChoice( clist=pl.keys(), master=self, title="Choose Skeinforge Profile", message="Choose Skeinforge profile" ) pn = l.returnValue() if pn: self.skeinforge.setProfile(pn) self.setSFProfileMenuText() self.toolbar.setSliceText() else: self.logger.logMsg("Unable to retrieve available skeinforge profiles") def setS3ProfileMenuText(self): self.slicermenu.entryconfig(self.S3profileindex, label="Choose Profile (%s)" % self.slic3r.getProfile()) def setSFProfileMenuText(self): self.slicermenu.entryconfig(self.SFprofileindex, label="Choose Profile (%s)" % self.skeinforge.getProfile()) def quitApp(self): self.cleanUp() self.master.quit() def cleanUp(self): if self.connected: self.printer.disconnect() if self.slicing: self.slicerCancel = True self.httpServer.close() self.statline.cleanUp() self.settings.cleanUp() def doEditMacro(self): idir = os.path.join(self.settings.cmdFolder, "macros") try: l = os.listdir(idir) except: self.logger.logMsg("Unable to get listing from macros directory: " + idir) return r = [] for f in sorted(l): if f.endswith(".macro"): r.append(f) l = ListBoxChoice(master=self, title="Macro Files", message="Choose a macro to edit", clist=r) fn = l.returnValue() if fn: try: fn = os.path.join(idir, fn) with open(fn) as f: text = f.read() self.macroEdit = MacroEdit(self, self.printer, self.settings, self.logger, fn, text) except: self.logger.logMsg("Unable to open %s for input" % fn) def doEditAlterations(self): idir = os.path.expandvars(os.path.expanduser(self.settings.sfalterationsdir)) try: l = os.listdir(idir) except: self.logger.logMsg("Unable to get listing from alterations directory: " + idir) return r = [] for f in sorted(l): if f.endswith(".gcode"): r.append(f) l = ListBoxChoice(master=self, title="Alteration Files", message="Choose an alteration file to edit", clist=r) fn = l.returnValue() if fn: try: fn = os.path.join(idir, fn) text = [line.strip() for line in open(fn)] GEditor(self, text, fn) except: self.logger.logMsg("Unable to open %s for input" % fn) def doNewMacro(self): self.macroEdit = MacroEdit(self, self.printer, self.settings, self.logger, None, "") def doDelMacro(self): idir = os.path.join(self.settings.cmdFolder, "macros") try: l = os.listdir(idir) except: self.logger.logMsg("Unable to get listing from macros directory: " + idir) return r = [] for f in sorted(l): if f.endswith(".macro"): r.append(f) l = ListBoxChoice(master=self, title="Macro Files", message="Choose a macro to delete", clist=r) fn = l.returnValue() if fn: if askyesno("Delete?", "Are you sure you want to delete this macro?", parent=self): try: os.unlink(os.path.join(idir, fn)) self.adjustMacroMenu(fn, True) if self.settings.getMacroList().delMacroByName(fn): self.settings.setModified() if self.settings.showmacrobuttons: self.macroButtons.close() self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger) except: self.logger.logMsg("Unable to delete %s" % fn) def macroEditSave(self, fn, text, btn, editwindow): if fn == None: idir = os.path.join(self.settings.cmdFolder, "macros") try: l = os.listdir(idir) except: self.logger.logMsg("Unable to get listing from macros directory: " + idir) return r = [] for f in sorted(l): if f.endswith(".macro"): r.append(f) l = ListBoxChoice( master=self, title="Macro Files", message="Choose a macro to overwrite", clist=r, newmessage="or enter new file name:", ) fn = l.returnValue() if fn: fn = os.path.join(idir, fn) if not fn.endswith(".macro"): fn += ".macro" if fn is None: return False try: f = open(fn, "w") f.write(text) f.close() self.settings.setModified() if btn != None: if not self.settings.getMacroList().addMacro(btn[0], btn[1], os.path.basename(fn), btn[2]): self.settings.getMacroList().setMacroByName(btn[0], btn[1], os.path.basename(fn), btn[2]) self.settings.setModified() if self.settings.showmacrobuttons: self.macroButtons.close() self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger) self.adjustMacroMenu(fn) self.logger.logMsg("Macro %s successfully saved" % fn) return True except: self.logger.logMsg("Unable to open %s for output" % fn) return False def macroEditExit(self, fn): pass def loadMacros(self): p = os.path.join(".", "macros") if not os.path.exists(p): os.makedirs(p) self.macroList = {} for filename in sorted(os.listdir(p)): if filename.endswith(".macro"): n = os.path.splitext(filename)[0] self.macroList[n] = 1 self.runmacromenu.add_command(label=n, command=lambda m=n: self.doMacro(m)) def adjustMacroMenu(self, fn, delete=False): mn = os.path.splitext(os.path.basename(fn))[0] if not delete: if mn in self.macroList: # nothing to be done here pass else: self.macroList[mn] = 1 self.runmacromenu.add_command(label=mn, command=lambda m=mn: self.doMacro(name=mn)) else: # delete the menu entry if mn in self.macroList: self.runmacromenu.delete(self.runmacromenu.index(mn)) del self.macroList[mn] else: # huh?? pass def doMacro(self, name=None, fname=None, silent=False): if name: if not silent: self.logger.logMsg("Invoking macro: %s" % name) n = os.path.join(self.settings.cmdFolder, "macros", name + ".macro") elif fname: if not silent: self.logger.logMsg("Invoking macro file: %s" % fname) n = os.path.join(self.settings.cmdFolder, "macros", fname) else: self.logger.logMsg("Error - must provide a macro name or filename") return try: l = list(open(n)) for s in l: sl = s.lower() if sl.startswith("@log "): self.logger.logMsg(self.replace(s[5:].strip(), self.settings.slicer)) elif sl.startswith("@sh "): s = self.replace(sl[4:], self.settings.slicer) args = shlex.split(os.path.expandvars(os.path.expanduser(s))) subprocess.Popen(args, close_fds=True) else: verb = s.split()[0] if self.printerAvailable(cmd=verb): self.printer.send_now(s) else: self.logger.logMsg("Printer not available for %s command" % verb) if not silent: self.logger.logMsg("End of macro") except: self.logger.logMsg("Error attempting to invoke macro file %s" % n) def FirmwareSettings(self): if self.connected: if not self.firmware.isActive(): self.firmware.start() else: self.logger.logMsg("Unable to comply - printer not on-line") def doDataLogReport(self): for d in DLLIST: self.logger.logMsg("%s Usage: %s" % (DLNAMES[d], self.dataLoggers[d].getToNowStr())) def doDataLogReset(self): DataLogReset(self)
menu = Menu(root) acctMenu = Menu(menu, tearoff=0) menu.add_command(label="Update", command=oneShotUpdate) menu.add_command(label="Console", command=showConsole) menu.add_command(label="Search", command=hashThreader) menu.add_command(label="Delete last tweet", command=delThreader) menu.add_command(label="Shorten link", command=shortThreader) menu.add_cascade(label="Accounts", menu=acctMenu) menu.add_separator() menu.add_command(label="Quit", command=lambda: quit(UPDATE_THREAD)) for acct in cred_man.getScreenNames(): acctMenu.add_command(label=acct, command=lambda: switchToAcct(acct)) acctMenu.entryconfig(0, label="*" + acctMenu.entrycget(0, "label")) acctMenu.add_command(label="Add Account", command=addAccount) root.config(menu=menu) # # END OF TK GUI STUFF # # tries to start a thread that will keep the character count # see the docs on the numbers function try: NUMBER_THREAD = upThread(1, "numbers", entry) NUMBER_THREAD.start() except: