def Setup(self): self.SetProjectPath() self.EnableControls(False) self.open_zip.GetPickerCtrl().SetLabel(_('ZIP')) self.open_folder.GetPickerCtrl().SetLabel(_('Folder')) self.SetButtonBitmap(self.open_zip.GetPickerCtrl(), 'zip') self.SetButtonBitmap(self.open_folder.GetPickerCtrl(), 'folder')
def LoadProjectFromZIP(self, path): if not zipfile.is_zipfile(path): return self.Error(_('Invalid ZIP file !\n%s'), path) zip_path = os.path.dirname(path) zip_file = os.path.basename(path) zip_folder = zip_file[:-4] zip_target = os.path.join(zip_path, zip_folder) args = (zip_file, zip_target) response = self.Question(_('Unzip "%s" ?\n%s'), args) if response == wx.ID_NO: return None if os.path.isdir(zip_target): question = _('Project folder already exists, overwrite it ?\n%s') if self.Question(question, zip_target) == wx.ID_NO: return None shutil.rmtree(zip_target) self.Log(_('Unzip "%s" to "%s"'), (zip_file, zip_target)) try: os.mkdir(zip_target.encode(sys.getfilesystemencoding())) except Exception as e: return self.Error(_('Access denied !\n%s'), zip_target) try: zip_file = zipfile.ZipFile(path, 'r') zip_file.extractall(zip_target) except Exception as e: return self.Error(unicode(e)) self.LoadProjectFromFolder(zip_target)
def OnSaveClick(self, event): name = self.presets.GetValue() if self.PresetsIsModified(name): self.SavePresets(name) self.Alert(_('Presets "%s" saved !'), name) else: self.Alert(_('No changes in "%s" to save !'), name)
def OnConnected(self, port, baudrate): self.EnableControls(True) self.SetButtonBitmap(self.printer_on_off, 'power-on') self.printer_on_off.SetToolTipString(_('Disconnect')) self.Log(_('Connected to %s at %i BPS'), (port, baudrate)) time.sleep(2) # Wait for Grbl header self._printer.SendRelativeMode()
def ResetButtons(self): self.start_stop.Enable() self.pause_resume.Disable() self.start_stop.SetLabel(_('Start')) self.pause_resume.SetLabel(_('Pause')) self.start_stop.SetToolTipString(_('Start')) self.pause_resume.SetToolTipString(_('Pause'))
def AskForSavePresets(self, name=None): if name is None: name = self._settings.Get('presetsName') if not self.PresetsIsModified(name): return None question = _('Presets "%s" has been modified !\nSave changes ?') if self.Question(question, name) == wx.ID_YES: self.Log(_('Save "%s" presets...'), name) self._settings.SaveCurrentPresets(name)
def OnPrintStart(self): self.start_stop.Enable() self.pause_resume.Enable() start_time = time.time() local_start_time = time.localtime(start_time) local_start_time_string = time.strftime("%H:%M:%S", local_start_time) self.start_time.SetLabel(local_start_time_string) self.start_stop.SetToolTipString(_('Stop')) self.start_stop.SetLabel(_('Stop')) self.RefreshEndTime()
def PauseJob(self): if self._printer.Paused(): return self.Error(_('Job already paused !')) try: self.pause_resume.SetLabel(_('Wait...')) self.pause_resume.Disable() self.start_stop.Disable() self._printer.Pause() except PrinterException as e: self.Error(unicode(e))
def StopJob(self): if not self._printer.Printing(): return self.Error(_('Job already stoped !')) if self.Question(_('Abort current job ?')) == wx.ID_YES: try: self.start_stop.SetLabel(_('Wait...')) self.pause_resume.Disable() self.start_stop.Disable() self._printer.Abort() except PrinterException as e: self.Error(unicode(e))
def StartJob(self): if self._printer.Disconnected(): return self.Error(_('Printer not connected !')) if self._printer.Printing(): return self.Error(_('Job already started !')) if not self._project or not self._project.Loaded(): return self.Error(_('No project loaded !')) try: self.start_stop.SetLabel(_('Wait...')) self.start_stop.Disable() self._elapsed_time = 0 self._SendCommands() except PrinterException as e: self.Error(unicode(e))
def OnLightOnOffClick(self, event): if self._light_on: bitmap = 'light-off' self._light_on = False label = _('Turn light ON') self._printer.SendLightOff() else: bitmap = 'light-on' self._light_on = True label = _('Turn light OFF') self._printer.SendLightOn() self.light_on_off.SetLabel(label) self.light_on_off.SetToolTipString(label) self.SetButtonBitmap(self.light_on_off, bitmap)
def DeletePresets(self, name): if name == 'Defaults': return self.Alert(_('"Defaults" presets is protected !')) if self.Question(_('Delete "%s" presets ?'), name) == wx.ID_YES: self.Log(_('Delete "%s" presets...'), name) presets = self._settings.Get('presets', {}) position = self.presets.FindString(name) del presets[name] self._settings.Set('presets', presets) name = self.presets.GetString(position - 1) self.LoadPresets(name) self.SaveSettings() self.RefreshPresetsList() self.SetPresetsSelected()
def OnMotorOnOffClick(self, event): if self._motor_on: bitmap = 'motor-off' self._motor_on = False label = _('Turn motor ON') self._printer.SendMotorOff() else: bitmap = 'motor-on' self._motor_on = True label = _('Turn motor OFF') self._printer.SendMotorOn() self.motor_on_off.SetLabel(label) self.motor_on_off.SetToolTipString(label) self.SetButtonBitmap(self.motor_on_off, bitmap)
def OnPrinterOnOffClick(self, event): if not self._printer.Connected(): return self.Connect() port = self._printer.Port() response = self.Question(_('Disconnect from %s ?'), port) if response == wx.ID_YES: self.Disconnect()
def SetProjectPath(self, path=None): if path is None: path = _('No project loaded') self.project_path.SetToolTipString(path) if path is not None: path = os.path.basename(path) self.project_path.SetValue(path)
def ResumeJob(self): if not self._printer.Paused(): return self.Error(_('Job already running !')) try: self.start_stop.Enable() self._printer.Resume() except PrinterException as e: self.Error(unicode(e))
def LoadProjectFromFolder(self, path): self.Log(_('Loading: %s'), path) try: self._project.Load(path) self.SetProjectPath(path) self.RefreshSettings() except ProjectException as e: return self.Error(unicode(e))
def Disconnect(self): if self.Disconnected(): self.Error(_('Printer already disconnected.')) self.ClearPrinter() self.Pub('on_disconnect', port=self._port) self._writer_daemon.stop() self._reader_daemon.stop() self._serial.close() self._connected = False self.Pub('on_disconnected', port=self._port)
def RefreshDisplaysList(self): self.displays.Clear() count = wx.Display.GetCount() for index in range(count): display = wx.Display(index) mode = display.GetCurrentMode() description = '%i x %i' % (mode.GetWidth(), mode.GetHeight()) if display.IsPrimary(): description += ' (%s)' % _('primary') self.displays.Append('[ %i ] %s' % (index + 1, description)) self.displays.SetSelection(index)
def __init__(self): self.Pub('before_init') super(MainFrame, self).__init__(None) self.Sub('printer.on_disconnected', self.OnPrinterDisconnected) self.Sub('printer.on_connected', self.OnPrinterConnected) self.sb.SetStatusText(_('Offline'), 0) self._viewer_frame = ViewerFrame(self) self._printer = Printer() self._project = Project() self._settings = Settings() self.Setup() self.Fit() self.Show() self.Pub('after_init')
def RefreshSettings(self): self.Log(_('Refresh custom settings...')) lg1 = self._settings.Get('layersGroup.1') lg2 = self._settings.Get('layersGroup.2') lg3 = self._settings.Get('layersGroup.3') self.layers_group_1_count.SetValue(lg1['layers']) self.layers_group_2_count.SetValue(lg2['layers']) self.layers_group_3_count.SetValue(lg3['layers']) self.layers_group_1_time.SetValue(lg1['exposureTime']) self.layers_group_2_time.SetValue(lg2['exposureTime']) self.layers_group_3_time.SetValue(lg3['exposureTime']) self.layers_group_1_count.Enable(True) self.layers_group_1_time.Enable(lg1['enable']) self.layers_group_2_count.Enable(lg1['enable']) self.layers_group_2_time.Enable(lg2['enable']) self.layers_group_3_count.Enable(lg2['enable']) self.layers_group_3_time.Enable(lg3['enable']) self.Pub('on_refresh', settings=self._settings)
def RefreshSettings(self): self.Log(_('Refresh project settings...')) layers_number = int(self._project.GetSetting('layersNumber')) layers_height = float(self._project.GetSetting('layersHeight')) exposure_time = int(self._project.GetSetting('exposureTime')) lifting_speed = int(self._project.GetSetting('liftingSpeed')) lifting_height = float(self._project.GetSetting('liftingHeight')) lifting_offset = float(lifting_height - layers_height) total_height = layers_number * layers_height / 10 self._project.SetSetting('totalHeight', total_height) self._project.SetSetting('liftingOffset', lifting_offset) self.total_height.SetLabel(str(total_height)) self.layers_number.SetLabel(str(layers_number)) self.layers_height.SetLabel(str(layers_height)) self.exposure_time.SetValue(exposure_time) self.lifting_speed.SetValue(lifting_speed) self.lifting_height.SetValue(lifting_height) self.slice.SetMax(layers_number) self.Pub('on_refresh', project=self._project)
def UpdateSettings(self): self.Log(_('Update custom settings...')) lg1_layers = self.layers_group_1_count.GetValue() lg2_layers = self.layers_group_2_count.GetValue() lg3_layers = self.layers_group_3_count.GetValue() lg1_time = self.layers_group_1_time.GetValue() lg2_time = self.layers_group_2_time.GetValue() lg3_time = self.layers_group_3_time.GetValue() lg1 = bool(lg1_layers) lg2 = bool(lg2_layers) and lg1 lg3 = bool(lg3_layers) and lg2 group1 = dict(layers=lg1_layers, exposureTime=lg1_time, enable=lg1) group2 = dict(layers=lg2_layers, exposureTime=lg2_time, enable=lg2) group3 = dict(layers=lg3_layers, exposureTime=lg3_time, enable=lg3) self._settings.Set('layersGroup.1', group1) self._settings.Set('layersGroup.2', group2) self._settings.Set('layersGroup.3', group3) self.Pub('on_update', settings=self._settings) self.RefreshSettings()
def UpdateSettings(self): if not self._project.Loaded(): return None self._debounce = None self.Log(_('Update project settings...')) layers_number = int(self.layers_number.GetLabel()) layers_height = float(self.layers_height.GetLabel()) exposure_time = int(self.exposure_time.GetValue()) lifting_speed = int(self.lifting_speed.GetValue()) lifting_height = int(self.lifting_height.GetValue()) lifting_offset = lifting_height - layers_height total_height = layers_number * layers_height self._project.SetSetting('totalHeight', total_height) self._project.SetSetting('layersNumber', layers_number) self._project.SetSetting('layersHeight', layers_height) self._project.SetSetting('exposureTime', exposure_time) self._project.SetSetting('liftingSpeed', lifting_speed) self._project.SetSetting('liftingHeight', lifting_height) self._project.SetSetting('liftingOffset', lifting_offset) self.Pub('on_update', project=self._project)
def Connect(self, port, baudrate=115200): if self.Connected(): self.Error(_('Printer already connected to %s.'), self._port) try: self.ClearPrinter() self.Pub('on_connect', port=port, baudrate=baudrate) # https://github.com/kliment/Printrun/blob/8c046755063025b6b582d9579bdbdc1edfbda520/printrun/printcore.py#L196 self._serial = Serial(port=port, baudrate=baudrate, timeout=self._timeout, parity=PARITY_ODD) self._serial.close() self._serial.parity = PARITY_NONE self._serial.open() self._baudrate = self._serial.baudrate self._port = self._serial.port self._connected = True self._reader_daemon = PrinterReader(self) self._reader_daemon.start() self._writer_daemon = PrinterWriter(self) self._writer_daemon.start() except SerialException as e: self.Error(unicode(e)) self.Pub('on_connected', port=self._port, baudrate=self._baudrate)
def OnViewerOpened(self, size, position): self.Log(_('Viewer opened on display %i') % self._display['num']) self.open_close.SetToolTipString(_('Close viewer')) self.SetButtonBitmap(self.open_close, 'reduce')
def RefreshPresetsList(self): self.Log(_('Refresh presets list...')) self.presets.Clear() for name in sorted(self._settings.Get('presets', {})): self.presets.Append(name)
def Write(self, text, nl=True): if self.Disconnected(): self.Error(_('Printer not connected.')) if nl: text += '\n' self._serial.write(text.encode())
def LoadPresets(self, name): self.Log(_('Loading presets: %s'), name) self._settings.LoadPresets(name) self.RefreshSettings()
def Error(self, text, args=None): text = _('Error : %s') % text self.Log(text, args) self.Alert(text, args)
def Question(self, text, args=None): style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION return self.Dialog(_('Question ?'), text, args, style)
def Alert(self, text, args=None): style = wx.OK | wx.ICON_EXCLAMATION return self.Dialog(_('Alert !'), text, args, style)
def OnViewerClosed(self): self.Log(_('Viewer closed on display %i') % self._display['num']) self.open_close.SetToolTipString(_('Open viewer')) self.SetButtonBitmap(self.open_close, 'expand') self.SetSelectedDisplay()
def GetPresets(self, name): presets = self.Get('presets') try: return presets[name] except: self.Error(_('Presets "%s" not defined !'), name)
def OnResponse(self, name, command, response, args): if args: name += '(%s)' % args self.Log(_('<--- %s: %s'), (name, response))
def OnDisconnected(self, port): self.EnableControls(False) self.SetButtonBitmap(self.printer_on_off, 'power-off') self.printer_on_off.SetToolTipString(_('Connect')) self.Log(_('Disconnected from %s'), port)
def SetPath(self, path): if not os.path.isdir(path): self.Error(_('Not a valid folder !\n%s'), path) self._path = path
def OnCommand(self, name, command, args): if args: name += '(%s)' % args self.Log(_('---> %s: %s'), (name, command))