def run(cmd, args=[]): """Executes the command `cmd` with optional arguments `args`, provided it is available on the system. Parameters: - `cmd`: The program command. - `args`: a list of arguments to pass to `cmd` (default is []). """ if not dryrun: proc = QProcess() proc.start(cmd, args) while proc.waitForReadyRead(): if verbose: print '>>>' print 'ReadyRead:\n{0}'.format(proc.readAll()) print '<<<' if verbose: stderr = proc.readAllStandardError() if stderr != '': print '>>>' print 'Errors:\n{0}'.format(stderr) print '<<<' stdout = proc.readAllStandardOutput() if stdout != '': print '>>>' print 'Output:{0}\n'.format(proc.readAllStandardOutput()) print '<<<'
def run(cmd, args=[]): """Executes the command `cmd` with optional arguments `args`, provided it is available on the system. Parameters: - `cmd`: The program command. - `args`: a list of arguments to pass to `cmd` (default is []). """ if not dryrun: proc = QProcess() proc.start(cmd, args) while proc.waitForReadyRead(): if verbose: print '>>>' print 'ReadyRead:\n{0}'.format(proc.readAll()) print '<<<' if verbose: stderr = proc.readAllStandardError() if stderr != '': print '>>>' print 'Errors:\n{0}'.format(stderr) print '<<<' stdout = proc.readAllStandardOutput() if stdout != '': print '>>>' print 'Output:{0}\n'.format(proc.readAllStandardOutput()) print '<<<'
def runProcess(self, args): self.logDb( u"BEFEHL: '%s'" % ( u"' '".join(args) ) ) currout = "" currerr = "" p = QProcess() p.start( args[0], args[1:] ) i=0 while not p.waitForFinished(500): i += 1 self.alive.setText( self.alive.text()[:-1] + ("-\|/")[i%4] ) app.processEvents() currout = self.processOutput( currout, p.readAllStandardOutput() ) currerr = self.processOutput( currerr, p.readAllStandardError() ) if p.state()<>QProcess.Running: if self.canceled: self.log( u"Prozeß abgebrochen." ) break if self.canceled: self.log( u"Prozeß wird abgebrochen." ) p.kill() currout = self.processOutput( currout, p.readAllStandardOutput() ) if currout and currout!="": self.log( "E %s" % currout ) currerr = self.processOutput( currerr, p.readAllStandardError() ) if currerr and currerr!="": self.log( "E %s" % currerr ) ok = False if p.exitStatus()==QProcess.NormalExit: if p.exitCode()==0: ok = True else: self.log( u"Fehler bei Prozeß: %d" % p.exitCode() ) else: self.log( u"Prozeß abgebrochen: %d" % p.exitCode() ) self.logDb( "EXITCODE: %d" % p.exitCode() ) p.close() return ok
def runProcess(self, args): self.logDb(u"BEFEHL: '%s'" % (u"' '".join(args))) currout = "" currerr = "" p = QProcess() p.start(args[0], args[1:]) i = 0 while not p.waitForFinished(500): i += 1 self.alive.setText(self.alive.text()[:-1] + ("-\|/")[i % 4]) app.processEvents() currout = self.processOutput(currout, p.readAllStandardOutput()) currerr = self.processOutput(currerr, p.readAllStandardError()) if p.state() <> QProcess.Running: if self.canceled: self.log(u"Prozeß abgebrochen.") break if self.canceled: self.log(u"Prozeß wird abgebrochen.") p.kill() currout = self.processOutput(currout, p.readAllStandardOutput()) if currout and currout != "": self.log("E %s" % currout) currerr = self.processOutput(currerr, p.readAllStandardError()) if currerr and currerr != "": self.log("E %s" % currerr) ok = False if p.exitStatus() == QProcess.NormalExit: if p.exitCode() == 0: ok = True else: self.log(u"Fehler bei Prozeß: %d" % p.exitCode()) else: self.log(u"Prozeß abgebrochen: %d" % p.exitCode()) self.logDb("EXITCODE: %d" % p.exitCode()) p.close() return ok
class QProcessTransport(Transport): '''A Transport communicating with a child process. Start the process using .start(). Sent data is written to the process' stdin. Data is received from the process's stdout and processed on the Qt mainloop thread. ''' shorthand='qprocess' @classmethod def fromstring(cls, expression): '''qprocess:(<commandline>)''' _, _, expr = expression.partition(':') cmdline, _, _ = paren_partition(expr) return cls(cmdline, sendername=expression) def __init__(self, cmdline, sendername='qprocess'): self.cmdline = cmdline self.sendername = sendername self.leftover = b'' self.process = QProcess() self.process.readyRead.connect(self.on_ready_read) self.process.finished.connect(self.on_finished) def start(self): L().debug('starting: %r'%self.cmdline) self.process.start(self.cmdline) def stop(self, kill=False): if kill: self.process.kill() else: self.process.terminate() self.process.waitForFinished() def send(self, data, receivers=None): if receivers is not None and self.sendername not in receivers: return L().debug('message to child processs: %s'%data) self.process.write(data.decode('utf8')) def on_ready_read(self): data = self.process.readAllStandardOutput().data() errors = self.process.readAllStandardError().data().decode('utf8') if errors: L().error('Error from child process:\n%s' % errors) pdata = data.decode('utf8') if len(pdata) > 100: pdata = pdata[:100] + '...' #if pdata.startswith('{'): L().debug('message from child process: %s'%pdata) self.leftover = self.received( sender=self.sendername, data=self.leftover + data ) def on_finished(self): L().info('Child process exited.')
def run_command(cmd, args): process = QProcess() process.start(cmd, args) if not process.waitForFinished(): return "" output = process.readAllStandardOutput() return fromByteArray(output).strip()
class WorkThread(QThread): def __init__(self): QThread.__init__(self) self.process = QProcess() self.cmd = None self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self.fini) def fini(self,no): self.emit(SIGNAL("fini"),no,self.cmd) def setCmd(self,val): self.cmd = val def kill_process(self): self.process.kill() def close_process(self): self.process.close() def run(self): if(self.process.isOpen()): self.process.close() #print "open" #self.process.kill() self.process.start(self.cmd) else: #print "strgin" self.process.start(self.cmd) self.exec_() self.process.waitForFinished() self.process.kill() #self.procDone.emit(True) def run2(self): if(self.process.isOpen()): self.process.close() #print "open" #self.process.kill() self.process.start(self.cmd) else: #print "strgin" self.process.start(self.cmd) self.exec_() #self.process.kill() def readOutput(self): self.emit(SIGNAL("update"),str(self.process.readAllStandardOutput())) def readErrors(self): self.emit(SIGNAL("update"),str(self.process.readAllStandardError())) def __del__(self): self.wait()
class WallpaperChanger(object): def __init__(self): self.settings = Settings() self.process = QProcess() def apply_wallpaper(self, filepath): system_platform = platform.system() if system_platform == 'Windows': return self._windows(filepath) elif system_platform == 'Linux': # Read desktop environment from settings. env = self.settings.linux_desktop print 'Setting wallpaper using environment "{0:s}"'.format(env) if env == 'feh': return self._feh(filepath) elif env == 'unity': return self._unity(filepath) elif env == 'xfce4': return self._xfce4(filepath) elif env == 'mate': return self._mate(filepath) def _windows(self, filepath): import ctypes SPI_SETDESKWALLPAPER = 20 # According to http://support.microsoft.com/default.aspx?scid=97142 ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, filepath, 1) def _feh(self, filepath): error = self.process.execute('feh --bg-scale {0:s}'.format(filepath)) return not bool(error) def _unity(self, filepath): error = self.process.execute('gsettings set org.gnome.desktop.background picture-uri {0:s}'.format(filepath)) return not bool(error) def _mate(self, filepath): error = self.process.execute('gsettings set org.mate.background picture-filename {0:s}'.format(filepath)) return not bool(error) def _xfce4(self, filepath): self.process.start('xfconf-query -c xfce4-desktop -l') self.process.waitForFinished() properties = re.findall(r'(/backdrop/screen.*(?:last-image|image-path))', unicode(self.process.readAllStandardOutput())) error = False for item in properties: self.process.start('xfconf-query --channel xfce4-desktop --property {0:s} --set {1:s}'.format(item, '/')) self.process.waitForFinished() self.process.start( 'xfconf-query --channel xfce4-desktop --property {0:s} --set {1:s}'.format(item, filepath)) self.process.waitForFinished() if self.process.exitCode(): error = True return not error
class RunWidget(QPlainTextEdit): def __init__(self): QWidget.__init__(self) self.setReadOnly(True) styles.set_style(self, 'editor') self.setPlainText( 'For the moment NINJA only show output when the Program ends.') self.overlay = Overlay(self) self.overlay.hide() self.proc = QProcess(self) #self.proc.setProcessChannelMode(QProcess.ForwardedChannels) self.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self.refresh_output) self.connect(self.proc, SIGNAL("readyReadStandardError()"), self.refresh_error) self.connect(self.proc, SIGNAL("finished(int, QProcess::ExitStatus)"), self._finish_process) def start_process(self, fileName, pythonPath=False): self.setPlainText('Running: ' + fileName + '\n'\ + 'For the moment NINJA only show output when the Program ends.' + '\n\n') self.moveCursor(QTextCursor.Down) self.moveCursor(QTextCursor.Down) self.moveCursor(QTextCursor.Down) #runner.run_code_from_file(fileName) if not pythonPath: pythonPath = resources.python_path self.proc.start(pythonPath, [fileName]) self.overlay.show() def kill_process(self): self.proc.kill() def refresh_output(self): text = str(self.proc.readAllStandardOutput().data()) self.textCursor().insertText(text) def refresh_error(self): text = str(self.proc.readAllStandardError().data()) self.textCursor().insertText(text) def _finish_process(self): self.overlay.killTimer(self.overlay.timer) self.overlay.hide() def resizeEvent(self, event): self.overlay.resize(event.size()) event.accept()
class Rabisk(QtGui.QMainWindow): text="peganingas" pic=None def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.layers = [] self.canvasWidth = 640 # size of image, not entire widget self.canvasHeight = 480 self.ui.label.setGeometry(QtCore.QRect(0, 0, 66, 17)) print self.ui.centralwidget.width #self.ui.label.geometry.Width=self.ui.geometry.Width #self.ui.label.height=self.ui.height self.setWindowState(Qt.WindowFullScreen) print self.ui.centralwidget.width() self.ui.label.setGeometry(QtCore.QRect(0, 0, self.ui.centralwidget.width(), self.ui.centralwidget.height())) self.pic=QPixmap(self.ui.centralwidget.width(), self.ui.centralwidget.height()) self.camera=QProcess(self) self.camera.readyReadStandardOutput.connect(self.handle_stdout) self.camera.start('python sense.py') self.show() def paintEvent(self, event): print "drawing" qp=QtGui.QPainter() qp.begin(self) qp.setPen(QtGui.QColor(1,10,0)) qp.drawText(10,10, self.text) qp.end() def handle_stdout(self): byteArray=self.camera.readAllStandardOutput() data=re.sub(r'''\n+$''', "", byteArray.data()) print data self.text=data #self.ui.label.setText("whatever"+data); qp=QtGui.QPainter(self.pic) qp.setPen(QtGui.QColor(1,10,0)) qp.drawText(100,10, self.text) self.ui.label.setPixmap(self.pic) def keyPressEvent(self, e): k=e.key() print e.key()
class ExtGuesser(object): _TAVI = "AVI" _MMP4 = "video/mp4" _MFLV = "video/x-flv" _TFLV = "Macromedia Flash Video" def __init__(self, path, filepgm='file'): self._path = path self._proc = QProcess() self._file_pgm = filepgm if not exists(self._path): raise InvalidPathError(path) def _guessExtension(self, text, mime): if text.find(self._TAVI) >= 0: return 'avi' elif mime.find(self._MMP4) >= 0: return 'mp4' elif ((mime.find(self._MFLV) >= 0) and (text.find(self._TFLV) >= 0)): return 'flv' else: return 'unk' def get(self): self._proc.start(self._file_pgm, ["-b", self._path]) ret0 = self._proc.waitForFinished() textual = str(self._proc.readAllStandardOutput()) self._proc.start(self._file_pgm, ["-bi", self._path]) ret1 = self._proc.waitForFinished() mime = str(self._proc.readAllStandardOutput()) if ret0 and ret1: return self._guessExtension(textual, mime) else: raise ExternalProgramError()
def get_devices(): devices = [] process = QProcess() process.start('scanimage', ['-f', '%d=>%v=>%m%n']) if not process.waitForFinished(): return devices data = bytes(process.readAllStandardOutput()).decode("utf-8").strip() if data=="": return devices lines = data.split("\n") for line in lines: dev, vendor, model = line.strip().split('=>') if not " " in dev: devices.append({'device':dev, 'vendor':vendor, 'model':model}) return devices
class RunWidget(QPlainTextEdit): def __init__(self): QWidget.__init__(self) self.setReadOnly(True) styles.set_style(self, 'editor') self.setPlainText('For the moment NINJA only show output when the Program ends.') self.overlay = Overlay(self) self.overlay.hide() self.proc = QProcess(self) #self.proc.setProcessChannelMode(QProcess.ForwardedChannels) self.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self.refresh_output) self.connect(self.proc, SIGNAL("readyReadStandardError()"), self.refresh_error) self.connect(self.proc, SIGNAL("finished(int, QProcess::ExitStatus)"), self._finish_process) def start_process(self, fileName, pythonPath=False): self.setPlainText('Running: ' + fileName + '\n'\ + 'For the moment NINJA only show output when the Program ends.' + '\n\n') self.moveCursor(QTextCursor.Down) self.moveCursor(QTextCursor.Down) self.moveCursor(QTextCursor.Down) #runner.run_code_from_file(fileName) if not pythonPath: pythonPath = resources.python_path self.proc.start(pythonPath, [fileName]) self.overlay.show() def kill_process(self): self.proc.kill() def refresh_output(self): text = str(self.proc.readAllStandardOutput().data()) self.textCursor().insertText(text) def refresh_error(self): text = str(self.proc.readAllStandardError().data()) self.textCursor().insertText(text) def _finish_process(self): self.overlay.killTimer(self.overlay.timer) self.overlay.hide() def resizeEvent(self, event): self.overlay.resize(event.size()) event.accept()
class InoProcess(QtCore.QThread): def __init__(self,project,command): QtCore.QThread.__init__(self,project.parent()) self.project=project self.command=command def run(self): self.project.newMessage.emit() self.project.addMessage.emit("# running: "+self.command+"\n") start_time=time.time() self.proc = QProcess(None) self.proc.readyReadStandardError.connect(self.stdErrReady) self.proc.readyReadStandardOutput.connect(self.stdOutReady) self.proc.setWorkingDirectory(self.project.path) commands = self.command.split(' ') args=QStringList() for cmd in commands[1:]: args.append(cmd) self.proc.start(QString(commands[0]), args, mode=QIODevice.ReadOnly) self.proc.waitForFinished() end_time=time.time() if (self.proc.exitCode()==0): self.project.statusChanged.emit("SUCCESS") self.project.addMessage.emit("# \""+self.command+"\" finished in "+str(end_time-start_time)+"sec\n") else: self.project.statusChanged.emit("FAILED") self.project.addErrorMessage.emit("# \""+self.command+"\" finished in "+str(end_time-start_time)+ "sec with status:"+str(self.proc.exitCode())+"\n") def stop(self): if self.proc!=None and self.proc.state()!=QProcess.NotRunning: self.project.addErrorMessage.emit("# Received stop process command\n") self.proc.kill() def stdErrReady(self): #Reading possible errors errors=unicode(self.proc.readAllStandardError().data(),errors='ignore') if (errors!=None and len(errors)>0): self.project.addErrorMessage.emit(QString(errors)) def stdOutReady(self): msg=unicode(self.proc.readAllStandardOutput().data(),errors='ignore') if (msg!=None and len(msg)>0): self.project.addMessage.emit(QString(msg))
def getProcList(): retProcs = [] if HAIKU or LINUX or MACOS: process = QProcess() process.start("ps", ["-u", str(os.getuid())]) process.waitForFinished() processDump = process.readAllStandardOutput().split("\n") for i in range(len(processDump)): if (i == 0): continue dumpTest = str(processDump[i], encoding="utf-8").rsplit(":", 1)[-1].split(" ") if len(dumpTest) > 1 and dumpTest[1]: retProcs.append(dumpTest[1]) else: print("getProcList() - Not supported in this system") return retProcs
def getProcList(): retProcs = [] if HAIKU or LINUX or MACOS: process = QProcess() process.start("ps", ["-u", str(os.getuid())]) process.waitForFinished() processDump = process.readAllStandardOutput().split("\n") for i in range(len(processDump)): if (i == 0): continue dumpTest = str(processDump[i], encoding="utf-8").rsplit(":", 1)[-1].split(" ") if len(dumpTest) > 1 and dumpTest[1]: retProcs.append(dumpTest[1]) else: print("getProcList() - Not supported in this system") return retProcs
class RdpConnection(object): _cfg = None _conn = None def __init__(self, cfg): self._cfg = cfg def connect(self, parent_window=None): if not parent_window is None: setattr(self._cfg, 'parent-window', parent_window) self._conn = QProcess() # print(self._cfg.as_list()) self._conn.start('xfreerdp', self._cfg.as_list()) self._conn.readyReadStandardOutput.connect(self._read_out) self._conn.readyReadStandardError.connect(self._read_err) def close(self): self._conn.close() self._conn.terminate() def connect_output(self, out_listener): self._out_listener = out_listener def _read_out(self): if not self._out_listener is None: self._out_listener(str(self._conn.readAllStandardOutput())) def _read_err(self): if not self._out_listener is None: self._out_listener(str(self._conn.readAllStandardError())) @property def cfg(self): return self._cfg
class RdpConnection(object): _cfg = None _conn = None def __init__(self, cfg): self._cfg = cfg def connect(self, parent_window=None): if not parent_window is None: setattr(self._cfg, 'parent-window', parent_window) self._conn = QProcess() # print(self._cfg.as_list()) self._conn.start('xfreerdp', self._cfg.as_list()) self._conn.readyReadStandardOutput.connect(self._read_out) self._conn.readyReadStandardError.connect(self._read_err) def close(self): self._conn.close() self._conn.terminate() def connect_output(self, out_listener): self._out_listener = out_listener def _read_out(self): if not self._out_listener is None: self._out_listener(str(self._conn.readAllStandardOutput())) def _read_err(self): if not self._out_listener is None: self._out_listener(str(self._conn.readAllStandardError())) @property def cfg(self): return self._cfg
class RenderW(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.ui = ui_render.Ui_RenderW() self.ui.setupUi(self) self.fFreewheel = False self.fLastTime = -1 self.fMaxTime = 180 self.fTimer = QTimer(self) self.fProcess = QProcess(self) # ------------------------------------------------------------- # Get JACK client and base information global gJackClient if gJackClient: self.fJackClient = gJackClient else: self.fJackClient = jacklib.client_open("Render-Dialog", jacklib.JackNoStartServer, None) self.fBufferSize = int(jacklib.get_buffer_size(self.fJackClient)) self.fSampleRate = int(jacklib.get_sample_rate(self.fJackClient)) for i in range(self.ui.cb_buffer_size.count()): if int(self.ui.cb_buffer_size.itemText(i)) == self.fBufferSize: self.ui.cb_buffer_size.setCurrentIndex(i) break else: self.ui.cb_buffer_size.addItem(str(self.fBufferSize)) self.ui.cb_buffer_size.setCurrentIndex( self.ui.cb_buffer_size.count() - 1) # ------------------------------------------------------------- # Set-up GUI stuff # Get List of formats self.fProcess.start(gJackCapturePath, ["-pf"]) self.fProcess.waitForFinished() formats = str(self.fProcess.readAllStandardOutput(), encoding="utf-8").split(" ") formatsList = [] for i in range(len(formats) - 1): iFormat = formats[i].strip() if iFormat: formatsList.append(iFormat) formatsList.sort() # Put all formats in combo-box, select 'wav' option for i in range(len(formatsList)): self.ui.cb_format.addItem(formatsList[i]) if formatsList[i] == "wav": self.ui.cb_format.setCurrentIndex(i) self.ui.cb_depth.setCurrentIndex(4) #Float self.ui.rb_stereo.setChecked(True) self.ui.te_end.setTime(QTime(0, 3, 0)) self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(1) self.ui.progressBar.setValue(0) self.ui.b_render.setIcon(getIcon("media-record")) self.ui.b_stop.setIcon(getIcon("media-playback-stop")) self.ui.b_close.setIcon(getIcon("window-close")) self.ui.b_open.setIcon(getIcon("document-open")) self.ui.b_stop.setVisible(False) self.ui.le_folder.setText(HOME) # ------------------------------------------------------------- # Set-up connections self.connect(self.ui.b_render, SIGNAL("clicked()"), SLOT("slot_renderStart()")) self.connect(self.ui.b_stop, SIGNAL("clicked()"), SLOT("slot_renderStop()")) self.connect(self.ui.b_open, SIGNAL("clicked()"), SLOT("slot_getAndSetPath()")) self.connect(self.ui.b_now_start, SIGNAL("clicked()"), SLOT("slot_setStartNow()")) self.connect(self.ui.b_now_end, SIGNAL("clicked()"), SLOT("slot_setEndNow()")) self.connect(self.ui.te_start, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateStartTime(const QTime)")) self.connect(self.ui.te_end, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateEndTime(const QTime)")) self.connect(self.ui.group_time, SIGNAL("clicked(bool)"), SLOT("slot_transportChecked(bool)")) self.connect(self.fTimer, SIGNAL("timeout()"), SLOT("slot_updateProgressbar()")) # ------------------------------------------------------------- self.loadSettings() @pyqtSlot() def slot_renderStart(self): if not os.path.exists(self.ui.le_folder.text()): QMessageBox.warning( self, self.tr("Warning"), self. tr("The selected directory does not exist. Please choose a valid one." )) return timeStart = self.ui.te_start.time() timeEnd = self.ui.te_end.time() minTime = (timeStart.hour() * 3600) + (timeStart.minute() * 60) + (timeStart.second()) maxTime = (timeEnd.hour() * 3600) + (timeEnd.minute() * 60) + (timeEnd.second()) newBufferSize = int(self.ui.cb_buffer_size.currentText()) useTransport = self.ui.group_time.isChecked() self.fFreewheel = bool(self.ui.cb_render_mode.currentIndex() == 1) self.fLastTime = -1 self.fMaxTime = maxTime if self.fFreewheel: self.fTimer.setInterval(100) else: self.fTimer.setInterval(500) self.ui.group_render.setEnabled(False) self.ui.group_time.setEnabled(False) self.ui.group_encoding.setEnabled(False) self.ui.b_render.setVisible(False) self.ui.b_stop.setVisible(True) self.ui.b_close.setEnabled(False) if useTransport: self.ui.progressBar.setFormat("%p%") self.ui.progressBar.setMinimum(minTime) self.ui.progressBar.setMaximum(maxTime) self.ui.progressBar.setValue(minTime) else: self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(0) self.ui.progressBar.setValue(0) self.ui.progressBar.update() arguments = [] # Filename prefix arguments.append("-fp") arguments.append(self.ui.le_prefix.text()) # Format arguments.append("-f") arguments.append(self.ui.cb_format.currentText()) # Bit depth arguments.append("-b") arguments.append(self.ui.cb_depth.currentText()) # Channels arguments.append("-c") if self.ui.rb_mono.isChecked(): arguments.append("1") elif self.ui.rb_stereo.isChecked(): arguments.append("2") else: arguments.append(str(self.ui.sb_channels.value())) # Controlled only by freewheel if self.fFreewheel: arguments.append("-jf") # Controlled by transport elif useTransport: arguments.append("-jt") # Silent mode arguments.append("-dc") arguments.append("-s") # Change current directory os.chdir(self.ui.le_folder.text()) if newBufferSize != int(jacklib.get_buffer_size(self.fJackClient)): print("NOTICE: buffer size changed before render") jacklib.set_buffer_size(self.fJackClient, newBufferSize) if useTransport: if jacklib.transport_query( self.fJackClient, None ) > jacklib.JackTransportStopped: # rolling or starting jacklib.transport_stop(self.fJackClient) jacklib.transport_locate(self.fJackClient, minTime * self.fSampleRate) self.fProcess.start(gJackCapturePath, arguments) self.fProcess.waitForStarted() if self.fFreewheel: print("NOTICE: rendering in freewheel mode") sleep(1) jacklib.set_freewheel(self.fJackClient, 1) if useTransport: self.fTimer.start() jacklib.transport_start(self.fJackClient) @pyqtSlot() def slot_renderStop(self): useTransport = self.ui.group_time.isChecked() if useTransport: jacklib.transport_stop(self.fJackClient) if self.fFreewheel: jacklib.set_freewheel(self.fJackClient, 0) sleep(1) self.fProcess.close() if useTransport: self.fTimer.stop() self.ui.group_render.setEnabled(True) self.ui.group_time.setEnabled(True) self.ui.group_encoding.setEnabled(True) self.ui.b_render.setVisible(True) self.ui.b_stop.setVisible(False) self.ui.b_close.setEnabled(True) self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(1) self.ui.progressBar.setValue(0) self.ui.progressBar.update() # Restore buffer size newBufferSize = int(jacklib.get_buffer_size(self.fJackClient)) if newBufferSize != self.fBufferSize: jacklib.set_buffer_size(self.fJackClient, newBufferSize) @pyqtSlot() def slot_getAndSetPath(self): getAndSetPath(self, self.ui.le_folder.text(), self.ui.le_folder) @pyqtSlot() def slot_setStartNow(self): time = int( jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate) secs = time % 60 mins = int(time / 60) % 60 hrs = int(time / 3600) % 60 self.ui.te_start.setTime(QTime(hrs, mins, secs)) @pyqtSlot() def slot_setEndNow(self): time = int( jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate) secs = time % 60 mins = int(time / 60) % 60 hrs = int(time / 3600) % 60 self.ui.te_end.setTime(QTime(hrs, mins, secs)) @pyqtSlot(QTime) def slot_updateStartTime(self, time): if time >= self.ui.te_end.time(): self.ui.te_end.setTime(time) renderEnabled = False else: renderEnabled = True if self.ui.group_time.isChecked(): self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot(QTime) def slot_updateEndTime(self, time): if time <= self.ui.te_start.time(): self.ui.te_start.setTime(time) renderEnabled = False else: renderEnabled = True if self.ui.group_time.isChecked(): self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot(bool) def slot_transportChecked(self, yesNo): if yesNo: renderEnabled = bool( self.ui.te_end.time() > self.ui.te_start.time()) else: renderEnabled = True self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot() def slot_updateProgressbar(self): time = int(jacklib.get_current_transport_frame( self.fJackClient)) / self.fSampleRate self.ui.progressBar.setValue(time) if time > self.fMaxTime or (self.fLastTime > time and not self.fFreewheel): self.slot_renderStop() self.fLastTime = time def saveSettings(self): settings = QSettings("Cadence", "Cadence-Render") if self.ui.rb_mono.isChecked(): channels = 1 elif self.ui.rb_stereo.isChecked(): channels = 2 else: channels = self.ui.sb_channels.value() settings.setValue("Geometry", self.saveGeometry()) settings.setValue("OutputFolder", self.ui.le_folder.text()) settings.setValue("FilenamePrefix", self.ui.le_prefix.text()) settings.setValue("EncodingFormat", self.ui.cb_format.currentText()) settings.setValue("EncodingDepth", self.ui.cb_depth.currentText()) settings.setValue("EncodingChannels", channels) settings.setValue("UseTransport", self.ui.group_time.isChecked()) settings.setValue("StartTime", self.ui.te_start.time()) settings.setValue("EndTime", self.ui.te_end.time()) def loadSettings(self): settings = QSettings("Cadence", "Cadence-Render") self.restoreGeometry(settings.value("Geometry", "")) outputFolder = settings.value("OutputFolder", HOME) if os.path.exists(outputFolder): self.ui.le_folder.setText(outputFolder) self.ui.le_prefix.setText( settings.value("FilenamePrefix", "jack_capture_")) encFormat = settings.value("EncodingFormat", "Wav", type=str) for i in range(self.ui.cb_format.count()): if self.ui.cb_format.itemText(i) == encFormat: self.ui.cb_format.setCurrentIndex(i) break encDepth = settings.value("EncodingDepth", "Float", type=str) for i in range(self.ui.cb_depth.count()): if self.ui.cb_depth.itemText(i) == encDepth: self.ui.cb_depth.setCurrentIndex(i) break encChannels = settings.value("EncodingChannels", 2, type=int) if encChannels == 1: self.ui.rb_mono.setChecked(True) elif encChannels == 2: self.ui.rb_stereo.setChecked(True) else: self.ui.rb_outro.setChecked(True) self.ui.sb_channels.setValue(encChannels) self.ui.group_time.setChecked( settings.value("UseTransport", False, type=bool)) self.ui.te_start.setTime( settings.value("StartTime", self.ui.te_start.time(), type=QTime)) self.ui.te_end.setTime( settings.value("EndTime", self.ui.te_end.time(), type=QTime)) def closeEvent(self, event): self.saveSettings() if self.fJackClient: jacklib.client_close(self.fJackClient) QDialog.closeEvent(self, event) def done(self, r): QDialog.done(self, r) self.close()
class GimConverter: def __init__(self, parent=None): self.parent = parent self.process = QProcess() self.temp_dir = tempfile.mkdtemp(prefix="sdse-") def __del__(self): import shutil shutil.rmtree(self.temp_dir) def quantize_png(self, png_file, quant_type=QuantizeType.auto): if quant_type == QuantizeType.none: return png_file basename = os.path.basename(png_file) temp_png = os.path.join(self.temp_dir, basename) shutil.copy(png_file, temp_png) options = ["--force", "--ext", ".png", "--speed", "1"] if quant_type == QuantizeType.auto: options.extend(["--quality", "100"]) elif quant_type == QuantizeType.index4: options.append("16") elif quant_type == QuantizeType.index8: options.append("256") options.append(temp_png) self.process.start("tools/pngquant", options) self.process.waitForFinished(-1) return temp_png def png_to_gim(self, png_file, gim_file=None, quant_type=QuantizeType.auto): # So there's no confusion. png_file = os.path.abspath(png_file) if gim_file == None: gim_file = os.path.splitext(png_file)[0] + ".gim" png_file = self.quantize_png(png_file, quant_type) data = ConstBitStream(filename=png_file) data.bytepos = 0x18 options = ["-jar", "tools/gimexport.jar", png_file, gim_file, "3"] depth = data.read("int:8") color_type = data.read("int:8") if color_type == 3: # Indexed options.append("true") else: options.append("false") self.process.start("java", options) self.process.waitForFinished(-1) def gim_to_png(self, gim_file, png_file=None, quant_type=QuantizeType.none): # So there's no confusion. gim_file = os.path.abspath(gim_file) if png_file: png_file = os.path.abspath(png_file) # Convert our GIM. self.process.start("tools/gim2png", ["-9", gim_file]) self.process.waitForFinished(-1) # Now get the output location. output = QString(self.process.readAllStandardOutput()) output = output.split("\n", QString.SkipEmptyParts) saved_file = None for line in output: line = common.qt_to_unicode(line) match = OUTPUT_RE.match(line) if match == None: continue saved_file = match.group(1) break # Make sure we actually generated a file. if not saved_file: _LOGGER.error("Failed to convert %s" % gim_file) return quant = self.quantize_png(saved_file, quant_type) if not quant == saved_file and not quant == png_file: os.remove(saved_file) # And move it to the requested location, if one exists. if png_file: shutil.move(quant, png_file) else: shutil.move(quant, saved_file)
class DialogueNew(QtGui.QDialog, FORM_CLASS): SOURCES = ["ASCII squared raster", "CSV file", "Python function"] METHODS = ["Multi-quadratic", "Nearest neighbour"] METHODS_ABRV = ["mq", "nn"] iface = None def __init__(self, parent=None): """Constructor.""" super(DialogueNew, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.comboBoxSource.addItems(self.SOURCES) self.comboBoxSource.currentIndexChanged.connect(self.sourceChanged) self.comboBoxMethod.addItems(self.METHODS) self.buttonBox.button(QDialogButtonBox.Ok).setText("Run") self.buttonBox.button(QDialogButtonBox.Cancel).setText("Exit") self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) # Activate file search buttons self.pushButtonSource.clicked.connect(self.selectFileSource) self.pushButtonOutput.clicked.connect(self.selectFileOutput) self.resize(520, 430) def accept(self): if(not self.checkOptions()): return self.resize(520, 610) if(self.comboBoxSource.currentText() == self.SOURCES[0]): if(self.comboBoxMethod == self.METHODS[0]): meth_abv = self.METHODS_ABRV[0] else: meth_abv = self.METHODS_ABRV[1] args = QStringList() args.append("-i" + self.filePathSource.text()) args.append("-o" + self.filePathOutput.text()) args.append("-m" + meth_abv) self.proc = QProcess() self.proc.start("asc2hasc", args) self.proc.setProcessChannelMode(QProcess.MergedChannels); QObject.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self, SLOT("readStdOutput()")) #self.setGeometry(self._parent.x(), self._parent.y(), self.width(), 610) if(self.comboBoxSource.currentText() == self.SOURCES[1]): args = QStringList() args.append("-i" + self.filePathSource.text()) args.append("-o" + self.filePathOutput.text()) args.append("-s" + self.cellSide.text()) self.proc = QProcess() self.proc.start("csv2hasc", args) self.proc.setProcessChannelMode(QProcess.MergedChannels); QObject.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self, SLOT("readStdOutput()")) if(self.comboBoxSource.currentText() == self.SOURCES[2]): args = QStringList() args.append("-m" + self.filePathSource.text()) args.append("-o" + self.filePathOutput.text()) args.append("-f" + self.pythonFunction.text()) args.append("-s" + self.cellSide.text()) args.append("-x" + self.eastingRight.text()) args.append("-X" + self.eastingLeft.text()) args.append("-y" + self.northingBottom.text()) args.append("-Y" + self.northingTop.text()) self.proc = QProcess() self.proc.start("surface2hasc", args) self.proc.setProcessChannelMode(QProcess.MergedChannels); QObject.connect(self.proc, SIGNAL("readyReadStandardOutput()"), self, SLOT("readStdOutput()")) @pyqtSlot() def readStdOutput(self): self.commandOutput.append(QString(self.proc.readAllStandardOutput())) def reject(self): self.done(0) def selectFileSource(self): extension = "" if(self.comboBoxSource.currentText() == self.SOURCES[0]): extension = '*.asc' elif(self.comboBoxSource.currentText() == self.SOURCES[1]): extension = '*.csv' elif(self.comboBoxSource.currentText() == self.SOURCES[2]): extension = '*.py' self.fileNameSource = QFileDialog.getOpenFileName(self, "Select file ","", extension); self.filePathSource.setText(self.fileNameSource) def selectFileOutput(self): self.fileNameOutput = QFileDialog.getOpenFileName(self, "Select file ","", "*.hasc"); self.filePathOutput.setText(self.fileNameOutput) def sourceChanged(self, i): if(self.comboBoxSource.currentText() == self.SOURCES[0]): self.pushButtonSource.setEnabled(True) self.labelExtent.setEnabled(False) self.labelNorthingTop.setEnabled(False) self.labelNorthingBottom.setEnabled(False) self.labelEastingRight.setEnabled(False) self.labelEastingLeft.setEnabled(False) self.northingTop.setEnabled(False) self.northingBottom.setEnabled(False) self.eastingRight.setEnabled(False) self.eastingLeft.setEnabled(False) self.labelMethod.setEnabled(True) self.comboBoxMethod.setEnabled(True) self.pythonFunction.setEnabled(False) self.labelPythonFunction.setEnabled(False) self.cellSide.setEnabled(False) self.labelCellSide.setEnabled(False) elif(self.comboBoxSource.currentText() == self.SOURCES[1]): self.pushButtonSource.setEnabled(True) self.labelExtent.setEnabled(False) self.labelNorthingTop.setEnabled(False) self.labelNorthingBottom.setEnabled(False) self.labelEastingRight.setEnabled(False) self.labelEastingLeft.setEnabled(False) self.northingTop.setEnabled(False) self.northingBottom.setEnabled(False) self.eastingRight.setEnabled(False) self.eastingLeft.setEnabled(False) self.labelMethod.setEnabled(False) self.comboBoxMethod.setEnabled(False) self.pythonFunction.setEnabled(False) self.labelPythonFunction.setEnabled(False) self.cellSide.setEnabled(True) self.labelCellSide.setEnabled(True) elif(self.comboBoxSource.currentText() == self.SOURCES[2]): self.pushButtonSource.setEnabled(True) self.labelExtent.setEnabled(True) self.labelNorthingTop.setEnabled(True) self.labelNorthingBottom.setEnabled(True) self.labelEastingRight.setEnabled(True) self.labelEastingLeft.setEnabled(True) self.northingTop.setEnabled(True) self.northingBottom.setEnabled(True) self.eastingRight.setEnabled(True) self.eastingLeft.setEnabled(True) self.labelMethod.setEnabled(False) self.comboBoxMethod.setEnabled(False) self.pythonFunction.setEnabled(True) self.labelPythonFunction.setEnabled(True) self.cellSide.setEnabled(True) self.labelCellSide.setEnabled(True) else: return def checkOptions(self): if(self.comboBoxSource.currentText() == ""): self.showErrorMessage("Please select a source type.") return False if(self.filePathOutput.text() == None or self.filePathOutput.text() == ""): self.showErrorMessage("Please provide an output file.") return False if(self.filePathSource.text() == None or self.filePathSource.text() == ""): self.showErrorMessage("Please select a source file.") return False if(self.comboBoxSource.currentText() != self.SOURCES[0]): if(self.northingTop.text() == None or self.northingTop.text() == "" or self.northingBottom.text() == None or self.northingBottom.text() == "" or self.eastingRight.text() == None or self.eastingRight.text() == "" or self.eastingLeft.text() == None or self.eastingLeft.text() == ""): self.showErrorMessage("Extent is mandatory for this source type.") return False if(self.cellSide.text() == None or self.cellSide.text() == ""): self.showErrorMessage("A cell side length is required for this source type.") return False if(self.comboBoxSource.currentText() == self.SOURCES[2]): if(self.pythonFunction.text() == None or self.pythonFunction.text() == ""): self.showErrorMessage("Please select a Python function in the module.") return False return True def showErrorMessage(self, mesg): msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setText(mesg) msgBox.setWindowTitle("Unable to proceed") msgBox.exec_()
class RenderW(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.ui = ui_render.Ui_RenderW() self.ui.setupUi(self) self.fFreewheel = False self.fLastTime = -1 self.fMaxTime = 180 self.fTimer = QTimer(self) self.fProcess = QProcess(self) # ------------------------------------------------------------- # Get JACK client and base information global gJackClient if gJackClient: self.fJackClient = gJackClient else: self.fJackClient = jacklib.client_open("Render-Dialog", jacklib.JackNoStartServer, None) self.fBufferSize = int(jacklib.get_buffer_size(self.fJackClient)) self.fSampleRate = int(jacklib.get_sample_rate(self.fJackClient)) for i in range(self.ui.cb_buffer_size.count()): if int(self.ui.cb_buffer_size.itemText(i)) == self.fBufferSize: self.ui.cb_buffer_size.setCurrentIndex(i) break else: self.ui.cb_buffer_size.addItem(str(self.fBufferSize)) self.ui.cb_buffer_size.setCurrentIndex(self.ui.cb_buffer_size.count() - 1) # ------------------------------------------------------------- # Set-up GUI stuff # Get List of formats self.fProcess.start(gJackCapturePath, ["-pf"]) self.fProcess.waitForFinished() formats = str(self.fProcess.readAllStandardOutput(), encoding="utf-8").split(" ") formatsList = [] for i in range(len(formats) - 1): iFormat = formats[i].strip() if iFormat: formatsList.append(iFormat) formatsList.sort() # Put all formats in combo-box, select 'wav' option for i in range(len(formatsList)): self.ui.cb_format.addItem(formatsList[i]) if formatsList[i] == "wav": self.ui.cb_format.setCurrentIndex(i) self.ui.cb_depth.setCurrentIndex(4) #Float self.ui.rb_stereo.setChecked(True) self.ui.te_end.setTime(QTime(0, 3, 0)) self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(1) self.ui.progressBar.setValue(0) self.ui.b_render.setIcon(getIcon("media-record")) self.ui.b_stop.setIcon(getIcon("media-playback-stop")) self.ui.b_close.setIcon(getIcon("window-close")) self.ui.b_open.setIcon(getIcon("document-open")) self.ui.b_stop.setVisible(False) self.ui.le_folder.setText(HOME) # ------------------------------------------------------------- # Set-up connections self.connect(self.ui.b_render, SIGNAL("clicked()"), SLOT("slot_renderStart()")) self.connect(self.ui.b_stop, SIGNAL("clicked()"), SLOT("slot_renderStop()")) self.connect(self.ui.b_open, SIGNAL("clicked()"), SLOT("slot_getAndSetPath()")) self.connect(self.ui.b_now_start, SIGNAL("clicked()"), SLOT("slot_setStartNow()")) self.connect(self.ui.b_now_end, SIGNAL("clicked()"), SLOT("slot_setEndNow()")) self.connect(self.ui.te_start, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateStartTime(const QTime)")) self.connect(self.ui.te_end, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateEndTime(const QTime)")) self.connect(self.ui.group_time, SIGNAL("clicked(bool)"), SLOT("slot_transportChecked(bool)")) self.connect(self.fTimer, SIGNAL("timeout()"), SLOT("slot_updateProgressbar()")) # ------------------------------------------------------------- self.loadSettings() @pyqtSlot() def slot_renderStart(self): if not os.path.exists(self.ui.le_folder.text()): QMessageBox.warning(self, self.tr("Warning"), self.tr("The selected directory does not exist. Please choose a valid one.")) return timeStart = self.ui.te_start.time() timeEnd = self.ui.te_end.time() minTime = (timeStart.hour() * 3600) + (timeStart.minute() * 60) + (timeStart.second()) maxTime = (timeEnd.hour() * 3600) + (timeEnd.minute() * 60) + (timeEnd.second()) newBufferSize = int(self.ui.cb_buffer_size.currentText()) useTransport = self.ui.group_time.isChecked() self.fFreewheel = bool(self.ui.cb_render_mode.currentIndex() == 1) self.fLastTime = -1 self.fMaxTime = maxTime if self.fFreewheel: self.fTimer.setInterval(100) else: self.fTimer.setInterval(500) self.ui.group_render.setEnabled(False) self.ui.group_time.setEnabled(False) self.ui.group_encoding.setEnabled(False) self.ui.b_render.setVisible(False) self.ui.b_stop.setVisible(True) self.ui.b_close.setEnabled(False) if useTransport: self.ui.progressBar.setFormat("%p%") self.ui.progressBar.setMinimum(minTime) self.ui.progressBar.setMaximum(maxTime) self.ui.progressBar.setValue(minTime) else: self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(0) self.ui.progressBar.setValue(0) self.ui.progressBar.update() arguments = [] # Filename prefix arguments.append("-fp") arguments.append(self.ui.le_prefix.text()) # Format arguments.append("-f") arguments.append(self.ui.cb_format.currentText()) # Bit depth arguments.append("-b") arguments.append(self.ui.cb_depth.currentText()) # Channels arguments.append("-c") if self.ui.rb_mono.isChecked(): arguments.append("1") elif self.ui.rb_stereo.isChecked(): arguments.append("2") else: arguments.append(str(self.ui.sb_channels.value())) # Controlled only by freewheel if self.fFreewheel: arguments.append("-jf") # Controlled by transport elif useTransport: arguments.append("-jt") # Silent mode arguments.append("-dc") arguments.append("-s") # Change current directory os.chdir(self.ui.le_folder.text()) if newBufferSize != int(jacklib.get_buffer_size(self.fJackClient)): print("NOTICE: buffer size changed before render") jacklib.set_buffer_size(self.fJackClient, newBufferSize) if useTransport: if jacklib.transport_query(self.fJackClient, None) > jacklib.JackTransportStopped: # rolling or starting jacklib.transport_stop(self.fJackClient) jacklib.transport_locate(self.fJackClient, minTime * self.fSampleRate) self.fProcess.start(gJackCapturePath, arguments) self.fProcess.waitForStarted() if self.fFreewheel: print("NOTICE: rendering in freewheel mode") sleep(1) jacklib.set_freewheel(self.fJackClient, 1) if useTransport: self.fTimer.start() jacklib.transport_start(self.fJackClient) @pyqtSlot() def slot_renderStop(self): useTransport = self.ui.group_time.isChecked() if useTransport: jacklib.transport_stop(self.fJackClient) if self.fFreewheel: jacklib.set_freewheel(self.fJackClient, 0) sleep(1) self.fProcess.close() if useTransport: self.fTimer.stop() self.ui.group_render.setEnabled(True) self.ui.group_time.setEnabled(True) self.ui.group_encoding.setEnabled(True) self.ui.b_render.setVisible(True) self.ui.b_stop.setVisible(False) self.ui.b_close.setEnabled(True) self.ui.progressBar.setFormat("") self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(1) self.ui.progressBar.setValue(0) self.ui.progressBar.update() # Restore buffer size newBufferSize = int(jacklib.get_buffer_size(self.fJackClient)) if newBufferSize != self.fBufferSize: jacklib.set_buffer_size(self.fJackClient, newBufferSize) @pyqtSlot() def slot_getAndSetPath(self): getAndSetPath(self, self.ui.le_folder.text(), self.ui.le_folder) @pyqtSlot() def slot_setStartNow(self): time = int(jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate) secs = time % 60 mins = int(time / 60) % 60 hrs = int(time / 3600) % 60 self.ui.te_start.setTime(QTime(hrs, mins, secs)) @pyqtSlot() def slot_setEndNow(self): time = int(jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate) secs = time % 60 mins = int(time / 60) % 60 hrs = int(time / 3600) % 60 self.ui.te_end.setTime(QTime(hrs, mins, secs)) @pyqtSlot(QTime) def slot_updateStartTime(self, time): if time >= self.ui.te_end.time(): self.ui.te_end.setTime(time) renderEnabled = False else: renderEnabled = True if self.ui.group_time.isChecked(): self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot(QTime) def slot_updateEndTime(self, time): if time <= self.ui.te_start.time(): self.ui.te_start.setTime(time) renderEnabled = False else: renderEnabled = True if self.ui.group_time.isChecked(): self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot(bool) def slot_transportChecked(self, yesNo): if yesNo: renderEnabled = bool(self.ui.te_end.time() > self.ui.te_start.time()) else: renderEnabled = True self.ui.b_render.setEnabled(renderEnabled) @pyqtSlot() def slot_updateProgressbar(self): time = int(jacklib.get_current_transport_frame(self.fJackClient)) / self.fSampleRate self.ui.progressBar.setValue(time) if time > self.fMaxTime or (self.fLastTime > time and not self.fFreewheel): self.slot_renderStop() self.fLastTime = time def saveSettings(self): settings = QSettings("Cadence", "Cadence-Render") if self.ui.rb_mono.isChecked(): channels = 1 elif self.ui.rb_stereo.isChecked(): channels = 2 else: channels = self.ui.sb_channels.value() settings.setValue("Geometry", self.saveGeometry()) settings.setValue("OutputFolder", self.ui.le_folder.text()) settings.setValue("FilenamePrefix", self.ui.le_prefix.text()) settings.setValue("EncodingFormat", self.ui.cb_format.currentText()) settings.setValue("EncodingDepth", self.ui.cb_depth.currentText()) settings.setValue("EncodingChannels", channels) settings.setValue("UseTransport", self.ui.group_time.isChecked()) settings.setValue("StartTime", self.ui.te_start.time()) settings.setValue("EndTime", self.ui.te_end.time()) def loadSettings(self): settings = QSettings("Cadence", "Cadence-Render") self.restoreGeometry(settings.value("Geometry", "")) outputFolder = settings.value("OutputFolder", HOME) if os.path.exists(outputFolder): self.ui.le_folder.setText(outputFolder) self.ui.le_prefix.setText(settings.value("FilenamePrefix", "jack_capture_")) encFormat = settings.value("EncodingFormat", "Wav", type=str) for i in range(self.ui.cb_format.count()): if self.ui.cb_format.itemText(i) == encFormat: self.ui.cb_format.setCurrentIndex(i) break encDepth = settings.value("EncodingDepth", "Float", type=str) for i in range(self.ui.cb_depth.count()): if self.ui.cb_depth.itemText(i) == encDepth: self.ui.cb_depth.setCurrentIndex(i) break encChannels = settings.value("EncodingChannels", 2, type=int) if encChannels == 1: self.ui.rb_mono.setChecked(True) elif encChannels == 2: self.ui.rb_stereo.setChecked(True) else: self.ui.rb_outro.setChecked(True) self.ui.sb_channels.setValue(encChannels) self.ui.group_time.setChecked(settings.value("UseTransport", False, type=bool)) self.ui.te_start.setTime(settings.value("StartTime", self.ui.te_start.time(), type=QTime)) self.ui.te_end.setTime(settings.value("EndTime", self.ui.te_end.time(), type=QTime)) def closeEvent(self, event): self.saveSettings() if self.fJackClient: jacklib.client_close(self.fJackClient) QDialog.closeEvent(self, event) def done(self, r): QDialog.done(self, r) self.close()
def __createProgramEntry(self, description, exe, versionCommand = "", versionStartsWith = "", versionPosition = 0, version = "", versionCleanup = None, versionRe = None): """ Private method to generate a program entry. @param description descriptive text (string or QString) @param exe name of the executable program (string) @param versionCommand command line switch to get the version info (string) if this is empty, the given version will be shown. @param versionStartsWith start of line identifying version info (string) @param versionPosition index of part containing the version info (integer) @keyparam version version string to show (string) @keyparam versionCleanup tuple of two integers giving string positions start and stop for the version string (tuple of integers) @keyparam versionRe regexp to determine the line identifying version info (string). Takes precedence over versionStartsWith. @return version string of detected or given version (string) """ itm = QTreeWidgetItem(self.programsList, QStringList(description)) font = itm.font(0) font.setBold(True) itm.setFont(0, font) if not exe: itm.setText(1, self.trUtf8("(not configured)")) else: if os.path.isabs(exe): if not Utilities.isExecutable(exe): exe = "" else: exe = Utilities.getExecutablePath(exe) if exe: if versionCommand and \ (versionStartsWith != "" or \ (versionRe is not None and versionRe != "")) and \ versionPosition: proc = QProcess() proc.setProcessChannelMode(QProcess.MergedChannels) proc.start(exe, QStringList(versionCommand)) finished = proc.waitForFinished(10000) if finished: output = \ unicode(proc.readAllStandardOutput(), str(Preferences.getSystem("IOEncoding")), 'replace') if versionRe is None: versionRe = "^%s" % re.escape(versionStartsWith) versionRe = re.compile(versionRe, re.UNICODE) for line in output.splitlines(): if versionRe.search(line): try: version = line.split()[versionPosition] if versionCleanup: version = \ version[versionCleanup[0]:versionCleanup[1]] break except IndexError: version = self.trUtf8("(unknown)") else: version = self.trUtf8("(not executable)") itm2 = QTreeWidgetItem(itm, QStringList() << exe << version) itm.setExpanded(True) else: itm.setText(1, self.trUtf8("(not found)")) QApplication.processEvents() self.programsList.header().resizeSections(QHeaderView.ResizeToContents) self.programsList.header().setStretchLastSection(True) return version
class GDALLocationInfoMapTool(QgsMapTool): def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.cursor = QCursor(QPixmap(":/plugins/AGSInfo/icons/cursor.png"), 1, 1) def activate(self): self.canvas.setCursor(self.cursor) def parseJSON(self, jsonLocationInfo): if jsonLocationInfo.has_key("error"): err_msg = "" err_msg += "Error code: " + str(jsonLocationInfo["error"]["code"]) + "\n" err_msg += "Error message: \n" + jsonLocationInfo["error"]["message"] + "\n" QMessageBox.warning(self.canvas, self.tr("Error"), str(err_msg) ) else: results = jsonLocationInfo["results"] if (len(results) == 0): QMessageBox.warning(self.canvas, self.tr("Warning"), self.tr("Not found any objects") ) return #locationInfoPure = "" locationInfoPure = {} #i = 1 for result in results: attrs = {} #locationInfoPure += str(i) + ".\n" #locationInfoPure += "\tlayerName: " + result["layerName"] + "\n" #locationInfoPure += "\tvalue: " + result["value"] + "\n" #locationInfoPure += "\tattributes: " + str(result["attributes"]) + "\n" #i += 1 attrs.update({"layerName": result["layerName"]}) attrs.update({"Shape": result["attributes"]["Shape"]}) attrs.update({"DESCRIPTION": result["attributes"]["DESCRIPTION"]}) locationInfoPure.update({result["attributes"]["OBJECTID"]: attrs}) #QMessageBox.information(self.canvas, # self.tr("Info"), # locationInfoPure # ) self.a = GDALLocationInfoForm(locationInfoPure) self.a.show() def parseXML(self, xmlLocationInfo): #locationInfoPure = u"" locationInfoPure = {} #i = 1 for child in xmlLocationInfo: attrs = {} #locationInfoPure += u"" + str(i) + u".\n" #locationInfoPure += u"\t" + string.join([string.join( (k, str(child.attrib[k])), ":") for k in child.attrib.keys() ],",") + u".\n" #locationInfoPure += string.join([ string.join( (k, child.attrib[k]), ":") for k in child.attrib.keys() ],"\n") + u".\n" #i += 1 for k in child.attrib.keys(): attrs.update({k: child.attrib[k]}) locationInfoPure.update({child.attrib["OBJECTID"]: attrs}) #QMessageBox.information(self.canvas, # self.tr("Info"), # locationInfoPure # ) self.a = GDALLocationInfoForm(locationInfoPure) self.a.show() def canvasReleaseEvent(self, event): #self.a = GDALLocationInfoForm({"a":{"asd1":"xcvsdfvss", "asd2":"xcvsdfvss", "asd3":"xcvsdfvss"}, "b":{"asd1":"xcvsdfvss", "asd2":"xcvsdfvss", "asd3":"xcvsdfvss"}}) #self.a.show() currentlayer = self.canvas.currentLayer() if currentlayer is None: QMessageBox.warning(self.canvas, self.tr("No active layer"), self.tr("To identify features, you must choose an active layer by clicking on its name in the legend") ) return if currentlayer.type() != QgsMapLayer.RasterLayer: QMessageBox.warning(self.canvas, self.tr("Wrong layer type"), self.tr("This tool works only for vector layers. Please select another layer in legend and try again") ) return self.canvas.setCursor(Qt.WaitCursor) point = self.canvas.getCoordinateTransform().toMapCoordinates(event.x(), event.y()) self.process = QProcess(self) GdalTools_utils.setProcessEnvironment(self.process) self.process.start("gdallocationinfo", ["-xml","-b", "1" ,"-geoloc", currentlayer.source(), str(point[0]), str(point[1])], QIODevice.ReadOnly) self.process.waitForFinished() self.canvas.setCursor(self.cursor) if(self.process.exitCode() != 0): err_msg = str(self.process.readAllStandardError()) if err_msg != '': QMessageBox.warning(self.canvas, self.tr("Error"), err_msg ) else: QMessageBox.warning(self.canvas, self.tr("Error"), str(self.process.readAllStandardOutput()) ) else: data = str(self.process.readAllStandardOutput()); root = ET.fromstring(data) alert_node = root.find('Alert') if (alert_node != None): QMessageBox.warning(self.canvas, self.tr("Warning"), alert_node.text ) return location_info_node = root.find('BandReport').find('LocationInfo') try: jsonLocationInfo = json.JSONDecoder().decode(location_info_node.text.encode("utf-8")) self.parseJSON(jsonLocationInfo) return except ValueError as err: print "json parse error" pass try: data = location_info_node.text.encode("utf-8") #data.decode("cp1251").encode("utf-8") xmlLocationInfo = ET.fromstring(data) self.parseXML(xmlLocationInfo) return except ValueError as err: print "xml parse error: ", err pass
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.group0 = QGroupBox() self.group0.setTitle(' Source ') self.source, self.infile = QComboBox(), QLineEdit(path.expanduser("~")) self.source.addItems(['Local File', 'Remote URL']) self.source.currentIndexChanged.connect(self.on_source_changed) self.infile.setPlaceholderText(' /full/path/to/file.html ') self.infile.setCompleter(self.completer) self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open.setCursor(QCursor(Qt.PointingHandCursor)) self.open.clicked.connect(lambda: self.infile.setText( str( QFileDialog.getOpenFileName( self.dock, "Open a File to read from", path.expanduser( "~"), ';;'.join([ '{}(*.{})'.format(e.upper(), e) for e in ['html', 'webp', 'webm', 'svg', 'css', 'js', '*'] ]))))) self.inurl, self.output = QLineEdit('http://www.'), QTextEdit() self.inurl.setPlaceholderText( 'http://www.full/url/to/remote/file.html') self.inurl.hide() vboxg0 = QVBoxLayout(self.group0) for each_widget in (self.source, self.infile, self.open, self.inurl): vboxg0.addWidget(each_widget) self.group1 = QGroupBox() self.group1.setTitle(' Mobile ') self.ckcss1 = QCheckBox('Run in full screen using current resolution') self.ckcss2 = QCheckBox('Disable touch mode and use keypad mode') self.ckcss3 = QCheckBox( 'Disable touch mode but allow to use the mouse') self.ckcss4 = QCheckBox( 'Enable mouse,disable pointer & zoom emulation') self.ckcss5 = QCheckBox('Start the Mobile version of the browser') self.ckcss6 = QCheckBox('Start the Tablet version of the browser') self.ckcss7 = QCheckBox('Emulate hardware with Menu and Back keys') self.ckcss8 = QCheckBox('Start the browser in Kiosk mode') self.width, self.height = QSpinBox(), QSpinBox() self.zoom, self.ram, self.dpi = QSpinBox(), QSpinBox(), QSpinBox() self.cpulag, self.gpulag = QSpinBox(), QSpinBox() self.lang, self.agent = QComboBox(), QComboBox() self.lang.addItems(['EN', 'ES', 'PT', 'JA', 'ZH', 'DE', 'RU', 'FR']) self.agent.addItems(['Default', 'Android', 'MeeGo', 'Desktop']) self.fonts = QLineEdit() self.width.setMaximum(9999) self.width.setMinimum(100) self.width.setValue(480) self.height.setMaximum(9999) self.height.setMinimum(100) self.height.setValue(800) self.zoom.setMaximum(999) self.zoom.setMinimum(1) self.zoom.setValue(100) self.ram.setMaximum(999) self.ram.setMinimum(1) self.ram.setValue(100) self.dpi.setMaximum(200) self.dpi.setMinimum(50) self.dpi.setValue(96) self.cpulag.setMaximum(9999) self.cpulag.setMinimum(0) self.cpulag.setValue(1) self.gpulag.setMaximum(9999) self.gpulag.setMinimum(0) self.gpulag.setValue(1) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, QLabel('Width Pixels of the emulated device screen'), self.width, QLabel('Height Pixels of the emulated device screen'), self.height, QLabel('Zoom Percentage of emulated screen'), self.zoom, QLabel('RAM MegaBytes of the emulated device'), self.ram, QLabel('Language of the emulated device'), self.lang, QLabel('D.P.I. of the emulated device'), self.dpi, QLabel('User-Agent of the emulated device'), self.agent, QLabel('CPU Core Lag Miliseconds of emulated device'), self.cpulag, QLabel('GPU Video Lag Miliseconds of emulated device'), self.gpulag, QLabel('Extra Fonts Directory Full Path'), self.fonts): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' General ') self.nice, self.opera = QSpinBox(), QLineEdit(path.expanduser("~")) self.nice.setValue(20) self.nice.setMaximum(20) self.nice.setMinimum(0) self.opera.setCompleter(self.completer) if path.exists(CONFIG_FILE): with codecs.open(CONFIG_FILE, encoding='utf-8') as fp: self.opera.setText(fp.read()) self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open2.setCursor(QCursor(Qt.PointingHandCursor)) self.open2.clicked.connect(lambda: self.opera.setText( str( QFileDialog.getOpenFileName( self.dock, "Open Opera Mobile Emulator", path.expanduser("~"), 'Opera Mobile Emulator Executable(opera-mobile-emulator)')) )) self.help1 = QLabel('''<a href= "http://www.opera.com/developer/mobile-emulator"> <small><center>Download Opera Mobile Emulator !</a>''') self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse) self.help1.setOpenExternalLinks(True) vboxg4 = QVBoxLayout(self.group2) for each_widget in (QLabel(' Backend CPU priority: '), self.nice, QLabel(' Opera Mobile Emulator Full Path: '), self.opera, self.open2, self.help1): vboxg4.addWidget(each_widget) self.button = QPushButton('Preview on Mobile') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(100, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) glow.setEnabled(True) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget(( QLabel('<b>Mobile Browser Emulator'), self.group0, self.group1, self.group2, self.output, self.button, )) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Mobile") QPushButton( QIcon.fromTheme("help-about"), 'About', self.dock).clicked.connect( lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def run(self): ' run the string replacing ' self.output.clear() self.button.setEnabled(False) self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) if self.source.currentText() == 'Local File': target = 'file://' + str(self.infile.text()).strip() else: target = self.inurl.text() self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Arguments')) cmd = ' '.join( ('nice --adjustment={}'.format(self.nice.value()), '"{}"'.format( self.opera.text()), '-fullscreen' if self.ckcss1.isChecked() is True else '', '-notouch' if self.ckcss2.isChecked() is True else '', '-notouchwithtouchevents' if self.ckcss3.isChecked() is True else '', '-usemouse' if self.ckcss4.isChecked() is True else '', '-mobileui' if self.ckcss5.isChecked() is True else '', '-tabletui' if self.ckcss6.isChecked() is True else '', '-hasmenuandback' if self.ckcss7.isChecked() is True else '', '-k' if self.ckcss8.isChecked() is True else '', '-displaysize {}x{}'.format( self.width.value(), self.height.value()), '-displayzoom {}'.format( self.zoom.value()), '-mem {}M'.format(self.ram.value()), '-lang {}'.format(self.lang.currentText()), '-ppi {}'.format( self.dpi.value()), '-extra-fonts {}'.format(self.fonts.text()) if str(self.fonts.text()).strip() is not '' else '', '-user-agent-string {}'.format( self.agent.currentText()), '-delaycorethread {}'.format( self.cpulag.value()), '-delayuithread {}'.format( self.gpulag.value()), '-url "{}"'.format(target))) self.output.append(self.formatInfoMsg( 'INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append( self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(cmd))) self.button.setEnabled(True) return self.output.setFocus() self.output.selectAll() self.button.setEnabled(True) def on_source_changed(self): ' do something when the desired source has changed ' if self.source.currentText() == 'Local File': self.open.show() self.infile.show() self.inurl.hide() else: self.inurl.show() self.open.hide() self.infile.hide() def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) self.output.selectAll() self.output.setFocus() def readOutput(self): """Read and append output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append errors to the logBrowser""" self.output.append( self.formatErrorMsg(str(self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def finish(self): ' save when finish ' with codecs.open(CONFIG_FILE, "w", encoding='utf-8') as fp: fp.write(self.opera.text())
class Services (): def __init__(self): self.service_bin = '/usr/bin/service' self.services = ('apache2', 'mysql', 'postfix', 'ssh', 'postgresql') self.initd = "/etc/init.d/" self.proceso = QProcess() self.proceso.connect(self.proceso, SIGNAL("readyReadStandardOutput()"), self.readStdout) self.installed_services = [] for serv in self.services: if os.path.isfile(self.initd + serv): self.installed_services.append(serv) def readStdout(self): self.mensaje = self.proceso.readAllStandardOutput() def apache(self): status = None run = False if not os.path.isfile(self.initd + self.services[0]): status = 2 else: run = True if run: #apacheStatus = Popen(self.service_bin + ' ' + self.services[0] + ' status', stdout=PIPE, shell=True).communicate()[0] self.run_command(self.services[0], 'status') apacheStatus = self.mensaje resultado = re.search('NOT running', apacheStatus) if resultado: status = 0 else: status = 1 return status def mysql(self): status = None run = False if not os.path.isfile(self.initd + self.services[1]): status = 2 else: run = True if run: #mysqlStatus = Popen(self.service_bin + ' ' + self.services[1] + ' status', stdout=PIPE, shell=True).communicate()[0] self.run_command(self.services[1], 'status') mysqlStatus = self.mensaje resultado = re.search('stop/waiting', mysqlStatus) if resultado: status = 0 else: status = 1 return status def postfix(self): status = None run = False if not os.path.isfile(self.initd + self.services[2]): status = 2 else: run = True if run: #postfixStatus = Popen(self.service_bin + ' ' + self.services[2] + ' status', stdout=PIPE, shell=True).communicate()[0] self.run_command(self.services[2], 'status') postfixStatus = self.mensaje resultado = re.search('not running', postfixStatus) if resultado: status = 0 else: status = 1 return status def ssh(self): status = None run = False if not os.path.isfile(self.initd + self.services[3]): status = 2 else: run = True if run: #sshStatus = Popen(self.service_bin + ' ' + self.services[3] + ' status', stdout=PIPE, shell=True).communicate()[0] self.run_command(self.services[3], 'status') sshStatus = self.mensaje resultado = re.search('stop/waiting', sshStatus) if resultado: status = 0 else: status = 1 return status def postgresql(self): status = None run = False if not os.path.isfile(self.initd + self.services[4]): status = 2 else: run = True if run: #postgreStatus = Popen(self.service_bin + ' ' + self.services[4] + ' status', stdout=PIPE, shell=True).communicate()[0] self.run_command(self.services[4], 'status') postgreStatus = self.mensaje resultado = re.search('8.4/main', postgreStatus) if not resultado: status = 0 else: status = 1 return status def stop_all(self): for servicio in self.installed_services: self.run_command(servicio, 'stop') def run_command(self, servicio, accion): self.proceso.start(self.service_bin + ' ' + servicio + ' ' + accion) self.proceso.waitForFinished()
class GdalToolsBaseDialog(QDialog, Ui_Dialog): def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand): QDialog.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.iface = iface self.process = QProcess(self) Utils.setProcessEnvironment(self.process) self.connect(self.process, SIGNAL("error(QProcess::ProcessError)"), self.processError) self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished) self.setupUi(self) self.arguments = [] self.editCmdBtn.setIcon(QIcon(":/icons/edit.png")) self.connect(self.editCmdBtn, SIGNAL("toggled(bool)"), self.editCommand) self.resetCmdBtn.setIcon(QIcon(":/icons/reset.png")) self.connect(self.resetCmdBtn, SIGNAL("clicked()"), self.resetCommand) self.editCommand(False) self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject) self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept) self.connect(self.buttonBox, SIGNAL("helpRequested()"), self.help) self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True) self.plugin = pluginBase self.connect(self.plugin, SIGNAL("valuesChanged(PyQt_PyObject)"), self.refreshArgs) self.pluginLayout.addWidget(self.plugin) self.plugin.setFocus() self.setWindowTitle(pluginName) self.setPluginCommand(pluginCommand) def setPluginCommand(self, cmd): # on Windows replace the .py with .bat extension if platform.system() == "Windows" and cmd[-3:] == ".py": self.command = cmd[:-3] + ".bat" else: self.command = cmd if cmd[-3:] == ".py": self.helpFileName = cmd[:-3] + ".html" else: self.helpFileName = cmd + ".html" def editCommand(self, enabled): if not self.commandIsEnabled(): return self.editCmdBtn.setChecked(enabled) self.resetCmdBtn.setEnabled(enabled) self.textEditCommand.setReadOnly(not enabled) self.controlsWidget.setEnabled(not enabled) self.emit(SIGNAL("refreshArgs()")) def resetCommand(self): if not self.commandIsEditable(): return self.emit(SIGNAL("refreshArgs()")) def commandIsEditable(self): return self.commandIsEnabled() and self.editCmdBtn.isChecked() def setCommandViewerEnabled(self, enable): if not enable: self.editCommand(False) self.commandWidget.setEnabled(enable) def commandIsEnabled(self): return self.commandWidget.isEnabled() def reject(self): if self.process.state() != QProcess.NotRunning: ret = QMessageBox.warning( self, self.tr("Warning"), self. tr("The command is still running. \nDo you want terminate it anyway?" ), QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: return self.disconnect(self.process, SIGNAL("error(QProcess::ProcessError)"), self.processError) self.disconnect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished) self.emit(SIGNAL("closeClicked()")) def accept(self): self.emit(SIGNAL("okClicked()")) def help(self): self.emit(SIGNAL("helpClicked()")) def processError(self, error): self.emit(SIGNAL("processError(QProcess::ProcessError)"), error) def processFinished(self, exitCode, status): self.emit(SIGNAL("processFinished(int, QProcess::ExitStatus)"), exitCode, status) # show the online tool documentation in the default browser def onHelp(self): helpPath = Utils.getHelpPath() if helpPath == '': url = QUrl("http://www.gdal.org/" + self.helpFileName) else: url = QUrl.fromLocalFile(helpPath + '/' + self.helpFileName) QDesktopServices.openUrl(url) # called when a value in the plugin widget interface changed def refreshArgs(self, args): self.arguments = [unicode(a) for a in args] if not self.commandIsEnabled(): self.textEditCommand.setPlainText(self.command) else: self.textEditCommand.setPlainText( self.command + " " + Utils.escapeAndJoin(self.arguments)) # enables the OK button def enableRun(self, enable=True): self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable) # start the command execution def onRun(self): self.enableRun(False) self.setCursor(Qt.WaitCursor) if not self.commandIsEditable(): #print(self.command+' '+unicode(self.arguments)) self.process.start(self.command, self.arguments, QIODevice.ReadOnly) else: self.process.start(self.textEditCommand.toPlainText(), QIODevice.ReadOnly) # stop the command execution def stop(self): self.enableRun(True) self.setCursor(Qt.ArrowCursor) self.process.kill() # called on closing the dialog, stop the process if it's running def onClosing(self): self.stop() QDialog.reject(self) # called if an error occurs when the command has not already finished, shows the occurred error message def onError(self, error): if error == QProcess.FailedToStart: msg = QCoreApplication.translate( "GdalTools", "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program." ) elif error == QProcess.Crashed: msg = QCoreApplication.translate( "GdalTools", "The process crashed some time after starting successfully.") else: msg = QCoreApplication.translate("GdalTools", "An unknown error occurred.") QErrorMessage(self).showMessage(msg) QApplication.processEvents() # give the user chance to see the message self.stop() # called when the command finished its execution, shows an error message if there's one # and, if required, load the output file in canvas def onFinished(self, exitCode, status): if status == QProcess.CrashExit: self.stop() return if self.command.find("gdalinfo") != -1 and exitCode == 0: self.emit(SIGNAL("finished(bool)"), self.loadCheckBox.isChecked()) self.stop() return # show the error message if there's one, otherwise show the process output message msg = unicode(self.process.readAllStandardError()) if msg == '': outMessages = unicode( self.process.readAllStandardOutput()).splitlines() # make sure to not show the help for m in outMessages: m = string.strip(m) if m == '': continue # TODO fix this #if m.contains( QRegExp( "^(?:[Uu]sage:\\s)?" + QRegExp.escape(self.command) + "\\s" ) ): # if msg.isEmpty(): # msg = self.tr ( "Invalid parameters." ) # break #if m.contains( QRegExp( "0(?:\\.+[1-9]0{1,2})+" ) ): # continue if msg: msg += "\n" msg += m QErrorMessage(self).showMessage(msg.replace("\n", "<br>")) if exitCode == 0: self.emit(SIGNAL("finished(bool)"), self.loadCheckBox.isChecked()) self.stop()
class TerreImageProcess(): def __init__(self): self.process = QProcess() self.process.error[QProcess.ProcessError].connect(self.error_management) self.env = QProcessEnvironment().systemEnvironment() self.set_otb_process_env_default() self.command = "" def run_process(self, command): logger.info(u"Running {}".format(command)) self.process.setProcessEnvironment(self.env) # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH"))) # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH"))) # logger.debug("Environ : PATH {}".format(os.environ["PATH"])) # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty"))) self.command = command self.process.start(command) if self.process.waitForStarted(): self.process.waitForFinished(-1) exit_code = self.process.exitCode() if exit_code != 0: self.error_management(exit_code) result = self.process.readAllStandardOutput() # logger.debug(" {} {}".format(type(result), result)) error = self.process.readAllStandardError().data() # logger.debug(repr(error)) if not error in ["\n", ""]: logger.error("error : %s"%(error)) output = result.data() logger.info(output) return result else: code_d_erreur = self.process.error() self.error_management(code_d_erreur) return None def error_management(self, errorCode): dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError", 127:"Other, The application may not have been found"} try: type_qt_error = dic_err[errorCode] logger.error(u"Error {} {}".format(errorCode, type_qt_error)) except KeyError: type_qt_error = "" error = self.process.readAllStandardError().data() logger.error(error) logger.error( self.process.readAllStandardOutput()) try: raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}{}".format(self.command, type_qt_error, error )) except UnicodeError: raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}".format(self.command, type_qt_error)) def set_env_var(self, varname, varval, append = False, pre = False): if append == True: if pre == False: # insert value at the end of the variable self.env.insert(varname, self.env.value(varname) + os.pathsep + varval) else: # insert value in head self.env.insert(varname, varval + os.pathsep + self.env.value(varname)) else: # replace value if existing self.env.insert(varname, varval) # logger.debug("env {} {}".format(varname, self.env.value(varname))) def set_otb_process_env(self): dirname = os.path.dirname(os.path.abspath(__file__)) self.set_env_var("OTB_APPLICATION_PATH", os.path.join(dirname, "win32", "plugin"), pre=True) self.set_env_var("PATH", os.path.join(dirname, "win32", "bin"), append = False, pre=True) def set_otb_process_env_custom(self, otb_app_path="", path=""): """ Add the given values to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True) self.set_env_var("PATH", path, append = False, pre=True) def set_otb_process_env_default(self): """ Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", terre_image_configuration.OTB_APPLICATION_PATH, pre=True) self.set_env_var("PATH", terre_image_configuration.PATH, append = True, pre=True) if terre_image_configuration.LD_LIBRARY_PATH: self.set_env_var("LD_LIBRARY_PATH", terre_image_configuration.LD_LIBRARY_PATH, append = True, pre=True)
class RestEditor(WithSingleIO, QWidget): """Restructredtext editor """ def __init__(self, params, parent=None): QWidget.__init__(self, parent) self.setMinimumWidth(300) self.setMinimumHeight(300) # create widgets self._editor_widget = mixin( WithFind, WithMqEditIO, WithBasicIdentationManager, WithLineHighlight, WithFixedFont, WithLineNumbers, WithViewPortMargins, WithWordCompletionMulty_, WithCompletion, QPlainTextEdit)(self) self.webview = QWebView(self) #self.webview.load(QUrl("/home/maiquel/develop/developing/main/qt/qadoc/bin/__builds/documents.html")) self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget(self._editor_widget) self.splitter.addWidget(self.webview) self.splitter.setSizes([self.size().width(), self.size().width()]) self.splitterv = QSplitter(Qt.Vertical) self.splitterv.addWidget(self.splitter) self.log_widget = QPlainTextEdit() self.splitterv.addWidget(self.log_widget) layout = QVBoxLayout(self) layout.addWidget(self.splitterv) layout.setMargin(0) self.setLayout(layout) # proc_compile self.proc_compile = QProcess() self.proc_compile.finished.connect(self.proc_compile_finished) self.proc_compile.error.connect(self.proc_compile_error) self.proc_compile.readyReadStandardOutput.connect(self.proc_compile_readyReadStandardOutput) self.proc_compile.readyReadStandardError.connect(self.proc_compile_readyReadStandardError) WithSingleIO.__init__(self, params) def bw_add_command_list(self, command_list): command_list += [ ("generate preview restructuretext", "pp", 1.0, "self.get_current_widget().command_generate_preview('rst2html')"), ] super(RestEditor, self).bw_add_command_list(command_list) self._editor_widget.bw_add_command_list(command_list) command_list += [ ("focus editor", "fe", 0.5, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self._editor_widget.setFocus();"), ("focus preview", "fp", 0.5, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self.webview.setFocus();"), ] def command_generate_preview(self, backend): self.command_save_file() if not os.path.exists(TEMP_DIR): os.mkdir(TEMP_DIR) temp_source_file = open(TEMP_DIR + 'pr.rst','wt') temp_source_file.write(self._editor_widget.toPlainText()) temp_source_file.close() self.compile(backend + " --stylesheet=./widgets/rst2html.style " + TEMP_DIR + "pr.rst" + " " + self.get_html_output()) if self.webview.url() != QUrl("file://" + self.get_html_output()): self.webview.load(QUrl(self.get_html_output())) def compile(self, command): self.log(command) self.proc_compile.start(command) def bw_lock_command_window(self): return self._editor_widget.completer.popup().isVisible() def focusInEvent(self, focus_event): super(RestEditor, self).focusInEvent(focus_event) self._editor_widget.setFocus() def get_html_output(self): return TEMP_DIR + "pr.html" def proc_compile_finished(self, result, exit_status): self.log("compilation finished") if self.webview.url().toString() == "": self.webview.load(QUrl(self.get_html_output())) else: self.webview.reload() def proc_compile_error(self, q_process_error): self.log("compilation error") print(q_process_error) def proc_compile_readyReadStandardOutput(self): result = self.proc_compile.readAllStandardOutput(); self.log(result) def proc_compile_readyReadStandardError(self): result = str(self.proc_compile.readAllStandardError()) self.log(result) def log(self, text): self.log_widget.appendPlainText(text)
def run_process(fused_command, read_output = False): # print "run process", fused_command # qprocess = QProcess() # set_process_env(qprocess) # code_de_retour = qprocess.execute(fused_command) # print "code de retour", code_de_retour # logger.info("command: ") # logger.info(fused_command) # logger.info("code de retour" + str(code_de_retour)) # # # if not qprocess.waitForStarted(): # # # handle a failed command here # # print "qprocess.waitForStarted()" # # return # # # # if not qprocess.waitForReadyRead(): # # # handle a timeout or error here # # print "qprocess.waitForReadyRead()" # # return # # #if not qprocess.waitForFinished(1): # # # qprocess.kill() # # # qprocess.waitForFinished(1) # # # if read_output: # # # logger.info("Erreur") # code_d_erreur = qprocess.error() # dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } # logger.info("Code de retour: " + str(code_d_erreur)) # logger.info(dic_err[code_d_erreur]) # # print "get output" # output = str(qprocess.readAllStandardOutput()) # # print "output", output # print 'end output' process = QProcess() process.start(fused_command) if process.waitForStarted(): process.waitForFinished(-1) exit_code = process.exitCode() logger.info("Code de sortie : " + str(exit_code)) if exit_code < 0: code_d_erreur = process.error().data dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) result = process.readAllStandardOutput() # print type(result), result error = process.readAllStandardError().data() # print repr(error) if not error == "\n": logger.info("error : " + "\'" + str(error) + "\'") logger.info("output : " + result.data() + "fin output") return result else: code_d_erreur = process.error() dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) return None
class ConsoleWidget(QPlainTextEdit): def __init__(self): QPlainTextEdit.__init__(self, '>>> ') self.setUndoRedoEnabled(False) self.apply_editor_style() self.setToolTip(self.tr("Show/Hide (F4)")) self.moveCursor(QTextCursor.EndOfLine) self._patIsWord = re.compile('\w+') self.prompt = '>>> ' self._console = console.Console() self._history = [] self.history_index = 0 self._current_command = '' self._braces = None self.imports = ['import __builtin__'] self.patFrom = re.compile('^(\\s)*from ((\\w)+(\\.)*(\\w)*)+ import') self.patImport = re.compile('^(\\s)*import (\\w)+') self.patObject = re.compile('[^a-zA-Z0-9_\\.]') self.completer = completer_widget.CompleterWidget(self) self.okPrefix = QRegExp('[.)}:,\]]') self._pre_key_press = { Qt.Key_Enter: self._enter_pressed, Qt.Key_Return: self._enter_pressed, Qt.Key_Tab: self._tab_pressed, Qt.Key_Home: self._home_pressed, Qt.Key_PageUp: lambda x: True, Qt.Key_PageDown: lambda x: True, Qt.Key_Left: self._left_pressed, Qt.Key_Up: self._up_pressed, Qt.Key_Down: self._down_pressed, Qt.Key_Backspace: self._backspace, } #Create Context Menu self._create_context_menu() #Set Font self.set_font() #Create Highlighter parts_scanner, code_scanner, formats = \ syntax_highlighter.load_syntax(python_syntax.syntax) self.highlighter = syntax_highlighter.SyntaxHighlighter( self.document(), parts_scanner, code_scanner, formats) self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlight_current_line) self.highlight_current_line() self._proc = QProcess(self) self.connect(self._proc, SIGNAL("readyReadStandardOutput()"), self._python_path_detected) self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"), self.process_error) self._add_system_path_for_frozen() def _add_system_path_for_frozen(self): try: self._proc.start(settings.PYTHON_PATH, [resources.GET_SYSTEM_PATH]) except Exception as reason: logger.warning('Could not get system path, error: %r' % reason) def _python_path_detected(self): paths = self._proc.readAllStandardOutput().data().decode('utf8') add_system_path = ('import sys; ' 'sys.path = list(set(sys.path + %s))' % paths) self._write(add_system_path) self._proc.deleteLater() def process_error(self, error): message = '' if error == 0: message = 'Failed to start' else: message = 'Error during execution, QProcess error: %d' % error logger.warning('Could not get system path, error: %r' % message) def set_font(self, family=settings.FONT_FAMILY, size=settings.FONT_SIZE): font = QFont(family, size) self.document().setDefaultFont(font) def _create_context_menu(self): self.popup_menu = self.createStandardContextMenu() self.popup_menu.clear() actionCut = self.popup_menu.addAction(self.tr("Cut")) actionCopy = self.popup_menu.addAction(self.tr("Copy")) actionPaste = self.popup_menu.addAction(self.tr("Paste")) actionClean = self.popup_menu.addAction(self.tr("Clean Console")) actionCopyHistory = self.popup_menu.addAction(self.tr("Copy History")) actionCopyConsoleContent = self.popup_menu.addAction( self.tr("Copy Console Content")) self.popup_menu.addAction(actionCut) self.popup_menu.addAction(actionCopy) self.popup_menu.addAction(actionPaste) self.popup_menu.addSeparator() self.popup_menu.addAction(actionClean) self.popup_menu.addSeparator() self.popup_menu.addAction(actionCopyHistory) self.popup_menu.addAction(actionCopyConsoleContent) self.connect(actionCut, SIGNAL("triggered()"), self._cut) self.connect(actionCopy, SIGNAL("triggered()"), self.copy) self.connect(actionPaste, SIGNAL("triggered()"), self._paste) self.connect(actionClean, SIGNAL("triggered()"), self._clean_console) self.connect(actionCopyHistory, SIGNAL("triggered()"), self._copy_history) self.connect(actionCopyConsoleContent, SIGNAL("triggered()"), self._copy_console_content) def _cut(self): event = QKeyEvent(QEvent.KeyPress, Qt.Key_X, Qt.ControlModifier, "x") self.keyPressEvent(event) def _paste(self): if self.textCursor().hasSelection(): self.moveCursor(QTextCursor.End) self.paste() def _clean_console(self): self.clear() self._add_prompt() def _copy_history(self): historyContent = '\n'.join(self._history) clipboard = QApplication.instance().clipboard() clipboard.setText(historyContent) def _copy_console_content(self): content = self.toPlainText() clipboard = QApplication.instance().clipboard() clipboard.setText(content) def setCursorPosition(self, position, mode=QTextCursor.MoveAnchor): self.moveCursor(QTextCursor.StartOfLine, mode) for i in range(len(self.prompt) + position): self.moveCursor(QTextCursor.Right, mode) def _check_event_on_selection(self, event): if event.text(): cursor = self.textCursor() begin_last_block = (self.document().lastBlock().position() + len(self.prompt)) if cursor.hasSelection() and \ ((cursor.selectionEnd() < begin_last_block) or (cursor.selectionStart() < begin_last_block)): self.moveCursor(QTextCursor.End) def _enter_pressed(self, event): self._write_command() return True def _tab_pressed(self, event): self.textCursor().insertText(' ' * settings.INDENT) return True def _home_pressed(self, event): if event.modifiers() == Qt.ShiftModifier: self.setCursorPosition(0, QTextCursor.KeepAnchor) else: self.setCursorPosition(0) return True def _left_pressed(self, event): return self._get_cursor_position() == 0 def _up_pressed(self, event): if self.history_index == len(self._history): command = self.document().lastBlock().text()[len(self.prompt):] self._current_command = command self._set_command(self._get_prev_history_entry()) return True def _down_pressed(self, event): if len(self._history) == self.history_index: command = self._current_command else: command = self._get_next_history_entry() self._set_command(command) return True def _backspace(self, event): cursor = self.textCursor() selected_text = cursor.selectedText() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) text = cursor.selectedText()[len(self.prompt):] if (len(text) % settings.INDENT == 0) and text.isspace(): cursor.movePosition(QTextCursor.StartOfLine) cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, settings.INDENT) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, settings.INDENT) cursor.removeSelectedText() return True elif (selected_text == self.document().lastBlock().text()[len(self.prompt):]): self.textCursor().removeSelectedText() return True return self._get_cursor_position() == 0 def keyPressEvent(self, event): if self.completer.popup().isVisible(): if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab): event.ignore() self.completer.popup().hide() return elif event.key in (Qt.Key_Space, Qt.Key_Escape, Qt.Key_Backtab): self.completer.popup().hide() self._check_event_on_selection(event) if self._pre_key_press.get(event.key(), lambda x: False)(event): return if event.text() in (set(BRACES.values()) - set(["'", '"'])): cursor = self.textCursor() cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) brace = cursor.selection().toPlainText() cursor = self.textCursor() cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) braceClose = cursor.selection().toPlainText() if BRACES.get(brace, False) == event.text() and \ braceClose == event.text(): self.moveCursor(QTextCursor.Right) return QPlainTextEdit.keyPressEvent(self, event) if event.text() in BRACES: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) self.textCursor().insertText( BRACES[event.text()]) self.moveCursor(QTextCursor.Left) completionPrefix = self._text_under_cursor() if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier): self.completer.setCompletionPrefix(completionPrefix) self._resolve_completion_argument() if self.completer.popup().isVisible() and \ completionPrefix != self.completer.completionPrefix(): self.completer.setCompletionPrefix(completionPrefix) self.completer.popup().setCurrentIndex( self.completer.completionModel().index(0, 0)) self.completer.setCurrentRow(0) self._resolve_completion_argument() def _resolve_completion_argument(self): try: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) var = cursor.selectedText() chars = self.patObject.findall(var) var = var[var.rfind(chars[-1]) + 1:] cr = self.cursorRect() proposals = completer.get_all_completions(var, imports=self.imports) if not proposals: if self.completer.popup().isVisible(): prefix = var[var.rfind('.') + 1:] var = var[:var.rfind('.') + 1] var = self._console.get_type(var) var += prefix else: var = self._console.get_type(var) proposals = completer.get_all_completions(var, imports=self.imports) self.completer.complete(cr, proposals) except: self.completer.popup().hide() def highlight_current_line(self): self.extraSelections = [] selection = QTextEdit.ExtraSelection() lineColor = QColor(resources.CUSTOM_SCHEME.get('current-line', resources.COLOR_SCHEME['current-line'])) lineColor.setAlpha(20) selection.format.setBackground(lineColor) selection.format.setProperty(QTextFormat.FullWidthSelection, True) selection.cursor = self.textCursor() selection.cursor.clearSelection() self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) if self._braces is not None: self._braces = None cursor = self.textCursor() if cursor.position() == 0: self.setExtraSelections(self.extraSelections) return cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) text = cursor.selectedText() pos1 = cursor.position() if text in (')', ']', '}'): pos2 = self._match_braces(pos1, text, forward=False) elif text in ('(', '[', '{'): pos2 = self._match_braces(pos1, text, forward=True) else: self.setExtraSelections(self.extraSelections) return if pos2 is not None: self._braces = (pos1, pos2) selection = QTextEdit.ExtraSelection() selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.cursor = cursor self.extraSelections.append(selection) selection = QTextEdit.ExtraSelection() selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.cursor = self.textCursor() selection.cursor.setPosition(pos2) selection.cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) self.extraSelections.append(selection) else: self._braces = (pos1,) selection = QTextEdit.ExtraSelection() selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.cursor = cursor self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) def _text_under_cursor(self): tc = self.textCursor() tc.select(QTextCursor.WordUnderCursor) return tc.selectedText() def get_selection(self, posStart, posEnd): cursor = self.textCursor() cursor.setPosition(posStart) if posEnd == QTextCursor.End: cursor2 = self.textCursor() cursor2.movePosition(posEnd) cursor.setPosition(cursor2.position(), QTextCursor.KeepAnchor) else: cursor.setPosition(posEnd, QTextCursor.KeepAnchor) return cursor.selectedText() def _match_braces(self, position, brace, forward): """based on: http://gitorious.org/khteditor""" if forward: braceMatch = {'(': ')', '[': ']', '{': '}'} text = self.get_selection(position, QTextCursor.End) braceOpen, braceClose = 1, 1 else: braceMatch = {')': '(', ']': '[', '}': '{'} text = self.get_selection(QTextCursor.Start, position) braceOpen, braceClose = len(text) - 1, len(text) - 1 while True: if forward: posClose = text.find(braceMatch[brace], braceClose) else: posClose = text.rfind(braceMatch[brace], 0, braceClose + 1) if posClose > -1: if forward: braceClose = posClose + 1 posOpen = text.find(brace, braceOpen, posClose) else: braceClose = posClose - 1 posOpen = text.rfind(brace, posClose, braceOpen + 1) if posOpen > -1: if forward: braceOpen = posOpen + 1 else: braceOpen = posOpen - 1 else: if forward: return position + posClose else: return position - (len(text) - posClose) else: return def _add_prompt(self, incomplete=False): if incomplete: prompt = '.' * 3 + ' ' else: prompt = self.prompt self.appendPlainText(prompt) self.moveCursor(QTextCursor.End) def _get_cursor_position(self): return self.textCursor().columnNumber() - len(self.prompt) def _write_command(self): command = self.document().lastBlock().text() #remove the prompt from the QString command = command[len(self.prompt):] self._add_history(command) incomplete = self._write(command) if self.patFrom.match(command) or self.patImport.match(command): self.imports += [command] if not incomplete: output = self._read() if output is not None: if isinstance(output, str): output = output.encode('utf8') self.appendPlainText(output.decode('utf8')) self._add_prompt(incomplete) def _set_command(self, command): self.moveCursor(QTextCursor.End) cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(self.prompt)) cursor.insertText(command) def contextMenuEvent(self, event): self.popup_menu.exec_(event.globalPos()) def _write(self, line): return self._console.push(line) def _read(self): return self._console.output def _add_history(self, command): if command and (not self._history or self._history[-1] != command): self._history.append(command) self.history_index = len(self._history) def _get_prev_history_entry(self): if self._history: self.history_index = max(0, self.history_index - 1) return self._history[self.history_index] return '' def _get_next_history_entry(self): if self._history: hist_len = len(self._history) - 1 self.history_index = min(hist_len, self.history_index + 1) index = self.history_index if self.history_index == hist_len: self.history_index += 1 return self._history[index] return '' def restyle(self): self.apply_editor_style() parts_scanner, code_scanner, formats = \ syntax_highlighter.load_syntax(python_syntax.syntax) self.highlighter = syntax_highlighter.SyntaxHighlighter( self.document(), parts_scanner, code_scanner, formats) def apply_editor_style(self): css = 'QPlainTextEdit {color: %s; background-color: %s;' \ 'selection-color: %s; selection-background-color: %s;}' \ % (resources.CUSTOM_SCHEME.get('editor-text', resources.COLOR_SCHEME['editor-text']), resources.CUSTOM_SCHEME.get('editor-background', resources.COLOR_SCHEME['editor-background']), resources.CUSTOM_SCHEME.get('editor-selection-color', resources.COLOR_SCHEME['editor-selection-color']), resources.CUSTOM_SCHEME.get('editor-selection-background', resources.COLOR_SCHEME['editor-selection-background'])) self.setStyleSheet(css) self.set_font(settings.FONT_FAMILY, settings.FONT_SIZE) def load_project_into_console(self, projectFolder): """Load the projectFolder received into the sys.path.""" self._console.push("import sys; sys.path += ['%s']" % projectFolder) def unload_project_from_console(self, projectFolder): """Unload the project from the system path.""" self._console.push("import sys; " "sys.path = [path for path in sys.path " "if path != '%s']" % projectFolder) def zoom_in(self): font = self.document().defaultFont() size = font.pointSize() if size < settings.FONT_MAX_SIZE: size += 2 font.setPointSize(size) self.setFont(font) def zoom_out(self): font = self.document().defaultFont() size = font.pointSize() if size > settings.FONT_MIN_SIZE: size -= 2 font.setPointSize(size) self.setFont(font) def wheelEvent(self, event): if event.modifiers() == Qt.ControlModifier: if event.delta() == 120: self.zoom_in() elif event.delta() == -120: self.zoom_out() event.ignore() super(ConsoleWidget, self).wheelEvent(event)
class Window(QWidget): __pyqtSignals__ = ("burningProgress(int)") __pyqtSignals__ = ("burningFinished()") __pyqtSignals__ = ("burningStartingIn(int)") __pyqtSignals__ = ("burningError(int)") def __init__(self): QWidget.__init__(self) self.rawstr3 = r"""(?:^Current:\s)(.*)""" self.rawstr2 = r"""(?:^.*?)(\d)(?:\sseconds\.$)""" self.rawstr = r"""(?:^.*Track .*?\d*\D*)(\d{1,})(?:\D*of.*?)(\d{1,})(?:.*?MB written.*$)""" self.compile_obj = re.compile(self.rawstr, re.MULTILINE) self.compile_obj_2 = re.compile(self.rawstr2, re.MULTILINE) self.compile_obj_3 = re.compile(self.rawstr3, re.MULTILINE) self.process = QProcess() self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.readOutput) self.connect(self.process, SIGNAL("readyReadStandardError()"), self.readErrors) self.connect(self.process, SIGNAL("finished(int)"), self.resetButtons) self.connect(self, SIGNAL("burningProgress(int)"), self.readProgress) self.noError=True def blankCommand(self): print "blankCDRW" b=QString("cdrecord -v dev=1000,0,0 --blank=fast") a=b.split(" ") self.process.start(a.first(), a.mid(1)) if self.process.exitCode(): print "exitCode" self.resetButtons() return def startCommand(self, isofile): print "startCommand" b=QString("cdrecord -v -pad speed=8 dev=/dev/cdrom "+isofile) a=b.split(" ") self.process.start(a.first(), a.mid(1)) if self.process.exitCode(): print "exitCode" self.resetButtons() return def stopCommand(self, i): self.resetButtons(i) self.process.terminate() QTimer.singleShot(5000, self.process, SLOT("kill()")) def readOutput(self): a= self.process.readAllStandardOutput().data() match_obj = self.compile_obj.search(a) match_obj_2 = self.compile_obj_2.search(a) match_obj_3 = self.compile_obj_3.search(a) print a if match_obj: all_groups = match_obj.groups() group_1 = float(match_obj.group(1)) group_2 = float(match_obj.group(2)) g=int(group_1*100.0/group_2) if group_1: self.emit(SIGNAL("burningProgress(int)"), g) if match_obj_2: group_1 = int(match_obj_2.group(1)) print "group_1: "+str(group_1) if group_1: self.emit(SIGNAL("burningStartingIn(int)"), group_1) if match_obj_3: group_1 = match_obj_3.group(1) if group_1 == "none": print "NO MEDIA" self.stopCommand(334) if a=="Re-load disk and hit \<CR\>": print "Non writable disc" self.stopCommand() def readProgress(self, g): print g def readErrors(self): a= self.process.readAllStandardError().data() print "ERORR: "+a if a.startswith("cdrecord: Try to load media by hand"): print "ERROR: Non writable disc" self.stopCommand(333) def resetButtons(self, i): print "resetButtons" print i if i==0: if self.noError: self.emit(SIGNAL("burningFinished()")) if i==333: self.noError=False self.emit(SIGNAL("burningError(int)"), i) if i==334: self.noError=False self.emit(SIGNAL("burningError(int)"), i) if i==335: self.noError=False self.emit(SIGNAL("burningCanceled(int)"), i)
class AsciidocEditor(WithSingleIO, QWidget): """Asciidoc editor """ def __init__(self, params, parent=None): self.base_dir = os.path.dirname(__file__) QWidget.__init__(self, parent) self.setMinimumWidth(300) self.setMinimumHeight(300) # create widgets self._editor_widget = mixin( WithFind, WidthMqHighlighter, WithMqEditIO, WithBasicIdentationManager, WithLineHighlight, WithFixedFont, WithLineNumbers, WithViewPortMargins, WithWordCompletionMulty_, WithCompletion, QPlainTextEdit)(self) self.webview = QWebView(self) #self.webview.load(QUrl("/home/maiquel/develop/developing/main/qt/qadoc/bin/__builds/documents.html")) self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget(self._editor_widget) self.splitter.addWidget(self.webview) self.splitter.setSizes([self.size().width(), self.size().width()]) self.splitterv = QSplitter(Qt.Vertical) self.splitterv.addWidget(self.splitter) self.log_widget = QPlainTextEdit() self.splitterv.addWidget(self.log_widget) layout = QVBoxLayout(self) layout.addWidget(self.splitterv) layout.setMargin(0) self.setLayout(layout) # proc_compile self.proc_compile = QProcess() self.proc_compile.finished.connect(self.proc_compile_finished) self.proc_compile.error.connect(self.proc_compile_error) self.proc_compile.readyReadStandardOutput.connect(self.proc_compile_readyReadStandardOutput) self.proc_compile.readyReadStandardError.connect(self.proc_compile_readyReadStandardError) WithSingleIO.__init__(self, params) def bw_add_command_list(self, command_list): command_list += [ ("generate preview asciidoc", "pp", 1.0, "self.get_current_widget().command_generate_preview('asciidoc -a toc -a data-uri -a icons -a iconsdir="+self.base_dir+"/adoc/icons/')"), ("generate preview asciidoc style_sheet no images embeded", "pp", 1.0, "self.get_current_widget().command_generate_preview('asciidoc -a toc --attribute stylesheet="+self.base_dir+"/adoc/mq_red.css -a icons -a iconsdir="+self.base_dir+"/adoc/icons/')"), ("generate preview asciidoc style_sheet", "pp", 1.2, "self.get_current_widget().command_generate_preview('asciidoc -a toc --attribute stylesheet="+self.base_dir+"/adoc/mq_red.css -a data-uri -a icons -a iconsdir="+self.base_dir+"/adoc/icons/')"), ("generate preview slidy", "pp slides", 0.8, "self.get_current_widget().command_generate_preview('asciidoc -a toc -b slidy -a data-uri -a icons')"), ("generate preview slidy2", "pp slides", 0.9, "self.get_current_widget().command_generate_preview('asciidoc -a toc -b slidy2 -a data-uri -a icons')"), ("generate preview asciidoctor", "pp", 0.7, "self.get_current_widget().command_generate_preview('asciidoctor -a toc -a data-uri -a icons')"), ("generate preview deck.js", "pp slides", 0.7, "self.get_current_widget().command_generate_preview('asciidoc -a toc -b deckjs -a data-uri -a icons')"), ("generate pdf small", "", 0., """self.get_current_widget().command_generate_document('a2x --verbose -d article --icons --dblatex-opts "-T native -P doc.pdfcreator.show=0 -P doc.collab.show=0 -P latex.output.revhistory=0 -P doc.toc.show=1 -P table.title.top" -f pdf -D /tmp/adoc/ ')"""), ("generate pdf book", "", 0., """self.get_current_widget().command_generate_document('a2x --verbose -d book --icons --dblatex-opts "-T native -P doc.pdfcreator.show=0 -P doc.collab.show=0 -P latex.output.revhistory=0 -P doc.toc.show=1 -P table.title.top" -f pdf -D /tmp/adoc/ ')"""), ] super(AsciidocEditor, self).bw_add_command_list(command_list) self._editor_widget.bw_add_command_list(command_list) command_list += [ ("focus editor", "fe", 0.5, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self._editor_widget.setFocus();"), ("focus preview", "fp", 0.5, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self.webview.setFocus();"), ("increase font webview", "if if", 0.7, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self.webview.setTextSizeMultiplier(_self.webview.textSizeMultiplier()+0.1);"), ("decrease font webview", "df df", 0.7, "import ctypes; _self = ctypes.cast(" + str(id(self)) + ", ctypes.py_object).value;" "_self.webview.setTextSizeMultiplier(_self.webview.textSizeMultiplier()-0.1);"), ] def copy2tmp(self): if not os.path.exists(TEMP_DIR): os.mkdir(TEMP_DIR) source = os.listdir(self.base_dir) destination = TEMP_DIR for files in source: shutil.move(files,destination) def command_generate_preview(self, adoc_command): self.command_save_file() #self.compile(backend + " -b deckjs -o " + self.get_html_output() + " " + TEMP_DIR + "pr.adoc") #asciidoc --verbose -a data-uri -a icons -a toc -a max-width=55em -o __builds/index.html /home/maiquel/Documents/qadoc/adoc/index.adoc #self.compile(adoc_command + " --attribute stylesheet=/home/maiquel/inet.prj/miow/widgets/adoc/mq_red.css -a data-uri -a icons -o " + self.get_html_output() + " " + TEMP_DIR + "pr.adoc") self.compile(adoc_command + ' -o ' +self.get_html_output() + ' ./"' + self.file_name + '"') if self.webview.url() != QUrl("file://" + self.get_html_output()): self.webview.load(QUrl(self.get_html_output())) def command_generate_document(self, adoc_command): self.command_save_file() self.compile(adoc_command + " " + TEMP_DIR + "pr.adoc") if self.webview.url() != QUrl("file://" + self.get_html_output()): self.webview.load(QUrl(self.get_html_output())) def compile(self, command): self.log(command) self.proc_compile.start(command) def bw_lock_command_window(self): return self._editor_widget.completer.popup().isVisible() def focusInEvent(self, focus_event): super(AsciidocEditor, self).focusInEvent(focus_event) self._editor_widget.setFocus() def get_html_output(self): return TEMP_DIR + "pr.html" def proc_compile_finished(self, result, exit_status): self.log("compilation finished") if self.webview.url().toString() == "": self.webview.load(QUrl(self.get_html_output())) else: self.webview.reload() def proc_compile_error(self, q_process_error): self.log("compilation error") print(q_process_error) def proc_compile_readyReadStandardOutput(self): result = self.proc_compile.readAllStandardOutput(); self.log(result) def proc_compile_readyReadStandardError(self): result = str(self.proc_compile.readAllStandardError()) self.log(result) def log(self, text): self.log_widget.appendPlainText(unicode(text))
class TerreImageProcess(): def __init__(self): self.process = QProcess() self.process.error[QProcess.ProcessError].connect( self.error_management) self.env = QProcessEnvironment().systemEnvironment() self.set_otb_process_env_default() self.command = "" def run_process(self, command): logger.info(u"Running {}".format(command)) self.process.setProcessEnvironment(self.env) # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH"))) # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH"))) # logger.debug("Environ : PATH {}".format(os.environ["PATH"])) # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty"))) self.command = command self.process.start(command) if self.process.waitForStarted(): self.process.waitForFinished(-1) exit_code = self.process.exitCode() if exit_code != 0: self.error_management(exit_code) result = self.process.readAllStandardOutput() # logger.debug(" {} {}".format(type(result), result)) error = self.process.readAllStandardError().data() # logger.debug(repr(error)) if not error in ["\n", ""]: logger.error("error : %s" % (error)) output = result.data() logger.info(output) return result else: code_d_erreur = self.process.error() self.error_management(code_d_erreur) return None def error_management(self, errorCode): dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError", 127: "Other, The application may not have been found" } try: type_qt_error = dic_err[errorCode] logger.error(u"Error {} {}".format(errorCode, type_qt_error)) except KeyError: type_qt_error = "" error = self.process.readAllStandardError().data() logger.error(error) logger.error(self.process.readAllStandardOutput()) try: raise terre_image_exceptions.TerreImageRunProcessError( u"Error running : {}\n {}{}".format(self.command, type_qt_error, error)) except UnicodeError: raise terre_image_exceptions.TerreImageRunProcessError( u"Error running : {}\n {}".format(self.command, type_qt_error)) def set_env_var(self, varname, varval, append=False, pre=False): if append == True: if pre == False: # insert value at the end of the variable self.env.insert(varname, self.env.value(varname) + os.pathsep + varval) else: # insert value in head self.env.insert(varname, varval + os.pathsep + self.env.value(varname)) else: # replace value if existing self.env.insert(varname, varval) # logger.debug("env {} {}".format(varname, self.env.value(varname))) def set_otb_process_env(self): dirname = os.path.dirname(os.path.abspath(__file__)) self.set_env_var("OTB_APPLICATION_PATH", os.path.join(dirname, "win32", "plugin"), pre=True) self.set_env_var("PATH", os.path.join(dirname, "win32", "bin"), append=False, pre=True) def set_otb_process_env_custom(self, otb_app_path="", path=""): """ Add the given values to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True) self.set_env_var("PATH", path, append=False, pre=True) def set_otb_process_env_default(self): """ Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", terre_image_configuration.OTB_APPLICATION_PATH, pre=True) self.set_env_var("PATH", terre_image_configuration.PATH, append=True, pre=True) if terre_image_configuration.LD_LIBRARY_PATH: self.set_env_var("LD_LIBRARY_PATH", terre_image_configuration.LD_LIBRARY_PATH, append=True, pre=True)
class serverwidget(QtGui.QFrame): def __init__(self, aname, apath): super(serverwidget, self).__init__() self.process = None self.path = apath self.name = aname self.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken) title = QtGui.QLabel(self.name) startbutton = QtGui.QPushButton('START') killbutton = QtGui.QPushButton('TERMINATE') pingbutton = QtGui.QPushButton('PING') self.textfield = QtGui.QTextEdit() self.textfield.setReadOnly(True) startbutton.pressed.connect(self.start_server) killbutton.pressed.connect(self.kill_server) pingbutton.pressed.connect(self.ping_server) sublayout = QtGui.QVBoxLayout() sublayout.addWidget(title) sublayout.addWidget(startbutton) sublayout.addWidget(killbutton) sublayout.addWidget(pingbutton) sublayout.addWidget(self.textfield) self.setLayout(sublayout) def start_server(self): if self.process is None: self.process = QProcess() self.process.readyReadStandardOutput.connect(self.read_output) self.process.started.connect( lambda: self.write_message('Server started')) self.process.finished.connect( lambda: self.write_message('Server stopped')) self.process.setProcessChannelMode(QProcess.MergedChannels) self.process.setWorkingDirectory(os.path.dirname(self.path)) self.process.start('python', [self.path]) else: self.textfield.append( 'Cannot start "{:}", as it is already running'.format( self.name)) def kill_server(self): if self.process is not None: self.process.terminate() self.process = None else: self.textfield.append( 'Cannot terminate "{:}", as it is not running'.format( self.name)) def ping_server(self): if self.process is not None: state = self.process.state() msg = "PING: " if state == 0: msg += 'Process died' elif state == 1: msg += 'Process is starting up' elif state == 2: msg += 'Process is alive' self.textfield.append(msg) cnx = labrad.connect() labradserver = eval('cnx.{:}'.format(self.name)) msg = 'PING: Labradserver is ' + labradserver.echo('alive') self.textfield.append(msg) cnx.disconnect() else: self.textfield.append('Cannot ping a server that is not started') def read_output(self): data = self.process.readAllStandardOutput() self.textfield.append(str(data)) def write_message(self, message): self.textfield.append(message)
class Window(QWidget): def __init__(self): QWidget.__init__(self) self.rawstr = r"""(?:^.*Track .*?\d*\D*)(\d{1,})(?:\D*of.*?)(\d{1,})(?:.*?MB written.*$)""" self.compile_obj = re.compile(self.rawstr, re.MULTILINE) self.textBrowser = QTextBrowser(self) self.lineEdit = QLineEdit(self) self.startButton = QPushButton(self.tr("Start"), self) self.stopButton = QPushButton(self.tr("Stop"), self) self.stopButton.setEnabled(False) self.list1 = QStringList() self.connect(self.lineEdit, SIGNAL("returnPressed()"), self.startCommand) self.connect(self.startButton, SIGNAL("clicked()"), self.startCommand) self.connect(self.stopButton, SIGNAL("clicked()"), self.stopCommand) layout = QGridLayout(self) layout.setSpacing(8) layout.addWidget(self.textBrowser, 0, 0) layout.addWidget(self.lineEdit, 1, 0) layout.addWidget(self.startButton, 1, 1) layout.addWidget(self.stopButton, 1, 2) self.process = QProcess() self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.readOutput) self.connect(self.process, SIGNAL("readyReadStandardError()"), self.readErrors) self.connect(self.process, SIGNAL("finished(int)"), self.resetButtons) def startCommand(self): a=self.lineEdit.text().split(" ") self.process.start(a.first(), a.mid(1)) self.startButton.setEnabled(False) self.stopButton.setEnabled(True) self.textBrowser.clear() if self.process.exitCode(): self.textBrowser.setText( QString("*** Failed to run %1 ***").arg(self.lineEdit.text()) ) self.resetButtons() return def stopCommand(self): self.resetButtons() self.process.terminate() QTimer.singleShot(5000, self.process, SLOT("kill()")) def readOutput(self): a= self.process.readAllStandardOutput().data() match_obj = self.compile_obj.search(a) if match_obj: all_groups = match_obj.groups() group_1 = float(match_obj.group(1)) group_2 = float(match_obj.group(2)) g=int(group_1*100.0/group_2) if group_1: self.textBrowser.append(QString(str(g))) def readErrors(self): a= self.process.readAllStandardError().data() self.textBrowser.append("error: " + QString(a)) def resetButtons(self, i): self.startButton.setEnabled(True) self.stopButton.setEnabled(False)
class HostWindow(QMainWindow): # signals SIGTERM = pyqtSignal() SIGUSR1 = pyqtSignal() # -------------------------------------------------------------------------------------------------------- def __init__(self): QMainWindow.__init__(self) self.ui = Ui_HostWindow() self.ui.setupUi(self) # ---------------------------------------------------------------------------------------------------- # Internal stuff # Current mod-ui title #self.fCurrentBundle = "" self.fCurrentTitle = "" # Next bundle to load (done by startup arguments) self.fNextBundle = "" # first attempt of auto-start backend doesn't show an error self.fFirstBackendInit = True # need to call session reconnect after connecting the 1st time self.fNeedsSessionReconnect = False # Qt idle timer self.fIdleTimerId = 0 # Qt web frame, used for evaluating javascript self.fWebFrame = None # to be filled with key-value pairs of current settings self.fSavedSettings = {} # List of pedalboards self.fPedalboards = get_all_pedalboards() # List of current-pedalboard presets self.fPresetMenuList = [] # Process that runs the backend self.fProccessBackend = QProcess(self) self.fProccessBackend.setProcessChannelMode(QProcess.MergedChannels) self.fProccessBackend.setReadChannel(QProcess.StandardOutput) self.fStoppingBackend = False # Thread for managing the webserver self.fWebServerThread = WebServerThread(self) # ---------------------------------------------------------------------------------------------------- # Set up GUI self.ui.webview = QWebView(self.ui.swp_webview) self.ui.webview.setMinimumWidth(980) self.ui.swp_webview.layout().addWidget(self.ui.webview) self.ui.webpage = HostWebPage(self) self.ui.webpage.setViewportSize(QSize(980, 600)) self.ui.webview.setPage(self.ui.webpage) self.ui.webinspector = QWebInspector(None) self.ui.webinspector.resize(800, 600) self.ui.webinspector.setPage(self.ui.webpage) self.ui.webinspector.setVisible(False) self.ui.act_file_connect.setEnabled(False) self.ui.act_file_connect.setVisible(False) self.ui.act_file_disconnect.setEnabled(False) self.ui.act_file_disconnect.setVisible(False) self.ui.label_app.setText("MOD Application v%s" % config["version"]) # disable file menu self.ui.act_file_refresh.setEnabled(False) self.ui.act_file_inspect.setEnabled(False) # disable pedalboard menu self.ui.act_pedalboard_new.setEnabled(False) self.ui.act_pedalboard_open.setEnabled(False) self.ui.act_pedalboard_save.setEnabled(False) self.ui.act_pedalboard_save_as.setEnabled(False) self.ui.act_pedalboard_share.setEnabled(False) self.ui.menu_Pedalboard.setEnabled(False) # disable presets menu self.ui.act_presets_new.setEnabled(False) self.ui.act_presets_save.setEnabled(False) self.ui.act_presets_save_as.setEnabled(False) self.ui.menu_Presets.setEnabled(False) # initial stopped state self.slot_backendFinished(-1, -1) # Qt needs this so it properly creates & resizes the webview self.ui.stackedwidget.setCurrentIndex(1) self.ui.stackedwidget.setCurrentIndex(0) # FIXME #self.ui.act_backend_stop.setVisible(False) #self.ui.act_backend_restart.setVisible(False) # ---------------------------------------------------------------------------------------------------- # Set up GUI (special stuff for Mac OS) if MACOS: self.ui.act_file_quit.setMenuRole(QAction.QuitRole) self.ui.act_settings_configure.setMenuRole(QAction.PreferencesRole) self.ui.act_help_about.setMenuRole(QAction.AboutRole) #self.ui.menu_Settings.setTitle("Panels") #self.ui.menu_Help.hide() # ---------------------------------------------------------------------------------------------------- # Set up GUI (special stuff for Live-MOD ISO) if USING_LIVE_ISO: self.ui.menubar.hide() self.ui.b_start.hide() self.ui.b_configure.hide() self.ui.b_about.hide() # ---------------------------------------------------------------------------------------------------- # Load Settings self.loadSettings(True) # ---------------------------------------------------------------------------------------------------- # Connect actions to functions self.SIGUSR1.connect(self.slot_handleSIGUSR1) self.SIGTERM.connect(self.slot_handleSIGTERM) self.fProccessBackend.error.connect(self.slot_backendError) self.fProccessBackend.started.connect(self.slot_backendStarted) self.fProccessBackend.finished.connect(self.slot_backendFinished) self.fProccessBackend.readyRead.connect(self.slot_backendRead) self.fWebServerThread.running.connect(self.slot_webServerRunning) self.fWebServerThread.finished.connect(self.slot_webServerFinished) self.ui.menu_Pedalboard.aboutToShow.connect(self.slot_pedalboardCheckOnline) self.ui.act_file_refresh.triggered.connect(self.slot_fileRefresh) self.ui.act_file_inspect.triggered.connect(self.slot_fileInspect) self.ui.act_backend_information.triggered.connect(self.slot_backendInformation) self.ui.act_backend_start.triggered.connect(self.slot_backendStart) self.ui.act_backend_stop.triggered.connect(self.slot_backendStop) self.ui.act_backend_restart.triggered.connect(self.slot_backendRestart) self.ui.act_pedalboard_new.triggered.connect(self.slot_pedalboardNew) self.ui.act_pedalboard_open.triggered.connect(self.slot_pedalboardOpen) self.ui.act_pedalboard_save.triggered.connect(self.slot_pedalboardSave) self.ui.act_pedalboard_save_as.triggered.connect(self.slot_pedalboardSaveAs) self.ui.act_pedalboard_share.triggered.connect(self.slot_pedalboardShare) self.ui.act_settings_configure.triggered.connect(self.slot_configure) self.ui.act_help_about.triggered.connect(self.slot_about) self.ui.act_help_project.triggered.connect(self.slot_showProject) self.ui.act_help_website.triggered.connect(self.slot_showWebsite) self.ui.b_start.clicked.connect(self.slot_backendStart) self.ui.b_configure.clicked.connect(self.slot_configure) self.ui.b_about.clicked.connect(self.slot_about) # force our custom refresh webReloadAction = self.ui.webpage.action(QWebPage.Reload) webReloadAction.triggered.disconnect() webReloadAction.triggered.connect(self.slot_fileRefresh) # ---------------------------------------------------------------------------------------------------- # Final setup self.setProperWindowTitle() SESSION.setupApp(self._pedal_changed_callback) if not "--no-autostart" in sys.argv: QTimer.singleShot(0, self.slot_backendStart) QTimer.singleShot(1, self.fixWebViewSize) def __del__(self): self.stopAndWaitForWebServer() self.stopAndWaitForBackend() def _pedal_changed_callback(self, ok, bundlepath, title): #self.fCurrentBundle = bundlepath self.fCurrentTitle = title or "" #self.updatePresetsMenu() self.setProperWindowTitle() # -------------------------------------------------------------------------------------------------------- # Files (menu actions) @pyqtSlot() def slot_fileRefresh(self): if self.fWebFrame is None: return self.ui.label_progress.setText(self.tr("Refreshing UI...")) self.ui.stackedwidget.setCurrentIndex(0) QTimer.singleShot(0, self.slot_fileRefreshPost) @pyqtSlot() def slot_fileRefreshPost(self): self.ui.webview.loadStarted.connect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.connect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.connect(self.slot_webviewLoadFinished) self.ui.webview.reload() @pyqtSlot() def slot_fileInspect(self): self.ui.webinspector.show() # -------------------------------------------------------------------------------------------------------- # Pedalboard (menu actions) @pyqtSlot() def slot_pedalboardCheckOnline(self): if self.fWebFrame is None: return isOnline = self.fWebFrame.evaluateJavaScript("$('#mod-cloud').hasClass('logged')") if isOnline is None: return print("isOnline is None") self.ui.act_pedalboard_share.setEnabled(isOnline) @pyqtSlot() def slot_pedalboardNew(self): if self.fWebFrame is None: return self.fWebFrame.evaluateJavaScript("desktop.reset()") # -------------------------------------------------------------------------------------------------------- @pyqtSlot() def slot_pedalboardOpen(self): if len(self.fPedalboards) == 0: return QMessageBox.information(self, self.tr("information"), "No pedalboards found") dialog = OpenPedalboardWindow(self, self.fPedalboards) if not dialog.exec_(): return pedalboard = dialog.getSelectedURI() if not pedalboard: return QMessageBox.information(self, self.tr("information"), "Invalid pedalboard selected") try: bundle = get_bundle_dirname(pedalboard) except: return if self.fWebFrame is None: return self.fWebFrame.evaluateJavaScript("desktop.loadPedalboard(\"%s\")" % bundle) def openPedalboardLater(self, filename): try: self.fNextBundle = QFileInfo(filename).absoluteFilePath() self.fCurrentTitle = get_pedalboard_info(self.fNextBundle)['name'] except: self.fNextBundle = "" self.fCurrentTitle = "" # -------------------------------------------------------------------------------------------------------- @pyqtSlot() def slot_pedalboardSave(self, saveAs=False): if self.fWebFrame is None: return self.fWebFrame.evaluateJavaScript("desktop.saveCurrentPedalboard(%s)" % ("true" if saveAs else "false")) @pyqtSlot() def slot_pedalboardSaveAs(self): self.slot_pedalboardSave(True) # -------------------------------------------------------------------------------------------------------- @pyqtSlot() def slot_pedalboardShare(self): if self.fWebFrame is None: return self.fWebFrame.evaluateJavaScript("desktop.shareCurrentPedalboard()") # -------------------------------------------------------------------------------------------------------- # Presets (menu actions) @pyqtSlot() def slot_presetClicked(self): print(self.sender().data()) # -------------------------------------------------------------------------------------------------------- # Settings (menu actions) @pyqtSlot() def slot_configure(self): dialog = SettingsWindow(self, True) if not dialog.exec_(): return self.loadSettings(False) # -------------------------------------------------------------------------------------------------------- # About (menu actions) @pyqtSlot() def slot_about(self): QMessageBox.about(self, self.tr("About"), self.tr(""" <b>MOD Desktop Application</b><br/> <br/> A software to have the complete MOD environment running in your desktop.<br/> (C) 2015-2016 - The MOD Team<br/> <br/> Publications, products, content or services referenced herein or on the website are the exclusive trademarks or servicemarks of MOD.<br/> Other product and company names mentioned in the site may be the trademarks of their respective owners.<br/> <br/> All software is available under the <a href="https://www.gnu.org/licenses/gpl-2.0.html">GPL license</a>.<br/> """)) @pyqtSlot() def slot_showProject(self): QDesktopServices.openUrl(QUrl("https://github.com/moddevices/mod-app")) @pyqtSlot() def slot_showWebsite(self): QDesktopServices.openUrl(QUrl("http://moddevices.com/")) # -------------------------------------------------------------------------------------------------------- # Backend (menu actions) @pyqtSlot() def slot_backendInformation(self): table = """ <table><tr> <td> MOD-UI port: <td></td> %s </td> </tr><tr> <td> Backend address: <td></td> %s </td> </tr></table> """ % (config["port"], "unix:///tmp/mod-app-%s.sock" % config["port"]) QMessageBox.information(self, self.tr("information"), table) @pyqtSlot() def slot_backendStart(self): if self.fProccessBackend.state() != QProcess.NotRunning: print("slot_backendStart ignored") return print("slot_backendStart in progress...") if USING_LIVE_ISO: os.system("jack_wait -w") os.system("jack_load mod-monitor") hostPath = "jack_load" hostArgs = ["-w", "-a", "mod-host"] else: hostPath = self.fSavedSettings[MOD_KEY_HOST_PATH] if hostPath.endswith("ingen"): hostPath = MOD_DEFAULT_HOST_PATH hostArgs = ["-n"] self.fProccessBackend.start(hostPath, hostArgs) @pyqtSlot() def slot_backendStop(self, forced = False): #if self.fPluginCount > 0: #if not forced: #ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n" #"Do you want to do this now?"), #QMessageBox.Yes | QMessageBox.No, QMessageBox.No) #if ask != QMessageBox.Yes: #return #self.removeAllPlugins() #self.host.set_engine_about_to_close() #self.host.remove_all_plugins() # testing red color for server stopped self.ui.webview.blockSignals(True) self.ui.webview.setHtml("<html><body bgcolor='green'></body></html>") self.ui.webview.blockSignals(False) self.stopAndWaitForWebServer() self.stopAndWaitForBackend() @pyqtSlot() def slot_backendRestart(self): #self.ui.stackedwidget.setCurrentIndex(0) self.slot_backendStop() #QApplication.instance().processEvents() self.slot_backendStart() # -------------------------------------------------------------------------------------------------------- @pyqtSlot() def slot_backendStarted(self): self.ui.act_backend_start.setEnabled(False) self.ui.act_backend_stop.setEnabled(True) self.ui.act_backend_restart.setEnabled(True) self.ui.w_buttons.setEnabled(False) self.ui.label_progress.setText(self.tr("Loading backend...")) @pyqtSlot(int, QProcess.ExitStatus) def slot_backendFinished(self, exitCode, exitStatus): self.fFirstBackendInit = False self.fStoppingBackend = False self.ui.act_backend_start.setEnabled(True) self.ui.act_backend_stop.setEnabled(False) self.ui.act_backend_restart.setEnabled(False) self.ui.w_buttons.setEnabled(True) self.ui.label_progress.setText("") self.ui.stackedwidget.setCurrentIndex(0) # stop webserver self.stopAndWaitForWebServer() @pyqtSlot(QProcess.ProcessError) def slot_backendError(self, error): firstBackendInit = self.fFirstBackendInit self.fFirstBackendInit = False # stop webserver self.stopAndWaitForWebServer() # crashed while stopping, ignore if error == QProcess.Crashed and self.fStoppingBackend: return errorStr = self.tr("Could not start host backend.\n") + self.getProcessErrorAsString(error) qWarning(errorStr) # don't show error if this is the first time starting the host or using live-iso if firstBackendInit or USING_LIVE_ISO: return # show the error message QMessageBox.critical(self, self.tr("Error"), errorStr) @pyqtSlot() def slot_backendRead(self): #if self.fProccessBackend.state() != QProcess.Running: #return for line in str(self.fProccessBackend.readAllStandardOutput().trimmed(), encoding="utf-8", errors="ignore").strip().split("\n"): line = line.replace("\x1b[0m","").replace("\x1b[0;31m","").replace("\x1b[0;33m","").strip() if not line: continue if self.fSavedSettings[MOD_KEY_HOST_VERBOSE]: print("BACKEND:", line) if line == "mod-host ready!" or line == "mod-host is running.": QTimer.singleShot(0, self.slot_backendStartPhase2) #elif "Listening on socket " in line: #QTimer.singleShot(1000, self.slot_ingenStarted) ##elif "Activated Jack client " in line: ##QTimer.singleShot(1000, self.fWebServerThread.start) #elif "Failed to create UNIX socket" in line or "Could not activate Jack client" in line: ## need to wait for ingen to create sockets so it can delete them on termination #QTimer.singleShot(1000, self.slot_ingenStartError) @pyqtSlot() def slot_backendStartPhase2(self): if self.fProccessBackend.state() == QProcess.NotRunning: return if not self.fNeedsSessionReconnect: # we'll need it for next time self.fNeedsSessionReconnect = True else: # we need it now SESSION.reconnectApp() self.fWebServerThread.start() @pyqtSlot() def slot_backendStartError(self): self.stopAndWaitForBackend() self.slot_backendError(-2) # -------------------------------------------------------------------------------------------------------- # Web Server @pyqtSlot() def slot_webServerRunning(self): try: self.ui.webview.loadStarted.connect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.connect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.connect(self.slot_webviewLoadFinished) except: pass print("webserver running") self.ui.webview.load(QUrl(config["addr"])) @pyqtSlot() def slot_webServerFinished(self): try: self.ui.webview.loadStarted.connect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.connect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.connect(self.slot_webviewLoadFinished) except: pass print("webserver finished") # testing red color for server finished self.ui.webview.blockSignals(True) self.ui.webview.setHtml("<html><body bgcolor='red'></body></html>") self.ui.webview.blockSignals(False) # -------------------------------------------------------------------------------------------------------- # Web View @pyqtSlot() def slot_webviewLoadStarted(self): self.ui.label_progress.setText(self.tr("Loading UI...")) print("load started") @pyqtSlot(int) def slot_webviewLoadProgress(self, progress): self.ui.label_progress.setText(self.tr("Loading UI... %i%%" % progress)) @pyqtSlot(bool) def slot_webviewLoadFinished(self, ok): self.ui.webview.loadStarted.disconnect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.disconnect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.disconnect(self.slot_webviewLoadFinished) if ok: # message self.ui.label_progress.setText(self.tr("Loading UI... finished!")) # enable file menu self.ui.act_file_refresh.setEnabled(True) self.ui.act_file_inspect.setEnabled(True) # for js evaulation self.fWebFrame = self.ui.webpage.currentFrame() # postpone app stuff QTimer.singleShot(100, self.slot_webviewPostFinished) else: # message self.ui.label_progress.setText(self.tr("Loading UI... failed!")) # disable file menu self.ui.act_file_refresh.setEnabled(False) self.ui.act_file_inspect.setEnabled(False) # disable pedalboard menu self.ui.act_pedalboard_new.setEnabled(False) self.ui.act_pedalboard_open.setEnabled(False) self.ui.act_pedalboard_save.setEnabled(False) self.ui.act_pedalboard_save_as.setEnabled(False) self.ui.act_pedalboard_share.setEnabled(False) self.ui.menu_Pedalboard.setEnabled(False) # stop js evaulation self.fWebFrame = None # stop backend&server self.stopAndWaitForWebServer() self.stopAndWaitForBackend() print("load finished") @pyqtSlot() def slot_webviewPostFinished(self): if self.fNextBundle: bundle = self.fNextBundle self.fNextBundle = "" self.fWebFrame.evaluateJavaScript("desktop.loadPedalboard(\"%s\")" % bundle) QTimer.singleShot(0, self.slot_webviewPostFinished2) @pyqtSlot() def slot_webviewPostFinished2(self): self.ui.stackedwidget.setCurrentIndex(1) # -------------------------------------------------------------------------------------------------------- # Settings def saveSettings(self): settings = QSettings() settings.setValue("Geometry", self.saveGeometry()) def loadSettings(self, firstTime): qsettings = QSettings() websettings = self.ui.webview.settings() self.fSavedSettings = { # Main MOD_KEY_MAIN_PROJECT_FOLDER: qsettings.value(MOD_KEY_MAIN_PROJECT_FOLDER, MOD_DEFAULT_MAIN_PROJECT_FOLDER, type=str), MOD_KEY_MAIN_REFRESH_INTERVAL: qsettings.value(MOD_KEY_MAIN_REFRESH_INTERVAL, MOD_DEFAULT_MAIN_REFRESH_INTERVAL, type=int), # Host MOD_KEY_HOST_VERBOSE: qsettings.value(MOD_KEY_HOST_VERBOSE, MOD_DEFAULT_HOST_VERBOSE, type=bool), MOD_KEY_HOST_PATH: qsettings.value(MOD_KEY_HOST_PATH, MOD_DEFAULT_HOST_PATH, type=str), # WebView MOD_KEY_WEBVIEW_INSPECTOR: qsettings.value(MOD_KEY_WEBVIEW_INSPECTOR, MOD_DEFAULT_WEBVIEW_INSPECTOR, type=bool), MOD_KEY_WEBVIEW_VERBOSE: qsettings.value(MOD_KEY_WEBVIEW_VERBOSE, MOD_DEFAULT_WEBVIEW_VERBOSE, type=bool), MOD_KEY_WEBVIEW_SHOW_INSPECTOR: qsettings.value(MOD_KEY_WEBVIEW_SHOW_INSPECTOR, MOD_DEFAULT_WEBVIEW_SHOW_INSPECTOR, type=bool) } inspectorEnabled = self.fSavedSettings[MOD_KEY_WEBVIEW_INSPECTOR] and not USING_LIVE_ISO websettings.setAttribute(QWebSettings.DeveloperExtrasEnabled, inspectorEnabled) if firstTime: if qsettings.contains("Geometry"): self.restoreGeometry(qsettings.value("Geometry", "")) else: self.setWindowState(self.windowState() | Qt.WindowMaximized) if inspectorEnabled and self.fSavedSettings[MOD_KEY_WEBVIEW_SHOW_INSPECTOR]: QTimer.singleShot(1000, self.ui.webinspector.show) self.ui.act_file_inspect.setVisible(inspectorEnabled) if self.fIdleTimerId != 0: self.killTimer(self.fIdleTimerId) self.fIdleTimerId = self.startTimer(self.fSavedSettings[MOD_KEY_MAIN_REFRESH_INTERVAL]) # -------------------------------------------------------------------------------------------------------- # Misc @pyqtSlot() def slot_handleSIGUSR1(self): print("Got SIGUSR1 -> Saving project now") self.slot_pedalboardSave() @pyqtSlot() def slot_handleSIGTERM(self): print("Got SIGTERM -> Closing now") self.close() # -------------------------------------------------------------------------------------------------------- # Qt events def closeEvent(self, event): if self.fIdleTimerId != 0: self.killTimer(self.fIdleTimerId) self.fIdleTimerId = 0 self.saveSettings() self.slot_backendStop(True) QMainWindow.closeEvent(self, event) # Needed in case the web inspector is still alive #self.ui.webinspector.close() QApplication.instance().quit() def timerEvent(self, event): if event.timerId() == self.fIdleTimerId: pass QMainWindow.timerEvent(self, event) def resizeEvent(self, event): QMainWindow.resizeEvent(self, event) self.fixWebViewSize() # -------------------------------------------------------------------------------------------------------- # Internal stuff def getProcessErrorAsString(self, error): if error == -2: return self.tr("Ingen failed to create UNIX socket.") if error == QProcess.FailedToStart: return self.tr("Process failed to start.") if error == QProcess.Crashed: return self.tr("Process crashed.") if error == QProcess.Timedout: return self.tr("Process timed out.") if error == QProcess.WriteError: return self.tr("Process write error.") return self.tr("Unkown error.") def fixWebViewSize(self): if self.ui.stackedwidget.currentIndex() == 1: return size = self.ui.swp_intro.size() self.ui.swp_webview.resize(size) self.ui.webview.resize(size) self.ui.webpage.setViewportSize(size) def stopAndWaitForBackend(self): if self.fProccessBackend.state() == QProcess.NotRunning: return self.fStoppingBackend = True self.fProccessBackend.terminate() if not self.fProccessBackend.waitForFinished(2000): qWarning("Backend failed top stop cleanly, forced kill") self.fProccessBackend.kill() def stopAndWaitForWebServer(self): if not self.fWebServerThread.isRunning(): return if not self.fWebServerThread.stopWait(): qWarning("WebServer Thread failed top stop cleanly, forced terminate") self.fWebServerThread.terminate() def setProperWindowTitle(self): title = "MOD Application" if self.fCurrentTitle: title += " - %s" % self.fCurrentTitle self.setWindowTitle(title)
def _performMonitor(self): """ Protected method implementing the monitoring action. This method populates the statusList member variable with a list of strings giving the status in the first column and the path relative to the project directory starting with the third column. The allowed status flags are: <ul> <li>"A" path was added but not yet comitted</li> <li>"M" path has local changes</li> <li>"O" path was removed</li> <li>"R" path was deleted and then re-added</li> <li>"U" path needs an update</li> <li>"Z" path contains a conflict</li> <li>" " path is back at normal</li> </ul> @return tuple of flag indicating successful operation (boolean) and a status message in case of non successful operation (QString) """ self.shouldUpdate = False process = QProcess() args = QStringList() args.append('status') if not Preferences.getVCS("MonitorLocalStatus"): args.append('--show-updates') args.append('--non-interactive') args.append('.') process.setWorkingDirectory(self.projectDir) process.start('svn', args) procStarted = process.waitForStarted() if procStarted: finished = process.waitForFinished(300000) if finished and process.exitCode() == 0: output = \ unicode(process.readAllStandardOutput(), self.__ioEncoding, 'replace') states = {} for line in output.splitlines(): if self.rx_status1.exactMatch(line): flags = str(self.rx_status1.cap(1)) path = self.rx_status1.cap(3).trimmed() elif self.rx_status2.exactMatch(line): flags = str(self.rx_status2.cap(1)) path = self.rx_status2.cap(5).trimmed() else: continue if flags[0] in "ACDMR" or \ (flags[0] == " " and flags[-1] == "*"): if flags[-1] == "*": status = "U" else: status = flags[0] if status == "C": status = "Z" # give it highest priority elif status == "D": status = "O" if status == "U": self.shouldUpdate = True name = unicode(path) states[name] = status try: if self.reportedStates[name] != status: self.statusList.append("%s %s" % (status, name)) except KeyError: self.statusList.append("%s %s" % (status, name)) for name in self.reportedStates.keys(): if name not in states: self.statusList.append(" %s" % name) self.reportedStates = states return True, \ self.trUtf8("Subversion status checked successfully (using svn)") else: process.kill() process.waitForFinished() return False, QString(process.readAllStandardError()) else: process.kill() process.waitForFinished() return False, self.trUtf8("Could not start the Subversion process.")
def run_process(fused_command, read_output=False): # print "run process", fused_command # qprocess = QProcess() # set_process_env(qprocess) # code_de_retour = qprocess.execute(fused_command) # print "code de retour", code_de_retour # logger.info("command: ") # logger.info(fused_command) # logger.info("code de retour" + str(code_de_retour)) # # # if not qprocess.waitForStarted(): # # # handle a failed command here # # print "qprocess.waitForStarted()" # # return # # # # if not qprocess.waitForReadyRead(): # # # handle a timeout or error here # # print "qprocess.waitForReadyRead()" # # return # # #if not qprocess.waitForFinished(1): # # # qprocess.kill() # # # qprocess.waitForFinished(1) # # # if read_output: # # # logger.info("Erreur") # code_d_erreur = qprocess.error() # dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } # logger.info("Code de retour: " + str(code_d_erreur)) # logger.info(dic_err[code_d_erreur]) # # print "get output" # output = str(qprocess.readAllStandardOutput()) # # print "output", output # print 'end output' process = QProcess() process.start(fused_command) if process.waitForStarted(): process.waitForFinished(-1) exit_code = process.exitCode() logger.info("Code de sortie : " + str(exit_code)) if exit_code < 0: code_d_erreur = process.error().data dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) result = process.readAllStandardOutput() # print type(result), result error = process.readAllStandardError().data() # print repr(error) if not error == "\n": logger.info("error : " + "\'" + str(error) + "\'") logger.info("output : " + result.data() + "fin output") return result else: code_d_erreur = process.error() dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) return None
class MyMainWindow(QMainWindow): ' Main Window ' def __init__(self, parent=None): ' Initialize QWidget inside MyMainWindow ' super(MyMainWindow, self).__init__(parent) self.statusBar().showMessage(__doc__.title()) self.setWindowTitle(__doc__) self.setMinimumSize(600, 800) self.setMaximumSize(2048, 1024) self.resize(1024, 800) self.setWindowIcon(QIcon.fromTheme("face-monkey")) if not A11Y: self.setStyleSheet('''QWidget{color:#fff;font-family:Oxygen} QWidget:item:hover, QWidget:item:selected { background-color: cyan; color: #000 } QWidget:disabled { color: #404040; background-color: #323232 } QWidget:focus { border: 1px solid cyan } QPushButton { background-color: gray; padding: 3px; border: 1px solid gray; border-radius: 9px; margin: 0;font-size: 12px; padding-left: 5px; padding-right: 5px } QLineEdit, QTextEdit { background-color: #4a4a4a; border: 1px solid gray; border-radius: 0; font-size: 12px; } QPushButton:pressed { background-color: #323232 } QComboBox { background-color: #4a4a4a; padding-left: 9px; border: 1px solid gray; border-radius: 5px; } QComboBox:pressed { background-color: gray } QComboBox QAbstractItemView, QMenu { border: 1px solid #4a4a4a; background:grey; selection-background-color: cyan; selection-color: #000; } QSlider { padding: 3px; font-size: 8px; padding-left: 2px; padding-right: 2px; border: 5px solid #1e1e1e } QSlider::sub-page:vertical { background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1, y2:0.27, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(50, 0, 0, 200)); border: 4px solid #1e1e1e; border-radius: 5px } QSlider::add-page:vertical { background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1, y2:0.27, stop:0 rgba(0, 255, 0, 255), stop:1 rgba(0, 99, 0, 255)); border: 4px solid #1e1e1e; border-radius: 5px; } QSlider::handle:vertical { background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1, y2:0.273, stop:0 rgba(0, 0, 0, 255), stop:1 gray); height: 5px; border: 1px dotted #fff; text-align: center; border-top-left-radius: 2px; border-bottom-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius 2px; margin-left: 2px; margin-right: 2px; } QSlider::handle:vertical:hover { border: 1px solid cyan } QSlider::sub-page:vertical:disabled { background: #bbb; border-color: #999; } QSlider::add-page:vertical:disabled { background: #eee; border-color: #999; } QSlider::handle:vertical:disabled { background: #eee; border: 1px solid #aaa; border-radius: 4px; } QToolBar, QStatusBar, QDockWidget::title{background-color:#323232;} QToolBar::handle, QToolBar::handle:vertical, QToolBar::handle:horizontal { border: 1px solid gray; border-radius: 9px; width: 19px; height: 19px; margin: 0.5px } QGroupBox { border: 1px solid gray; border-radius: 9px; padding-top: 9px; } QStatusBar, QToolBar::separator:horizontal, QToolBar::separator:vertical {color:gray} QScrollBar:vertical{ background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #212121,stop: 1.0 #323232); width: 10px; } QScrollBar:horizontal{ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #212121,stop: 1.0 #323232); height: 10px; } QScrollBar::handle:vertical{ padding: 2px; min-height: 50px; background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #585858,stop: 1.0 #404040); border-radius: 5px; border: 1px solid #191919; } QScrollBar::handle:horizontal{ padding: 2px; min-width: 50px; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #585858,stop: 1.0 #404040); border-radius: 5px; border: 1px solid #191919; } QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; border: none; } QDockWidget::close-button, QDockWidget::float-button { border: 1px solid gray; border-radius: 3px; background: darkgray; }''') self.process = QProcess() self.process.readyReadStandardOutput.connect(self.read_output) self.process.readyReadStandardError.connect(self.read_errors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) self.group0, self.group1 = QGroupBox("Options"), QGroupBox("Paths") self.group2 = QGroupBox("Nodes") self.group3 = QGroupBox("Python Code") self.group4, self.group5 = QGroupBox("Logs"), QGroupBox("Backend") g0grid, g1vlay = QGridLayout(self.group0), QVBoxLayout(self.group1) g5vlay = QVBoxLayout(self.group5) self.treeview_nodes, self.textedit_source = QTextEdit(), QTextEdit() self.dock1, self.dock2 = QDockWidget(), QDockWidget() self.output, self.dock3 = QTextEdit(), QDockWidget() self.treeview_nodes.setAutoFormatting(QTextEdit.AutoAll) self.treeview_nodes.setWordWrapMode(QTextOption.NoWrap) self.dock1.setWidget(self.treeview_nodes) self.dock2.setWidget(self.textedit_source) self.dock3.setWidget(self.output) self.dock1.setWindowTitle("Tree") self.dock2.setWindowTitle("Sources") self.dock3.setWindowTitle("STDOutput") featur = QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable self.dock1.setFeatures(featur) self.dock2.setFeatures(featur) self.dock3.setFeatures(featur) QVBoxLayout(self.group2).addWidget(self.dock1) QVBoxLayout(self.group3).addWidget(self.dock2) QVBoxLayout(self.group4).addWidget(self.dock3) self.slider1, self.slider2 = QSlider(), QSlider() g0grid.addWidget(self.slider1, 0, 0) g0grid.addWidget(QLabel('Use Debug'), 0, 1) self.slider2.setValue(1) g0grid.addWidget(self.slider2, 1, 0) g0grid.addWidget(QLabel('Use verbose'), 1, 1) self.slider3, self.slider4 = QSlider(), QSlider() self.slider3.setValue(1) g0grid.addWidget(self.slider3, 2, 0) g0grid.addWidget(QLabel('Show compiling progress'), 2, 1) self.slider4.setValue(1) g0grid.addWidget(self.slider4, 3, 0) g0grid.addWidget(QLabel('Show Scons building debug'), 3, 1) self.slider5, self.slider6 = QSlider(), QSlider() g0grid.addWidget(self.slider5, 4, 0) g0grid.addWidget(QLabel('Keep debug unstriped binary'), 4, 1) g0grid.addWidget(self.slider6, 5, 0) g0grid.addWidget(QLabel('Traced execution outputs'), 5, 1) self.slider7, self.slider8 = QSlider(), QSlider() self.slider7.setValue(1) g0grid.addWidget(self.slider7, 6, 0) g0grid.addWidget(QLabel('Remove the build folder'), 6, 1) g0grid.addWidget(self.slider8, 7, 0) g0grid.addWidget(QLabel('No Python Optimizations'), 7, 1) self.slider9, self.slider10 = QSlider(), QSlider() g0grid.addWidget(self.slider9, 8, 0) g0grid.addWidget(QLabel('No Statements line numbers'), 8, 1) g0grid.addWidget(self.slider10, 9, 0) g0grid.addWidget(QLabel('Execute the output binary'), 9, 1) self.slider11, self.slider12 = QSlider(), QSlider() g0grid.addWidget(self.slider11, 10, 0) g0grid.addWidget(QLabel('Warning detected implicit exceptions'), 10, 1) g0grid.addWidget(self.slider12, 11, 0) g0grid.addWidget(QLabel('Keep the PYTHONPATH, do not Reset it'), 11, 1) self.slider13 = QSlider() g0grid.addWidget(self.slider13, 12, 0) g0grid.addWidget(QLabel('Enhance compile, CPython incompatible'), 12, 1) self.slider1a, self.slider2a = QSlider(), QSlider() g0grid.addWidget(self.slider1a, 0, 2) g0grid.addWidget(QLabel('Descendent Recursive Compile'), 0, 3) self.slider2a.setValue(1) g0grid.addWidget(self.slider2a, 1, 2) g0grid.addWidget(QLabel('Force non recursive compile'), 1, 3) self.slider3a, self.slider4a = QSlider(), QSlider() g0grid.addWidget(self.slider3a, 2, 2) g0grid.addWidget(QLabel('STD Lib Recursive Compile'), 2, 3) g0grid.addWidget(self.slider4a, 3, 2) g0grid.addWidget(QLabel('Enforce the use of Clang'), 3, 3) self.slider5a, self.slider6a = QSlider(), QSlider() self.slider5a.setValue(1) g0grid.addWidget(self.slider5a, 4, 2) g0grid.addWidget(QLabel('Use G++ link time optimizations'), 4, 3) g0grid.addWidget(self.slider6a, 5, 2) g0grid.addWidget(QLabel('Disable the console window'), 5, 3) self.slider7a, self.slider8a = QSlider(), QSlider() g0grid.addWidget(self.slider7a, 6, 2) g0grid.addWidget(QLabel('Force compile for MS Windows'), 6, 3) g0grid.addWidget(self.slider8a, 7, 2) g0grid.addWidget(QLabel('Use Python Debug versions'), 7, 3) self.slider9a, self.slider10a = QSlider(), QSlider() self.slider9a.setValue(1) g0grid.addWidget(self.slider9a, 8, 2) g0grid.addWidget(QLabel('Create standalone executable'), 8, 3) g0grid.addWidget(self.slider10a, 9, 2) g0grid.addWidget(QLabel('Enable Standalone mode build'), 9, 3) self.slider11a, self.slider12a = QSlider(), QSlider() g0grid.addWidget(self.slider11a, 10, 2) g0grid.addWidget(QLabel('Make module executable instead of app'), 10, 3) g0grid.addWidget(self.slider12a, 11, 2) g0grid.addWidget(QLabel('No froze module of stdlib as bytecode'), 11, 3) self.slider13a = QSlider() g0grid.addWidget(self.slider13a, 12, 2) g0grid.addWidget(QLabel('Force use of MinGW on MS Windows'), 12, 3) for each_widget in (self.slider1, self.slider2, self.slider3, self.slider4, self.slider5, self.slider6, self.slider7, self.slider8, self.slider9, self.slider10, self.slider11, self.slider12, self.slider13, self.slider1a, self.slider2a, self.slider3a, self.slider4a, self.slider5a, self.slider6a, self.slider7a, self.slider8a, self.slider9a, self.slider10a, self.slider11a, self.slider12a, self.slider13a): each_widget.setRange(0, 1) each_widget.setCursor(QCursor(Qt.OpenHandCursor)) each_widget.setTickInterval(1) each_widget.TickPosition(QSlider.TicksBothSides) self.combo1 = QComboBox() self.combo1.addItems(('2.7', '2.6', '3.2', '3.3')) g5vlay.addWidget(QLabel('Python Version')) g5vlay.addWidget(self.combo1) self.combo2 = QComboBox() self.combo2.addItems(('Default', 'Low', 'High')) g5vlay.addWidget(QLabel('CPU priority')) g5vlay.addWidget(self.combo2) self.combo3 = QComboBox() self.combo3.addItems(('1', '2', '3', '4', '5', '6', '7', '8', '9')) g5vlay.addWidget(QLabel('MultiProcessing Workers')) g5vlay.addWidget(self.combo3) self.outdir = QLineEdit() self.outdir.setStyleSheet("QLineEdit{margin-left:25px}") self.clearButton = QToolButton(self.outdir) self.clearButton.setIcon(QIcon.fromTheme("edit-clear")) self.clearButton.setIconSize(QSize(25, 25)) self.clearButton.setStyleSheet("QToolButton{border:none}") self.clearButton.hide() self.clearButton.clicked.connect(self.outdir.clear) self.outdir.textChanged.connect( lambda: self.clearButton.setVisible(True)) self.clearButton.clicked.connect( lambda: self.clearButton.setVisible(False)) self.outdir.setPlaceholderText('Output Directory') if path.isfile('.nuitka-output-dir.txt'): self.outdir.setText(open('.nuitka-output-dir.txt', 'r').read()) else: self.outdir.setText(path.expanduser("~")) self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.completer.popup().setStyleSheet( """border:1px solid #4a4a4a;background:grey; selection-background-color:cyan;selection-color:#000""") self.completer.popup().setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.outdir.setCompleter(self.completer) self.btn1 = QPushButton(QIcon.fromTheme("document-open"), 'Open' if IS_WIN else '') self.btn1.clicked.connect( lambda: open('.nuitka-output-dir.txt', 'w').write( str( QFileDialog.getExistingDirectory( None, 'Open Output Directory', path.expanduser("~"))))) self.btn1.released.connect(lambda: self.outdir.setText( open('.nuitka-output-dir.txt', 'r').read())) g1vlay.addWidget(QLabel('Output Directory')) g1vlay.addWidget(self.outdir) g1vlay.addWidget(self.btn1) self.target = QLineEdit() self.target.setStyleSheet("QLineEdit{margin-left:25px}") self.clearButton2 = QToolButton(self.target) self.clearButton2.setIcon(QIcon.fromTheme("edit-clear")) self.clearButton2.setIconSize(QSize(25, 25)) self.clearButton2.setStyleSheet("QToolButton{border:none}") self.clearButton2.hide() self.clearButton2.clicked.connect(self.target.clear) self.target.textChanged.connect( lambda: self.clearButton2.setVisible(True)) self.clearButton2.clicked.connect( lambda: self.clearButton2.setVisible(False)) self.target.setPlaceholderText('Target Python App to Binary Compile') self.target.setCompleter(self.completer) self.btn2 = QPushButton(QIcon.fromTheme("document-open"), 'Open' if IS_WIN else '') self.btn2.clicked.connect(lambda: self.target.setText( str( QFileDialog.getOpenFileName( None, "Open", path.expanduser("~"), ';;'.join([ '{}(*.{})'.format(e.upper(), e) for e in ('py', 'pyw', '*') ]))))) g1vlay.addWidget(QLabel('Input File')) g1vlay.addWidget(self.target) g1vlay.addWidget(self.btn2) self.icon, self.icon_label = QLineEdit(), QLabel('Icon File') self.icon.setStyleSheet("QLineEdit{margin-left:25px}") self.clearButton3 = QToolButton(self.icon) self.clearButton3.setIcon(QIcon.fromTheme("edit-clear")) self.clearButton3.setIconSize(QSize(25, 25)) self.clearButton3.setStyleSheet("QToolButton{border:none}") self.clearButton3.hide() self.clearButton3.clicked.connect(self.icon.clear) self.icon.textChanged.connect( lambda: self.clearButton3.setVisible(True)) self.clearButton3.clicked.connect( lambda: self.clearButton3.setVisible(False)) self.icon.setPlaceholderText('Path to Icon file for your App') self.icon.setCompleter(self.completer) self.btn3 = QPushButton(QIcon.fromTheme("document-open"), 'Open' if IS_WIN else '') self.btn3.clicked.connect(lambda: self.icon.setText( str( QFileDialog.getOpenFileName( None, "Open", path.expanduser("~"), ';;'.join([ '{}(*.{})'.format(e.upper(), e) for e in ('ico', 'png', 'bmp', 'svg', '*') ]))))) g1vlay.addWidget(self.icon_label) g1vlay.addWidget(self.icon) g1vlay.addWidget(self.btn3) # Menu Bar inicialization and detail definitions menu_salir = QAction(QIcon.fromTheme("application-exit"), 'Quit', self) menu_salir.setStatusTip('Quit') menu_salir.triggered.connect(exit) menu_minimize = QAction(QIcon.fromTheme("go-down"), 'Minimize', self) menu_minimize.setStatusTip('Minimize') menu_minimize.triggered.connect(lambda: self.showMinimized()) menu_qt = QAction(QIcon.fromTheme("help-about"), 'About Qt', self) menu_qt.setStatusTip('About Qt...') menu_qt.triggered.connect(lambda: QMessageBox.aboutQt(self)) menu_dev = QAction(QIcon.fromTheme("applications-development"), 'Developer Manual PDF', self) menu_dev.setStatusTip('Open Nuitka Developer Manual PDF...') menu_dev.triggered.connect(lambda: call( OPEN + '/usr/share/doc/nuitka/Developer_Manual.pdf.gz', shell=True) ) menu_usr = QAction(QIcon.fromTheme("help-contents"), 'User Docs', self) menu_usr.setStatusTip('Open Nuitka End User Manual PDF...') menu_usr.triggered.connect(lambda: call( OPEN + '/usr/share/doc/nuitka/README.pdf.gz', shell=True)) menu_odoc = QAction(QIcon.fromTheme("help-browser"), 'OnLine Doc', self) menu_odoc.setStatusTip('Open Nuitka on line Documentation pages...') menu_odoc.triggered.connect( lambda: open_new_tab('http://nuitka.net/doc/user-manual.html')) menu_man = QAction(QIcon.fromTheme("utilities-terminal"), 'Man', self) menu_man.setStatusTip('Open Nuitka technical command line Man Pages..') menu_man.triggered.connect( lambda: call('xterm -e "man nuitka"', shell=True)) menu_tra = QAction(QIcon.fromTheme("applications-development"), 'View Nuitka-GUI Source Code', self) menu_tra.setStatusTip('View, study, edit Nuitka-GUI Libre Source Code') menu_tra.triggered.connect(lambda: call(OPEN + __file__, shell=True)) menu_foo = QAction(QIcon.fromTheme("folder"), 'Open Output Dir', self) menu_foo.setStatusTip('Open the actual Output Directory location...') menu_foo.triggered.connect( lambda: call(OPEN + str(self.outdir.text()), shell=True)) menu_pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self) menu_pic.setStatusTip('Take a Screenshot for Documentation purposes..') menu_pic.triggered.connect( lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save( QFileDialog.getSaveFileName(None, "Save", path.expanduser("~"), 'PNG(*.png)', 'png'))) menu_don = QAction(QIcon.fromTheme("emblem-favorite"), 'Help Nuitka', self) menu_don.setStatusTip('Help the Nuitka Open Source Libre Free Project') menu_don.triggered.connect( lambda: open_new_tab('http://nuitka.net/pages/donations.html')) # movable draggable toolbar self.toolbar = QToolBar(self) self.toolbar.setIconSize(QSize(16, 16)) self.toolbar.toggleViewAction().setText("Show/Hide Toolbar") l_spacer, r_spacer = QWidget(self), QWidget(self) l_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) r_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(l_spacer) self.toolbar.addSeparator() self.toolbar.addActions((menu_salir, menu_minimize, menu_qt, menu_odoc, menu_foo, menu_pic, menu_don)) if not IS_WIN: self.toolbar.addActions((menu_man, menu_dev, menu_tra, menu_usr)) self.toolbar.addSeparator() self.toolbar.addWidget(r_spacer) self.addToolBar(Qt.BottomToolBarArea, self.toolbar) # Bottom Buttons Bar self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Close) self.buttonBox.rejected.connect(exit) self.buttonBox.accepted.connect(self.run) self.guimode = QComboBox() self.guimode.addItems(('Full UX / UI', 'Simple UX / UI')) self.guimode.setStyleSheet( """QComboBox{background:transparent;border:0; margin-left:25px;color:gray;text-decoration:underline}""") self.guimode.currentIndexChanged.connect(self.set_guimode) container = QWidget() container_layout = QGridLayout(container) # Y, X container_layout.addWidget(self.guimode, 0, 1) container_layout.addWidget(self.group2, 1, 0) container_layout.addWidget(self.group3, 2, 0) container_layout.addWidget(self.group0, 1, 1) container_layout.addWidget(self.group1, 2, 1) container_layout.addWidget(self.group4, 1, 2) container_layout.addWidget(self.group5, 2, 2) container_layout.addWidget(self.buttonBox, 3, 1) self.setCentralWidget(container) # Paleta de colores para pintar transparente if not A11Y: palette = self.palette() palette.setBrush(QPalette.Base, Qt.transparent) self.setPalette(palette) self.setAttribute(Qt.WA_OpaquePaintEvent, False) def get_fake_tree(self, target): """Return the fake tree.""" try: fake_tree = check_output(NUITKA + ' --dump-xml ' + target, shell=True) except: fake_tree = "ERROR: Failed to get Tree Dump." finally: return fake_tree.strip() def run(self): ' run the actual backend process ' self.treeview_nodes.clear() self.textedit_source.clear() self.output.clear() self.statusBar().showMessage('WAIT!, Working...') target = str(self.target.text()).strip() self.treeview_nodes.setText(self.get_fake_tree(target)) self.textedit_source.setText(open(target, "r").read().strip()) conditional_1 = sys.platform.startswith('linux') conditional_2 = self.combo3.currentIndex() != 2 command_to_run_nuitka = " ".join( ('chrt -i 0' if conditional_1 and conditional_2 else '', NUITKA, '--debug' if self.slider1.value() else '', '--verbose' if self.slider2.value() else '', '--show-progress' if self.slider3.value() else '', '--show-scons --show-modules' if self.slider4.value() else '', '--unstriped' if self.slider5.value() else '', '--trace-execution' if self.slider6.value() else '', '--remove-output' if self.slider7.value() else '', '--no-optimization' if self.slider8.value() else '', '--code-gen-no-statement-lines' if self.slider9.value() else '', '--execute' if self.slider10.value() else '', '--recurse-all' if self.slider1a.value() else '', '--recurse-none' if self.slider2a.value() else '', '--recurse-stdlib' if self.slider3a.value() else '', '--clang' if self.slider4a.value() else '', '--lto' if self.slider5a.value() else '', '--windows-disable-console' if self.slider6a.value() else '', '--windows-target' if self.slider7a.value() else '', '--python-debug' if self.slider8a.value() else '', '--exe' if self.slider9a.value() else '', '--standalone' if self.slider10a.value() else '', '--module' if self.slider11a.value() else '', '--nofreeze-stdlib' if self.slider12a.value() else '', '--mingw' if self.slider13a.value() else '', '--warn-implicit-exceptions' if self.slider11.value() else '', '--execute-with-pythonpath' if self.slider12.value() else '', '--enhanced' if self.slider13.value() else '', '--icon="{}"'.format(self.icon.text()) if self.icon.text() else '', '--python-version={}'.format( self.combo1.currentText()), '--jobs={}'.format( self.combo3.currentText()), '--output-dir="{}"'.format( self.outdir.text()), "{}".format(target))) if DEBUG: print(command_to_run_nuitka) self.process.start(command_to_run_nuitka) if not self.process.waitForStarted() and not IS_WIN: return # ERROR ! self.statusBar().showMessage(__doc__.title()) def _process_finished(self): """finished sucessfully""" self.output.setFocus() self.output.selectAll() def read_output(self): """Read and append output to the log""" self.output.append(str(self.process.readAllStandardOutput())) def read_errors(self): """Read and append errors to the log""" self.output.append(str(self.process.readAllStandardError())) def paintEvent(self, event): """Paint semi-transparent background,animated pattern,background text""" if not A11Y: p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) p.setRenderHint(QPainter.TextAntialiasing) p.setRenderHint(QPainter.HighQualityAntialiasing) p.fillRect(event.rect(), Qt.transparent) # animated random dots background pattern for i in range(4096): x = randint(25, self.size().width() - 25) y = randint(25, self.size().height() - 25) # p.setPen(QPen(QColor(randint(9, 255), 255, 255), 1)) p.drawPoint(x, y) p.setPen(QPen(Qt.white, 1)) p.rotate(40) p.setFont(QFont('Ubuntu', 250)) p.drawText(200, 99, "Nuitka") p.rotate(-40) p.setPen(Qt.NoPen) p.setBrush(QColor(0, 0, 0)) p.setOpacity(0.8) p.drawRoundedRect(self.rect(), 9, 9) p.end() def set_guimode(self): """Switch between simple and full UX""" for widget in (self.group2, self.group3, self.group4, self.group5, self.icon, self.icon_label, self.btn3, self.toolbar, self.statusBar()): widget.hide() if self.guimode.currentIndex() else widget.show()
class Main(plugin.Plugin): ' main class for plugin ' def initialize(self, *args, **kwargs): ' class init ' super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) # menu menu = QMenu('VirtualEnv') menu.addAction('Make VirtualEnv here', lambda: self.make_virtualenv()) self.locator.get_service('explorer').add_project_menu(menu, lang='all') self.group1 = QGroupBox() self.group1.setTitle(' Paths ') self.outdir = QLineEdit(path.expanduser("~")) self.outdir.setPlaceholderText('Target Directory for Virtualenv files') self.outdir.setCompleter(self.completer) self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn1.clicked.connect(lambda: self.outdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Target Directory for the Python VirtualEnv...', path.expanduser("~"))))) self.srcdir, self.prefx = QLineEdit(), QLineEdit() self.srcdir.setPlaceholderText( 'Extra search path to look for setuptools/distribute/pip') self.srcdir.setToolTip(''' Specify Extra search path to look for setuptools/distribute/pip. Defaults to Empty, then the setting is ignored.Defaults are OK.''') self.srcdir.setCompleter(self.completer) self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn2.setToolTip( 'Specify Extra search path to look for setuptools/distribute/pip') self.btn2.clicked.connect(lambda: self.srcdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Extra search path to look for setuptools/pip...', path.expanduser("~"))))) self.prefx.setPlaceholderText('Prompt prefix for this environment') self.prefx.setToolTip(''' Specify a custom alternative prompt prefix for this environment. Defaults to Empty,this is optional,short prefix are recommended.''') self.btn3 = QPushButton(QIcon.fromTheme("face-smile-big"), 'Suggestion') self.btn3.setToolTip('Suggest me a Random CLI prompt prefix !') self.btn3.clicked.connect(lambda: self.prefx.setText(choice((getuser(), 'tesla', 'einstein', 'turing', 'ritchie', 'darwin', 'curie', 'planck', 'lovelace', 'dijsktra', 'galileo', 'schroedinger', 'perlman', 'hopper', 'newton', 'pasteur', 'maxwell', 'aristotle', 'volta', 'mendelev', 'bohr', 'crick', 'watson', 'archimedes', 'nash', 'fermi', 'dirac', 'feynman', 'kepler', 'copernicus', 'lorentz', 'faraday', 'heisenberg', )))) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( QLabel(' Target directory dath: '), self.outdir, self.btn1, QLabel(' Extra search path: '), self.srcdir, self.btn2, QLabel(' CLI Prompt prefix (Optional): '), self.prefx, self.btn3): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' Options ') self.group2.setCheckable(True) self.group2.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group2.graphicsEffect().setEnabled(False) self.group2.toggled.connect(self.toggle_options_group) self.qckb1, self.combo1 = QCheckBox(' Use Debug'), QDoubleSpinBox() self.qckb2 = QCheckBox(' Clear out the target directory') self.qckb3 = QCheckBox(' System-wide Python Packages') self.qckb4 = QCheckBox(' Unzip Setuptool or Distribute to virtualenv') self.qckb5 = QCheckBox(' Force the use of SetupTools') self.qckb6 = QCheckBox(' Never download packages') self.qckb7 = QCheckBox(' Delete .PYC files from virtualenv') self.qckb8 = QCheckBox(' Open target directory later') self.qckb9 = QCheckBox(' Save a LOG file to target later') self.qckb10 = QCheckBox(' No install PIP in the new virtualenv') self.qckb11 = QCheckBox('Save Bash script to reproduce virtenv later') self.chrt = QCheckBox('LOW CPU priority for Backend Process') self.combo1.setValue(2.7) self.combo1.setMaximum(3.4) self.combo1.setMinimum(2.4) self.combo1.setDecimals(1) self.combo1.setSingleStep(0.1) try: self.vinfo = QLabel('<small><b> Virtualenv Version: </b>' + getoutput('virtualenv --version', shell=1).strip()) except: self.vinfo = QLabel('Warning: Failed to query Virtualenv Backend!') [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4, self.qckb5, self.qckb6, self.qckb7, self.qckb8, self.qckb9, self.qckb10, self.qckb11, QLabel(' Python interpreter version: '), self.combo1, QLabel(' Backend CPU priority: '), self.chrt): vboxg2.addWidget(each_widget) self.button = QPushButton(' Make Virtualenv ') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) self.output = QTextEdit(''' " Let the future tell the truth, and evaluate each one according to his work and accomplishments. The present is theirs; the future, for which I really worked, is mine. " -Nikola Tesla. ''') class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((self.group1, self.group2, QLabel('Backend Logs'), self.output, self.vinfo, self.button)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Virtualenv") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append sphinx-build output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append sphinx-build errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def make_virtualenv(self): ' make virtualenv from contextual sub menu ' self.outdir.setText(self.ex_locator.get_current_project_item().path) self.run() def run(self): ' run the actions ' self.output.clear() self.output.append(self.formatInfoMsg( 'INFO: OK: Starting at {}'.format(datetime.now()))) self.button.setDisabled(True) # Parse Values arg0 = '' if self.qckb10.isChecked() is False else '--no-pip ' arg1 = '--quiet ' if self.qckb1.isChecked() is False else '--verbose ' arg2 = '' if self.qckb2.isChecked() is False else '--clear ' arg3 = '' if self.qckb3.isChecked() is False else '--system-site-packages ' arg4 = '' if self.qckb4.isChecked() is False else '--unzip-setuptools ' arg5 = '' if self.qckb5.isChecked() is False else '--setuptools ' arg6 = '' if self.qckb6.isChecked() is False else '--never-download ' # if the target is empty return if not len(str(self.outdir.text()).strip()): self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty')) self.button.setEnabled(True) return else: self.output.append(self.formatInfoMsg( 'INFO: OK: Output Directory is {}'.format(self.outdir.text()))) # prefix prf = str(self.prefx.text()).upper().strip().replace(' ', '') arg10 = '' if prf is '' else '--prompt="{}_" '.format(prf) self.output.append(self.formatInfoMsg('INFO: Prefix: {}'.format(arg10))) # extra search dir src = str(self.srcdir.text()).strip() arg11 = '' if src is '' else '--extra-search-dir="{}" '.format(src) self.output.append(self.formatInfoMsg(' INFO: Extra: {}'.format(arg11))) self.output.append(self.formatInfoMsg( ' INFO: OK: Write Logs ?: {} '.format(self.qckb9.isChecked()))) self.output.append(self.formatInfoMsg( ' INFO: OK: Open Directory ?: {} '.format(self.qckb8.isChecked()))) # run the subprocesses cmd = '{}virtualenv {}{}{}{}{}{}{}-p python{} {}{} {}'.format( 'chrt --verbose -i 0 ' if self.chrt.isChecked() is True else '', arg0, arg1, arg2, arg3, arg4, arg5, arg6, self.combo1.value(), arg11, arg10, str(self.outdir.text()).strip()) self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append(self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(cmd))) self.button.setEnabled(True) return # write a .sh bash script file on target if self.qckb11.isChecked() is True: sh_file = 'create_virtualenv.sh' with open(path.join(str(self.outdir.text()), sh_file), 'w') as _sh: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash: {}'''.format(path.join(str(self.outdir.text()), sh_file)))) _sh.write('#!/usr/bin/env bash' + linesep + cmd) _sh.close() self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775')) try: chmod(path.join(str(self.outdir.text()), sh_file), 0775) # Py2 except: chmod(path.join(str(self.outdir.text()), sh_file), 0o775) # Py3 self.readOutput() self.readErrors() self.button.setEnabled(True) def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg( 'INFO: OK: Finished at {}'.format(datetime.now()))) # remove all *.PYC bytecode if self.qckb7.isChecked() is True: self.output.append(self.formatInfoMsg(' INFO: OK: Removing *.PYC ')) self.output.append(self.formatInfoMsg(' INFO: This takes a moment')) [remove(path.join(root, f)) for root, f in list(itertools.chain(* [list(itertools.product([root], files)) for root, dirs, files in walk(str(self.outdir.text()).strip())])) if f.endswith(('.pyc', '.PYC')) and not f.startswith('.')] # write a .log file on target if self.qckb9.isChecked() is True: log_file = 'virtualenv_gui.log' with open(path.join(str(self.outdir.text()), log_file), 'w') as log: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs: {}'''.format(path.join(str(self.outdir.text()), log_file)))) log.write(self.output.toPlainText()) log.close() # open target dir if self.qckb8.isChecked() is True: try: startfile(str(self.outdir.text())) except: Popen(["xdg-open", str(self.outdir.text())]) self.output.selectAll() self.output.setFocus() def toggle_options_group(self): ' toggle on off the options group ' if self.group2.isChecked() is True: [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] self.combo1.setValue(2.7) self.group2.graphicsEffect().setEnabled(False) else: [a.setChecked(False) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] self.group2.graphicsEffect().setEnabled(True) def finish(self): ' clear when finish ' self.process.kill()
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) # self.process.error.connect(self._process_error) self.sourceDirectory, self.outputDirectory = None, None self.group2 = QGroupBox() self.group2.setTitle(' Paths ') self.inf = QLineEdit(path.expanduser("~")) self.inf.setPlaceholderText(' /full/path/to/directory ') self.out, self.fle = QLineEdit(path.expanduser("~")), QLineEdit() self.out.setPlaceholderText(' /full/path/to/directory ') self.fle.setPlaceholderText(' /full/path/to/single/file ') self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.inf.setCompleter(self.completer) self.out.setCompleter(self.completer) self.fle.setCompleter(self.completer) self.open1 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open1.setCursor(QCursor(Qt.PointingHandCursor)) self.open1.clicked.connect(lambda: self.inf.setText(str( QFileDialog.getExistingDirectory(self.dock, "Open Source Directory", path.expanduser("~"))))) self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open2.setCursor(QCursor(Qt.PointingHandCursor)) self.open2.clicked.connect(lambda: self.out.setText(str( QFileDialog.getExistingDirectory(self.dock, "Open Target Directory", path.expanduser("~"))))) self.open3 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open3.setCursor(QCursor(Qt.PointingHandCursor)) self.open3.clicked.connect(lambda: self.fle.setText(str( QFileDialog.getOpenFileName(self.dock, "Open a Target File...", path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e) for e in ['py', 'pyw', '*']]))))) vboxg2 = QVBoxLayout(self.group2) for each_widget in ( QLabel('Source Directory Project:'), self.inf, self.open1, QLabel(' Target Directory Outputs: '), self.out, self.open2, QLabel(' Source Single File (Optional):'), self.fle, self.open3, ): vboxg2.addWidget(each_widget) self.group1 = QGroupBox() self.group1.setTitle(' Options ') self.chckbx1 = QCheckBox(' Inject Twitter Bootstrap CSS3 ') self.chckbx1.toggled.connect(self.toggle_styles_group) self.chckbx2 = QCheckBox(' Warn all missing references ') self.chckbx3 = QCheckBox(' Open Docs when done building ') self.chckbx4 = QCheckBox('Save Bash script to reproduce Sphinx Builds') vboxg1 = QVBoxLayout(self.group1) for each_widget in (self.chckbx1, self.chckbx2, self.chckbx3, self.chckbx4): vboxg1.addWidget(each_widget) each_widget.setChecked(True) self.group3 = QGroupBox() self.group3.setTitle(' Styles ') self.group3.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group3.graphicsEffect().setEnabled(False) self.basecss, self.fontcss = QComboBox(), QComboBox() self.basecss.addItems(['slate', 'united', 'spacelab', 'superhero', 'simplex', 'journal', 'flatly', 'cyborg', 'cosmo', 'cerulean']) self.fontcss.addItems(['Ubuntu Light', 'Oxygen', 'Roboto', 'Droid Sans', 'Open Sans', 'Pacifico', 'Rancho', 'Arvo', 'Fresca', 'Graduate']) self.backcss = QComboBox() self.backcss.addItems(['shattered', 'retina_wood', 'ricepaper', 'brickwall', 'sneaker_mesh_fabric', 'diagonales_decalees', 'noisy_grid', 'pw_pattern', 'escheresque', 'diamond_upholstery']) vboxg3 = QVBoxLayout(self.group3) for each_widget in (QLabel('<b>Twitter Bootstrap Theme'), self.basecss, QLabel('<b>Fonts Family'), self.fontcss, QLabel('<b>Background Seamless Tiled Pattern'), self.backcss): vboxg3.addWidget(each_widget) self.output = QTextEdit(''' My brain is something more than merely mortal; As time will show. - Ada Lovelace ''') self.output.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.button = QPushButton('Document My Code') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.build) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((self.group2, self.group1, self.group3, QLabel(linesep + ' Logs: '), self.output, self.button)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Sphinx") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append sphinx-build output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput())) def readErrors(self): """Read and append sphinx-build errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def build(self): """Main function calling sphinx-build to generate the project""" self.output.setText('') self.output.append(self.formatInfoMsg( 'INFO: OK: Starting at {}'.format(datetime.now()))) self.button.setDisabled(True) self.sourceDirectory = str(self.inf.text()).strip() self.outputDirectory = str(self.out.text()).strip() if not len(self.sourceDirectory): self.output.append(' ERROR: FAIL: Source directory cannot be empty') else: self.output.append(self.formatInfoMsg( 'INFO: OK: Source Directory is {}'.format(self.sourceDirectory))) if not len(self.outputDirectory): self.output.append(' ERROR: FAIL: Output directory cannot be empty') else: self.output.append(self.formatInfoMsg( 'INFO: OK: Output Directory is {}'.format(self.outputDirectory))) if not(len(self.sourceDirectory) or len(self.outputDirectory)): self.button.setDisabled(False) return self.output.append(self.formatInfoMsg('INFO:OK: Building. Please wait')) args = ['-n' if self.chckbx2.isChecked() is True else '', '-b', 'html', self.sourceDirectory, self.outputDirectory] if len(self.fle.text()): args.append(str(self.fle.text()).strip().replace('file:///', '/')) self.output.append(self.formatInfoMsg( 'INFO: OK: Source Single File is {}'.format(self.fle.text()))) self.output.append(self.formatInfoMsg('INFO:OK: Running sphinx-build!')) self.process.start('sphinx-build', args) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg('ERROR: FAIL: Build Failed')) self.output.append(self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(args))) self.button.setEnabled(True) return # write a .sh bash script file on target if self.chckbx4.isChecked() is True: sh_file = 'build_sphinx_documentation.sh' with open(path.join(self.sourceDirectory, sh_file), 'w') as _sh: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash: {}'''.format(path.join(self.sourceDirectory, sh_file)))) _sh.write('#!/usr/bin/env bash {}'.format(linesep) + 'sphinx-build {}'.format(' '.join(args))) _sh.close() self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775')) try: chmod(path.join(self.sourceDirectory, sh_file), 0775) # Py2 except: chmod(path.join(self.sourceDirectory, sh_file), 0o775) # Py3 self.button.setEnabled(True) def _process_finished(self): """sphinx-build finished sucessfully""" self.output.append(self.formatInfoMsg( 'INFO: OK: Finished at {}'.format(datetime.now()))) if self.chckbx1.isChecked() is True: with open(path.join(self.outputDirectory, '_static', 'default.css'), 'a') as f: css = CSS3.replace('CSSWEBFONT', str(self.fontcss.currentText()) ).replace('CSSBACKGR', str(self.backcss.currentText()) ).replace('CSSCUSTOM', str(self.basecss.currentText())) f.write(css) f.close() if self.chckbx3.isChecked() is True: call('xdg-open ' + path.join(self.outputDirectory, 'index.html'), shell=True) def toggle_styles_group(self): ' toggle on or off the styles checkboxes ' try: if self.chckbx1.isChecked() is True: self.group3.graphicsEffect().setEnabled(False) self.group3.setEnabled(True) else: self.group3.graphicsEffect().setEnabled(True) self.group3.setEnabled(False) except: pass
class HostWindow(QMainWindow): # signals SIGTERM = pyqtSignal() SIGUSR1 = pyqtSignal() # -------------------------------------------------------------------------------------------------------- def __init__(self): QMainWindow.__init__(self) self.ui = Ui_HostWindow() self.ui.setupUi(self) # ---------------------------------------------------------------------------------------------------- # Internal stuff # Current mod-ui title #self.fCurrentBundle = "" self.fCurrentTitle = "" # Next bundle to load (done by startup arguments) self.fNextBundle = "" # first attempt of auto-start backend doesn't show an error self.fFirstBackendInit = True # need to call session reconnect after connecting the 1st time self.fNeedsSessionReconnect = False # Qt idle timer self.fIdleTimerId = 0 # Qt web frame, used for evaluating javascript self.fWebFrame = None # to be filled with key-value pairs of current settings self.fSavedSettings = {} # List of pedalboards self.fPedalboards = get_all_pedalboards() # List of current-pedalboard presets self.fPresetMenuList = [] # Process that runs the backend self.fProccessBackend = QProcess(self) self.fProccessBackend.setProcessChannelMode(QProcess.MergedChannels) self.fProccessBackend.setReadChannel(QProcess.StandardOutput) self.fStoppingBackend = False # Thread for managing the webserver self.fWebServerThread = WebServerThread(self) # ---------------------------------------------------------------------------------------------------- # Set up GUI self.ui.webview = QWebView(self.ui.swp_webview) self.ui.webview.setMinimumWidth(980) self.ui.swp_webview.layout().addWidget(self.ui.webview) self.ui.webpage = HostWebPage(self) self.ui.webpage.setViewportSize(QSize(980, 600)) self.ui.webview.setPage(self.ui.webpage) self.ui.webinspector = QWebInspector(None) self.ui.webinspector.resize(800, 600) self.ui.webinspector.setPage(self.ui.webpage) self.ui.webinspector.setVisible(False) self.ui.act_file_connect.setEnabled(False) self.ui.act_file_connect.setVisible(False) self.ui.act_file_disconnect.setEnabled(False) self.ui.act_file_disconnect.setVisible(False) self.ui.label_app.setText("MOD Application v%s" % config["version"]) # disable file menu self.ui.act_file_refresh.setEnabled(False) self.ui.act_file_inspect.setEnabled(False) # disable pedalboard menu self.ui.act_pedalboard_new.setEnabled(False) self.ui.act_pedalboard_open.setEnabled(False) self.ui.act_pedalboard_save.setEnabled(False) self.ui.act_pedalboard_save_as.setEnabled(False) self.ui.act_pedalboard_share.setEnabled(False) self.ui.menu_Pedalboard.setEnabled(False) # disable presets menu self.ui.act_presets_new.setEnabled(False) self.ui.act_presets_save.setEnabled(False) self.ui.act_presets_save_as.setEnabled(False) self.ui.menu_Presets.setEnabled(False) # initial stopped state self.slot_backendFinished(-1, -1) # Qt needs this so it properly creates & resizes the webview self.ui.stackedwidget.setCurrentIndex(1) self.ui.stackedwidget.setCurrentIndex(0) # FIXME #self.ui.act_backend_stop.setVisible(False) #self.ui.act_backend_restart.setVisible(False) # ---------------------------------------------------------------------------------------------------- # Set up GUI (special stuff for Mac OS) if MACOS: self.ui.act_file_quit.setMenuRole(QAction.QuitRole) self.ui.act_settings_configure.setMenuRole(QAction.PreferencesRole) self.ui.act_help_about.setMenuRole(QAction.AboutRole) #self.ui.menu_Settings.setTitle("Panels") #self.ui.menu_Help.hide() # ---------------------------------------------------------------------------------------------------- # Load Settings self.loadSettings(True) # ---------------------------------------------------------------------------------------------------- # Connect actions to functions self.SIGUSR1.connect(self.slot_handleSIGUSR1) self.SIGTERM.connect(self.slot_handleSIGTERM) self.fProccessBackend.error.connect(self.slot_backendError) self.fProccessBackend.started.connect(self.slot_backendStarted) self.fProccessBackend.finished.connect(self.slot_backendFinished) self.fProccessBackend.readyRead.connect(self.slot_backendRead) self.fWebServerThread.running.connect(self.slot_webServerRunning) self.fWebServerThread.finished.connect(self.slot_webServerFinished) self.ui.act_file_refresh.triggered.connect(self.slot_fileRefresh) self.ui.act_file_inspect.triggered.connect(self.slot_fileInspect) self.ui.act_settings_configure.triggered.connect(self.slot_configure) self.ui.act_help_about.triggered.connect(self.slot_about) self.ui.act_help_project.triggered.connect(self.slot_showProject) self.ui.act_help_website.triggered.connect(self.slot_showWebsite) self.ui.b_start.clicked.connect(self.slot_backendStart) self.ui.b_configure.clicked.connect(self.slot_configure) self.ui.b_about.clicked.connect(self.slot_about) # force our custom refresh webReloadAction = self.ui.webpage.action(QWebPage.Reload) webReloadAction.triggered.disconnect() webReloadAction.triggered.connect(self.slot_fileRefresh) # ---------------------------------------------------------------------------------------------------- # Final setup self.setProperWindowTitle() SESSION.setupApp(self._pedal_changed_callback) if not "--no-autostart" in sys.argv: QTimer.singleShot(0, self.slot_backendStart) QTimer.singleShot(1, self.fixWebViewSize) def __del__(self): self.stopAndWaitForWebServer() self.stopAndWaitForBackend() def _pedal_changed_callback(self, ok, bundlepath, title): #self.fCurrentBundle = bundlepath self.fCurrentTitle = title or "" #self.updatePresetsMenu() self.setProperWindowTitle() # -------------------------------------------------------------------------------------------------------- # Files (menu actions) @pyqtSlot() def slot_fileRefresh(self): if self.fWebFrame is None: return self.ui.label_progress.setText(self.tr("Refreshing UI...")) self.ui.stackedwidget.setCurrentIndex(0) QTimer.singleShot(0, self.ui.webview.reload) @pyqtSlot() def slot_fileInspect(self): self.ui.webinspector.show() # -------------------------------------------------------------------------------------------------------- # Settings (menu actions) @pyqtSlot() def slot_configure(self): dialog = SettingsWindow(self, True) if not dialog.exec_(): return self.loadSettings(False) # -------------------------------------------------------------------------------------------------------- # About (menu actions) @pyqtSlot() def slot_about(self): QMessageBox.about( self, self.tr("About"), self.tr(""" <b>MOD Desktop Application</b><br/> <br/> A software to have the complete MOD environment running in your desktop.<br/> (C) 2015-2016 - The MOD Team<br/> <br/> Publications, products, content or services referenced herein or on the website are the exclusive trademarks or servicemarks of MOD.<br/> Other product and company names mentioned in the site may be the trademarks of their respective owners.<br/> <br/> All software is available under the <a href="https://www.gnu.org/licenses/gpl-2.0.html">GPL license</a>.<br/> """)) @pyqtSlot() def slot_showProject(self): QDesktopServices.openUrl(QUrl("https://github.com/moddevices/mod-app")) @pyqtSlot() def slot_showWebsite(self): QDesktopServices.openUrl(QUrl("http://moddevices.com/")) # -------------------------------------------------------------------------------------------------------- # Backend (menu actions) @pyqtSlot() def slot_backendInformation(self): table = """ <table><tr> <td> MOD-UI port: <td></td> %s </td> </tr></table> """ % (config["port"], ) QMessageBox.information(self, self.tr("information"), table) @pyqtSlot() def slot_backendStart(self): if self.fProccessBackend.state() != QProcess.NotRunning: print("slot_backendStart ignored") return print("slot_backendStart in progress...") hostPath = self.fSavedSettings[MOD_KEY_HOST_PATH] if hostPath.endswith("ingen"): hostPath = MOD_DEFAULT_HOST_PATH hostArgs = ["-p", "5555", "-f", "5556"] if self.fSavedSettings[MOD_KEY_HOST_VERBOSE]: hostArgs.append("-v") else: hostArgs.append("-n") self.fProccessBackend.start(hostPath, hostArgs) @pyqtSlot() def slot_backendStop(self): #if self.fPluginCount > 0: #if not forced: #ask = QMessageBox.question(self, self.tr("Warning"), self.tr("There are still some plugins loaded, you need to remove them to stop the engine.\n" #"Do you want to do this now?"), #QMessageBox.Yes | QMessageBox.No, QMessageBox.No) #if ask != QMessageBox.Yes: #return #self.removeAllPlugins() #self.host.set_engine_about_to_close() #self.host.remove_all_plugins() # testing red color for server stopped self.ui.webview.blockSignals(True) self.ui.webview.setHtml("<html><body bgcolor='green'></body></html>") self.ui.webview.blockSignals(False) self.stopAndWaitForWebServer() self.stopAndWaitForBackend() @pyqtSlot() def slot_backendRestart(self): self.slot_backendStop() self.slot_backendStart() # -------------------------------------------------------------------------------------------------------- @pyqtSlot() def slot_backendStarted(self): self.ui.act_backend_start.setEnabled(False) self.ui.act_backend_stop.setEnabled(True) self.ui.act_backend_restart.setEnabled(True) self.ui.w_buttons.setEnabled(False) self.ui.label_progress.setText(self.tr("Loading backend...")) @pyqtSlot(int, QProcess.ExitStatus) def slot_backendFinished(self, exitCode, exitStatus): self.fFirstBackendInit = False self.fStoppingBackend = False self.ui.act_backend_start.setEnabled(True) self.ui.act_backend_stop.setEnabled(False) self.ui.act_backend_restart.setEnabled(False) self.ui.w_buttons.setEnabled(True) self.ui.label_progress.setText("") self.ui.stackedwidget.setCurrentIndex(0) # stop webserver self.stopAndWaitForWebServer() @pyqtSlot(QProcess.ProcessError) def slot_backendError(self, error): firstBackendInit = self.fFirstBackendInit self.fFirstBackendInit = False # stop webserver self.stopAndWaitForWebServer() # crashed while stopping, ignore if error == QProcess.Crashed and self.fStoppingBackend: return errorStr = self.tr("Could not start host backend.\n" ) + self.getProcessErrorAsString(error) qWarning(errorStr) # don't show error if this is the first time starting the host or using live-iso if firstBackendInit: return # show the error message QMessageBox.critical(self, self.tr("Error"), errorStr) @pyqtSlot() def slot_backendRead(self): #if self.fProccessBackend.state() != QProcess.Running: #return for line in str( self.fProccessBackend.readAllStandardOutput().trimmed(), encoding="utf-8", errors="ignore").strip().split("\n"): line = line.replace("\x1b[0m", "").replace("\x1b[0;31m", "").replace("\x1b[0;33m", "").strip() if not line: continue if self.fSavedSettings[MOD_KEY_HOST_VERBOSE]: print("BACKEND:", line) if line == "mod-host ready!" or line == "mod-host is running.": QTimer.singleShot(0, self.slot_backendStartPhase2) #elif "Listening on socket " in line: #QTimer.singleShot(1000, self.slot_ingenStarted) ##elif "Activated Jack client " in line: ##QTimer.singleShot(1000, self.fWebServerThread.start) #elif "Failed to create UNIX socket" in line or "Could not activate Jack client" in line: ## need to wait for ingen to create sockets so it can delete them on termination #QTimer.singleShot(1000, self.slot_ingenStartError) @pyqtSlot() def slot_backendStartPhase2(self): if self.fProccessBackend.state() == QProcess.NotRunning: return if not self.fNeedsSessionReconnect: # we'll need it for next time self.fNeedsSessionReconnect = True else: # we need it now SESSION.reconnectApp() self.fWebServerThread.start() @pyqtSlot() def slot_backendStartError(self): self.stopAndWaitForBackend() self.slot_backendError(-2) # -------------------------------------------------------------------------------------------------------- # Web Server @pyqtSlot() def slot_webServerRunning(self): self.ui.webview.loadStarted.connect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.connect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.connect(self.slot_webviewLoadFinished) print("webserver running with URL:", config["addr"]) self.ui.webview.load(QUrl(config["addr"])) @pyqtSlot() def slot_webServerFinished(self): try: self.ui.webview.loadStarted.disconnect( self.slot_webviewLoadStarted) self.ui.webview.loadProgress.disconnect( self.slot_webviewLoadProgress) self.ui.webview.loadFinished.disconnect( self.slot_webviewLoadFinished) except: pass print("webserver finished") # testing red color for server finished self.ui.webview.blockSignals(True) self.ui.webview.setHtml("<html><body bgcolor='red'></body></html>") self.ui.webview.blockSignals(False) # -------------------------------------------------------------------------------------------------------- # Web View @pyqtSlot() def slot_webviewLoadStarted(self): self.ui.label_progress.setText(self.tr("Loading UI...")) print("load started") @pyqtSlot(int) def slot_webviewLoadProgress(self, progress): self.ui.label_progress.setText(self.tr("Loading UI... %i%%" % progress)) @pyqtSlot(bool) def slot_webviewLoadFinished(self, ok): self.ui.webview.loadStarted.disconnect(self.slot_webviewLoadStarted) self.ui.webview.loadProgress.disconnect(self.slot_webviewLoadProgress) self.ui.webview.loadFinished.disconnect(self.slot_webviewLoadFinished) if ok: # message self.ui.label_progress.setText(self.tr("Loading UI... finished!")) # enable file menu self.ui.act_file_refresh.setEnabled(True) self.ui.act_file_inspect.setEnabled(True) # for js evaulation self.fWebFrame = self.ui.webpage.currentFrame() # postpone app stuff QTimer.singleShot(100, self.slot_webviewPostFinished) else: # message self.ui.label_progress.setText(self.tr("Loading UI... failed!")) # disable file menu self.ui.act_file_refresh.setEnabled(False) self.ui.act_file_inspect.setEnabled(False) # disable pedalboard menu self.ui.act_pedalboard_new.setEnabled(False) self.ui.act_pedalboard_open.setEnabled(False) self.ui.act_pedalboard_save.setEnabled(False) self.ui.act_pedalboard_save_as.setEnabled(False) self.ui.act_pedalboard_share.setEnabled(False) self.ui.menu_Pedalboard.setEnabled(False) # stop js evaulation self.fWebFrame = None # stop backend&server self.stopAndWaitForWebServer() self.stopAndWaitForBackend() print("load finished") @pyqtSlot() def slot_webviewPostFinished(self): if self.fNextBundle: bundle = self.fNextBundle self.fNextBundle = "" self.fWebFrame.evaluateJavaScript( "desktop.loadPedalboard(\"%s\")" % bundle) QTimer.singleShot(0, self.slot_webviewPostFinished2) @pyqtSlot() def slot_webviewPostFinished2(self): self.ui.stackedwidget.setCurrentIndex(1) # -------------------------------------------------------------------------------------------------------- # Settings def saveSettings(self): settings = QSettings() settings.setValue("Geometry", self.saveGeometry()) def loadSettings(self, firstTime): qsettings = QSettings() websettings = self.ui.webview.settings() self.fSavedSettings = { # Main MOD_KEY_MAIN_PROJECT_FOLDER: qsettings.value(MOD_KEY_MAIN_PROJECT_FOLDER, MOD_DEFAULT_MAIN_PROJECT_FOLDER, type=str), MOD_KEY_MAIN_REFRESH_INTERVAL: qsettings.value(MOD_KEY_MAIN_REFRESH_INTERVAL, MOD_DEFAULT_MAIN_REFRESH_INTERVAL, type=int), # Host MOD_KEY_HOST_VERBOSE: qsettings.value(MOD_KEY_HOST_VERBOSE, MOD_DEFAULT_HOST_VERBOSE, type=bool), MOD_KEY_HOST_PATH: qsettings.value(MOD_KEY_HOST_PATH, MOD_DEFAULT_HOST_PATH, type=str), # WebView MOD_KEY_WEBVIEW_INSPECTOR: qsettings.value(MOD_KEY_WEBVIEW_INSPECTOR, MOD_DEFAULT_WEBVIEW_INSPECTOR, type=bool), MOD_KEY_WEBVIEW_VERBOSE: qsettings.value(MOD_KEY_WEBVIEW_VERBOSE, MOD_DEFAULT_WEBVIEW_VERBOSE, type=bool), MOD_KEY_WEBVIEW_SHOW_INSPECTOR: qsettings.value(MOD_KEY_WEBVIEW_SHOW_INSPECTOR, MOD_DEFAULT_WEBVIEW_SHOW_INSPECTOR, type=bool) } inspectorEnabled = self.fSavedSettings[MOD_KEY_WEBVIEW_INSPECTOR] websettings.setAttribute(QWebSettings.DeveloperExtrasEnabled, inspectorEnabled) if firstTime: if qsettings.contains("Geometry"): self.restoreGeometry(qsettings.value("Geometry", "")) else: self.setWindowState(self.windowState() | Qt.WindowMaximized) if inspectorEnabled and self.fSavedSettings[ MOD_KEY_WEBVIEW_SHOW_INSPECTOR]: QTimer.singleShot(1000, self.ui.webinspector.show) self.ui.act_file_inspect.setVisible(inspectorEnabled) if self.fIdleTimerId != 0: self.killTimer(self.fIdleTimerId) self.fIdleTimerId = self.startTimer( self.fSavedSettings[MOD_KEY_MAIN_REFRESH_INTERVAL]) # -------------------------------------------------------------------------------------------------------- # Misc @pyqtSlot() def slot_handleSIGUSR1(self): print("Got SIGUSR1 -> Saving project now") self.slot_pedalboardSave() @pyqtSlot() def slot_handleSIGTERM(self): print("Got SIGTERM -> Closing now") self.close() # -------------------------------------------------------------------------------------------------------- # Qt events def closeEvent(self, event): if self.fIdleTimerId != 0: self.killTimer(self.fIdleTimerId) self.fIdleTimerId = 0 self.saveSettings() self.slot_backendStop() QMainWindow.closeEvent(self, event) # Needed in case the web inspector is still alive #self.ui.webinspector.close() QApplication.instance().quit() def timerEvent(self, event): if event.timerId() == self.fIdleTimerId: pass QMainWindow.timerEvent(self, event) def resizeEvent(self, event): QMainWindow.resizeEvent(self, event) self.fixWebViewSize() # -------------------------------------------------------------------------------------------------------- # Internal stuff def getProcessErrorAsString(self, error): if error == -2: return self.tr("Ingen failed to create UNIX socket.") if error == QProcess.FailedToStart: return self.tr("Process failed to start.") if error == QProcess.Crashed: return self.tr("Process crashed.") if error == QProcess.Timedout: return self.tr("Process timed out.") if error == QProcess.WriteError: return self.tr("Process write error.") return self.tr("Unkown error.") def fixWebViewSize(self): if self.ui.stackedwidget.currentIndex() == 1: return size = self.ui.swp_intro.size() self.ui.swp_webview.resize(size) self.ui.webview.resize(size) self.ui.webpage.setViewportSize(size) def stopAndWaitForBackend(self): SESSION.host.close_jack() if self.fProccessBackend.state() == QProcess.NotRunning: return self.fStoppingBackend = True self.fProccessBackend.terminate() if not self.fProccessBackend.waitForFinished(2000): qWarning("Backend failed top stop cleanly, forced kill") self.fProccessBackend.kill() def stopAndWaitForWebServer(self): if not self.fWebServerThread.isRunning(): return if not self.fWebServerThread.stopWait(): qWarning( "WebServer Thread failed top stop cleanly, forced terminate") self.fWebServerThread.terminate() def setProperWindowTitle(self): title = "MOD Application" if self.fCurrentTitle: title += " - %s" % self.fCurrentTitle self.setWindowTitle(title)
class PylintWidget(QWidget): """ Pylint widget """ DATAPATH = get_conf_path('.pylint.results') VERSION = '1.0.2' def __init__(self, parent, max_entries=100): QWidget.__init__(self, parent) self.output = None self.error_output = None self.max_entries = max_entries self.data = [self.VERSION] if osp.isfile(self.DATAPATH): try: data = cPickle.load(file(self.DATAPATH)) if data[0] == self.VERSION: self.data = data except EOFError: pass self.filecombo = PythonModulesComboBox(self) if self.data: self.remove_obsolete_items() self.filecombo.addItems(self.get_filenames()) self.start_button = create_toolbutton(self, get_icon('run.png'), translate('Pylint', "Analyze"), tip=translate( 'Pylint', "Run analysis"), triggered=self.start) self.stop_button = create_toolbutton(self, get_icon('terminate.png'), translate('Pylint', "Stop"), tip=translate( 'Pylint', "Stop current analysis")) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.start_button.setEnabled) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data) browse_button = create_toolbutton(self, get_icon('fileopen.png'), tip=translate( 'Pylint', 'Select Python script'), triggered=self.select_file) self.ratelabel = QLabel() self.datelabel = QLabel() self.log_button = create_toolbutton(self, get_icon('log.png'), translate('Pylint', "Output"), tip=translate( 'Pylint', "Complete Pylint output"), triggered=self.show_log) self.treewidget = ResultsTree(self) hlayout1 = QHBoxLayout() hlayout1.addWidget(self.filecombo) hlayout1.addWidget(browse_button) hlayout1.addWidget(self.start_button) hlayout1.addWidget(self.stop_button) hlayout2 = QHBoxLayout() hlayout2.addWidget(self.ratelabel) hlayout2.addStretch() hlayout2.addWidget(self.datelabel) hlayout2.addStretch() hlayout2.addWidget(self.log_button) layout = QVBoxLayout() layout.addLayout(hlayout1) layout.addLayout(hlayout2) layout.addWidget(self.treewidget) self.setLayout(layout) self.process = None self.set_running_state(False) if not is_pylint_installed(): for widget in (self.treewidget, self.filecombo, self.start_button, self.stop_button): widget.setDisabled(True) text = translate('Pylint', 'Please install <b>pylint</b>:') url = 'http://www.logilab.fr' text += ' <a href=%s>%s</a>' % (url, url) self.ratelabel.setText(text) else: self.show_data() def analyze(self, filename): if not is_pylint_installed(): return filename = unicode(filename) # filename is a QString instance self.kill_if_running() index, _data = self.get_data(filename) if index is None: self.filecombo.addItem(filename) self.filecombo.setCurrentIndex(self.filecombo.count() - 1) else: self.filecombo.setCurrentIndex(index) self.filecombo.selected() if self.filecombo.is_valid(): self.start() def select_file(self): self.emit(SIGNAL('redirect_stdio(bool)'), False) filename = QFileDialog.getOpenFileName( self, translate('Pylint', "Select Python script"), os.getcwdu(), translate('Pylint', "Python scripts") + " (*.py ; *.pyw)") self.emit(SIGNAL('redirect_stdio(bool)'), False) if filename: self.analyze(filename) def remove_obsolete_items(self): """Removing obsolete items""" self.data = [self.VERSION] + \ [(filename, data) for filename, data in self.data[1:] if is_module_or_package(filename)] def get_filenames(self): return [filename for filename, _data in self.data[1:]] def get_data(self, filename): filename = osp.abspath(filename) for index, (fname, data) in enumerate(self.data[1:]): if fname == filename: return index, data else: return None, None def set_data(self, filename, data): filename = osp.abspath(filename) index, _data = self.get_data(filename) if index is not None: self.data.pop(index) self.data.append((filename, data)) self.save() def set_max_entries(self, max_entries): self.max_entries = max_entries self.save() def save(self): while len(self.data) > self.max_entries + 1: self.data.pop(1) cPickle.dump(self.data, file(self.DATAPATH, 'w')) def show_log(self): if self.output: TextEditor(self.output, title=translate('Pylint', "Pylint output"), readonly=True, size=(700, 500)).exec_() def start(self): filename = unicode(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(osp.dirname(filename)) self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.read_output) self.connect(self.process, SIGNAL("readyReadStandardError()"), lambda: self.read_output(error=True)) self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"), self.finished) self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill) self.output = '' self.error_output = '' p_args = [osp.basename(filename)] self.process.start(PYLINT_PATH, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical( self, translate('Pylint', "Error"), translate('Pylint', "Process failed to start")) def set_running_state(self, state=True): self.start_button.setEnabled(not state) self.stop_button.setEnabled(state) def read_output(self, error=False): if error: self.process.setReadChannel(QProcess.StandardError) else: self.process.setReadChannel(QProcess.StandardOutput) bytes = QByteArray() while self.process.bytesAvailable(): if error: bytes += self.process.readAllStandardError() else: bytes += self.process.readAllStandardOutput() text = unicode(QString.fromLocal8Bit(bytes.data())) if error: self.error_output += text else: self.output += text def finished(self): self.set_running_state(False) if not self.output: return # Convention, Refactor, Warning, Error results = {'C:': [], 'R:': [], 'W:': [], 'E:': []} txt_module = '************* Module ' module = '' # Should not be needed - just in case something goes wrong for line in self.output.splitlines(): if line.startswith(txt_module): # New module module = line[len(txt_module):] continue for prefix in results: if line.startswith(prefix): break else: continue i1 = line.find(':') if i1 == -1: continue i2 = line.find(':', i1 + 1) if i2 == -1: continue line_nb = line[i1 + 1:i2].strip() if not line_nb: continue line_nb = int(line_nb) message = line[i2 + 1:] item = (module, line_nb, message) results[line[:i1 + 1]].append(item) # Rate rate = None txt_rate = 'Your code has been rated at ' i_rate = self.output.find(txt_rate) if i_rate > 0: i_rate_end = self.output.find('/10', i_rate) if i_rate_end > 0: rate = self.output[i_rate + len(txt_rate):i_rate_end] # Previous run previous = '' if rate is not None: txt_prun = 'previous run: ' i_prun = self.output.find(txt_prun, i_rate_end) if i_prun > 0: i_prun_end = self.output.find('/10', i_prun) previous = self.output[i_prun + len(txt_prun):i_prun_end] filename = unicode(self.filecombo.currentText()) self.set_data(filename, (time.localtime(), rate, previous, results)) self.output = self.error_output + self.output self.show_data(justanalyzed=True) def kill_if_running(self): if self.process is not None: if self.process.state() == QProcess.Running: self.process.kill() self.process.waitForFinished() def show_data(self, justanalyzed=False): if not justanalyzed: self.output = None self.log_button.setEnabled(self.output is not None \ and len(self.output) > 0) self.kill_if_running() filename = unicode(self.filecombo.currentText()) if not filename: return _index, data = self.get_data(filename) if data is None: text = translate('Pylint', 'Source code has not been rated yet.') self.treewidget.clear() date_text = '' else: datetime, rate, previous_rate, results = data if rate is None: text = translate( 'Pylint', 'Analysis did not succeed ' '(see output for more details).') self.treewidget.clear() date_text = '' else: text_style = "<span style=\'color: #444444\'><b>%s </b></span>" rate_style = "<span style=\'color: %s\'><b>%s</b></span>" prevrate_style = "<span style=\'color: #666666\'>%s</span>" color = "#FF0000" if float(rate) > 5.: color = "#22AA22" elif float(rate) > 3.: color = "#EE5500" text = translate('Pylint', 'Global evaluation:') text = (text_style % text) + (rate_style % (color, ('%s/10' % rate))) if previous_rate: text_prun = translate('Pylint', 'previous run:') text_prun = ' (%s %s/10)' % (text_prun, previous_rate) text += prevrate_style % text_prun self.treewidget.set_results(filename, results) date_text = text_style % time.strftime("%d %b %Y %H:%M", datetime) self.ratelabel.setText(text) self.datelabel.setText(date_text)
def getParamVideo(cheminVideoEntre, parameter, hashInfo = None): """Renvoie un ou plusieurs paramètres de la vidéo sous forme de flottant. La variable «cheminVideoEntre» est le chemin de la vidéo de type unicode. La variable «parameter» est un tuple de paramètres à renvoyer. La dernière variable renvoyée est un tuple des lignes de log 23/07/2009 : hashInfo contiendra la hashmap des infos demandées """ #cheminVideoEntre = cheminVideoEntre.encode("UTF8") if hashInfo == None: hashInfo = {} # Condition pour détection windows if os.name == 'nt': commande = u'mplayer.exe -vo null -ao null -identify -frames 0 '+ u"\"" + unicode(cheminVideoEntre) + u"\"" # Condition pour détection Linux ou MacOSX elif os.name in ['posix', 'mac']: commande = u'mplayer ' + u"\""+ unicode(cheminVideoEntre) + u"\" -vo null -ao null -frames 0 -identify '$@' 2>/dev/null" #recupDonneesVideo = os.popen(commande.encode(coding)).readlines() processus = QProcess() processus.start(commande) if (not processus.waitForStarted()): raise (u"Erreur de récupération des informations") if ( not processus.waitForFinished()): raise (u"Erreur de récupération des informations") recupDonneesVideo = QString(processus.readAllStandardOutput()) lstValeurs = [] log = [] #for ligne in recupDonneesVideo: for ligne in recupDonneesVideo.split("\n"): try: # On veut que les caractères non ASCII s'affichent # correctement pour les noms de fichiers log.append(ligne) except UnicodeDecodeError: debug("Traitement d'exception unicode au niveau de " \ "getParamVideo() probablement dûe aux " \ "méta-données de la vidéo") log.append(ligne) for param in parameter: if param in ligne: ligne = ligne.replace(param, "") ligne = ligne.replace("=", "") ligne = ligne.replace("\n", "") ############################################ # Commenté le 01/09/10 --> voir si tout # fonctionne malgré tout (commenté pour # pouvoir lire les tags vidéos correctement) #ligne = ligne.replace(" ", "") ############################################ ############################################ # Le 01/09/10 Essai de réglage de la sortie # pour les accents dans les tags vidéo # VOIR SI SYNTAXE PLUS GENERIQUE ligne = ligne.replace("é", "e") ligne = ligne.replace("è", "e") ligne = ligne.replace("ç", "c") ligne = ligne.replace("à", "a") ligne = ligne.replace("ù", "u") ligne = ligne.replace("ä", "a") ligne = ligne.replace("ü", "u") ligne = ligne.replace("ö", "o") ############################################ try : lstValeurs.append(float(ligne)) hashInfo[param] = float(ligne) except : lstValeurs.append(str(ligne)) hashInfo[param] = str(ligne) lstValeurs.append(log) #lstValeurs.append(hashInfo) return lstValeurs
class PylintWidget(QWidget): """ Pylint widget """ DATAPATH = get_conf_path('.pylint.results') VERSION = '1.0.2' def __init__(self, parent, max_entries=100): QWidget.__init__(self, parent) self.output = None self.error_output = None self.max_entries = max_entries self.data = [self.VERSION] if osp.isfile(self.DATAPATH): try: data = cPickle.load(file(self.DATAPATH)) if data[0] == self.VERSION: self.data = data except EOFError: pass self.filecombo = PythonModulesComboBox(self) if self.data: self.remove_obsolete_items() self.filecombo.addItems(self.get_filenames()) self.start_button = create_toolbutton(self, get_icon('run.png'), translate('Pylint', "Analyze"), tip=translate('Pylint', "Run analysis"), triggered=self.start) self.stop_button = create_toolbutton(self, get_icon('terminate.png'), translate('Pylint', "Stop"), tip=translate('Pylint', "Stop current analysis")) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.start_button.setEnabled) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data) browse_button = create_toolbutton(self, get_icon('fileopen.png'), tip=translate('Pylint', 'Select Python script'), triggered=self.select_file) self.ratelabel = QLabel() self.datelabel = QLabel() self.log_button = create_toolbutton(self, get_icon('log.png'), translate('Pylint', "Output"), tip=translate('Pylint', "Complete Pylint output"), triggered=self.show_log) self.treewidget = ResultsTree(self) hlayout1 = QHBoxLayout() hlayout1.addWidget(self.filecombo) hlayout1.addWidget(browse_button) hlayout1.addWidget(self.start_button) hlayout1.addWidget(self.stop_button) hlayout2 = QHBoxLayout() hlayout2.addWidget(self.ratelabel) hlayout2.addStretch() hlayout2.addWidget(self.datelabel) hlayout2.addStretch() hlayout2.addWidget(self.log_button) layout = QVBoxLayout() layout.addLayout(hlayout1) layout.addLayout(hlayout2) layout.addWidget(self.treewidget) self.setLayout(layout) self.process = None self.set_running_state(False) if not is_pylint_installed(): for widget in (self.treewidget, self.filecombo, self.start_button, self.stop_button): widget.setDisabled(True) text = translate('Pylint', 'Please install <b>pylint</b>:') url = 'http://www.logilab.fr' text += ' <a href=%s>%s</a>' % (url, url) self.ratelabel.setText(text) else: self.show_data() def analyze(self, filename): if not is_pylint_installed(): return filename = unicode(filename) # filename is a QString instance self.kill_if_running() index, _data = self.get_data(filename) if index is None: self.filecombo.addItem(filename) self.filecombo.setCurrentIndex(self.filecombo.count()-1) else: self.filecombo.setCurrentIndex(index) self.filecombo.selected() if self.filecombo.is_valid(): self.start() def select_file(self): self.emit(SIGNAL('redirect_stdio(bool)'), False) filename = QFileDialog.getOpenFileName(self, translate('Pylint', "Select Python script"), os.getcwdu(), translate('Pylint', "Python scripts")+" (*.py ; *.pyw)") self.emit(SIGNAL('redirect_stdio(bool)'), False) if filename: self.analyze(filename) def remove_obsolete_items(self): """Removing obsolete items""" self.data = [self.VERSION] + \ [(filename, data) for filename, data in self.data[1:] if is_module_or_package(filename)] def get_filenames(self): return [filename for filename, _data in self.data[1:]] def get_data(self, filename): filename = osp.abspath(filename) for index, (fname, data) in enumerate(self.data[1:]): if fname == filename: return index, data else: return None, None def set_data(self, filename, data): filename = osp.abspath(filename) index, _data = self.get_data(filename) if index is not None: self.data.pop(index) self.data.append( (filename, data) ) self.save() def set_max_entries(self, max_entries): self.max_entries = max_entries self.save() def save(self): while len(self.data) > self.max_entries+1: self.data.pop(1) cPickle.dump(self.data, file(self.DATAPATH, 'w')) def show_log(self): if self.output: TextEditor(self.output, title=translate('Pylint', "Pylint output"), readonly=True, size=(700, 500)).exec_() def start(self): filename = unicode(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(osp.dirname(filename)) self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.read_output) self.connect(self.process, SIGNAL("readyReadStandardError()"), lambda: self.read_output(error=True)) self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"), self.finished) self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill) self.output = '' self.error_output = '' p_args = [osp.basename(filename)] self.process.start(PYLINT_PATH, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, translate('Pylint', "Error"), translate('Pylint', "Process failed to start")) def set_running_state(self, state=True): self.start_button.setEnabled(not state) self.stop_button.setEnabled(state) def read_output(self, error=False): if error: self.process.setReadChannel(QProcess.StandardError) else: self.process.setReadChannel(QProcess.StandardOutput) bytes = QByteArray() while self.process.bytesAvailable(): if error: bytes += self.process.readAllStandardError() else: bytes += self.process.readAllStandardOutput() text = unicode( QString.fromLocal8Bit(bytes.data()) ) if error: self.error_output += text else: self.output += text def finished(self): self.set_running_state(False) if not self.output: return # Convention, Refactor, Warning, Error results = {'C:': [], 'R:': [], 'W:': [], 'E:': []} txt_module = '************* Module ' module = '' # Should not be needed - just in case something goes wrong for line in self.output.splitlines(): if line.startswith(txt_module): # New module module = line[len(txt_module):] continue for prefix in results: if line.startswith(prefix): break else: continue i1 = line.find(':') if i1 == -1: continue i2 = line.find(':', i1+1) if i2 == -1: continue line_nb = line[i1+1:i2].strip() if not line_nb: continue line_nb = int(line_nb) message = line[i2+1:] item = (module, line_nb, message) results[line[:i1+1]].append(item) # Rate rate = None txt_rate = 'Your code has been rated at ' i_rate = self.output.find(txt_rate) if i_rate > 0: i_rate_end = self.output.find('/10', i_rate) if i_rate_end > 0: rate = self.output[i_rate+len(txt_rate):i_rate_end] # Previous run previous = '' if rate is not None: txt_prun = 'previous run: ' i_prun = self.output.find(txt_prun, i_rate_end) if i_prun > 0: i_prun_end = self.output.find('/10', i_prun) previous = self.output[i_prun+len(txt_prun):i_prun_end] filename = unicode(self.filecombo.currentText()) self.set_data(filename, (time.localtime(), rate, previous, results)) self.output = self.error_output + self.output self.show_data(justanalyzed=True) def kill_if_running(self): if self.process is not None: if self.process.state() == QProcess.Running: self.process.kill() self.process.waitForFinished() def show_data(self, justanalyzed=False): if not justanalyzed: self.output = None self.log_button.setEnabled(self.output is not None \ and len(self.output) > 0) self.kill_if_running() filename = unicode(self.filecombo.currentText()) if not filename: return _index, data = self.get_data(filename) if data is None: text = translate('Pylint', 'Source code has not been rated yet.') self.treewidget.clear() date_text = '' else: datetime, rate, previous_rate, results = data if rate is None: text = translate('Pylint', 'Analysis did not succeed ' '(see output for more details).') self.treewidget.clear() date_text = '' else: text_style = "<span style=\'color: #444444\'><b>%s </b></span>" rate_style = "<span style=\'color: %s\'><b>%s</b></span>" prevrate_style = "<span style=\'color: #666666\'>%s</span>" color = "#FF0000" if float(rate) > 5.: color = "#22AA22" elif float(rate) > 3.: color = "#EE5500" text = translate('Pylint', 'Global evaluation:') text = (text_style % text)+(rate_style % (color, ('%s/10' % rate))) if previous_rate: text_prun = translate('Pylint', 'previous run:') text_prun = ' (%s %s/10)' % (text_prun, previous_rate) text += prevrate_style % text_prun self.treewidget.set_results(filename, results) date_text = text_style % time.strftime("%d %b %Y %H:%M", datetime) self.ratelabel.setText(text) self.datelabel.setText(date_text)
class GdalToolsBaseDialog(QDialog, Ui_Dialog): def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand): QDialog.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.iface = iface self.process = QProcess(self) Utils.setProcessEnvironment(self.process) self.connect(self.process, SIGNAL("error(QProcess::ProcessError)"), self.processError) self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished) self.setupUi(self) self.arguments = [] self.editCmdBtn.setIcon(QIcon(":/icons/edit.png")) self.connect(self.editCmdBtn, SIGNAL("toggled(bool)"), self.editCommand) self.resetCmdBtn.setIcon(QIcon(":/icons/reset.png")) self.connect(self.resetCmdBtn, SIGNAL("clicked()"), self.resetCommand) self.editCommand(False) self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject) self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept) self.connect(self.buttonBox, SIGNAL("helpRequested()"), self.help) self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True) self.plugin = pluginBase self.connect(self.plugin, SIGNAL("valuesChanged(PyQt_PyObject)"), self.refreshArgs) self.pluginLayout.addWidget(self.plugin) self.plugin.setFocus() self.setWindowTitle(pluginName) self.setPluginCommand(pluginCommand) def setPluginCommand(self, cmd): # on Windows replace the .py with .bat extension if platform.system() == "Windows" and cmd[-3:] == ".py": self.command = cmd[:-3] + ".bat" else: self.command = cmd if cmd[-3:] == ".py": self.helpFileName = cmd[:-3] + ".html" else: self.helpFileName = cmd + ".html" def editCommand(self, enabled): if not self.commandIsEnabled(): return self.editCmdBtn.setChecked(enabled) self.resetCmdBtn.setEnabled(enabled) self.textEditCommand.setReadOnly(not enabled) self.controlsWidget.setEnabled(not enabled) self.emit(SIGNAL("refreshArgs()")) def resetCommand(self): if not self.commandIsEditable(): return self.emit(SIGNAL("refreshArgs()")) def commandIsEditable(self): return self.commandIsEnabled() and self.editCmdBtn.isChecked() def setCommandViewerEnabled(self, enable): if not enable: self.editCommand(False) self.commandWidget.setEnabled(enable) def commandIsEnabled(self): return self.commandWidget.isEnabled() def reject(self): if self.process.state() != QProcess.NotRunning: ret = QMessageBox.warning(self, self.tr("Warning"), self.tr("The command is still running. \nDo you want terminate it anyway?"), QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: return self.disconnect(self.process, SIGNAL("error(QProcess::ProcessError)"), self.processError) self.disconnect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished) self.emit(SIGNAL("closeClicked()")) def accept(self): self.emit(SIGNAL("okClicked()")) def help(self): self.emit(SIGNAL("helpClicked()")) def processError(self, error): self.emit(SIGNAL("processError(QProcess::ProcessError)"), error) def processFinished(self, exitCode, status): self.emit(SIGNAL("processFinished(int, QProcess::ExitStatus)"), exitCode, status) # show the online tool documentation in the default browser def onHelp(self): helpPath = Utils.getHelpPath() if helpPath == '': url = QUrl("http://www.gdal.org/" + self.helpFileName) else: url = QUrl.fromLocalFile(helpPath + '/' + self.helpFileName) QDesktopServices.openUrl(url) # called when a value in the plugin widget interface changed def refreshArgs(self, args): self.arguments = [unicode(a) for a in args] if not self.commandIsEnabled(): self.textEditCommand.setPlainText(self.command) else: self.textEditCommand.setPlainText(self.command + " " + Utils.escapeAndJoin(self.arguments)) # enables the OK button def enableRun(self, enable=True): self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable) # start the command execution def onRun(self): self.enableRun(False) self.setCursor(Qt.WaitCursor) if not self.commandIsEditable(): #print(self.command+' '+unicode(self.arguments)) self.process.start(self.command, self.arguments, QIODevice.ReadOnly) else: self.process.start(self.textEditCommand.toPlainText(), QIODevice.ReadOnly) # stop the command execution def stop(self): self.enableRun(True) self.setCursor(Qt.ArrowCursor) self.process.kill() # called on closing the dialog, stop the process if it's running def onClosing(self): self.stop() QDialog.reject(self) # called if an error occurs when the command has not already finished, shows the occurred error message def onError(self, error): if error == QProcess.FailedToStart: msg = QCoreApplication.translate("GdalTools", "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.") elif error == QProcess.Crashed: msg = QCoreApplication.translate("GdalTools", "The process crashed some time after starting successfully.") else: msg = QCoreApplication.translate("GdalTools", "An unknown error occurred.") QErrorMessage(self).showMessage(msg) QApplication.processEvents() # give the user chance to see the message self.stop() # called when the command finished its execution, shows an error message if there's one # and, if required, load the output file in canvas def onFinished(self, exitCode, status): if status == QProcess.CrashExit: self.stop() return if self.command.find("gdalinfo") != -1 and exitCode == 0: self.emit(SIGNAL("finished(bool)"), self.loadCheckBox.isChecked()) self.stop() return # show the error message if there's one, otherwise show the process output message msg = unicode(self.process.readAllStandardError()) if msg == '': outMessages = unicode(self.process.readAllStandardOutput()).splitlines() # make sure to not show the help for m in outMessages: m = string.strip(m) if m == '': continue # TODO fix this #if m.contains( QRegExp( "^(?:[Uu]sage:\\s)?" + QRegExp.escape(self.command) + "\\s" ) ): # if msg.isEmpty(): # msg = self.tr ( "Invalid parameters." ) # break #if m.contains( QRegExp( "0(?:\\.+[1-9]0{1,2})+" ) ): # continue if msg: msg += "\n" msg += m QErrorMessage(self).showMessage(msg.replace("\n", "<br>")) if exitCode == 0: self.emit(SIGNAL("finished(bool)"), self.loadCheckBox.isChecked()) self.stop()
class ScriptRunner(QObject): def __init__(self, caller, parent=None, env=None, addEnv=None): QObject.__init__(self, parent) self._proc = None self._caller = caller self._decode = None if env is None: env = os.environ.copy() self._env = env if addEnv: self._env.update(addEnv) def stop(self, kill=False): if self._proc is None: return if kill: self._proc.kill() else: self._proc.terminate() def run(self, scriptFile, args=None, env=None, wd=None): if self._proc: return self._proc = QProcess(self) if wd: self._proc.setWorkingDirectory(wd) if not env is None: self._env.update(env) envList = dict2qlst(self._env) if args is None: args = [] script = quote(scriptFile) if not os.path.exists(script): script = find_script(script) if not script or not os.path.exists(script): raise PublishException("Script '%s' cannot be found" % script) self._caller.handleScriptOutput("%s %s" % (scriptFile, ' '.join(args))) self._proc.setEnvironment(envList) self._proc.setProcessChannelMode(QProcess.MergedChannels) QObject.connect(self._proc, QtCore.SIGNAL("readyReadStandardOutput()"), self.readScriptOutput) QObject.connect(self._proc, QtCore.SIGNAL("finished(int, " \ "QProcess::ExitStatus)"), self.scriptFinished) self._proc.start(script, args, QIODevice.ReadOnly) def scriptFinished(self, exitCode, exitStatus): if self._caller: self.readScriptOutput() self._caller.scriptFinished(exitCode, exitStatus == QProcess.Crashed) self._proc = None def readScriptOutput(self): if self._proc is None: return qba = self._proc.readAllStandardOutput() if self._caller and qba.length(): if not self._decode: lang, deflocale = locale.getdefaultlocale() self._decode = codecs.getdecoder(deflocale) data, datalen = self._decode(qba.data()) self._caller.handleScriptOutput(data)
class PluginProcessBase(QObject): proc_list = [] def __init__(self, wdir): QObject.__init__(self) PluginProcess.proc_list.append(self) self.is_rebuild = False self.is_query_fl = False self.sig = QuerySignal() self.proc = QProcess() self.proc.finished.connect(self._finished_cb) self.proc.error.connect(self._error_cb) self.proc.setWorkingDirectory(wdir) self.wdir = wdir def _cleanup(self): PluginProcess.proc_list.remove(self) if self.err_str != '': s = '<b>' + self.p_cmd + '</b><p>' + '<p>'.join( self.err_str.splitlines()) QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok) if self.res != '': s = '<b>' + self.p_cmd + '</b><p>Summary<p>' + self.res QMessageBox.information(None, "Seascope", s, QMessageBox.Ok) def _error_cb(self, err): err_dict = { QProcess.FailedToStart: 'FailedToStart', QProcess.Crashed: 'Crashed', QProcess.Timedout: 'The last waitFor...() function timed out', QProcess.WriteError: 'An error occurred when attempting to write to the process', QProcess.ReadError: 'An error occurred when attempting to read from the process', QProcess.UnknownError: 'An unknown error occurred', } self.err_str = '<b>' + self.p_cmd + '</b><p>' + err_dict[err] self._cleanup() def _finished_cb(self, ret): res = str(self.proc.readAllStandardOutput()) self.err_str = str(self.proc.readAllStandardError()) #print 'output', res #print 'cmd:', self.p_cmd if self.is_rebuild: self.res = res self.sig.sig_rebuild.emit() elif self.is_query_fl: self.res = '' res = self.parse_query_fl(res) self.sig.sig_query_fl.emit(res) else: self.res = '' self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str) try: res = self.parse_result(res, self.sig) except Exception as e: print e res = [[ '', '', '', 'error while parsing output of: ' + self.p_cmd ]] if res != None: self.sig.emit_result(res) self._cleanup() def run_query_process(self, pargs, sym, rquery=None): self.sig.sym = sym self.sig.rquery = rquery self.p_cmd = ' '.join(pargs) if os.getenv('SEASCOPE_DEBUG'): print self.p_cmd self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None self.proc.closeWriteChannel() return [self.sig.sig_result, self.sig.sig_result_dbg] def run_rebuild_process(self, pargs): self.is_rebuild = True self.p_cmd = ' '.join(pargs) self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None #print 'cmd:', pargs self.sig.sig_rebuild.connect(CtagsCache.flush) return self.sig.sig_rebuild def run_query_fl(self, pargs): self.is_query_fl = True self.p_cmd = ' '.join(pargs) self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None return self.sig.sig_query_fl def parse_query_fl(self, text): fl = [] for f in re.split('\r?\n', text.strip()): if f == '': continue fl.append(os.path.join(self.wdir, f)) return fl
class Dlg(QDialog, Ui_Dialog): def __init__(self, parent=None): super(Dlg, self).__init__(parent) self.setupUi(self) self.dockWidget.hide() self.fileLineEdit.setDisabled(True) self.fileButton.setDisabled(True) self.closeButton.clicked.connect(self.close) self.buildButton.clicked.connect(self.build) self.fileButton.clicked.connect(self.getFile) self.fileRadioButton.toggled.connect(self.fileLineEdit.setEnabled) self.fileRadioButton.toggled.connect(self.fileButton.setEnabled) self.logButton.toggled.connect(self.dockWidget.setVisible) for button in (self.sourceButton, self.outputButton): button.clicked.connect(self.getDirectory) self.sourceDirectory = None self.outputDirectory = None self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) #restore settings settings = QSettings() size = settings.value('Dialog/Size', QVariant(QSize(600, 500))).toSize() self.resize(size) pos = settings.value('Dialog/Position', QVariant(QPoint(0, 0))).toPoint() self.move(pos) for widget, setting in ((self.sourceLineEdit, 'Data/SourceDirectory'), (self.outputLineEdit, 'Data/OutputDirectory')): widget.setText(settings.value(setting).toString()) def closeEvent(self, event): """Save settings and exit""" settings = QSettings() for value, setting in ((self.size(), 'Dialog/Size'), (self.pos(), 'Dialog/Position'), (self.sourceDirectory, 'Data/SourceDirectory'), (self.outputDirectory, 'Data/OutputDirectory')): settings.setValue(setting, QVariant(value)) def getDirectory(self): """Opens the platform dialog to select directory""" sender = self.sender() if sender is self.sourceButton: receiver = self.sourceLineEdit elif sender is self.outputButton: receiver = self.outputLineEdit fname = QFileDialog.getExistingDirectory(self, 'Select Directory') if fname: receiver.setText(fname) def getFile(self): """Opens the platform file open dialog to select a file""" if not self.sourceDirectory: source_dir = self.sourceLineEdit.text() else: source_dir = self.sourceDirectory fname = QFileDialog.getOpenFileName(self, 'Select File', source_dir) if fname: self.fileLineEdit.setText(fname) def build(self): """Main function calling sphinx-build to generate the project""" self.statusLabel.clear() self.buildButton.setDisabled(True) self.sourceDirectory = str(self.sourceLineEdit.text().trimmed()) self.outputDirectory = str(self.outputLineEdit.text().trimmed()) if not len(self.sourceDirectory): self.logBrowser.append('Source directory cannot be empty') if not len(self.outputDirectory): self.logBrowser.append('Output directory cannot be empty') if not(len(self.sourceDirectory) or len(self.outputDirectory)): self.buildButton.setDisabled(False) return self.logBrowser.clear() self.logBrowser.append(self.formatInfoMsg('Building. Please wait...')) fname = None if self.fileRadioButton.isChecked(): fname = str(self.fileLineEdit.text().trimmed()) args = ['-b', 'html', self.sourceDirectory, self.outputDirectory] if fname: args.append(fname) self.statusLabel.setText(self.formatInfoMsg('Running sphinx-build...')) QApplication.processEvents() self.process.start(SPHINX_BUILD, args) if (not self.process.waitForFinished(-1)): msg = self.formatErrorMsg('Build Failed!') self.logBrowser.append(msg) self.statusLabel.setText(msg) self.buildButton.setEnabled(True) return QApplication.processEvents() self.buildButton.setEnabled(True) self.statusLabel.setText(self.formatInfoMsg('Finished')) def readOutput(self): """Read and append sphinx-build output to the logBrowser""" msg = str(QString(self.process.readAllStandardOutput())) self.logBrowser.append(msg) def readErrors(self): """Read and append sphinx-build errors to the logBrowser""" msg = str(QString(self.process.readAllStandardError())) self.logBrowser.append(self.formatErrorMsg(msg)) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'blue') def formatMsg(self, msg, color): """Format message with the given color""" msg = '<font color="%s">%s</font>' % (color, msg) return msg
class ConsoleWidget(QPlainTextEdit): def __init__(self): super(ConsoleWidget, self).__init__('>>> ') self.setUndoRedoEnabled(False) self.apply_editor_style() self.setToolTip(self.tr("Show/Hide (F4)")) self.moveCursor(QTextCursor.EndOfLine) self._patIsWord = re.compile('\w+') self.prompt = '>>> ' self._console = console.Console() self._history = [] self.history_index = 0 self._current_command = '' self._braces = None self.imports = ['import __builtin__'] self.patFrom = re.compile('^(\\s)*from ((\\w)+(\\.)*(\\w)*)+ import') self.patImport = re.compile('^(\\s)*import (\\w)+') self.patObject = re.compile('[^a-zA-Z0-9_\\.]') #self.completer = completer_widget.CompleterWidget(self) self.okPrefix = QRegExp('[.)}:,\]]') self._pre_key_press = { Qt.Key_Enter: self._enter_pressed, Qt.Key_Return: self._enter_pressed, Qt.Key_Tab: self._tab_pressed, Qt.Key_Home: self._home_pressed, Qt.Key_PageUp: lambda x: True, Qt.Key_PageDown: lambda x: True, Qt.Key_Left: self._left_pressed, Qt.Key_Up: self._up_pressed, Qt.Key_Down: self._down_pressed, Qt.Key_Backspace: self._backspace, } #Create Context Menu self._create_context_menu() #Set Font self.set_font(settings.FONT) #Create Highlighter parts_scanner, code_scanner, formats = \ syntax_highlighter.load_syntax(python_syntax.syntax) self.highlighter = syntax_highlighter.SyntaxHighlighter( self.document(), parts_scanner, code_scanner, formats) self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlight_current_line) self.highlight_current_line() self._proc = QProcess(self) self.connect(self._proc, SIGNAL("readyReadStandardOutput()"), self._python_path_detected) self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"), self.process_error) self._add_system_path_for_frozen() ninjaide = IDE.get_service('ide') self.connect(ninjaide, SIGNAL("ns_preferences_editor_font(PyQt_PyObject)"), self.set_font) def _add_system_path_for_frozen(self): try: self._proc.start(settings.PYTHON_PATH, [resources.GET_SYSTEM_PATH]) except Exception as reason: logger.warning('Could not get system path, error: %r' % reason) def _python_path_detected(self): paths = self._proc.readAllStandardOutput().data().decode('utf8') add_system_path = ('import sys; ' 'sys.path = list(set(sys.path + %s))' % paths) self._write(add_system_path) self._proc.deleteLater() def process_error(self, error): message = '' if error == 0: message = 'Failed to start' else: message = 'Error during execution, QProcess error: %d' % error logger.warning('Could not get system path, error: %r' % message) def set_font(self, font): self.document().setDefaultFont(font) # Fix for older version of Qt which doens't has ForceIntegerMetrics if "ForceIntegerMetrics" in dir(QFont): self.document().defaultFont().setStyleStrategy( QFont.ForceIntegerMetrics) def _create_context_menu(self): self.popup_menu = self.createStandardContextMenu() self.popup_menu.clear() actionCut = self.popup_menu.addAction(self.tr("Cut")) actionCopy = self.popup_menu.addAction(self.tr("Copy")) actionPaste = self.popup_menu.addAction(self.tr("Paste")) actionClean = self.popup_menu.addAction(self.tr("Clean Console")) actionCopyHistory = self.popup_menu.addAction(self.tr("Copy History")) actionCopyConsoleContent = self.popup_menu.addAction( self.tr("Copy Console Content")) self.popup_menu.addAction(actionCut) self.popup_menu.addAction(actionCopy) self.popup_menu.addAction(actionPaste) self.popup_menu.addSeparator() self.popup_menu.addAction(actionClean) self.popup_menu.addSeparator() self.popup_menu.addAction(actionCopyHistory) self.popup_menu.addAction(actionCopyConsoleContent) self.connect(actionCut, SIGNAL("triggered()"), self._cut) self.connect(actionCopy, SIGNAL("triggered()"), self.copy) self.connect(actionPaste, SIGNAL("triggered()"), self._paste) self.connect(actionClean, SIGNAL("triggered()"), self._clean_console) self.connect(actionCopyHistory, SIGNAL("triggered()"), self._copy_history) self.connect(actionCopyConsoleContent, SIGNAL("triggered()"), self._copy_console_content) def _cut(self): event = QKeyEvent(QEvent.KeyPress, Qt.Key_X, Qt.ControlModifier, "x") self.keyPressEvent(event) def _paste(self): if self.textCursor().hasSelection(): self.moveCursor(QTextCursor.End) self.paste() def _clean_console(self): self.clear() self._add_prompt() def _copy_history(self): historyContent = '\n'.join(self._history) clipboard = QApplication.instance().clipboard() clipboard.setText(historyContent) def _copy_console_content(self): content = self.toPlainText() clipboard = QApplication.instance().clipboard() clipboard.setText(content) def setCursorPosition(self, position, mode=QTextCursor.MoveAnchor): self.moveCursor(QTextCursor.StartOfLine, mode) for i in range(len(self.prompt) + position): self.moveCursor(QTextCursor.Right, mode) def _check_event_on_selection(self, event): if event.text(): cursor = self.textCursor() begin_last_block = (self.document().lastBlock().position() + len(self.prompt)) if cursor.hasSelection() and \ ((cursor.selectionEnd() < begin_last_block) or (cursor.selectionStart() < begin_last_block)): self.moveCursor(QTextCursor.End) def _enter_pressed(self, event): self._write_command() return True def _tab_pressed(self, event): self.textCursor().insertText(' ' * settings.INDENT) return True def _home_pressed(self, event): if event.modifiers() == Qt.ShiftModifier: self.setCursorPosition(0, QTextCursor.KeepAnchor) else: self.setCursorPosition(0) return True def _left_pressed(self, event): return self._get_cursor_position() == 0 def _up_pressed(self, event): if self.history_index == len(self._history): command = self.document().lastBlock().text()[len(self.prompt):] self._current_command = command self._set_command(self._get_prev_history_entry()) return True def _down_pressed(self, event): if len(self._history) == self.history_index: command = self._current_command else: command = self._get_next_history_entry() self._set_command(command) return True def _backspace(self, event): cursor = self.textCursor() selected_text = cursor.selectedText() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) text = cursor.selectedText()[len(self.prompt):] if (len(text) % settings.INDENT == 0) and text.isspace(): cursor.movePosition(QTextCursor.StartOfLine) cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, settings.INDENT) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, settings.INDENT) cursor.removeSelectedText() return True elif (selected_text == self.document().lastBlock().text() [len(self.prompt):]): self.textCursor().removeSelectedText() return True position = self.textCursor().positionInBlock() - len(self.prompt) text = self.document().lastBlock().text()[len(self.prompt):] if position < len(text): if (text[position - 1] in BRACES and text[position] in BRACES.values()): self.textCursor().deleteChar() return self._get_cursor_position() == 0 def keyPressEvent(self, event): #if self.completer.popup().isVisible(): #if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab): #event.ignore() #self.completer.popup().hide() #return #elif event.key in (Qt.Key_Space, Qt.Key_Escape, Qt.Key_Backtab): #self.completer.popup().hide() self._check_event_on_selection(event) if self._pre_key_press.get(event.key(), lambda x: False)(event): return if event.text() in (set(BRACES.values()) - set(["'", '"'])): cursor = self.textCursor() cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) brace = cursor.selection().toPlainText() cursor = self.textCursor() cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) braceClose = cursor.selection().toPlainText() if BRACES.get(brace, False) == event.text() and \ braceClose == event.text(): self.moveCursor(QTextCursor.Right) return QPlainTextEdit.keyPressEvent(self, event) if event.text() in BRACES: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) self.textCursor().insertText(BRACES[event.text()]) self.moveCursor(QTextCursor.Left) #completionPrefix = self._text_under_cursor() #if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and #event.modifiers() == Qt.ControlModifier): #self.completer.setCompletionPrefix(completionPrefix) #self._resolve_completion_argument() #if self.completer.popup().isVisible() and \ #completionPrefix != self.completer.completionPrefix(): #self.completer.setCompletionPrefix(completionPrefix) #self.completer.popup().setCurrentIndex( #self.completer.completionModel().index(0, 0)) #self.completer.setCurrentRow(0) #self._resolve_completion_argument() #def _resolve_completion_argument(self): #try: #cursor = self.textCursor() #cursor.movePosition(QTextCursor.StartOfLine, #QTextCursor.KeepAnchor) #var = cursor.selectedText() #chars = self.patObject.findall(var) #var = var[var.rfind(chars[-1]) + 1:] #cr = self.cursorRect() #proposals = completer.get_all_completions(var, #imports=self.imports) #if not proposals: #if self.completer.popup().isVisible(): #prefix = var[var.rfind('.') + 1:] #var = var[:var.rfind('.') + 1] #var = self._console.get_type(var) #var += prefix #else: #var = self._console.get_type(var) #proposals = completer.get_all_completions(var, #imports=self.imports) #self.completer.complete(cr, proposals) #except: #self.completer.popup().hide() def highlight_current_line(self): self.extraSelections = [] selection = QTextEdit.ExtraSelection() lineColor = QColor( resources.CUSTOM_SCHEME.get('CurrentLine', resources.COLOR_SCHEME['CurrentLine'])) lineColor.setAlpha(20) selection.format.setBackground(lineColor) selection.format.setProperty(QTextFormat.FullWidthSelection, True) selection.cursor = self.textCursor() selection.cursor.clearSelection() self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) if self._braces is not None: self._braces = None cursor = self.textCursor() if cursor.position() == 0: self.setExtraSelections(self.extraSelections) return cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) text = cursor.selectedText() pos1 = cursor.position() if text in (')', ']', '}'): pos2 = self._match_braces(pos1, text, forward=False) elif text in ('(', '[', '{'): pos2 = self._match_braces(pos1, text, forward=True) else: self.setExtraSelections(self.extraSelections) return #if pos2 is not None: #self._braces = (pos1, pos2) #selection = QTextEdit.ExtraSelection() #selection.format.setForeground(QColor( #resources.CUSTOM_SCHEME.get('brace-foreground', #resources.COLOR_SCHEME.get('brace-foreground')))) #selection.format.setBackground(QColor( #resources.CUSTOM_SCHEME.get('brace-background', #resources.COLOR_SCHEME.get('brace-background')))) #selection.cursor = cursor #self.extraSelections.append(selection) #selection = QTextEdit.ExtraSelection() #selection.format.setForeground(QColor( #resources.CUSTOM_SCHEME.get('brace-foreground', #resources.COLOR_SCHEME.get('brace-foreground')))) #selection.format.setBackground(QColor( #resources.CUSTOM_SCHEME.get('brace-background', #resources.COLOR_SCHEME.get('brace-background')))) #selection.cursor = self.textCursor() #selection.cursor.setPosition(pos2) #selection.cursor.movePosition(QTextCursor.NextCharacter, #QTextCursor.KeepAnchor) #self.extraSelections.append(selection) #else: #self._braces = (pos1,) #selection = QTextEdit.ExtraSelection() #selection.format.setBackground(QColor( #resources.CUSTOM_SCHEME.get('brace-background', #resources.COLOR_SCHEME.get('brace-background')))) #selection.format.setForeground(QColor( #resources.CUSTOM_SCHEME.get('brace-foreground', #resources.COLOR_SCHEME.get('brace-foreground')))) #selection.cursor = cursor #self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) def _text_under_cursor(self): tc = self.textCursor() tc.select(QTextCursor.WordUnderCursor) return tc.selectedText() def get_selection(self, posStart, posEnd): cursor = self.textCursor() cursor.setPosition(posStart) if posEnd == QTextCursor.End: cursor2 = self.textCursor() cursor2.movePosition(posEnd) cursor.setPosition(cursor2.position(), QTextCursor.KeepAnchor) else: cursor.setPosition(posEnd, QTextCursor.KeepAnchor) return cursor.selectedText() def _match_braces(self, position, brace, forward): """based on: http://gitorious.org/khteditor""" if forward: braceMatch = {'(': ')', '[': ']', '{': '}'} text = self.get_selection(position, QTextCursor.End) braceOpen, braceClose = 1, 1 else: braceMatch = {')': '(', ']': '[', '}': '{'} text = self.get_selection(QTextCursor.Start, position) braceOpen, braceClose = len(text) - 1, len(text) - 1 while True: if forward: posClose = text.find(braceMatch[brace], braceClose) else: posClose = text.rfind(braceMatch[brace], 0, braceClose + 1) if posClose > -1: if forward: braceClose = posClose + 1 posOpen = text.find(brace, braceOpen, posClose) else: braceClose = posClose - 1 posOpen = text.rfind(brace, posClose, braceOpen + 1) if posOpen > -1: if forward: braceOpen = posOpen + 1 else: braceOpen = posOpen - 1 else: if forward: return position + posClose else: return position - (len(text) - posClose) else: return def _add_prompt(self, incomplete=False): if incomplete: prompt = '.' * 3 + ' ' else: prompt = self.prompt self.appendPlainText(prompt) self.moveCursor(QTextCursor.End) def _get_cursor_position(self): return self.textCursor().columnNumber() - len(self.prompt) def _write_command(self): command = self.document().lastBlock().text() #remove the prompt from the QString command = command[len(self.prompt):] self._add_history(command) conditional = command.strip() != 'quit()' incomplete = self._write(command) if conditional else None if self.patFrom.match(command) or self.patImport.match(command): self.imports += [command] if not incomplete: output = self._read() if output is not None: if isinstance(output, str): output = output.encode('utf8') self.appendPlainText(output.decode('utf8')) self._add_prompt(incomplete) def _set_command(self, command): self.moveCursor(QTextCursor.End) cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(self.prompt)) cursor.insertText(command) def contextMenuEvent(self, event): self.popup_menu.exec_(event.globalPos()) def _write(self, line): return self._console.push(line) def _read(self): return self._console.output def _add_history(self, command): if command and (not self._history or self._history[-1] != command): self._history.append(command) self.history_index = len(self._history) def _get_prev_history_entry(self): if self._history: self.history_index = max(0, self.history_index - 1) return self._history[self.history_index] return '' def _get_next_history_entry(self): if self._history: hist_len = len(self._history) - 1 self.history_index = min(hist_len, self.history_index + 1) index = self.history_index if self.history_index == hist_len: self.history_index += 1 return self._history[index] return '' def restyle(self): self.apply_editor_style() parts_scanner, code_scanner, formats = \ syntax_highlighter.load_syntax(python_syntax.syntax) self.highlighter = syntax_highlighter.SyntaxHighlighter( self.document(), parts_scanner, code_scanner, formats) def apply_editor_style(self): css = 'QPlainTextEdit {color: %s; background-color: %s;' \ 'selection-color: %s; selection-background-color: %s;}' \ % (resources.CUSTOM_SCHEME.get('editor-text', resources.COLOR_SCHEME['Default']), resources.CUSTOM_SCHEME.get('EditorBackground', resources.COLOR_SCHEME['EditorBackground']), resources.CUSTOM_SCHEME.get('EditorSelectionColor', resources.COLOR_SCHEME['EditorSelectionColor']), resources.CUSTOM_SCHEME.get('EditorSelectionBackground', resources.COLOR_SCHEME['EditorSelectionBackground'])) self.setStyleSheet(css) def load_project_into_console(self, projectFolder): """Load the projectFolder received into the sys.path.""" self._console.push("import sys; sys.path += ['%s']" % projectFolder) def unload_project_from_console(self, projectFolder): """Unload the project from the system path.""" self._console.push("import sys; " "sys.path = [path for path in sys.path " "if path != '%s']" % projectFolder) def zoom_in(self): font = self.document().defaultFont() size = font.pointSize() if size < settings.FONT_MAX_SIZE: size += 2 font.setPointSize(size) self.setFont(font) def zoom_out(self): font = self.document().defaultFont() size = font.pointSize() if size > settings.FONT_MIN_SIZE: size -= 2 font.setPointSize(size) self.setFont(font) def wheelEvent(self, event): if event.modifiers() == Qt.ControlModifier: if event.delta() > 0: self.zoom_in() elif event.delta() < 0: self.zoom_out() event.ignore() super(ConsoleWidget, self).wheelEvent(event)
class Main(plugin.Plugin): ' main class for plugin ' def initialize(self, *args, **kwargs): ' class init ' super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) menu = QMenu('Clones') menu.addAction('Analyze for Code Clones here', lambda: self.make_clon()) self.locator.get_service('explorer').add_project_menu(menu, lang='all') self.group1 = QGroupBox() self.group1.setTitle(' Target ') self.outdir, self.igndir = QLineEdit(path.expanduser("~")), QLineEdit() self.outdir.setCompleter(self.completer) self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn1.clicked.connect(lambda: self.outdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Target Directory...', path.expanduser("~"))))) self.btn1a = QPushButton(QIcon.fromTheme("face-smile"), 'Get from Ninja active project') self.btn1a.clicked.connect(lambda: self.outdir.setText( self.locator.get_service('explorer').get_current_project_item().path)) self.ignckb, self.ignmor = QComboBox(), QTextEdit() self.ignckb.addItems(['Single Directory', 'Multiple Directories CSV']) self.ignckb.currentIndexChanged.connect(self.on_ignore_changed) self.ignmor.hide() self.igndir.setPlaceholderText('Exclude directory') self.igndir.setCompleter(self.completer) self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn2.clicked.connect(lambda: self.igndir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Ignore Directory...', path.expanduser("~"))))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('<b>Target directory path: '), self.outdir, self.btn1, self.btn1a, QLabel('<b>Ignore directory path: '), self.ignckb, self.ignmor, self.igndir, self.btn2, ): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' Output ') self.outfle = QLineEdit(path.join(path.expanduser("~"), 'output.html')) self.outfle.setPlaceholderText('Exclude directory') self.outfle.setCompleter(self.completer) self.btn3 = QPushButton(QIcon.fromTheme("document-save"), ' Save ') self.btn3.clicked.connect(lambda: self.outfle.setText( QFileDialog.getSaveFileName(self.dock, 'Save', path.expanduser("~"), 'XML(*.xml)' if self.xmlo.isChecked() is True else 'HTML(*.html)'))) vboxg2 = QVBoxLayout(self.group2) for each_widget in (QLabel('<b>Output report file path:'), self.outfle, self.btn3): vboxg2.addWidget(each_widget) self.group3 = QGroupBox() self.group3.setTitle(' Options ') self.group3.setCheckable(True) self.group3.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group3.graphicsEffect().setEnabled(False) self.group3.toggled.connect(self.toggle_options_group) self.qckb1, self.qckb2 = QCheckBox('Recursive'), QCheckBox('Time-less') self.qckb3, self.qckb4 = QCheckBox('Force Diff'), QCheckBox('Fast Mode') self.qckb5, self.tm = QCheckBox('Save a LOG file to target'), QLabel('') self.xmlo = QCheckBox('XML Output instead of HTML') self.opeo = QCheckBox('Open Clones Report when done') self.chrt = QCheckBox('LOW CPU priority for Backend Process') self.mdist, self.hdep, self.output = QSpinBox(), QSpinBox(), QTextEdit() self.ign_func = QLineEdit('test, forward, backward, Migration') self.mdist.setValue(5) self.hdep.setValue(1) self.mdist.setToolTip('''<b>Maximum amount of difference between pair of sequences in clone pair (5 default).Larger value more false positive''') self.hdep.setToolTip('''<b>Computation can be speeded up by increasing this value, but some clones can be missed (1 default)''') [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] vboxg3 = QVBoxLayout(self.group3) for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4, self.qckb5, self.chrt, self.xmlo, self.opeo, QLabel('<b>Max Distance Threshold:'), self.mdist, QLabel('<b>Max Hashing Depth:'), self.hdep, QLabel('<b>Ignore code block prefix:'), self.ign_func): vboxg3.addWidget(each_widget) self.group4, self.auto = QGroupBox(), QComboBox() self.group4.setTitle(' Automation ') self.group4.setCheckable(True) self.group4.setToolTip('<font color="red"><b>WARNING:Advanced Setting!') self.group4.toggled.connect(lambda: self.group4.hide()) self.auto.addItems(['Never run automatically', 'Run when File Saved', 'Run when File Executed', 'Run when Tab Changed', 'Run when File Opened', 'Run before File Saved']) self.auto.currentIndexChanged.connect(self.on_auto_changed) QVBoxLayout(self.group4).addWidget(self.auto) self.button = QPushButton(' Analyze for Clones ') self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) self.butkil = QPushButton(' Force Kill Clones ') self.butkil.clicked.connect(lambda: self.process.kill()) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((QLabel('<i>D.R.Y. principle analyzer'), self.group1, self.group2, self.group3, self.group4, QLabel('<b>Backend Logs'), self.output, self.tm, self.button, self.butkil)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Clones") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def make_clon(self): ' make clones analyze from contextual sub menu ' self.outdir.setText( self.locator.get_service('explorer').get_current_project_item().path) self.run() def run(self): ' run the actions ' self.output.clear() self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now()))) self.tm.setText('<center><b>Last Clone: </b>' + datetime.now().isoformat().split('.')[0]) self.button.setDisabled(True) if not len(self.outdir.text()) and not len(self.outfle.text()): self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty')) self.button.setEnabled(True) return # run the subprocesses cmd = ' '.join(( 'chrt -i 0' if self.chrt.isChecked() is True else '', 'clonedigger', '' if self.qckb1.isChecked() is True else '--no-recursion', '--dont-print-time' if self.qckb2.isChecked() is True else '', '--force' if self.qckb3.isChecked() is True else '', '--fast' if self.qckb4.isChecked() is True else '', '--cpd-output' if self.xmlo.isChecked() is True else '', '' if self.xmlo.isChecked() is True else '--report-unifiers', '--distance-threshold={}'.format(self.mdist.value()), '--hashing-depth={}'.format(self.hdep.value()), '--ignore-dir="{}"'.format(self.igndir.text() if self.ignckb.currentIndex() is 0 else self.ignmor.toPlainText()), '--func-prefixes="{}"'.format(self.ign_func.text()), '--output="{}"'.format(self.outfle.text()), '--language=python', path.abspath(self.outdir.text()), )) self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append(self.formatErrorMsg('ERROR:FAIL:{}'.format(cmd))) self.button.setEnabled(True) return self.readOutput() self.readErrors() self.button.setEnabled(True) def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now()))) # write a .log file on target if self.qckb5.isChecked() is True: log_file = 'ninja_clones.log' with open(path.join(str(self.outdir.text()), log_file), 'w') as log: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs: {}'''.format(path.join(str(self.outdir.text()), log_file)))) log.write(self.output.toPlainText()) log.close() # open target output if self.opeo.isChecked() is True and self.xmlo.isChecked() is False: try: startfile(self.outfle.text()) except: Popen(["xdg-open", self.outfle.text()]) self.output.selectAll() self.output.setFocus() def toggle_options_group(self): ' toggle on off the options group ' if self.group3.isChecked() is True: [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] self.mdist.setValue(5) self.hdep.setValue(1) self.group3.graphicsEffect().setEnabled(False) else: [a.setChecked(False) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] self.group3.graphicsEffect().setEnabled(True) def on_ignore_changed(self): 'hide or show one widget or another depending what kind of input need' if self.ignckb.currentIndex() is 0: self.igndir.show() self.btn2.show() self.ignmor.hide() else: self.igndir.hide() self.btn2.hide() self.ignmor.show() def on_auto_changed(self): ' automation connects ' if self.auto.currentIndex() is 1: self.locator.get_service('editor').fileSaved.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Saved !') elif self.auto.currentIndex() is 2: self.locator.get_service('editor').fileExecuted.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Executed !') elif self.auto.currentIndex() is 3: self.locator.get_service('editor').currentTabChanged.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when current Tab is Changed') elif self.auto.currentIndex() is 4: self.locator.get_service('editor').fileOpened.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Opened !') elif self.auto.currentIndex() is 5: self.locator.get_service('editor').beforeFileSaved.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically before any File is Saved !') self.group4.setDisabled(True) def finish(self): ' clear when finish ' self.process.kill()
class ConsoleWidget(QPlainTextEdit): def __init__(self): QPlainTextEdit.__init__(self, '>>> ') self.setUndoRedoEnabled(False) self.apply_editor_style() self.setToolTip(self.tr("Show/Hide (F4)")) self.moveCursor(QTextCursor.EndOfLine) self._patIsWord = re.compile('\w+') self.prompt = '>>> ' self._console = console.Console() self._history = [] self._braces = None self.imports = ['import __builtin__'] self.patFrom = re.compile('^(\\s)*from ((\\w)+(\\.)*(\\w)*)+ import') self.patImport = re.compile('^(\\s)*import (\\w)+') self.patObject = re.compile('[^a-zA-Z0-9_\\.]') self.completer = completer_widget.CompleterWidget(self) self.okPrefix = QRegExp('[.)}:,\]]') #Create Context Menu self._create_context_menu() self._highlighter = highlighter.Highlighter(self.document(), 'python', resources.CUSTOM_SCHEME) self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlight_current_line) self.highlight_current_line() self._proc = QProcess(self) self.connect(self._proc, SIGNAL("readyReadStandardOutput()"), self._python_path_detected) self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"), self.process_error) self._add_system_path_for_frozen() def _add_system_path_for_frozen(self): try: self._proc.start(settings.PYTHON_PATH, [resources.GET_SYSTEM_PATH]) except Exception as reason: logger.warning('Could not get system path, error: %r' % reason) def _python_path_detected(self): paths = self._proc.readAllStandardOutput().data().decode('utf8') add_system_path = ('import sys; ' 'sys.path = list(set(sys.path + %s))' % paths) self._write(add_system_path) def process_error(self, error): message = '' if error == 0: message = 'Failed to start' else: message = 'Error during execution, QProcess error: %d' % error logger.warning('Could not get system path, error: %r' % message) def _create_context_menu(self): self.popup_menu = self.createStandardContextMenu() self.popup_menu.clear() actionCut = self.popup_menu.addAction(self.tr("Cut")) actionCopy = self.popup_menu.addAction(self.tr("Copy")) actionPaste = self.popup_menu.addAction(self.tr("Paste")) actionClean = self.popup_menu.addAction(self.tr("Clean Console")) actionCopyHistory = self.popup_menu.addAction(self.tr("Copy History")) actionCopyConsoleContent = self.popup_menu.addAction( self.tr("Copy Console Content")) self.popup_menu.addAction(actionCut) self.popup_menu.addAction(actionCopy) self.popup_menu.addAction(actionPaste) self.popup_menu.addSeparator() self.popup_menu.addAction(actionClean) self.popup_menu.addSeparator() self.popup_menu.addAction(actionCopyHistory) self.popup_menu.addAction(actionCopyConsoleContent) self.connect(actionCut, SIGNAL("triggered()"), self.cut) self.connect(actionCopy, SIGNAL("triggered()"), self.copy) self.connect(actionPaste, SIGNAL("triggered()"), self.paste) self.connect(actionClean, SIGNAL("triggered()"), self._clean_console) self.connect(actionCopyHistory, SIGNAL("triggered()"), self._copy_history) self.connect(actionCopyConsoleContent, SIGNAL("triggered()"), self._copy_console_content) def _clean_console(self): self.setPlainText(self.prompt) def _copy_history(self): historyContent = '\n'.join(self._history) clipboard = QApplication.instance().clipboard() clipboard.setText(historyContent) def _copy_console_content(self): content = self.toPlainText() clipboard = QApplication.instance().clipboard() clipboard.setText(content) def setCursorPosition(self, position, mode=QTextCursor.MoveAnchor): self.moveCursor(QTextCursor.StartOfLine, mode) for i in range(len(self.prompt) + position): self.moveCursor(QTextCursor.Right, mode) def keyPressEvent(self, event): if self.completer.popup().isVisible(): if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab): event.ignore() self.completer.popup().hide() return elif event.key in (Qt.Key_Space, Qt.Key_Escape, Qt.Key_Backtab): self.completer.popup().hide() if event.key() in (Qt.Key_Enter, Qt.Key_Return): self._write_command() return if self._get_cursor_position() < 0: self.setCursorPosition(0) if event.key() == Qt.Key_Tab: self.textCursor().insertText(' ' * settings.INDENT) return if event.key() == Qt.Key_Home: if event.modifiers() == Qt.ShiftModifier: self.setCursorPosition(0, QTextCursor.KeepAnchor) else: self.setCursorPosition(0) return if event.key() == Qt.Key_PageUp: return elif event.key() == Qt.Key_Left and self._get_cursor_position() == 0: return elif event.key() == Qt.Key_Up: self._set_command(self._get_prev_history_entry()) return elif event.key() == Qt.Key_Down: self._set_command(self._get_next_history_entry()) return if event.key() == Qt.Key_Tab: if self.textCursor().hasSelection(): self.indent_more() return else: self.textCursor().insertText(' ' * settings.INDENT) return elif event.key() == Qt.Key_Backspace: if self.textCursor().hasSelection(): QPlainTextEdit.keyPressEvent(self, event) return elif self._get_cursor_position() == 0: return cursor = self.textCursor() cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, settings.INDENT) text = cursor.selection().toPlainText() if text == ' ' * settings.INDENT: cursor.removeSelectedText() return True elif event.key() == Qt.Key_Home: if event.modifiers() == Qt.ShiftModifier: move = QTextCursor.KeepAnchor else: move = QTextCursor.MoveAnchor if self.textCursor().atBlockStart(): self.moveCursor(QTextCursor.WordRight, move) return elif event.key() in (Qt.Key_Enter, Qt.Key_Return) and \ event.modifiers() == Qt.ShiftModifier: return elif event.text() in \ (set(BRACES.values()) - set(["'", '"'])): cursor = self.textCursor() cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) brace = cursor.selection().toPlainText() cursor = self.textCursor() cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) braceClose = cursor.selection().toPlainText() if BRACES.get(brace, False) == event.text() and \ braceClose == event.text(): self.moveCursor(QTextCursor.Right) return selection = self.textCursor().selectedText() QPlainTextEdit.keyPressEvent(self, event) if event.text() in BRACES: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) self.textCursor().insertText( BRACES[event.text()]) self.moveCursor(QTextCursor.Left) self.textCursor().insertText(selection) completionPrefix = self._text_under_cursor() if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier): self.completer.setCompletionPrefix(completionPrefix) self._resolve_completion_argument() elif event.key() == Qt.Key_Space and \ self.completer.popup().isVisible(): self.completer.popup().hide() if self.completer.popup().isVisible() and \ completionPrefix != self.completer.completionPrefix(): self.completer.setCompletionPrefix(completionPrefix) self.completer.popup().setCurrentIndex( self.completer.completionModel().index(0, 0)) self.completer.setCurrentRow(0) self._resolve_completion_argument() def _resolve_completion_argument(self): try: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) var = cursor.selectedText() chars = self.patObject.findall(var) var = var[var.rfind(chars[-1]) + 1:] cr = self.cursorRect() proposals = completer.get_all_completions(var, imports=self.imports) if not proposals: if self.completer.popup().isVisible(): prefix = var[var.rfind('.') + 1:] var = var[:var.rfind('.') + 1] var = self._console.get_type(var) var += prefix else: var = self._console.get_type(var) proposals = completer.get_all_completions(var, imports=self.imports) self.completer.complete(cr, proposals) except: self.completer.popup().hide() def highlight_current_line(self): self.emit(SIGNAL("cursorPositionChange(int, int)"), self.textCursor().blockNumber() + 1, self.textCursor().columnNumber()) self.extraSelections = [] if not self.isReadOnly(): selection = QTextEdit.ExtraSelection() lineColor = QColor(resources.CUSTOM_SCHEME.get('current-line', resources.COLOR_SCHEME['current-line'])) lineColor.setAlpha(20) selection.format.setBackground(lineColor) selection.format.setProperty(QTextFormat.FullWidthSelection, True) selection.cursor = self.textCursor() selection.cursor.clearSelection() self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) if self._braces is not None: self._braces = None cursor = self.textCursor() if cursor.position() == 0: self.setExtraSelections(self.extraSelections) return cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) text = cursor.selectedText() pos1 = cursor.position() if text in (')', ']', '}'): pos2 = self._match_braces(pos1, text, forward=False) elif text in ('(', '[', '{'): pos2 = self._match_braces(pos1, text, forward=True) else: self.setExtraSelections(self.extraSelections) return if pos2 is not None: self._braces = (pos1, pos2) selection = QTextEdit.ExtraSelection() selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.cursor = cursor self.extraSelections.append(selection) selection = QTextEdit.ExtraSelection() selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.cursor = self.textCursor() selection.cursor.setPosition(pos2) selection.cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) self.extraSelections.append(selection) else: self._braces = (pos1,) selection = QTextEdit.ExtraSelection() selection.format.setBackground(QColor( resources.CUSTOM_SCHEME.get('brace-background', resources.COLOR_SCHEME.get('brace-background')))) selection.format.setForeground(QColor( resources.CUSTOM_SCHEME.get('brace-foreground', resources.COLOR_SCHEME.get('brace-foreground')))) selection.cursor = cursor self.extraSelections.append(selection) self.setExtraSelections(self.extraSelections) def _text_under_cursor(self): tc = self.textCursor() tc.select(QTextCursor.WordUnderCursor) return tc.selectedText() def get_selection(self, posStart, posEnd): cursor = self.textCursor() cursor.setPosition(posStart) cursor2 = self.textCursor() if posEnd == QTextCursor.End: cursor2.movePosition(posEnd) cursor.setPosition(cursor2.position(), QTextCursor.KeepAnchor) else: cursor.setPosition(posEnd, QTextCursor.KeepAnchor) return cursor.selectedText() def _match_braces(self, position, brace, forward): """based on: http://gitorious.org/khteditor""" if forward: braceMatch = {'(': ')', '[': ']', '{': '}'} text = self.get_selection(position, QTextCursor.End) braceOpen, braceClose = 1, 1 else: braceMatch = {')': '(', ']': '[', '}': '{'} text = self.get_selection(QTextCursor.Start, position) braceOpen, braceClose = len(text) - 1, len(text) - 1 while True: if forward: posClose = text.find(braceMatch[brace], braceClose) else: posClose = text.rfind(braceMatch[brace], 0, braceClose + 1) if posClose > -1: if forward: braceClose = posClose + 1 posOpen = text.find(brace, braceOpen, posClose) else: braceClose = posClose - 1 posOpen = text.rfind(brace, posClose, braceOpen + 1) if posOpen > -1: if forward: braceOpen = posOpen + 1 else: braceOpen = posOpen - 1 else: if forward: return position + posClose else: return position - (len(text) - posClose) else: return def _add_prompt(self, incomplete): if incomplete: prompt = '.' * 3 + ' ' else: prompt = self.prompt self.appendPlainText(prompt) self.moveCursor(QTextCursor.End) def _get_cursor_position(self): return self.textCursor().columnNumber() - len(self.prompt) def _write_command(self): command = self.document().findBlockByLineNumber( self.document().lineCount() - 1).text() #remove the prompt from the QString command = command[len(self.prompt):] self._add_history(command) incomplete = self._write(command) if self.patFrom.match(command) or \ self.patImport.match(command): self.imports += [command] if not incomplete: output = self._read() if output is not None: if output.__class__.__name__ == 'unicode': output = output.encode('utf8') self.appendPlainText(output.decode('utf8')) self._add_prompt(incomplete) def _set_command(self, command): self.moveCursor(QTextCursor.End) self.moveCursor(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) for i in range(len(self.prompt)): self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor) self.textCursor().removeSelectedText() self.textCursor().insertText(command) self.moveCursor(QTextCursor.End) def mousePressEvent(self, event): #to avoid selection event.ignore() def contextMenuEvent(self, event): self.popup_menu.exec_(event.globalPos()) def _write(self, line): return self._console.push(line) def _read(self): return self._console.output def _add_history(self, command): if command and (not self._history or self._history[-1] != command): self._history.append(command) self.history_index = len(self._history) def _get_prev_history_entry(self): if self._history: self.history_index = max(0, self.history_index - 1) return self._history[self.history_index] return '' def _get_next_history_entry(self): if self._history: hist_len = len(self._history) self.history_index = min(hist_len, self.history_index + 1) if self.history_index < hist_len: return self._history[self.history_index] return '' def restyle(self): self.apply_editor_style() self._highlighter.apply_highlight('python', resources.CUSTOM_SCHEME) def apply_editor_style(self): css = 'QPlainTextEdit {color: %s; background-color: %s;' \ 'selection-color: %s; selection-background-color: %s;}' \ % (resources.CUSTOM_SCHEME.get('editor-text', resources.COLOR_SCHEME['editor-text']), resources.CUSTOM_SCHEME.get('editor-background', resources.COLOR_SCHEME['editor-background']), resources.CUSTOM_SCHEME.get('editor-selection-color', resources.COLOR_SCHEME['editor-selection-color']), resources.CUSTOM_SCHEME.get('editor-selection-background', resources.COLOR_SCHEME['editor-selection-background'])) self.setStyleSheet(css) def load_project_into_console(self, projectFolder): """Load the projectFolder received into the sys.path.""" self._console.push("import sys; sys.path += ['%s']" % projectFolder) def unload_project_from_console(self, projectFolder): """Unload the project from the system path.""" self._console.push("import sys; " "sys.path = [path for path in sys.path " "if path != '/home/gato/Desktop']")
class Window(mainwindow, ui_mainwindow): def __init__(self): QMainWindow.__init__(self) self.setWindowIcon(QIcon(":/scanner.png")) QIcon.setThemeName("Adwaita") self.setupUi(self) close_icon = QApplication.style().standardIcon(QStyle.SP_DialogCloseButton) self.closeBtn.setIcon(close_icon) # connect signals self.comboDevice.currentIndexChanged.connect(self.onDeviceChange) self.comboColor.currentIndexChanged.connect(self.onColorModeChange) self.scanBtn.clicked.connect(self.startScanning) self.closeBtn.clicked.connect(self.close) self.process = QProcess(self) QTimer.singleShot(100, self.updateDeviceList) def updateDeviceList(self): self.devices_info = get_devices() if len(self.devices_info)>0: self.comboDevice.clear() models = [ dev['model'] for dev in self.devices_info] self.comboDevice.addItems(models) self.selectDevice(0) def selectDevice(self, index): self.scanner = get_backend_from_scanner_device(self.devices_info[index]) self.comboColor.clear() self.comboResolution.clear() self.comboArea.clear() self.comboColor.addItems(self.scanner.supportedColorModes()) self.comboResolution.addItems(self.scanner.supportedResolutions()) self.comboArea.addItems(self.scanner.supportedScanAreas()) # Init values self.comboColor.setCurrentIndex(self.scanner.default_color_index) self.comboResolution.setCurrentIndex(self.scanner.default_resolution_index) self.comboArea.setCurrentIndex(self.scanner.default_scan_area_index) self.labelExt.setText(self.scanner.extension) self.filenameEdit.setText(self.newFileName()) def onDeviceChange(self, index): self.selectDevice(index) def onColorModeChange(self, index): """ Change file format on colormode change """ self.scanner.setSelectedColor(index) self.labelExt.setText(self.scanner.extension) self.filenameEdit.setText(self.newFileName()) def startScanning(self): if self.comboDevice.count()==0: return self.scanner.setSelectedColor(self.comboColor.currentIndex()) self.scanner.setSelectedResolution(self.comboResolution.currentIndex()) self.scanner.setSelectedScanArea(self.comboArea.currentIndex()) ext = self.scanner.extension args = self.scanner.getArgs() self.statusbar.showMessage("Scan Started") wait(20) self.process.start('scanimage', args) if not self.process.waitForFinished(-1) or self.process.exitCode(): self.statusbar.showMessage("Scanning Failed !") return data = self.process.readAllStandardOutput() filename = self.filenameEdit.text() + ext # to get more accurate scanned area when A4 at 300 dpi if (self.scanner.crop_needed): image = QImage.fromData(data) image = image.copy(self.scanner.crop_rect) image.save(filename) else: img_file = QFile(filename, self) img_file.open(QIODevice.WriteOnly) img_file.write(data) img_file.close() data.clear() self.statusbar.showMessage("Scan Completed Successfully") self.filenameEdit.setText(self.newFileName()) def newFileName(self): ext = self.scanner.extension index = 1 while True: filename = "Scan%3i" % index filename = filename.replace(" ", "0") if os.path.exists(filename + ext): index +=1 else: break return filename