class Player(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = None self.process = None self.init_ui() def init_ui(self): self.ui = mplayer_ui.Ui_mplayer() self.ui.setupUi(self) # 播放器初始化 self.process = QProcess(self) self.process.readyReadStandardOutput.connect(self.read_player_stdout) time_clock = QTimer(self) time_clock.timeout.connect(self.time_done) # 播放视频 path = '1.mp4' self.play_video(path) def time_done(self): self.process.write("get_time_length\n") self.process.write("get_time_pos\n") self.process.write("get_percent_pos\n") def read_player_stdout(self): while self.process.canReadLine(): b = self.process.readLine() print(b) if b.startsWith("ANS_TIME_POSITION"): print(b) elif b.startsWith("ANS_LENGTH"): print(b) elif b.startsWith("ANS_PERCENT_POSITION"): print(b) def play_video(self, path): if not os.path.exists(path): print('not exists:{0}'.format(path)) return args = QStringList() args << "-slave" # 使用slave模式 # args << "-quiet" # 不要输出冗余信息 args << "-wid" << QString.number(self.winId(), 10) # 将输出定位到ui下的widget窗口内 args << "-zoom" # 自适应窗口 args << "-vo" args << "x11,xv,gl,gl2,sdl" # 使用x11模式播放(只有这种模式下才支持23行的指定输出窗口到ui->widget) args << path # 播放file_name文件 self.process.start("MPlayer/mplayer.exe", args) # 启动该进程,并传入参数args
class Mplayer(QDialog): REVENIR, PAS_PRECEDENT_SUIVANT, PRECEDENT_SUIVANT, CURSEUR_SUR_UNE_LIGNE,\ CURSEUR_A_PART, PARCOURIR, PAS_PARCOURIR, LIST, RATIO = range(9) HAUTEUR, LARGEUR = range(2) def __init__(self, cheminVideo=[], taille=(250,225), choixWidget=(RATIO, REVENIR, PAS_PRECEDENT_SUIVANT,CURSEUR_SUR_UNE_LIGNE,PAS_PARCOURIR,LIST), debutFin=(0,0), cheminMPlayer=None, barreTaches=None, facteurLimitant=HAUTEUR, cheminParcourir=None, parent=None): """widget mplayer""" QDialog.__init__(self, parent) #=== Paramètres généraux ===# self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle(_(u"Player vidéo")) #On réduit la marge pour gagner de l'espace self.setContentsMargins(0,0,0,0) self.systeme = os.name ### Quand EKD windows est installé, le chemin des dépendances sont ########### ### positionnées dans les variables d'environnement donc pas besoin de ####### ### collecter le chemin des ces dépendances ################################## self.cheminMPlayer = "mplayer" ############################################################################## # liste de chemins vidéos if type(cheminVideo) != list : self.listeVideos=[cheminVideo] else : self.listeVideos = cheminVideo # est-ce que la vidéo est lue? self.estLue=False # est-ce que la vidéo est en pause? self.estEnPause=False self.debutFin = debutFin # Nom du fichier courant (le self n'est pas encore utile) txtParDefaut = u"Pas de fichier lu" if self.listeVideos.__len__()!=0: self.fichierCourant = [txtParDefaut, self.listeVideos[0]] else: self.fichierCourant = [txtParDefaut, ""] # Barre des tâches de la fenêtre self.barreTaches = barreTaches # Taille de la vidéo self.tailleLargeur=taille[0] self.tailleHauteur=taille[1] # paramètres des boutons-icones iconTaille=22 flat=1 # Pour récupérer le temps courant depuis certains cadre self.temps = 0 self.dureeTimer = 10 # temps en ms ############################################################################################################################### #Pour être plus précis lors de la lecture, on prend comme unité la miliseconde. ###################### ## Il faut donc utiliser une echelle 1000 fois plus grande pour les unités du slider self.echelle=1000 ############################################################################################################################### # Permet de récupérer la durée de la vidéo depuis une instance de la classe # Sert dans certains cadres self.dureeVideo = 0 # Chemin sur lequel peut s'ouvrir la boite de dialogue de fichier # associée au bouton parcourir self.cheminPourBoutonParcourir = cheminParcourir self.taille = taille debug("self.taille avant lecture : %s %s" % (self.taille, type(self.taille))) #=== Widgets ===# self.icone_lire=QIcon("Icones" + os.sep + "player_play.png") self.icone_pause=QIcon("Icones" + os.sep + "player_pause.png") self.icone_arret=QIcon("Icones" + os.sep + "player_stop.png") if Mplayer.REVENIR in choixWidget: self.bout_revenir = QPushButton(u"Revenir") self.bout_revenir.setIcon(QIcon("Icones" + os.sep + "revenir.png")) if Mplayer.PARCOURIR in choixWidget: self.bout_ouvVideo = QPushButton(u"Parcourir...") if Mplayer.PRECEDENT_SUIVANT in choixWidget: self.bout_prec = QPushButton(QIcon("Icones" + os.sep + "player_rew.png"),"") self.bout_prec.setIconSize(QSize(iconTaille, iconTaille)) self.bout_prec.setFlat(flat) self.bout_suivant = QPushButton(QIcon("Icones" + os.sep + "player_fwd.png"),"") self.bout_suivant.setIconSize(QSize(iconTaille, iconTaille)) self.bout_suivant.setFlat(flat) self.LISTW=False if Mplayer.LIST in choixWidget : self.LISTW = True self.listFichiers = QComboBox() self.listFichiers.hide() self.setListeVideo() self.bout_LectPause = QPushButton(self.icone_lire,"") self.bout_LectPause.setIconSize(QSize(iconTaille, iconTaille)) self.bout_LectPause.setFlat(flat) self.bout_Arret = QPushButton(self.icone_arret,"") self.bout_Arret.setIconSize(QSize(iconTaille, iconTaille)) self.bout_Arret.setFlat(flat) # widget qui contiendra la vidéo self.cibleVideo = DisplayVid(self) # par défaut le widget-cible est noir color = QColor(0, 0, 0) self.cibleVideo.setAutoFillBackground(True) self.cibleVideo.setPalette(QPalette(color)) self.cibleVideo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.cibleVideo.setFixedHeight(self.taille[1]) self.cibleVideo.setToolTip(self.fichierCourant[0]) #Choix de l'aspect ratio de la vidéo if Mplayer.RATIO in choixWidget : self.conf = QGroupBox() self.conf.setContentsMargins(0,0,0,0) self.conf.setMinimumSize(QSize(self.tailleLargeur, 0)) self.conf.setObjectName("conf") self.verticalLayout = QHBoxLayout(self.conf) self.verticalLayout.setObjectName("verticalLayout") self.choicenorm = QRadioButton(self.conf) self.choicenorm.setObjectName("choicenorm") self.verticalLayout.addWidget(self.choicenorm) self.choicewide = QRadioButton(self.conf) self.choicewide.setObjectName("choicewide") self.verticalLayout.addWidget(self.choicewide) self.choiceone = QRadioButton(self.conf) self.choiceone.setObjectName("choiceone") self.verticalLayout.addWidget(self.choiceone) self.choicenorm.setText("4:3") self.choicewide.setText("16:9") self.choiceone.setText("w:h") # Checked le ratio de la vidéo if self.listeVideos.__len__()!=0: self.changeRatio(self.listeVideos[0]) else : self.setRatio(4.0/3.0) if Mplayer.RATIO in choixWidget : self.choicenorm.setChecked(True) self.slider = QSlider(Qt.Horizontal) self.slider.setEnabled(True) self.mplayerProcess = QProcess(self) self.timer = QTimer(self) self.tempsChrono = TracerChrono() #=== mise-en-page/plan ===# mhbox = QHBoxLayout() vbox = QVBoxLayout() vbox.addWidget(self.cibleVideo) if Mplayer.RATIO in choixWidget : vbox.addWidget(self.conf) hbox = QHBoxLayout() if Mplayer.REVENIR in choixWidget: hbox.addWidget(self.bout_revenir) if Mplayer.PARCOURIR in choixWidget: hbox.addWidget(self.bout_ouvVideo) hbox.addWidget(self.bout_LectPause) hbox.addWidget(self.bout_Arret) if Mplayer.PRECEDENT_SUIVANT in choixWidget: hbox.addWidget(self.bout_prec) hbox.addWidget(self.bout_suivant) hbox.addWidget(self.tempsChrono) if Mplayer.CURSEUR_A_PART not in choixWidget: hbox.addWidget(self.slider) vbox.addLayout(hbox) if Mplayer.CURSEUR_A_PART in choixWidget: hbox.setAlignment(Qt.AlignLeft) hbox = QHBoxLayout() hbox.addWidget(self.slider) vbox.addLayout(hbox) # Liste fichier dans combobox if self.LISTW : hbox = QHBoxLayout() hbox.addWidget(self.listFichiers) vbox.addLayout(hbox) mhbox.addLayout(vbox) self.setLayout(mhbox) #=== connexion des widgets à des fonctions ===# if Mplayer.REVENIR in choixWidget: self.connect(self.bout_revenir, SIGNAL('clicked()'), SLOT('close()')) if Mplayer.PARCOURIR in choixWidget: self.connect(self.bout_ouvVideo, SIGNAL('clicked()'), self.ouvrirVideo) if Mplayer.PRECEDENT_SUIVANT in choixWidget: self.connect(self.bout_prec, SIGNAL('clicked()'), self.precedent) self.connect(self.bout_suivant, SIGNAL('clicked()'), self.suivant) #Ajouté le 08/11/2009 - Liste des fichiers dans une combobox if self.LISTW : self.connect(self.listFichiers, SIGNAL('currentIndexChanged(int)'), self.changeVideo) self.connect(self.bout_LectPause, SIGNAL('clicked()'), self.lectPause) self.connect(self.bout_Arret, SIGNAL('clicked()'), self.arretMPlayer) self.connect(self.mplayerProcess, SIGNAL('readyReadStandardOutput()'), self.recupSortie) self.connect(self.mplayerProcess, SIGNAL('finished(int,QProcess::ExitStatus)'), self.finVideo) self.connect(self.timer, SIGNAL('timeout()'), self.sonderTempsActuel) self.connect(self.slider, SIGNAL('sliderMoved(int)'), self.changerTempsCurseur) self.connect(self.cibleVideo, SIGNAL('changeSize'), self.sizeMplayer) if Mplayer.RATIO in choixWidget : self.connect(self.choicenorm, SIGNAL("clicked(bool)"), self.defRatio) self.connect(self.choicewide, SIGNAL("clicked(bool)"), self.defRatio) self.connect(self.choiceone, SIGNAL("clicked(bool)"), self.defRatio) def setListeVideo(self) : self.referenceVideo = [] self.listFichiers.clear() for vid in self.listeVideos : self.referenceVideo.append(vid) self.listFichiers.addItem(os.path.basename(vid)) if self.listeVideos.__len__() > 1 : self.listFichiers.show() def setAudio(self,au) : if au : self.cibleVideo.hide() if "conf" in self.__dict__ : self.conf.hide() else : self.cibleVideo.show() if "conf" in self.__dict__ : self.conf.show() def changeVideo(self, index) : self.arretMPlayer() if index >= 0 : # Condition ajoutée pour éviter une erreure de dépassement de range dans la liste. self.listeVideos = self.referenceVideo[index] self.listFichiers.setCurrentIndex(index) def defRatio(self, state=0) : if state : if self.choicenorm.isChecked() : self.setRatio(4.0/3.0) if self.choicewide.isChecked() : self.setRatio(16.0/9.0) if self.choiceone.isChecked() : try : dim=getVideoSize(unicode(self.listeVideos[0])) self.setRatio(dim[0]/dim[1]) except : None self.defRatio() else : self.adjustSize() def setRatio(self,ratio) : self.ratio = ratio self.sizeMplayer() def changeRatio(self,video) : rv = getVideoRatio(video) if rv[0]==0.0 and type(rv[1])==float : rat = rv[1] else : rat = rv[0] if rat > 1.7 : if "choicewide" in self.__dict__ : self.choicewide.setChecked(True) self.setRatio(16.0/9.0) elif rat > 1.3 and rat <= 1.7 : if "choicenorm" in self.__dict__ : self.choicenorm.setChecked(True) self.setRatio(4.0/3.0) elif rat < 1.3 and rat != 0.0 : if "choiceone" in self.__dict__ : self.choiceone.setChecked(True) dim=getVideoSize(video) self.setRatio(dim[0]/dim[1]) else : if "choicenorm" in self.__dict__ : self.choicenorm.setChecked(True) self.setRatio(4.0/3.0) def sizeMplayer(self) : self.cibleVideo.setFixedHeight(int(self.cibleVideo.width()/self.ratio)) def ouvrirVideo(self): """Ouverture de la boîte de dialogue de fichiers""" txt = u"Fichiers vidéo" if self.cheminPourBoutonParcourir: chemin = self.cheminPourBoutonParcourir else: try: chemin = EkdConfig.get('general','video_input_path').decode("UTF8") except: chemin = os.path.expanduser('~') liste=QFileDialog.getOpenFileNames(None, u"Ouvrir", chemin, "%s (*.avi *.mpg *.mpeg *.mjpeg *.flv *.mp4 *.ogg *.vob *.mov *.wmv *.3gp *.h264)\n*" %txt) if not liste: return self.listeVideos = liste self.changeRatio(unicode(self.listeVideos[0])) chemin = unicode(self.listeVideos[0]) EkdConfig.set('general','video_input_path',os.path.dirname(chemin).encode("UTF8")) def setVideos(self, videos) : '''Définie proprement la liste des vidéos à jouer''' if type(videos) != list : self.listeVideos = [videos] else : self.listeVideos = videos if self.LISTW and videos.__len__() > 1 : self.setListeVideo() elif self.LISTW : self.listFichiers.hide() def demarrerMPlayer(self): """démarrage de mplayer avec les arguments choisis""" if self.estLue: return True args = QStringList() # Liste Qt qui contiendra les options de mplayer # Ajout d'options à liste: args << "-option" # mplayer fonctionnera comme un terminal dans ce script args << "-slave" # on ne veut pas avoir des commentaires sans grand intérêt args << "-quiet" # Sous linux, aucun driver n'a été nécessaire et pas de manip pour Wid :) if self.systeme=='posix': # try - except? # la fenêtre de mplayer restera attaché à la fenêtre # wid prend en valeur le nombre identifiant le widget (celui qui contiendra la vidéo) args << "-wid" << QString.number(self.cibleVideo.winId()) # Objet QString car args est une liste de ch de caractères settings = QSettings() videoOutput = settings.value("vo", QVariant('')).toString() if videoOutput: args << '-vo' << videoOutput # Sous windows else: # reinterpret_cast<qlonglong> obligatoire, winId() ne se laissant pas convertir gentiment ;) args << "-wid" << self.cibleVideo.winId().__hex__() args << "-vo" << "directx:noaccel" #args << "-vo" << "gl" # alternative # chemin de la vidéo args << self.listeVideos if PYQT_VERSION_STR >= "4.1.0": # mode de canal: on fusionne le canal de sortie normal (stdout) et celui des erreurs (stderr) self.mplayerProcess.setProcessChannelMode(QProcess.MergedChannels) # démarrage de mplayer (en tenant compte des arguments définis ci-dessus) # comme un nouveau processus self.mplayerProcess.start(self.cheminMPlayer, args) # au cas où mplayer ne démarrerait pas au bout de 3 sec (ex. problème de codec) if not self.mplayerProcess.waitForStarted(3000): QMessageBox.critical(self, u"Avertissement", u"Bogue au lancement de la vidéo avec mplayer") return False # donne le temps toutes les x secondes self.timer.start(self.dureeTimer) self.estLue = True return True def recupSortie(self): """récupère les lignes d'information émises par QProcess (mplayerProcess) et en tire les conséquences""" while self.mplayerProcess.canReadLine(): # renvoie True si une ligne complète peut être lue à partir du système # stocker l'ensemble des bits d'une ligne tampon=QByteArray(self.mplayerProcess.readLine()) # readline: lit une ligne ascii à partir du système # On vérifie si on a eu des réponses if tampon.startsWith("Playing"): # On récupère les infos de base ('$ mplayer -input cmdlist' pour avoir la liste complète - file:///usr/share/doc/mplayer-doc/tech/slave.txt.gz pour plus de détails) self.mplayerProcess.write("get_video_resolution\n") # récupère la résolution de la vidéo self.mplayerProcess.write("get_time_length\n") # Nouveau fichier chargé -> on récupère son nom ind = tampon.length() - 2 # suppression du '.' à la fin tampon.remove(ind,ind) tampon.remove(0, 8) # vire Playing tampon.replace(QByteArray("\n"), QByteArray("")) tampon.replace(QByteArray("\r"), QByteArray("")) try: # Tour de passe-passe pour ne pas avoir de problème d'accents # Condition pour détection windows if os.name == 'nt': self.fichierCourant[1]=unicode(QString(tampon)) # Condition pour détection Linux ou MacOSX elif os.name in ['posix', 'mac']: self.fichierCourant[1]=unicode(QString(tampon)).encode("Latin1").decode("UTF8") except UnicodeEncodeError, e: debug(e) self.fichierCourant[1]="?" self.cibleVideo.setToolTip(self.fichierCourant[1]) if self.barreTaches is not None: self.barreTaches.showMessage(self.fichierCourant[1]) # réponse à get_video_resolution : ANS_VIDEO_RESOLUTION='<width> x <height>' if tampon.startsWith("ANS_VIDEO_RESOLUTION"): # retourne True si l'ensemble de bits démarre avec "..." debug("tampon : %s" % tampon) # ex. -> ANS_VIDEO_RESOLUTION='352 x 288' tampon.remove(0, 21) # suppression des 21 1er caract -> '352 x 288' tampon.replace(QByteArray("'"), QByteArray("")) # -> 352 x 288 tampon.replace(QByteArray(" "), QByteArray("")) # -> 352x288 tampon.replace(QByteArray("\n"), QByteArray("")) # -> 352x288 # retour chariot unix tampon.replace(QByteArray("\r"), QByteArray("")) # -> 352x288 # retour chariot windows #print "-----tampon.indexOf('x') :", tampon.indexOf('x'), type(tampon.indexOf('x')) sepIndex = tampon.indexOf('x') # récupère la position de 'x' # 3 <type 'int'> #print "-----tampon.left(sepIndex).toInt():", tampon.left(sepIndex).toInt(), type(tampon.left(sepIndex).toInt()) resX = tampon.left(sepIndex).toInt()[0] # -> 352 # (352, True) <type 'tuple'> #print "-----tampon.mid(sepIndex+1).toInt() :", tampon.mid(sepIndex+1).toInt(), type(tampon.mid(sepIndex+1).toInt()) resY = tampon.mid(sepIndex+1).toInt()[0] # -> 288 # (288, True) <type 'tuple'> # on définit les nouvelles dimensions de l'image du widget-mplayer. # try pour éviter les bogues sur les fichiers audio (sans dimension d'image)!!! #try: if resX!=0 or resY!=0: debug( "ratio : %s - %s" % (self.ratio, type(self.ratio))) else: debug("fichier audio") # réponse à get_time_length : ANS_LENGTH=xx.yy elif tampon.startsWith("ANS_LENGTH"): debug("tampon : %s" % tampon) # -> ANS_LENGTH=279.38 tampon.remove(0, 11) # vire ANS_LENGTH= tampon.replace(QByteArray("'"), QByteArray("")) tampon.replace(QByteArray(" "), QByteArray("")) tampon.replace(QByteArray("\n"), QByteArray("")) tampon.replace(QByteArray("\r"), QByteArray("")) # -> 279.38 #print "-----tampon.toFloat() :", tampon.toFloat(), type(tampon.toFloat()) tempsMax = tampon.toFloat()[0] # (279.3800048828125, True) <type 'tuple'> self.dureeVideo = tempsMax ## Modifié le 28/05/2009 : On augmente la précision du slider #self.slider.setMaximum(tempsMax) # déf du domaine de valeur du curseur self.slider.setMaximum(tempsMax*self.echelle) # ATTENTION J'AI COMMENTE CETTE LIGNE !!! #self.slider.setMaximum(tempsMax) # réponse à get_time_pos : ANS_TIME_POSITION=xx.y elif tampon.startsWith("ANS_TIME_POSITION"): #print "tampon :",tampon # -> ANS_TIME_POSITION=1.4 (temps courant) tampon.remove(0, 18) # vire ANS_TIME_POSITION= tampon.replace(QByteArray("'"), QByteArray("")) tampon.replace(QByteArray(" "), QByteArray("")) tampon.replace(QByteArray("\n"), QByteArray("")) tampon.replace(QByteArray("\r"), QByteArray("")) #print "-----tampon.toFloat() :", tampon.toFloat(), type(tampon.toFloat()) tempsCourant = tampon.toFloat()[0] # (1.3999999761581421, True) <type 'tuple'> # récupération du temps courant: utile dans certains cadres self.temps = tempsCourant # Programmer un arrêt. Utile pour les aperçus temps = float("%.1f" %self.temps) if self.debutFin!=(0,0) and self.debutFin[1]==temps: self.arretMPlayer() return self.slider.setValue(tempsCourant*self.echelle) ############################################################################# self.changerTempsChrono(tempsCourant) # modifier le chrono du bouton
class FrD_NukeBatchRender(QtGui.QMainWindow, form_class): def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowTitle('FrD Nuke Batch Render' + PROGRAM_VERSION) self.output_LW.setEnabled(0) # ============================ STYLE ======================= # # Progress Bar Style PB_STYLE = """ QProgressBar { border: 2px solid grey; border-radius: 5px; text-align: center; } QProgressBar::chunk { background-color: #d7801a; width: 3px; margin: 1.5px; } """ # self.PB.setStyleSheet(PB_STYLE) # QMenuBar Style MB_STYLE = """ QMenuBar::item { background: transparent; } QMenuBar::item:selected { background: background-color: rgb(49,49,49); border: 1px solid #000; } QMenuBar::item:pressed { background: #444; border: 1px solid #000; background-color: QLinearGradient( x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434/*, stop:0.2 #343434, stop:0.1 #ffaa00*/ ); margin-bottom:-1px; padding-bottom:1px; } """ self.menuFiles.setStyleSheet(MB_STYLE) # ============================ STYLE ======================= # # Enable Drah and Drop self.Queue_TW.setAcceptDrops(True) # Set up handlers for the TableWidget self.Queue_TW.dragEnterEvent = self.twDragEnterEvent self.Queue_TW.dragMoveEvent = self.twDragMoveEvent self.Queue_TW.dropEvent = self.twDropEvent # Size of Table Columns self.Queue_TW.setColumnWidth(0, 250) self.Queue_TW.setColumnWidth(1, 300) self.Queue_TW.setColumnWidth(2, 100) self.Queue_TW.setColumnWidth(3, 100) self.Queue_TW.setColumnWidth(4, 310) self.Queue_TW.setColumnWidth(5, 110) # operation ALL self.Clear_BN.clicked.connect(self.ClearQueue) self.Update_BN.clicked.connect(self.UpdateQueue) # Render self.Render_BN.clicked.connect(self.NBR_render) # ============ Drag and Drop Event) ============ # def twDragEnterEvent(self, event): if event.mimeData().hasUrls: event.accept() else: event.ignore() def twDragMoveEvent(self, event): if event.mimeData().hasUrls: event.setDropAction(QtCore.Qt.CopyAction) event.accept() else: event.ignore() def twDropEvent(self, event): if event.mimeData().hasUrls: event.setDropAction(QtCore.Qt.CopyAction) event.accept() links = [] for url in event.mimeData().urls(): links.append(str(url.toLocalFile())) # print links self.nukeProjDropped(links) else: event.ignore() # ============ Drag and Drop Ends ============ # # ============ Clear and Update All ============ # def NBR_askMsg(self, title, text): qmsgBox = QtGui.QMessageBox() qmsgBox.setStyleSheet('QMessageBox {background-color: #333; font-size: 12pt; font-family: Trebuchet MS}\nQLabel{color:white;}') # 585858 return QtGui.QMessageBox.question(qmsgBox, title, text, QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel) # | QtGui.QMessageBox.No def ClearQueue(self): global folderQueue if self.Queue_TW.rowCount() > 0: if (self.NBR_askMsg('Clear Render Queue', 'Are you sure you want to clear the whole Render Queue?') == QtGui.QMessageBox.Yes): self.Queue_TW.setRowCount(0) folderQueue = [] QtGui.QApplication.processEvents() def UpdateQueue(self): global folderQueue for project in xrange(len(folderQueue)): pass # ========== Clear and Update All Ends ========== # def nukeProjDropped(self, arg): global folderQueue appendedList = [] for url in sorted(arg): if os.path.exists(url) and os.path.isfile(url) and url.lower().endswith('.nk'): if url in folderQueue: pass else: appendedList.append(url) folderQueue.append(url) # Add table row rowPosition = self.Queue_TW.rowCount() self.Queue_TW.insertRow(rowPosition) # get All Write Node from .nk # QProcess for nuke self.nukeProcess = QProcess(self) self.nukeProcess.setProcessChannelMode(QProcess.MergedChannels) args = self.createCmdArg(str(url)) self.nukeProcess.start(NUKE_EXE, args) # For debug: read output lines self.nukeProcess.readyRead.connect(self.NBR_debug) self.nukeProcess.waitForFinished() self.nukeProcess.close() # Add row and info to table self.NBR_createCheckBoxItemTableWidget(rowPosition, 0, os.path.splitext(os.path.basename(url))[0]) # Get the write nodes from text files (D:/Temp/nukeBatch) layout = QtGui.QVBoxLayout() layout.setAlignment(QtCore.Qt.AlignLeft) with open("D:\\Temp\\nukeBatch\\" + os.path.basename(url) + ".txt", "r") as ins: bframe = False bCount = 0 for line in ins: if 'FrameRange:' in line: bframe = True continue if (bframe is False): item = QtGui.QCheckBox(str(line).strip()) item.setChecked(True) item.setFont(QtGui.QFont('meiryo', 9)) layout.addWidget(item) elif (bframe is True): self.NBR_createEditTextItemTableWidget(rowPosition, 2 + bCount, int(str(line).strip())) bCount += 1 cellWidget = QtGui.QWidget() cellWidget.setLayout(layout) self.Queue_TW.setCellWidget(rowPosition, 1, cellWidget) self.Queue_TW.resizeRowsToContents() self.Queue_TW.scrollToBottom() QtGui.QApplication.processEvents() def createCmdArg(self, nk): # nk = url return ["-ti", CHECKING_NK, nk] def createCmdArg2(self, nk, start, end, wnode=[]): return ["-ti", RENDER_NK, nk, wnode, start, end] def NBR_debug(self): while (self.nukeProcess.canReadLine()): print (str(self.nukeProcess.readLine())) def NBR_createCheckBoxItemTableWidget(self, row, col, text, color='#4c4c4c'): layout = QtGui.QVBoxLayout() layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) item = QtGui.QCheckBox(text) item.setChecked(True) item.setFont(QtGui.QFont('meiryo', 9)) layout.addWidget(item) cellWidget = QtGui.QWidget() cellWidget.setStyleSheet('color:white; background-color:' + color) cellWidget.setLayout(layout) self.Queue_TW.setCellWidget(row, col, cellWidget) # self.Queue_TW.setItem(row, 0, QtGui.QTableWidgetItem(str(text))) def NBR_createEditTextItemTableWidget(self, row, col, text, color='#4c4c4c'): layout = QtGui.QVBoxLayout() layout.setAlignment(QtCore.Qt.AlignCenter) item = QtGui.QSpinBox() item.setMaximum(9999) item.setValue(text) item.setFont(QtGui.QFont('meiryo', 9)) layout.addWidget(item) cellWidget = QtGui.QWidget() cellWidget.setStyleSheet('color:white; background-color:' + color) cellWidget.setLayout(layout) self.Queue_TW.setCellWidget(row, col, cellWidget) def NBR_getCellData(self, row, col, key): cellDict = {} target = self.Queue_TW.cellWidget(row, col) if target: lay = target.layout() if lay: for k in xrange(lay.count()): w = lay.itemAt(k).widget() if isinstance(w, QtGui.QCheckBox): cellDict[key] = w.checkState() # 0 false, > 0 true elif isinstance(w, QtGui.QSpinBox): cellDict[key] = w.value() return cellDict def NBR_getCellNodeData(self, row, col): target = self.Queue_TW.cellWidget(row, col) cellUserInputList = [] if target: lay = target.layout() if lay: for k in xrange(lay.count()): w = lay.itemAt(k).widget() if isinstance(w, QtGui.QCheckBox): cellUserInputList.append([str(w.text()), w.checkState()]) else: cellUserInputList.append(-1) return cellUserInputList def NBR_render(self): global folderQueue for nk in xrange(len(folderQueue)): renderNode = [] # proj = os.path.splitext(os.path.basename(folderQueue[nk]))[0] projDict = self.NBR_getCellData(nk, 0, 'Project') if int(projDict['Project']) > 0: nodeArr = self.NBR_getCellNodeData(nk, 1) startDict = self.NBR_getCellData(nk, 2, 'Start') endDict = self.NBR_getCellData(nk, 3, 'End') # Write nodes loop for node in xrange(len(nodeArr)): if nodeArr[node][1] > 0: # get each node check state (0/2), selected write node (render) renderNode.append(nodeArr[node][0].split(":")[0]) # Debug print str(renderNode) # print nodeArr self.nukeProcess = QProcess(self) # QProcess for nuke print nodeArr[node][0].split(":")[0] # get each node from array self.nukeProcess.setProcessChannelMode(QProcess.MergedChannels) args = self.createCmdArg2(str(folderQueue[nk]), renderNode, startDict['Start'], endDict['End']) self.nukeProcess.start(NUKE_EXE, str(args)) self.nukeProcess.readyRead.connect(self.NBR_debug) self.nukeProcess.waitForFinished() self.nukeProcess.close()
class PyLint(Plugin, QObject): """ PyLint Plugin """ capabilities = ['toolbarHook'] __version__ = '0.5' thread = None def do_toolbarHook(self, widget): """ Hook to install the pylint toolbar button""" widget.addAction('PyLint', self.do_pylint) @pyqtSlot() def do_pylint(self): """ Launch the lint process and create the result window """ print 'do_pylint' self.pylint_pross = QProcess() self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels) self.pylint_pross.setWorkingDirectory( \ os.path.dirname(str(self.parent.editor.filename))) self.pylint_pross.setReadChannel(QProcess.StandardOutput) self.connect(self.pylint_pross, \ SIGNAL('finished(int)'), \ self.finished) self.connect(self.pylint_pross, \ SIGNAL('readyReadStandardOutput()'), \ self.handle_stdout) self.connect(self.pylint_pross, \ SIGNAL('readyReadStandardError()'), \ self.handle_stderr) if (self.pylint_pross.start("pylint", \ [self.parent.editor.filename,])): print 'Cannot start process' self.win = ResultWin() self.win.setWindowTitle("PyLint Results :" \ + os.path.basename(str(self.parent.editor.filename))) self.win.show() if isMAEMO: self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True) self.win.connect(self.win.list_view, \ SIGNAL('doubleClicked(const QModelIndex&)'), \ self.goto_line) self.pylint_pross.waitForStarted() def finished(self, _): """ Call back called when lint end """ if isMAEMO: self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False) def handle_stdout(self): """ Private slot to handle the readyReadStdout signal of the pylint process. """ result_list = [] #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)') regex = QRegExp('(\w)\s*:\s*(\d*):(.*)') regex_score = \ QRegExp('.*at.(\d.\d*)/10.*') while self.pylint_pross and self.pylint_pross.canReadLine(): result = unicode(self.pylint_pross.readLine()) if result != None: pos = 0 while True: pos = regex.indexIn(result, pos) if pos < 0: if regex_score.indexIn(result, 0) >= 0: self.win.setWindowTitle( \ "PyLint Results :" \ + str(regex_score.cap(1)) \ + ':' + os.path.basename(str(self.parent.editor.filename))) break result_list.append( (regex.cap(1), regex.cap(2), regex.cap(3))) #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3)) pos = pos + regex.matchedLength() if len(result_list) > 0: self.win.append_results(result_list) def goto_line(self, index): """ Callback called when a lint result is double clicked """ line = int(self.win.list_model.items[index.row()][1]) self.parent.do_gotoLine(line) def handle_stderr(self): """ Private slot to handle the readyReadStderr signal of the pylint process. Currently not managed """ print 'error stderr'
class SvnChangeListsDialog(QDialog, Ui_SvnChangeListsDialog): """ Class implementing a dialog to browse the change lists. """ def __init__(self, vcs, parent=None): """ Constructor @param vcs reference to the vcs object @param parent parent widget (QWidget) """ QDialog.__init__(self, parent) self.setupUi(self) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.process = None self.vcs = vcs self.rx_status = \ QRegExp('(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*') # flags (8 or 9 anything), revision, changed rev, author, path self.rx_status2 = \ QRegExp('(.{8,9})\\s+(.+)\\s*') # flags (8 or 9 anything), path self.rx_changelist = \ QRegExp('--- \\S+ .([\\w\\s]+).:\\s+') # three dashes, Changelist (translated), quote, # changelist name, quote, : @pyqtSignature("QListWidgetItem*, QListWidgetItem*") def on_changeLists_currentItemChanged(self, current, previous): """ Private slot to handle the selection of a new item. @param current current item (QListWidgetItem) @param previous previous current item (QListWidgetItem) """ self.filesList.clear() if current is not None: changelist = unicode(current.text()) if changelist in self.changeListsDict: self.filesList.addItems(sorted(self.changeListsDict[changelist])) def start(self, path): """ Public slot to populate the data. @param path directory name to show change lists for (string) """ self.changeListsDict = {} self.filesLabel.setText(self.trUtf8("Files (relative to %1):").arg(path)) self.errorGroup.hide() self.intercept = False self.path = path self.currentChangelist = "" self.process = QProcess() self.process.finished.connect(self.__procFinished) self.process.readyReadStandardOutput.connect(self.__readStdout) self.process.readyReadStandardError.connect(self.__readStderr) args = [] args.append('status') self.vcs.addArguments(args, self.vcs.options['global']) self.vcs.addArguments(args, self.vcs.options['status']) if '--verbose' not in self.vcs.options['global'] and \ '--verbose' not in self.vcs.options['status']: args.append('--verbose') if isinstance(path, list): self.dname, fnames = self.vcs.splitPathList(path) self.vcs.addArguments(args, fnames) else: self.dname, fname = self.vcs.splitPath(path) args.append(fname) self.process.setWorkingDirectory(self.dname) self.process.start('svn', args) procStarted = self.process.waitForStarted() if not procStarted: self.inputGroup.setEnabled(False) self.inputGroup.hide() KQMessageBox.critical(self, self.trUtf8('Process Generation Error'), self.trUtf8( 'The process %1 could not be started. ' 'Ensure, that it is in the search path.' ).arg('svn')) else: self.inputGroup.setEnabled(True) self.inputGroup.show() def __finish(self): """ Private slot called when the process finished or the user pressed the button. """ if self.process is not None and \ self.process.state() != QProcess.NotRunning: self.process.terminate() QTimer.singleShot(2000, self.process.kill) self.process.waitForFinished(3000) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.inputGroup.setEnabled(False) self.inputGroup.hide() if len(self.changeListsDict) == 0: self.changeLists.addItem(self.trUtf8("No changelists found")) self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason) else: self.changeLists.addItems(sorted(self.changeListsDict.keys())) self.changeLists.setCurrentRow(0) self.changeLists.setFocus(Qt.OtherFocusReason) def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Close): self.close() elif button == self.buttonBox.button(QDialogButtonBox.Cancel): self.__finish() def __procFinished(self, exitCode, exitStatus): """ Private slot connected to the finished signal. @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ self.__finish() def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal. It reads the output of the process, formats it and inserts it into the contents pane. """ if self.process is not None: self.process.setReadChannel(QProcess.StandardOutput) while self.process.canReadLine(): s = unicode(self.process.readLine(), Preferences.getSystem("IOEncoding"), 'replace') if self.currentChangelist != "" and self.rx_status.exactMatch(s): file = unicode(self.rx_status.cap(5)).strip() filename = file.replace(self.path + os.sep, "") if filename not in self.changeListsDict[self.currentChangelist]: self.changeListsDict[self.currentChangelist].append(filename) elif self.currentChangelist != "" and self.rx_status2.exactMatch(s): file = unicode(self.rx_status2.cap(2)).strip() filename = file.replace(self.path + os.sep, "") if filename not in self.changeListsDict[self.currentChangelist]: self.changeListsDict[self.currentChangelist].append(filename) elif self.rx_changelist.exactMatch(s): self.currentChangelist = unicode(self.rx_changelist.cap(1)) if self.currentChangelist not in self.changeListsDict: self.changeListsDict[self.currentChangelist] = [] def __readStderr(self): """ Private slot to handle the readyReadStandardError signal. It reads the error output of the process and inserts it into the error pane. """ if self.process is not None: self.errorGroup.show() s = QString(self.process.readAllStandardError()) self.errors.insertPlainText(s) self.errors.ensureCursorVisible() def on_passwordCheckBox_toggled(self, isOn): """ Private slot to handle the password checkbox toggled. @param isOn flag indicating the status of the check box (boolean) """ if isOn: self.input.setEchoMode(QLineEdit.Password) else: self.input.setEchoMode(QLineEdit.Normal) @pyqtSignature("") def on_sendButton_clicked(self): """ Private slot to send the input to the subversion process. """ input = self.input.text() input += os.linesep if self.passwordCheckBox.isChecked(): self.errors.insertPlainText(os.linesep) self.errors.ensureCursorVisible() else: self.errors.insertPlainText(input) self.errors.ensureCursorVisible() self.process.write(input) self.passwordCheckBox.setChecked(False) self.input.clear() def on_input_returnPressed(self): """ Private slot to handle the press of the return key in the input field. """ self.intercept = True self.on_sendButton_clicked() def keyPressEvent(self, evt): """ Protected slot to handle a key press event. @param evt the key press event (QKeyEvent) """ if self.intercept: self.intercept = False evt.accept() return QDialog.keyPressEvent(self, evt)
class PyLint(Plugin, QObject): """ PyLint Plugin """ capabilities = ['toolbarHook'] __version__ = '0.5' thread = None def do_toolbarHook(self, widget): """ Hook to install the pylint toolbar button""" widget.addAction('PyLint', self.do_pylint) @pyqtSlot() def do_pylint(self): """ Launch the lint process and create the result window """ print 'do_pylint' self.pylint_pross = QProcess() self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels) self.pylint_pross.setWorkingDirectory( \ os.path.dirname(str(self.parent.editor.filename))) self.pylint_pross.setReadChannel(QProcess.StandardOutput) self.connect(self.pylint_pross, \ SIGNAL('finished(int)'), \ self.finished) self.connect(self.pylint_pross, \ SIGNAL('readyReadStandardOutput()'), \ self.handle_stdout) self.connect(self.pylint_pross, \ SIGNAL('readyReadStandardError()'), \ self.handle_stderr) if (self.pylint_pross.start("pylint", \ [self.parent.editor.filename,])): print 'Cannot start process' self.win = ResultWin() self.win.setWindowTitle("PyLint Results :" \ + os.path.basename(str(self.parent.editor.filename))) self.win.show() if isMAEMO: self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True) self.win.connect(self.win.list_view, \ SIGNAL('doubleClicked(const QModelIndex&)'), \ self.goto_line) self.pylint_pross.waitForStarted() def finished(self, _): """ Call back called when lint end """ if isMAEMO: self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False) def handle_stdout(self): """ Private slot to handle the readyReadStdout signal of the pylint process. """ result_list = [] #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)') regex = QRegExp('(\w)\s*:\s*(\d*):(.*)') regex_score = \ QRegExp('.*at.(\d.\d*)/10.*') while self.pylint_pross and self.pylint_pross.canReadLine(): result = unicode(self.pylint_pross.readLine()) if result != None: pos = 0 while True: pos = regex.indexIn(result, pos) if pos < 0: if regex_score.indexIn(result, 0) >= 0: self.win.setWindowTitle( \ "PyLint Results :" \ + str(regex_score.cap(1)) \ + ':' + os.path.basename(str(self.parent.editor.filename))) break result_list.append((regex.cap(1), regex.cap(2), regex.cap(3))) #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3)) pos = pos + regex.matchedLength() if len(result_list)>0: self.win.append_results(result_list) def goto_line(self, index): """ Callback called when a lint result is double clicked """ line = int(self.win.list_model.items[index.row()][1]) self.parent.do_gotoLine(line) def handle_stderr(self): """ Private slot to handle the readyReadStderr signal of the pylint process. Currently not managed """ print 'error stderr'
class CFDSTUDYGUI_QProcessDialog(QDialog, Ui_CFDSTUDYGUI_QProcessDialog): """ Advanced dialog. """ def __init__(self, parent, title, cmd_list, obj_directory="", start_directory=""): """ Constructor """ QDialog.__init__(self, parent) Ui_CFDSTUDYGUI_QProcessDialog.__init__(self) self.setupUi(self) self.setWindowTitle(title) self.pushButton.setEnabled(False) if start_directory != None and start_directory != "": os.chdir(start_directory) self.objBr = None if obj_directory != None and obj_directory != "": self.objBr = obj_directory self.proc = QProcess() #env = QProcessEnvironment().systemEnvironment() #self.proc.setProcessEnvironment(env) self.connect(self.proc, SIGNAL('readyReadStandardOutput()'), self.__readFromStdout) self.connect(self.proc, SIGNAL('readyReadStandardError()'), self.__readFromStderr) self.procErrorFlag = False self.cmd_list = cmd_list self.cmd = self.cmd_list.pop(0) cursor = QCursor(Qt.BusyCursor) QApplication.setOverrideCursor(cursor) self.__process() def __process(self): if self.proc.exitStatus() == QProcess.NormalExit and not self.procErrorFlag: self.proc.start(self.cmd) if self.cmd_list: self.cmd = self.cmd_list.pop(0) self.connect(self.proc, SIGNAL('finished(int, QProcess::ExitStatus)'), self.__process) else: self.connect(self.proc, SIGNAL('finished(int, QProcess::ExitStatus)'), self.__finished) def __readFromStdout(self): """ Private slot to handle the readyReadStandardOutput signal of the process. """ if self.proc is None: return self.proc.setReadChannel(QProcess.StandardOutput) while self.proc and self.proc.canReadLine(): ba = self.proc.readLine() if ba.isNull(): return str = QString() s = QString(str.fromUtf8(ba.data()))[:-1] self.logText.append(s) def __readFromStderr(self): """ Private slot to handle the readyReadStandardError signal of the process. """ if self.proc is None: return self.proc.setReadChannel(QProcess.StandardError) while self.proc and self.proc.canReadLine(): ba = self.proc.readLine() if ba.isNull(): return str = QString() s = QString(str.fromUtf8(ba.data()))[:-1] self.logText.append(s.prepend('<font color="red">').append('</font>')) self.procErrorFlag = True def __finished(self): if self.objBr: CFDSTUDYGUI_DataModel.UpdateSubTree(self.objBr) QApplication.restoreOverrideCursor() self.pushButton.setEnabled(True) def event(self, e): if e.type() == 9999: return QDialog.event(self, QCloseEvent()) if e.type() == 9998: return QDialog.event(self, QCloseEvent()) if e.type() == QEvent.Close: e.ignore() return True return QDialog.event(self, e)